195
192
<p>You can download this release in source or binary form.</p>
199
"http://initd.org/pub/software/pysqlite/apsw/3.3.13-r1/apsw-3.3.13-r1.zip">apsw-3.3.13-r1.zip</a>
203
"http://initd.org/pub/software/pysqlite/apsw/3.3.13-r1/apsw-3.3.13-r1.win32-py2.3">
204
apsw-3.3.13-r1.win32-py2.3.exe</a> (Windows Python 2.3)</li>
207
"http://initd.org/pub/software/pysqlite/apsw/3.3.13-r1/apsw-3.3.13-r1.win32-py2.4">
208
apsw-3.3.13-r1.win32-py2.4.exe</a> (Windows Python 2.4)</li>
211
"http://initd.org/pub/software/pysqlite/apsw/3.3.13-r1/apsw-3.3.13-r1.win32-py2.5">
212
apsw-3.3.13-r1.win32-py2.5.exe</a> (Windows Python 2.5)</li>
196
<li><a href="http://apsw.googlecode.com/files/apsw-3.5.9-r2.zip">apsw-3.5.9-r2.zip</a> (source)</li>
198
<li><a href="http://apsw.googlecode.com/files/apsw-3.5.9-r2.win32-py2.3.exe">apsw-3.5.9-r2.win32-py2.3.exe</a>
199
(Windows Python 2.3)</li>
201
<li><a href="http://apsw.googlecode.com/files/apsw-3.5.9-r2.win32-py2.4.exe">apsw-3.5.9-r2.win32-py2.4.exe</a>
202
(Windows Python 2.4)</li>
204
<li><a href="http://apsw.googlecode.com/files/apsw-3.5.9-r2.win32-py2.5.exe">apsw-3.5.9-r2.win32-py2.5.exe</a>
205
(Windows Python 2.5)</li>
215
<p>Some Linux distributions also have packages. Debian users can grab the
216
package <a href="http://packages.debian.org/python-apsw">python-apsw</a>.
217
Gentoo users can grab the package <a href=
208
<p>Some Linux distributions also have packages. Debian/Ubuntu users can grab the package <a href=
209
"http://packages.debian.org/python-apsw">python-apsw</a>. Gentoo users can grab the package <a href=
218
210
"http://www.gentoo-portage.com/dev-python/apsw">dev-python/apsw</a>.</p>
220
212
<h2><a name="Sourcecode" id="Sourcecode">Source code control</a></h2>
222
<p>The source is controlled by Subversion accessible as <a href=
223
"http://initd.org/svn/pysqlite/apsw/trunk">http://initd.org/svn/pysqlite/apsw/trunk</a></p>
225
<h1><a name="SQLiteVersionCompatibilityAndBenchmarking" id=
226
"SQLiteVersionCompatibilityAndBenchmarking">SQLite version compatibility and
227
benchmarking</a></h1>
229
<p>APSW binds to the C interface of SQLite. That interface is stable for each
230
major version of SQLite (ie the C interface for any SQLite 3.x is stable, but
231
SQLite 4.x would be an incompatible change). Consequently you can use APSW
232
against any revision of SQLite with the same major version number. There are
233
small enhancements to the C api over time, and APSW adds support for them as
234
appropriate. The version number of APSW covers the version these enhancements
235
were added. The vast majority of changes to SQLite are in the SQL syntax and
236
engine. Those will be picked up with any version of APSW. The one exception
237
to this is experimental features in SQLite which may change API between
238
revisions. Consequently you will need to turn them off if you want to work
239
against a variety of versions of SQLite (see EXPERIMENTAL in
240
<code>setup.py</code>). I strongly recommend you embed the SQLite library
241
into APSW which will put you in control of versions.</p>
243
<p>Before you do any benchmarking with APSW or other ways of accessing
244
SQLite, you must understand how and when SQLite does transactions. See
245
section 7.0, <i>Transaction Control At The SQL Level</i> of <a href=
246
"http://sqlite.org/lockingv3.html">sqlite.org/lockingv3.html</a>. <b>APSW
247
does not alter SQLite's behaviour with transactions.</b> Some access layers
248
try to interpret your SQL and manage transactions behind your back, which may
249
or may not work well with SQLite also do its own transactions. You should
250
always manage your transactions yourself. For example to insert 1,000 rows
251
wrap it in a single transaction else you will have 1,000 transactions. The
252
best clue that you have one transaction per statement is having a maximum of
253
60 statements per second. You need two drive rotations to do a transaction -
254
the data has to be committed to the main file and the journal - and 7200 RPM
255
drives do 120 rotations a second. On the other hand if you don't put in the
256
transaction boundaries yourself and get more than 60 statements a second,
257
then your access mechanism is silently starting transactions for you. This
258
topic also comes up fairly frequently in the SQLite mailing list
214
<p>The source is controlled by Subversion documented at <a href=
215
"http://code.google.com/p/apsw/source/checkout">http://code.google.com/p/apsw/source/checkout</a></p>
217
<h1><a name="SQLiteVersionCompatibilityAndBenchmarking" id="SQLiteVersionCompatibilityAndBenchmarking">SQLite version
218
compatibility and benchmarking</a></h1>
220
<p>APSW binds to the C interface of SQLite. That interface is stable for each major version of SQLite (ie the C
221
interface for any SQLite 3.x is stable, but SQLite 4.x would be an incompatible change). Consequently you can use
222
APSW against any revision of SQLite with the same major version number. There are small enhancements to the C api
223
over time, and APSW adds support for them as appropriate. The version number of APSW covers the version these
224
enhancements were added. The vast majority of changes to SQLite are in the SQL syntax and engine. Those will be
225
picked up with any version of APSW. The one exception to this is experimental features in SQLite which may change API
226
between revisions. Consequently you will need to turn them off if you want to work against a variety of versions of
227
SQLite (see EXPERIMENTAL in <code>setup.py</code>). I strongly recommend you embed the SQLite library into APSW which
228
will put you in control of versions.</p>
230
<p>Before you do any benchmarking with APSW or other ways of accessing SQLite, you must understand how and when
231
SQLite does transactions. See section 7.0, <i>Transaction Control At The SQL Level</i> of <a href=
232
"http://sqlite.org/lockingv3.html">sqlite.org/lockingv3.html</a>. <b>APSW does not alter SQLite's behaviour with
233
transactions.</b> Some access layers try to interpret your SQL and manage transactions behind your back, which may or
234
may not work well with SQLite also do its own transactions. You should always manage your transactions yourself. For
235
example to insert 1,000 rows wrap it in a single transaction else you will have 1,000 transactions. The best clue
236
that you have one transaction per statement is having a maximum of 60 statements per second. You need two drive
237
rotations to do a transaction - the data has to be committed to the main file and the journal - and 7200 RPM drives
238
do 120 rotations a second. On the other hand if you don't put in the transaction boundaries yourself and get more
239
than 60 statements a second, then your access mechanism is silently starting transactions for you. This topic also
240
comes up fairly frequently in the SQLite mailing list archives.</p>
261
242
<h1><a name="Example" id="Example">Example</a></h1>
263
<p>This is an example of how to use apsw, and also demonstrates all the
244
<p>This is an example of how to use apsw, and also demonstrates all the features.</p>
268
248
<!--sourcestart-->
269
<font face="Lucida,Courier New"><font color=
270
"#C00000">import </font>os<font color="#0000C0">, </font>sys<font color=
271
"#0000C0">, </font>time
272
<font color="#C00000">import </font>apsw
249
<font face="Lucida,Courier New,monospace"><span class="pykeyword">import </span><span class=
250
"pyname">os</span><span class="pyoperator">, </span><span class="pyname">sys</span><span class=
251
"pyoperator">, </span><span class="pyname">time
252
</span><span class="pykeyword">import </span><span class="pyname">apsw
274
<font color="#008000">###
254
</span><span class="pycomment">###
275
255
### Check we have the expected version of apsw and sqlite
278
</font><font color="#C00000">print </font><font color=
279
"#004080">"Using APSW file"</font><font color=
280
"#0000C0">,</font>apsw<font color="#0000C0">.</font>__file__ <font color="#008000"># from the extension module
281
</font><font color="#C00000">print </font><font color=
282
"#004080">" APSW version"</font><font color=
283
"#0000C0">,</font>apsw<font color="#0000C0">.</font>apswversion<font color=
284
"#0000C0">() </font><font color="#008000"># from the extension module
285
</font><font color="#C00000">print </font><font color=
286
"#004080">" SQLite version"</font><font color=
287
"#0000C0">,</font>apsw<font color="#0000C0">.</font>sqlitelibversion<font color="#0000C0">() </font><font color="#008000"># from the sqlite library code
288
</font><font color="#C00000">print </font><font color=
289
"#004080">" SQLite version"</font><font color=
290
"#0000C0">,</font>apsw<font color="#0000C0">.</font>SQLITE_VERSION_NUMBER <font color="#008000"># from the sqlite header file at compile time
258
</span><span class="pykeyword">print </span><span class="pystring">" Using APSW file"</span><span class=
259
"pyoperator">,</span><span class="pyname">apsw</span><span class="pyoperator">.</span><span class=
260
"pyname">__file__ </span><span class="pycomment"># from the extension module
261
</span><span class="pykeyword">print </span><span class="pystring">" APSW version"</span><span class=
262
"pyoperator">,</span><span class="pyname">apsw</span><span class="pyoperator">.</span><span class=
263
"pyname">apswversion</span><span class="pyoperator">() </span><span class=
264
"pycomment"># from the extension module
265
</span><span class="pykeyword">print </span><span class="pystring">" SQLite lib version"</span><span class=
266
"pyoperator">,</span><span class="pyname">apsw</span><span class="pyoperator">.</span><span class=
267
"pyname">sqlitelibversion</span><span class="pyoperator">() </span><span class=
268
"pycomment"># from the sqlite library code
269
</span><span class="pykeyword">print </span><span class="pystring">"SQLite header version"</span><span class=
270
"pyoperator">,</span><span class="pyname">apsw</span><span class="pyoperator">.</span><span class=
271
"pyname">SQLITE_VERSION_NUMBER </span><span class="pycomment"># from the sqlite header file at compile time
292
</font><font color="blue"> Using APSW file /space/apsw/apsw.so
293
APSW version 3.3.13-r1
294
SQLite version 3.3.13
295
SQLite version 3003013
297
<font color="#008000">###
273
</span><span class="pyoutput"> Using APSW file /space/apsw/apsw.so
274
APSW version 3.5.9-r2
275
SQLite lib version 3.5.9
276
SQLite header version 3005009
278
<span class="pycomment">###
298
279
### Opening/creating database
301
</font><font color="#C00000">if </font>os<font color=
302
"#0000C0">.</font>path<font color="#0000C0">.</font>exists<font color=
303
"#0000C0">(</font><font color="#004080">"dbfile"</font><font color=
304
"#0000C0">): </font>os<font color="#0000C0">.</font>remove<font color=
305
"#0000C0">(</font><font color="#004080">"dbfile"</font><font color="#0000C0">)
306
</font>connection<font color="#0000C0">=</font>apsw<font color=
307
"#0000C0">.</font>Connection<font color="#0000C0">(</font><font color=
308
"#004080">"dbfile"</font><font color="#0000C0">)
309
</font>cursor<font color="#0000C0">=</font>connection<font color=
310
"#0000C0">.</font>cursor<font color="#0000C0">()
282
</span><span class="pykeyword">if </span><span class="pyname">os</span><span class="pyoperator">.</span><span class=
283
"pyname">path</span><span class="pyoperator">.</span><span class="pyname">exists</span><span class=
284
"pyoperator">(</span><span class="pystring">"dbfile"</span><span class="pyoperator">): </span><span class=
285
"pyname">os</span><span class="pyoperator">.</span><span class="pyname">remove</span><span class=
286
"pyoperator">(</span><span class="pystring">"dbfile"</span><span class="pyoperator">)
287
</span><span class="pyname">connection</span><span class="pyoperator">=</span><span class=
288
"pyname">apsw</span><span class="pyoperator">.</span><span class="pyname">Connection</span><span class=
289
"pyoperator">(</span><span class="pystring">"dbfile"</span><span class="pyoperator">)
290
</span><span class="pyname">cursor</span><span class="pyoperator">=</span><span class=
291
"pyname">connection</span><span class="pyoperator">.</span><span class="pyname">cursor</span><span class=
312
</font><font color="#008000">###
294
</span><span class="pycomment">###
313
295
### simple statement
316
</font>cursor<font color="#0000C0">.</font>execute<font color=
317
"#0000C0">(</font><font color=
318
"#004080">"create table foo(x,y,z)"</font><font color="#0000C0">)
298
</span><span class="pyname">cursor</span><span class="pyoperator">.</span><span class=
299
"pyname">execute</span><span class="pyoperator">(</span><span class=
300
"pystring">"create table foo(x,y,z)"</span><span class="pyoperator">)
320
</font><font color="#008000">###
302
</span><span class="pycomment">###
321
303
### multiple statements
324
</font>cursor<font color="#0000C0">.</font>execute<font color=
325
"#0000C0">(</font><font color=
326
"#004080">"insert into foo values(1,2,3); create table bar(a,b,c) ; insert into foo values(4, 'five', 6.0)"</font><font color="#0000C0">)
306
</span><span class="pyname">cursor</span><span class="pyoperator">.</span><span class=
307
"pyname">execute</span><span class="pyoperator">(</span><span class=
308
"pystring">"insert into foo values(1,2,3); create table bar(a,b,c) ; insert into foo values(4, 'five', 6.0)"</span><span class="pyoperator">)
328
</font><font color="#008000">###
310
</span><span class="pycomment">###
332
</font><font color="#C00000">for </font>x<font color=
333
"#0000C0">,</font>y<font color="#0000C0">,</font>z <font color=
334
"#C00000">in </font>cursor<font color="#0000C0">.</font>execute<font color=
335
"#0000C0">(</font><font color=
336
"#004080">"select x,y,z from foo"</font><font color="#0000C0">):
337
</font><font color="#C00000">print </font>cursor<font color=
338
"#0000C0">.</font>getdescription<font color="#0000C0">() </font><font color=
339
"#008000"># shows column names and declared types
340
</font><font color="#C00000">print </font>x<font color=
341
"#0000C0">,</font>y<font color="#0000C0">,</font>z
314
</span><span class="pykeyword">for </span><span class="pyname">x</span><span class="pyoperator">,</span><span class=
315
"pyname">y</span><span class="pyoperator">,</span><span class="pyname">z </span><span class=
316
"pykeyword">in </span><span class="pyname">cursor</span><span class="pyoperator">.</span><span class=
317
"pyname">execute</span><span class="pyoperator">(</span><span class=
318
"pystring">"select x,y,z from foo"</span><span class="pyoperator">):
319
</span><span class="pykeyword">print </span><span class="pyname">cursor</span><span class=
320
"pyoperator">.</span><span class="pyname">getdescription</span><span class="pyoperator">() </span><span class=
321
"pycomment"># shows column names and declared types
322
</span><span class="pykeyword">print </span><span class="pyname">x</span><span class=
323
"pyoperator">,</span><span class="pyname">y</span><span class="pyoperator">,</span><span class="pyname">z
343
<font color="#008000">###
325
</span><span class="pycomment">###
344
326
### iterator - multiple statements
347
</font><font color="#C00000">for </font>m<font color=
348
"#0000C0">,</font>n<font color="#0000C0">,</font>o <font color=
349
"#C00000">in </font>cursor<font color="#0000C0">.</font>execute<font color=
350
"#0000C0">(</font><font color=
351
"#004080">"select x,y,z from foo ; select a,b,c from bar"</font><font color=
353
</font><font color="#C00000">print </font>m<font color=
354
"#0000C0">,</font>n<font color="#0000C0">,</font>o
329
</span><span class="pykeyword">for </span><span class="pyname">m</span><span class="pyoperator">,</span><span class=
330
"pyname">n</span><span class="pyoperator">,</span><span class="pyname">o </span><span class=
331
"pykeyword">in </span><span class="pyname">cursor</span><span class="pyoperator">.</span><span class=
332
"pyname">execute</span><span class="pyoperator">(</span><span class=
333
"pystring">"select x,y,z from foo ; select a,b,c from bar"</span><span class="pyoperator">):
334
</span><span class="pykeyword">print </span><span class="pyname">m</span><span class=
335
"pyoperator">,</span><span class="pyname">n</span><span class="pyoperator">,</span><span class="pyname">o
356
<font color="#008000">###
337
</span><span class="pycomment">###
357
338
### bindings - sequence
360
</font>cursor<font color="#0000C0">.</font>execute<font color=
361
"#0000C0">(</font><font color=
362
"#004080">"insert into foo values(?,?,?)"</font><font color=
363
"#0000C0">, (</font><font color="#0080C0">7</font><font color=
364
"#0000C0">, </font><font color="#004080">'eight'</font><font color=
365
"#0000C0">, </font>False<font color="#0000C0">))
366
</font>cursor<font color="#0000C0">.</font>execute<font color=
367
"#0000C0">(</font><font color=
368
"#004080">"insert into foo values(?,?,?1)"</font><font color=
369
"#0000C0">, (</font><font color="#004080">'one'</font><font color=
370
"#0000C0">, </font><font color="#004080">'two'</font><font color=
371
"#0000C0">)) </font><font color="#008000"># nb sqlite does the numbers from 1
341
</span><span class="pyname">cursor</span><span class="pyoperator">.</span><span class=
342
"pyname">execute</span><span class="pyoperator">(</span><span class=
343
"pystring">"insert into foo values(?,?,?)"</span><span class="pyoperator">, (</span><span class=
344
"pynumber">7</span><span class="pyoperator">, </span><span class="pystring">'eight'</span><span class=
345
"pyoperator">, </span><span class="pyname">False</span><span class="pyoperator">))
346
</span><span class="pyname">cursor</span><span class="pyoperator">.</span><span class=
347
"pyname">execute</span><span class="pyoperator">(</span><span class=
348
"pystring">"insert into foo values(?,?,?1)"</span><span class="pyoperator">, (</span><span class=
349
"pystring">'one'</span><span class="pyoperator">, </span><span class="pystring">'two'</span><span class=
350
"pyoperator">)) </span><span class="pycomment"># nb sqlite does the numbers from 1
374
353
### bindings - dictionary
377
</font>cursor<font color="#0000C0">.</font>execute<font color=
378
"#0000C0">(</font><font color=
379
"#004080">"insert into foo values(:alpha, :beta, :gamma)"</font><font color=
380
"#0000C0">, {</font><font color="#004080">'alpha'</font><font color=
381
"#0000C0">: </font><font color="#0080C0">1</font><font color=
382
"#0000C0">, </font><font color="#004080">'beta'</font><font color=
383
"#0000C0">: </font><font color="#0080C0">2</font><font color=
384
"#0000C0">, </font><font color="#004080">'gamma'</font><font color=
385
"#0000C0">: </font><font color="#004080">'three'</font><font color="#0000C0">})
356
</span><span class="pyname">cursor</span><span class="pyoperator">.</span><span class=
357
"pyname">execute</span><span class="pyoperator">(</span><span class=
358
"pystring">"insert into foo values(:alpha, :beta, :gamma)"</span><span class="pyoperator">, {</span><span class=
359
"pystring">'alpha'</span><span class="pyoperator">: </span><span class="pynumber">1</span><span class=
360
"pyoperator">, </span><span class="pystring">'beta'</span><span class="pyoperator">: </span><span class=
361
"pynumber">2</span><span class="pyoperator">, </span><span class="pystring">'gamma'</span><span class=
362
"pyoperator">: </span><span class="pystring">'three'</span><span class="pyoperator">})
387
</font><font color="#008000">###
364
</span><span class="pycomment">###
388
365
### <a name="example-exectrace" id="example-exectrace">tracing execution</a>
391
</font><font color="#C00000">def </font>mytrace<font color=
392
"#0000C0">(</font>statement<font color="#0000C0">, </font>bindings<font color=
394
</font><font color="#004080">"Called just before executing each statement"
395
</font><font color="#C00000">print </font><font color=
396
"#004080">"SQL:"</font><font color="#0000C0">,</font>statement
397
<font color="#C00000">if </font>bindings<font color="#0000C0">:
398
</font><font color="#C00000">print </font><font color=
399
"#004080">"Bindings:"</font><font color="#0000C0">,</font>bindings
400
<font color="#C00000">return </font>True <font color=
401
"#008000"># if you return False then execution is aborted
403
</font>cursor<font color="#0000C0">.</font>setexectrace<font color=
404
"#0000C0">(</font>mytrace<font color="#0000C0">)
405
</font>cursor<font color="#0000C0">.</font>execute<font color=
406
"#0000C0">(</font><font color=
407
"#004080">"drop table bar ; create table bar(x,y,z); select * from foo where x=?"</font><font color="#0000C0">, (</font><font color="#0080C0">3</font><font color="#0000C0">,))
409
</font><font color="blue"> SQL: drop table bar ;
368
</span><span class="pykeyword">def </span><span class="pyname">mytrace</span><span class=
369
"pyoperator">(</span><span class="pyname">statement</span><span class="pyoperator">, </span><span class=
370
"pyname">bindings</span><span class="pyoperator">):
371
</span><span class="pystring">"Called just before executing each statement"
372
</span><span class="pykeyword">print </span><span class="pystring">"SQL:"</span><span class=
373
"pyoperator">,</span><span class="pyname">statement
374
</span><span class="pykeyword">if </span><span class="pyname">bindings</span><span class="pyoperator">:
375
</span><span class="pykeyword">print </span><span class="pystring">"Bindings:"</span><span class=
376
"pyoperator">,</span><span class="pyname">bindings
377
</span><span class="pykeyword">return </span><span class="pyname">True </span><span class=
378
"pycomment"># if you return False then execution is aborted
380
</span><span class="pyname">cursor</span><span class="pyoperator">.</span><span class=
381
"pyname">setexectrace</span><span class="pyoperator">(</span><span class="pyname">mytrace</span><span class=
383
</span><span class="pyname">cursor</span><span class="pyoperator">.</span><span class=
384
"pyname">execute</span><span class="pyoperator">(</span><span class=
385
"pystring">"drop table bar ; create table bar(x,y,z); select * from foo where x=?"</span><span class=
386
"pyoperator">, (</span><span class="pynumber">3</span><span class="pyoperator">,))
388
</span><span class="pyoutput"> SQL: drop table bar ;
410
389
SQL: create table bar(x,y,z);
411
390
SQL: select * from foo where x=?
414
<font color="#008000">###
393
<span class="pycomment">###
415
394
### <a name="example-rowtrace" id="example-rowtrace">tracing results</a>
418
</font><font color="#C00000">def </font>rowtrace<font color=
419
"#0000C0">(*</font>results<font color="#0000C0">):
421
"#004080">"""Called with each row of results before they are handed off. You can return None to
397
</span><span class="pykeyword">def </span><span class="pyname">rowtrace</span><span class=
398
"pyoperator">(*</span><span class="pyname">results</span><span class="pyoperator">):
400
"pystring">"""Called with each row of results before they are handed off. You can return None to
422
401
cause the row to be skipped or a different set of values to return"""
423
</font><font color="#C00000">print </font><font color=
424
"#004080">"Row:"</font><font color="#0000C0">,</font>results
425
<font color="#C00000">return </font>results
427
cursor<font color="#0000C0">.</font>setrowtrace<font color=
428
"#0000C0">(</font>rowtrace<font color="#0000C0">)
429
</font><font color="#C00000">for </font>row <font color=
430
"#C00000">in </font>cursor<font color="#0000C0">.</font>execute<font color=
431
"#0000C0">(</font><font color=
432
"#004080">"select x,y from foo where x>3"</font><font color="#0000C0">):
433
</font><font color="#C00000">pass
435
</font><font color="blue"> SQL: select x,y from foo where x>3
402
</span><span class="pykeyword">print </span><span class="pystring">"Row:"</span><span class=
403
"pyoperator">,</span><span class="pyname">results
404
</span><span class="pykeyword">return </span><span class="pyname">results
406
cursor</span><span class="pyoperator">.</span><span class="pyname">setrowtrace</span><span class=
407
"pyoperator">(</span><span class="pyname">rowtrace</span><span class="pyoperator">)
408
</span><span class="pykeyword">for </span><span class="pyname">row </span><span class=
409
"pykeyword">in </span><span class="pyname">cursor</span><span class="pyoperator">.</span><span class=
410
"pyname">execute</span><span class="pyoperator">(</span><span class=
411
"pystring">"select x,y from foo where x>3"</span><span class="pyoperator">):
412
</span><span class="pykeyword">pass
414
</span><span class="pyoutput"> SQL: select x,y from foo where x>3
438
417
Row: (u'one', u'two')
440
<font color="#008000"># Clear tracers
441
</font>cursor<font color="#0000C0">.</font>setrowtrace<font color=
442
"#0000C0">(</font>None<font color="#0000C0">)
443
</font>cursor<font color="#0000C0">.</font>setexectrace<font color=
444
"#0000C0">(</font>None<font color="#0000C0">)
419
<span class="pycomment"># Clear tracers
420
</span><span class="pyname">cursor</span><span class="pyoperator">.</span><span class=
421
"pyname">setrowtrace</span><span class="pyoperator">(</span><span class="pyname">None</span><span class="pyoperator">)
422
</span><span class="pyname">cursor</span><span class="pyoperator">.</span><span class=
423
"pyname">setexectrace</span><span class="pyoperator">(</span><span class="pyname">None</span><span class="pyoperator">)
446
</font><font color="#008000">###
425
</span><span class="pycomment">###
450
429
# (This will work correctly with multiple statements, as well as statements that
451
430
# return data. The second argument can be anything that is iterable.)
452
</font>cursor<font color="#0000C0">.</font>executemany<font color=
453
"#0000C0">(</font><font color=
454
"#004080">"insert into foo (x) values(?)"</font><font color=
455
"#0000C0">, ( [</font><font color="#0080C0">1</font><font color=
456
"#0000C0">], [</font><font color="#0080C0">2</font><font color=
457
"#0000C0">], [</font><font color="#0080C0">3</font><font color="#0000C0">] ) )
460
"#008000"># You can also use it for statements that return data
461
</font><font color="#C00000">for </font>row <font color=
462
"#C00000">in </font>cursor<font color="#0000C0">.</font>executemany<font color=
463
"#0000C0">(</font><font color=
464
"#004080">"select * from foo where x=?"</font><font color=
465
"#0000C0">, ( [</font><font color="#0080C0">1</font><font color=
466
"#0000C0">], [</font><font color="#0080C0">2</font><font color=
467
"#0000C0">], [</font><font color="#0080C0">3</font><font color="#0000C0">] ) ):
468
</font><font color="#C00000">print </font>row
470
<font color="#008000">###
431
</span><span class="pyname">cursor</span><span class="pyoperator">.</span><span class=
432
"pyname">executemany</span><span class="pyoperator">(</span><span class=
433
"pystring">"insert into foo (x) values(?)"</span><span class="pyoperator">, ( [</span><span class=
434
"pynumber">1</span><span class="pyoperator">], [</span><span class="pynumber">2</span><span class=
435
"pyoperator">], [</span><span class="pynumber">3</span><span class="pyoperator">] ) )
437
</span><span class="pycomment"># You can also use it for statements that return data
438
</span><span class="pykeyword">for </span><span class="pyname">row </span><span class=
439
"pykeyword">in </span><span class="pyname">cursor</span><span class="pyoperator">.</span><span class=
440
"pyname">executemany</span><span class="pyoperator">(</span><span class=
441
"pystring">"select * from foo where x=?"</span><span class="pyoperator">, ( [</span><span class=
442
"pynumber">1</span><span class="pyoperator">], [</span><span class="pynumber">2</span><span class=
443
"pyoperator">], [</span><span class="pynumber">3</span><span class="pyoperator">] ) ):
444
</span><span class="pykeyword">print </span><span class="pyname">row
446
</span><span class="pycomment">###
471
447
### defining your own functions
474
</font><font color="#C00000">def </font>ilove7<font color=
475
"#0000C0">(*</font>args<font color="#0000C0">):
476
</font><font color="#004080">"a scalar function"
477
</font><font color="#C00000">print </font><font color=
478
"#004080">"ilove7 got"</font><font color="#0000C0">,</font>args<font color=
479
"#0000C0">,</font><font color="#004080">"but I love 7"
480
</font><font color="#C00000">return </font><font color="#0080C0">7
482
</font>connection<font color="#0000C0">.</font>createscalarfunction<font color=
483
"#0000C0">(</font><font color="#004080">"seven"</font><font color=
484
"#0000C0">, </font>ilove7<font color="#0000C0">)
486
</font><font color="#C00000">for </font>row <font color=
487
"#C00000">in </font>cursor<font color="#0000C0">.</font>execute<font color=
488
"#0000C0">(</font><font color=
489
"#004080">"select seven(x,y) from foo"</font><font color="#0000C0">):
490
</font><font color="#C00000">print </font>row
492
<font color="#008000">###
450
</span><span class="pykeyword">def </span><span class="pyname">ilove7</span><span class=
451
"pyoperator">(*</span><span class="pyname">args</span><span class="pyoperator">):
452
</span><span class="pystring">"a scalar function"
453
</span><span class="pykeyword">print </span><span class="pystring">"ilove7 got"</span><span class=
454
"pyoperator">,</span><span class="pyname">args</span><span class="pyoperator">,</span><span class=
455
"pystring">"but I love 7"
456
</span><span class="pykeyword">return </span><span class="pynumber">7
458
</span><span class="pyname">connection</span><span class="pyoperator">.</span><span class=
459
"pyname">createscalarfunction</span><span class="pyoperator">(</span><span class="pystring">"seven"</span><span class=
460
"pyoperator">, </span><span class="pyname">ilove7</span><span class="pyoperator">)
462
</span><span class="pykeyword">for </span><span class="pyname">row </span><span class=
463
"pykeyword">in </span><span class="pyname">cursor</span><span class="pyoperator">.</span><span class=
464
"pyname">execute</span><span class="pyoperator">(</span><span class=
465
"pystring">"select seven(x,y) from foo"</span><span class="pyoperator">):
466
</span><span class="pykeyword">print </span><span class="pyname">row
468
</span><span class="pycomment">###
493
469
### aggregate functions are more complex
496
472
# here we return the longest item when represented as a string
498
</font><font color="#C00000">def </font>longeststep<font color=
499
"#0000C0">(</font>context<font color="#0000C0">, *</font>args<font color=
502
"#004080">"are any of the arguments longer than our current candidate"
503
</font><font color="#C00000">for </font>arg <font color=
504
"#C00000">in </font>args<font color="#0000C0">:
505
</font><font color="#C00000">if </font>len<font color=
506
"#0000C0">( </font>str<font color="#0000C0">(</font>arg<font color=
507
"#0000C0">) ) > </font>len<font color="#0000C0">( </font>context<font color=
508
"#0000C0">[</font><font color="#004080">'longest'</font><font color=
510
</font>context<font color="#0000C0">[</font><font color=
511
"#004080">'longest'</font><font color="#0000C0">]=</font>str<font color=
512
"#0000C0">(</font>arg<font color="#0000C0">)
514
</font><font color="#C00000">def </font>longestfinal<font color=
515
"#0000C0">(</font>context<font color="#0000C0">):
516
</font><font color="#004080">"return the winner"
517
</font><font color="#C00000">return </font>context<font color=
518
"#0000C0">[</font><font color="#004080">'longest'</font><font color="#0000C0">]
520
</font><font color="#C00000">def </font>longestfactory<font color="#0000C0">():
522
"#004080">"""called for a new query. The first item returned can be
474
</span><span class="pykeyword">def </span><span class="pyname">longeststep</span><span class=
475
"pyoperator">(</span><span class="pyname">context</span><span class="pyoperator">, *</span><span class=
476
"pyname">args</span><span class="pyoperator">):
477
</span><span class="pystring">"are any of the arguments longer than our current candidate"
478
</span><span class="pykeyword">for </span><span class="pyname">arg </span><span class=
479
"pykeyword">in </span><span class="pyname">args</span><span class="pyoperator">:
480
</span><span class="pykeyword">if </span><span class="pyname">len</span><span class=
481
"pyoperator">( </span><span class="pyname">str</span><span class="pyoperator">(</span><span class=
482
"pyname">arg</span><span class="pyoperator">) ) > </span><span class="pyname">len</span><span class=
483
"pyoperator">( </span><span class="pyname">context</span><span class="pyoperator">[</span><span class=
484
"pystring">'longest'</span><span class="pyoperator">] ):
485
</span><span class="pyname">context</span><span class="pyoperator">[</span><span class=
486
"pystring">'longest'</span><span class="pyoperator">]=</span><span class="pyname">str</span><span class=
487
"pyoperator">(</span><span class="pyname">arg</span><span class="pyoperator">)
489
</span><span class="pykeyword">def </span><span class="pyname">longestfinal</span><span class=
490
"pyoperator">(</span><span class="pyname">context</span><span class="pyoperator">):
491
</span><span class="pystring">"return the winner"
492
</span><span class="pykeyword">return </span><span class="pyname">context</span><span class=
493
"pyoperator">[</span><span class="pystring">'longest'</span><span class="pyoperator">]
495
</span><span class="pykeyword">def </span><span class="pyname">longestfactory</span><span class="pyoperator">():
496
</span><span class="pystring">"""called for a new query. The first item returned can be
523
497
anything and is passed as the context to the step
524
498
and final methods. We use a dict."""
525
</font><font color="#C00000">return </font><font color=
526
"#0000C0">( { </font><font color="#004080">'longest'</font><font color=
527
"#0000C0">: </font><font color="#004080">'' </font><font color=
528
"#0000C0">}, </font>longeststep<font color=
529
"#0000C0">, </font>longestfinal<font color="#0000C0">)
531
</font>connection<font color=
532
"#0000C0">.</font>createaggregatefunction<font color=
533
"#0000C0">(</font><font color="#004080">"longest"</font><font color=
534
"#0000C0">, </font>longestfactory<font color="#0000C0">)
536
</font><font color="#C00000">for </font>row <font color=
537
"#C00000">in </font>cursor<font color="#0000C0">.</font>execute<font color=
538
"#0000C0">(</font><font color=
539
"#004080">"select longest(x) from foo"</font><font color="#0000C0">):
540
</font><font color="#C00000">print </font>row
542
<font color="#008000">###
499
</span><span class="pykeyword">return </span><span class="pyoperator">( { </span><span class=
500
"pystring">'longest'</span><span class="pyoperator">: </span><span class="pystring">'' </span><span class=
501
"pyoperator">}, </span><span class="pyname">longeststep</span><span class="pyoperator">, </span><span class=
502
"pyname">longestfinal</span><span class="pyoperator">)
504
</span><span class="pyname">connection</span><span class="pyoperator">.</span><span class=
505
"pyname">createaggregatefunction</span><span class="pyoperator">(</span><span class=
506
"pystring">"longest"</span><span class="pyoperator">, </span><span class="pyname">longestfactory</span><span class=
509
</span><span class="pykeyword">for </span><span class="pyname">row </span><span class=
510
"pykeyword">in </span><span class="pyname">cursor</span><span class="pyoperator">.</span><span class=
511
"pyname">execute</span><span class="pyoperator">(</span><span class=
512
"pystring">"select longest(x) from foo"</span><span class="pyoperator">):
513
</span><span class="pykeyword">print </span><span class="pyname">row
515
</span><span class="pycomment">###
543
516
### Defining collations.
546
519
# The default sorting mechanisms don't understand numbers at the end of strings
547
520
# so here we define a collation that does
549
</font>cursor<font color="#0000C0">.</font>execute<font color=
550
"#0000C0">(</font><font color=
551
"#004080">"create table s(str)"</font><font color="#0000C0">)
552
</font>cursor<font color="#0000C0">.</font>executemany<font color=
553
"#0000C0">(</font><font color=
554
"#004080">"insert into s values(?)"</font><font color="#0000C0">,
555
( [</font><font color="#004080">"file1"</font><font color=
556
"#0000C0">], [</font><font color="#004080">"file7"</font><font color=
557
"#0000C0">], [</font><font color="#004080">"file17"</font><font color=
558
"#0000C0">], [</font><font color="#004080">"file20"</font><font color=
559
"#0000C0">], [</font><font color="#004080">"file3"</font><font color=
562
</font><font color="#C00000">for </font>row <font color=
563
"#C00000">in </font>cursor<font color="#0000C0">.</font>execute<font color=
564
"#0000C0">(</font><font color=
565
"#004080">"select * from s order by str"</font><font color="#0000C0">):
566
</font><font color="#C00000">print </font>row
568
</font><font color="blue"> (u'file1',)
522
</span><span class="pyname">cursor</span><span class="pyoperator">.</span><span class=
523
"pyname">execute</span><span class="pyoperator">(</span><span class="pystring">"create table s(str)"</span><span class=
525
</span><span class="pyname">cursor</span><span class="pyoperator">.</span><span class=
526
"pyname">executemany</span><span class="pyoperator">(</span><span class=
527
"pystring">"insert into s values(?)"</span><span class="pyoperator">,
528
( [</span><span class="pystring">"file1"</span><span class="pyoperator">], [</span><span class=
529
"pystring">"file7"</span><span class="pyoperator">], [</span><span class="pystring">"file17"</span><span class=
530
"pyoperator">], [</span><span class="pystring">"file20"</span><span class="pyoperator">], [</span><span class=
531
"pystring">"file3"</span><span class="pyoperator">] ) )
533
</span><span class="pykeyword">for </span><span class="pyname">row </span><span class=
534
"pykeyword">in </span><span class="pyname">cursor</span><span class="pyoperator">.</span><span class=
535
"pyname">execute</span><span class="pyoperator">(</span><span class=
536
"pystring">"select * from s order by str"</span><span class="pyoperator">):
537
</span><span class="pykeyword">print </span><span class="pyname">row
539
</span><span class="pyoutput"> (u'file1',)
574
<font color="#C00000">def </font>strnumcollate<font color=
575
"#0000C0">(</font>s1<font color="#0000C0">, </font>s2<font color="#0000C0">):
576
</font><font color="#008000"># return -1 if s1<s2, +1 if s1>s2 else 0
545
<span class="pykeyword">def </span><span class="pyname">strnumcollate</span><span class=
546
"pyoperator">(</span><span class="pyname">s1</span><span class="pyoperator">, </span><span class=
547
"pyname">s2</span><span class="pyoperator">):
548
</span><span class="pycomment"># return -1 if s1<s2, +1 if s1>s2 else 0
578
550
# split values into two parts - the head and the numeric tail
579
</font>values<font color="#0000C0">=[</font>s1<font color=
580
"#0000C0">, </font>s2<font color="#0000C0">]
581
</font><font color="#C00000">for </font>vn<font color=
582
"#0000C0">,</font>v <font color="#C00000">in </font>enumerate<font color=
583
"#0000C0">(</font>values<font color="#0000C0">):
584
</font><font color="#C00000">for </font>i <font color=
585
"#C00000">in </font>range<font color="#0000C0">(</font>len<font color=
586
"#0000C0">(</font>v<font color="#0000C0">), </font><font color=
587
"#0080C0">0</font><font color="#0000C0">, -</font><font color=
588
"#0080C0">1</font><font color="#0000C0">):
589
</font><font color="#C00000">if </font>v<font color=
590
"#0000C0">[</font>i<font color="#0000C0">-</font><font color=
591
"#0080C0">1</font><font color="#0000C0">] </font><font color=
592
"#C00000">not in </font><font color="#004080">"01234567890"</font><font color=
594
</font><font color="#C00000">break
595
try</font><font color="#0000C0">:
596
</font>v<font color="#0000C0">=( </font>v<font color=
597
"#0000C0">[:</font>i<font color="#0000C0">], </font>int<font color=
598
"#0000C0">(</font>v<font color="#0000C0">[</font>i<font color="#0000C0">:]) )
599
</font><font color="#C00000">except </font>ValueError<font color=
601
</font>v<font color="#0000C0">=( </font>v<font color=
602
"#0000C0">[:</font>i<font color="#0000C0">], </font>None <font color=
604
</font>values<font color="#0000C0">[</font>vn<font color=
606
<font color="#008000"># compare
607
</font><font color="#C00000">if </font>values<font color=
608
"#0000C0">[</font><font color="#0080C0">0</font><font color=
609
"#0000C0">]<</font>values<font color="#0000C0">[</font><font color=
610
"#0080C0">1</font><font color="#0000C0">]:
611
</font><font color="#C00000">return </font><font color=
612
"#0000C0">-</font><font color="#0080C0">1
613
</font><font color="#C00000">if </font>values<font color=
614
"#0000C0">[</font><font color="#0080C0">0</font><font color=
615
"#0000C0">]></font>values<font color="#0000C0">[</font><font color=
616
"#0080C0">1</font><font color="#0000C0">]:
617
</font><font color="#C00000">return </font><font color="#0080C0">1
618
</font><font color="#C00000">return </font><font color="#0080C0">0
620
</font>connection<font color="#0000C0">.</font>createcollation<font color=
621
"#0000C0">(</font><font color="#004080">"strnum"</font><font color=
622
"#0000C0">, </font>strnumcollate<font color="#0000C0">)
624
</font><font color="#C00000">for </font>row <font color=
625
"#C00000">in </font>cursor<font color="#0000C0">.</font>execute<font color=
626
"#0000C0">(</font><font color=
627
"#004080">"select * from s order by str collate strnum"</font><font color=
629
</font><font color="#C00000">print </font>row
631
<font color="blue"> (u'file1',)
551
</span><span class="pyname">values</span><span class="pyoperator">=[</span><span class=
552
"pyname">s1</span><span class="pyoperator">, </span><span class="pyname">s2</span><span class="pyoperator">]
553
</span><span class="pykeyword">for </span><span class="pyname">vn</span><span class=
554
"pyoperator">,</span><span class="pyname">v </span><span class="pykeyword">in </span><span class=
555
"pyname">enumerate</span><span class="pyoperator">(</span><span class="pyname">values</span><span class="pyoperator">):
556
</span><span class="pykeyword">for </span><span class="pyname">i </span><span class=
557
"pykeyword">in </span><span class="pyname">range</span><span class="pyoperator">(</span><span class=
558
"pyname">len</span><span class="pyoperator">(</span><span class="pyname">v</span><span class=
559
"pyoperator">), </span><span class="pynumber">0</span><span class="pyoperator">, -</span><span class=
560
"pynumber">1</span><span class="pyoperator">):
561
</span><span class="pykeyword">if </span><span class="pyname">v</span><span class=
562
"pyoperator">[</span><span class="pyname">i</span><span class="pyoperator">-</span><span class=
563
"pynumber">1</span><span class="pyoperator">] </span><span class="pykeyword">not in </span><span class=
564
"pystring">"01234567890"</span><span class="pyoperator">:
565
</span><span class="pykeyword">break
566
try</span><span class="pyoperator">:
567
</span><span class="pyname">v</span><span class="pyoperator">=( </span><span class=
568
"pyname">v</span><span class="pyoperator">[:</span><span class="pyname">i</span><span class=
569
"pyoperator">], </span><span class="pyname">int</span><span class="pyoperator">(</span><span class=
570
"pyname">v</span><span class="pyoperator">[</span><span class="pyname">i</span><span class="pyoperator">:]) )
571
</span><span class="pykeyword">except </span><span class="pyname">ValueError</span><span class="pyoperator">:
572
</span><span class="pyname">v</span><span class="pyoperator">=( </span><span class=
573
"pyname">v</span><span class="pyoperator">[:</span><span class="pyname">i</span><span class=
574
"pyoperator">], </span><span class="pyname">None </span><span class="pyoperator">)
575
</span><span class="pyname">values</span><span class="pyoperator">[</span><span class=
576
"pyname">vn</span><span class="pyoperator">]=</span><span class="pyname">v
577
</span><span class="pycomment"># compare
578
</span><span class="pykeyword">if </span><span class="pyname">values</span><span class=
579
"pyoperator">[</span><span class="pynumber">0</span><span class="pyoperator">]<</span><span class=
580
"pyname">values</span><span class="pyoperator">[</span><span class="pynumber">1</span><span class="pyoperator">]:
581
</span><span class="pykeyword">return </span><span class="pyoperator">-</span><span class="pynumber">1
582
</span><span class="pykeyword">if </span><span class="pyname">values</span><span class=
583
"pyoperator">[</span><span class="pynumber">0</span><span class="pyoperator">]></span><span class=
584
"pyname">values</span><span class="pyoperator">[</span><span class="pynumber">1</span><span class="pyoperator">]:
585
</span><span class="pykeyword">return </span><span class="pynumber">1
586
</span><span class="pykeyword">return </span><span class="pynumber">0
588
</span><span class="pyname">connection</span><span class="pyoperator">.</span><span class=
589
"pyname">createcollation</span><span class="pyoperator">(</span><span class="pystring">"strnum"</span><span class=
590
"pyoperator">, </span><span class="pyname">strnumcollate</span><span class="pyoperator">)
592
</span><span class="pykeyword">for </span><span class="pyname">row </span><span class=
593
"pykeyword">in </span><span class="pyname">cursor</span><span class="pyoperator">.</span><span class=
594
"pyname">execute</span><span class="pyoperator">(</span><span class=
595
"pystring">"select * from s order by str collate strnum"</span><span class="pyoperator">):
596
</span><span class="pykeyword">print </span><span class="pyname">row
598
</span><span class="pyoutput"> (u'file1',)
637
<font color="#008000">###
604
<span class="pycomment">###
638
605
### Authorizer (eg if you want to control what user supplied SQL can do)
641
</font><font color="#C00000">def </font>authorizer<font color=
642
"#0000C0">(</font>operation<font color="#0000C0">, </font>paramone<font color=
643
"#0000C0">, </font>paramtwo<font color=
644
"#0000C0">, </font>databasename<font color=
645
"#0000C0">, </font>triggerorview<font color="#0000C0">):
647
"#004080">"""Called when each operation is prepared. We can return SQLITE_OK, SQLITE_DENY or
608
</span><span class="pykeyword">def </span><span class="pyname">authorizer</span><span class=
609
"pyoperator">(</span><span class="pyname">operation</span><span class="pyoperator">, </span><span class=
610
"pyname">paramone</span><span class="pyoperator">, </span><span class="pyname">paramtwo</span><span class=
611
"pyoperator">, </span><span class="pyname">databasename</span><span class="pyoperator">, </span><span class=
612
"pyname">triggerorview</span><span class="pyoperator">):
613
</span><span class="pystring">"""Called when each operation is prepared. We can return SQLITE_OK, SQLITE_DENY or
649
</font><font color="#008000"># find the operation name
650
</font><font color="#C00000">print </font>apsw<font color=
651
"#0000C0">.</font>mapping_authorizer_function<font color=
652
"#0000C0">[</font>operation<font color="#0000C0">],
653
</font><font color="#C00000">print </font>paramone<font color=
654
"#0000C0">, </font>paramtwo<font color=
655
"#0000C0">, </font>databasename<font color="#0000C0">, </font>triggerorview
656
<font color="#C00000">if </font>operation<font color=
657
"#0000C0">==</font>apsw<font color=
658
"#0000C0">.</font>SQLITE_CREATE_TABLE <font color=
659
"#C00000">and </font>paramone<font color=
660
"#0000C0">.</font>startswith<font color="#0000C0">(</font><font color=
661
"#004080">"private"</font><font color="#0000C0">):
662
</font><font color="#C00000">return </font>apsw<font color=
663
"#0000C0">.</font>SQLITE_DENY <font color=
664
"#008000"># not allowed to create tables whose names start with private
666
</font><font color="#C00000">return </font>apsw<font color=
667
"#0000C0">.</font>SQLITE_OK <font color="#008000"># always allow
669
</font>connection<font color="#0000C0">.</font>setauthorizer<font color=
670
"#0000C0">(</font>authorizer<font color="#0000C0">)
671
</font>cursor<font color="#0000C0">.</font>execute<font color=
672
"#0000C0">(</font><font color=
673
"#004080">"insert into s values('foo')"</font><font color="#0000C0">)
674
</font>cursor<font color="#0000C0">.</font>execute<font color=
675
"#0000C0">(</font><font color=
676
"#004080">"select str from s limit 1"</font><font color="#0000C0">)
678
</font><font color="blue"> SQLITE_INSERT s None main None
615
</span><span class="pycomment"># find the operation name
616
</span><span class="pykeyword">print </span><span class="pyname">apsw</span><span class=
617
"pyoperator">.</span><span class="pyname">mapping_authorizer_function</span><span class=
618
"pyoperator">[</span><span class="pyname">operation</span><span class="pyoperator">],
619
</span><span class="pykeyword">print </span><span class="pyname">paramone</span><span class=
620
"pyoperator">, </span><span class="pyname">paramtwo</span><span class="pyoperator">, </span><span class=
621
"pyname">databasename</span><span class="pyoperator">, </span><span class="pyname">triggerorview
622
</span><span class="pykeyword">if </span><span class="pyname">operation</span><span class=
623
"pyoperator">==</span><span class="pyname">apsw</span><span class="pyoperator">.</span><span class=
624
"pyname">SQLITE_CREATE_TABLE </span><span class="pykeyword">and </span><span class="pyname">paramone</span><span class=
625
"pyoperator">.</span><span class="pyname">startswith</span><span class="pyoperator">(</span><span class=
626
"pystring">"private"</span><span class="pyoperator">):
627
</span><span class="pykeyword">return </span><span class="pyname">apsw</span><span class=
628
"pyoperator">.</span><span class="pyname">SQLITE_DENY </span><span class=
629
"pycomment"># not allowed to create tables whose names start with private
631
</span><span class="pykeyword">return </span><span class="pyname">apsw</span><span class=
632
"pyoperator">.</span><span class="pyname">SQLITE_OK </span><span class="pycomment"># always allow
634
</span><span class="pyname">connection</span><span class="pyoperator">.</span><span class=
635
"pyname">setauthorizer</span><span class="pyoperator">(</span><span class="pyname">authorizer</span><span class=
637
</span><span class="pyname">cursor</span><span class="pyoperator">.</span><span class=
638
"pyname">execute</span><span class="pyoperator">(</span><span class=
639
"pystring">"insert into s values('foo')"</span><span class="pyoperator">)
640
</span><span class="pyname">cursor</span><span class="pyoperator">.</span><span class=
641
"pyname">execute</span><span class="pyoperator">(</span><span class=
642
"pystring">"select str from s limit 1"</span><span class="pyoperator">)
644
</span><span class="pyoutput"> SQLITE_INSERT s None main None
679
645
SQLITE_SELECT None None None None
680
646
SQLITE_READ s str main None
682
<font color="#008000"># Cancel authorizer
683
</font>connection<font color="#0000C0">.</font>setauthorizer<font color=
684
"#0000C0">(</font>None<font color="#0000C0">)
648
<span class="pycomment"># Cancel authorizer
649
</span><span class="pyname">connection</span><span class="pyoperator">.</span><span class=
650
"pyname">setauthorizer</span><span class="pyoperator">(</span><span class="pyname">None</span><span class=
686
</font><font color="#008000">###
653
</span><span class="pycomment">###
687
654
### progress handler (SQLite 3 experimental feature)
690
657
# something to give us large numbers of random numbers
691
</font><font color="#C00000">import </font>random
692
<font color="#C00000">def </font>randomintegers<font color=
693
"#0000C0">(</font>howmany<font color="#0000C0">):
694
</font><font color="#C00000">for </font>i <font color=
695
"#C00000">in </font>xrange<font color="#0000C0">(</font>howmany<font color=
697
</font><font color="#C00000">yield </font><font color=
698
"#0000C0">(</font>random<font color="#0000C0">.</font>randint<font color=
699
"#0000C0">(</font><font color="#0080C0">0</font><font color=
700
"#0000C0">,</font><font color="#0080C0">9999999999</font><font color=
703
</font><font color="#008000"># create a table with 500 random numbers
704
</font>cursor<font color="#0000C0">.</font>execute<font color=
705
"#0000C0">(</font><font color=
706
"#004080">"begin ; create table bigone(x)"</font><font color="#0000C0">)
707
</font>cursor<font color="#0000C0">.</font>executemany<font color=
708
"#0000C0">(</font><font color=
709
"#004080">"insert into bigone values(?)"</font><font color=
710
"#0000C0">, </font>randomintegers<font color="#0000C0">(</font><font color=
711
"#0080C0">500</font><font color="#0000C0">))
712
</font>cursor<font color="#0000C0">.</font>execute<font color=
713
"#0000C0">(</font><font color="#004080">"commit"</font><font color="#0000C0">)
715
</font><font color="#008000"># display an ascii spinner
716
</font>_phcount<font color="#0000C0">=</font><font color="#0080C0">0
717
</font>_phspinner<font color="#0000C0">=</font><font color="#004080">"|/-\\"
718
</font><font color="#C00000">def </font>progresshandler<font color=
720
</font><font color="#C00000">global </font>_phcount
721
sys<font color="#0000C0">.</font>stdout<font color=
722
"#0000C0">.</font>write<font color="#0000C0">(</font>_phspinner<font color=
723
"#0000C0">[</font>_phcount<font color="#0000C0">%</font>len<font color=
724
"#0000C0">(</font>_phspinner<font color="#0000C0">)]+</font>chr<font color=
725
"#0000C0">(</font><font color="#0080C0">8</font><font color=
726
"#0000C0">)) </font><font color="#008000"># chr(8) is backspace
727
</font>sys<font color="#0000C0">.</font>stdout<font color=
728
"#0000C0">.</font>flush<font color="#0000C0">()
729
</font>_phcount<font color="#0000C0">+=</font><font color="#0080C0">1
730
</font>time<font color="#0000C0">.</font>sleep<font color=
731
"#0000C0">(</font><font color="#0080C0">0.1</font><font color=
732
"#0000C0">) </font><font color=
733
"#008000"># deliberate delay so we can see the spinner (SQLite is too fast otherwise!)
734
</font><font color="#C00000">return </font><font color=
735
"#0080C0">0 </font><font color="#008000"># returning non-zero aborts
658
</span><span class="pykeyword">import </span><span class="pyname">random
659
</span><span class="pykeyword">def </span><span class="pyname">randomintegers</span><span class=
660
"pyoperator">(</span><span class="pyname">howmany</span><span class="pyoperator">):
661
</span><span class="pykeyword">for </span><span class="pyname">i </span><span class=
662
"pykeyword">in </span><span class="pyname">xrange</span><span class="pyoperator">(</span><span class=
663
"pyname">howmany</span><span class="pyoperator">):
664
</span><span class="pykeyword">yield </span><span class="pyoperator">(</span><span class=
665
"pyname">random</span><span class="pyoperator">.</span><span class="pyname">randint</span><span class=
666
"pyoperator">(</span><span class="pynumber">0</span><span class="pyoperator">,</span><span class=
667
"pynumber">9999999999</span><span class="pyoperator">),)
669
</span><span class="pycomment"># create a table with 100 random numbers
670
</span><span class="pyname">cursor</span><span class="pyoperator">.</span><span class=
671
"pyname">execute</span><span class="pyoperator">(</span><span class=
672
"pystring">"begin ; create table bigone(x)"</span><span class="pyoperator">)
673
</span><span class="pyname">cursor</span><span class="pyoperator">.</span><span class=
674
"pyname">executemany</span><span class="pyoperator">(</span><span class=
675
"pystring">"insert into bigone values(?)"</span><span class="pyoperator">, </span><span class=
676
"pyname">randomintegers</span><span class="pyoperator">(</span><span class="pynumber">100</span><span class=
678
</span><span class="pyname">cursor</span><span class="pyoperator">.</span><span class=
679
"pyname">execute</span><span class="pyoperator">(</span><span class="pystring">"commit"</span><span class=
682
</span><span class="pycomment"># display an ascii spinner
683
</span><span class="pyname">_phcount</span><span class="pyoperator">=</span><span class="pynumber">0
684
</span><span class="pyname">_phspinner</span><span class="pyoperator">=</span><span class="pystring">"|/-\\"
685
</span><span class="pykeyword">def </span><span class="pyname">progresshandler</span><span class="pyoperator">():
686
</span><span class="pykeyword">global </span><span class="pyname">_phcount
687
sys</span><span class="pyoperator">.</span><span class="pyname">stdout</span><span class=
688
"pyoperator">.</span><span class="pyname">write</span><span class="pyoperator">(</span><span class=
689
"pyname">_phspinner</span><span class="pyoperator">[</span><span class="pyname">_phcount</span><span class=
690
"pyoperator">%</span><span class="pyname">len</span><span class="pyoperator">(</span><span class=
691
"pyname">_phspinner</span><span class="pyoperator">)]+</span><span class="pyname">chr</span><span class=
692
"pyoperator">(</span><span class="pynumber">8</span><span class="pyoperator">)) </span><span class=
693
"pycomment"># chr(8) is backspace
694
</span><span class="pyname">sys</span><span class="pyoperator">.</span><span class=
695
"pyname">stdout</span><span class="pyoperator">.</span><span class="pyname">flush</span><span class="pyoperator">()
696
</span><span class="pyname">_phcount</span><span class="pyoperator">+=</span><span class="pynumber">1
697
</span><span class="pyname">time</span><span class="pyoperator">.</span><span class=
698
"pyname">sleep</span><span class="pyoperator">(</span><span class="pynumber">0.1</span><span class=
699
"pyoperator">) </span><span class=
700
"pycomment"># deliberate delay so we can see the spinner (SQLite is too fast otherwise!)
701
</span><span class="pykeyword">return </span><span class="pynumber">0 </span><span class=
702
"pycomment"># returning non-zero aborts
737
704
# register progresshandler every 20 instructions
738
</font>connection<font color="#0000C0">.</font>setprogresshandler<font color=
739
"#0000C0">(</font>progresshandler<font color="#0000C0">, </font><font color=
740
"#0080C0">20</font><font color="#0000C0">)
743
"#008000"># see it in action - sorting 500 numbers to find the biggest takes a while
744
</font><font color="#C00000">print </font><font color=
745
"#004080">"spinny thing -> "</font><font color="#0000C0">,
746
</font><font color="#C00000">for </font>i <font color=
747
"#C00000">in </font>cursor<font color="#0000C0">.</font>execute<font color=
748
"#0000C0">(</font><font color=
749
"#004080">"select max(x) from bigone"</font><font color="#0000C0">):
750
</font><font color="#C00000">print </font><font color="#008000"># newline
751
</font><font color="#C00000">print </font>i <font color=
752
"#008000"># and the maximum number
754
</font>connection<font color="#0000C0">.</font>setprogresshandler<font color=
755
"#0000C0">(</font>None<font color="#0000C0">)
757
</font><font color="#008000">###
705
</span><span class="pyname">connection</span><span class="pyoperator">.</span><span class=
706
"pyname">setprogresshandler</span><span class="pyoperator">(</span><span class=
707
"pyname">progresshandler</span><span class="pyoperator">, </span><span class="pynumber">20</span><span class=
710
</span><span class="pycomment"># see it in action - sorting 100 numbers to find the biggest takes a while
711
</span><span class="pykeyword">print </span><span class="pystring">"spinny thing -> "</span><span class=
713
</span><span class="pykeyword">for </span><span class="pyname">i </span><span class="pykeyword">in </span><span class=
714
"pyname">cursor</span><span class="pyoperator">.</span><span class="pyname">execute</span><span class=
715
"pyoperator">(</span><span class="pystring">"select max(x) from bigone"</span><span class="pyoperator">):
716
</span><span class="pykeyword">print </span><span class="pycomment"># newline
717
</span><span class="pykeyword">print </span><span class="pyname">i </span><span class=
718
"pycomment"># and the maximum number
720
</span><span class="pyname">connection</span><span class="pyoperator">.</span><span class=
721
"pyname">setprogresshandler</span><span class="pyoperator">(</span><span class="pyname">None</span><span class=
724
</span><span class="pycomment">###
758
725
### commit hook (SQLite3 experimental feature)
761
</font><font color="#C00000">def </font>mycommithook<font color="#0000C0">():
762
</font><font color="#C00000">print </font><font color=
763
"#004080">"in commit hook"
764
</font>hour<font color="#0000C0">=</font>time<font color=
765
"#0000C0">.</font>localtime<font color="#0000C0">()[</font><font color=
766
"#0080C0">3</font><font color="#0000C0">]
767
</font><font color="#C00000">if </font>hour<font color=
768
"#0000C0"><</font><font color="#0080C0">8 </font><font color=
769
"#C00000">or </font>hour<font color="#0000C0">></font><font color=
770
"#0080C0">17</font><font color="#0000C0">:
771
</font><font color="#C00000">print </font><font color=
772
"#004080">"no commits out of hours"
773
</font><font color="#C00000">return </font><font color=
774
"#0080C0">1 </font><font color=
775
"#008000"># abort commits outside of 8am through 6pm
776
</font><font color="#C00000">print </font><font color=
777
"#004080">"commits okay at this time"
778
</font><font color="#C00000">return </font><font color=
779
"#0080C0">0 </font><font color="#008000"># let commit go ahead
781
</font>connection<font color="#0000C0">.</font>setcommithook<font color=
782
"#0000C0">(</font>mycommithook<font color="#0000C0">)
783
</font><font color="#C00000">try</font><font color="#0000C0">:
784
</font>cursor<font color="#0000C0">.</font>execute<font color=
785
"#0000C0">(</font><font color=
786
"#004080">"begin; create table example(x,y,z); insert into example values (3,4,5) ; commit"</font><font color="#0000C0">)
787
</font><font color="#C00000">except </font>apsw<font color=
788
"#0000C0">.</font>ConstraintError<font color="#0000C0">:
789
</font><font color="#C00000">print </font><font color=
790
"#004080">"commit was not allowed"
792
</font>connection<font color="#0000C0">.</font>setcommithook<font color=
793
"#0000C0">(</font>None<font color="#0000C0">)
795
</font><font color="#008000">###
728
</span><span class="pykeyword">def </span><span class="pyname">mycommithook</span><span class="pyoperator">():
729
</span><span class="pykeyword">print </span><span class="pystring">"in commit hook"
730
</span><span class="pyname">hour</span><span class="pyoperator">=</span><span class=
731
"pyname">time</span><span class="pyoperator">.</span><span class="pyname">localtime</span><span class=
732
"pyoperator">()[</span><span class="pynumber">3</span><span class="pyoperator">]
733
</span><span class="pykeyword">if </span><span class="pyname">hour</span><span class=
734
"pyoperator"><</span><span class="pynumber">8 </span><span class="pykeyword">or </span><span class=
735
"pyname">hour</span><span class="pyoperator">></span><span class="pynumber">17</span><span class="pyoperator">:
736
</span><span class="pykeyword">print </span><span class="pystring">"no commits out of hours"
737
</span><span class="pykeyword">return </span><span class="pynumber">1 </span><span class=
738
"pycomment"># abort commits outside of 8am through 6pm
739
</span><span class="pykeyword">print </span><span class="pystring">"commits okay at this time"
740
</span><span class="pykeyword">return </span><span class="pynumber">0 </span><span class=
741
"pycomment"># let commit go ahead
743
</span><span class="pyname">connection</span><span class="pyoperator">.</span><span class=
744
"pyname">setcommithook</span><span class="pyoperator">(</span><span class="pyname">mycommithook</span><span class=
746
</span><span class="pykeyword">try</span><span class="pyoperator">:
747
</span><span class="pyname">cursor</span><span class="pyoperator">.</span><span class=
748
"pyname">execute</span><span class="pyoperator">(</span><span class=
749
"pystring">"begin; create table example(x,y,z); insert into example values (3,4,5) ; commit"</span><span class=
751
</span><span class="pykeyword">except </span><span class="pyname">apsw</span><span class=
752
"pyoperator">.</span><span class="pyname">ConstraintError</span><span class="pyoperator">:
753
</span><span class="pykeyword">print </span><span class="pystring">"commit was not allowed"
755
</span><span class="pyname">connection</span><span class="pyoperator">.</span><span class=
756
"pyname">setcommithook</span><span class="pyoperator">(</span><span class="pyname">None</span><span class=
759
</span><span class="pycomment">###
760
### <a name="example-blobio" id="example-blobio">Blob I/O</a>
763
</span><span class="pyname">cursor</span><span class="pyoperator">.</span><span class=
764
"pyname">execute</span><span class="pyoperator">(</span><span class=
765
"pystring">"create table blobby(x,y)"</span><span class="pyoperator">)
766
</span><span class="pycomment"># Add a blob we will fill in later
767
</span><span class="pyname">cursor</span><span class="pyoperator">.</span><span class=
768
"pyname">execute</span><span class="pyoperator">(</span><span class=
769
"pystring">"insert into blobby values(1,zeroblob(10000))"</span><span class="pyoperator">)
770
</span><span class="pycomment"># Or as a binding
771
</span><span class="pyname">cursor</span><span class="pyoperator">.</span><span class=
772
"pyname">execute</span><span class="pyoperator">(</span><span class=
773
"pystring">"insert into blobby values(2,?)"</span><span class="pyoperator">, (</span><span class=
774
"pyname">apsw</span><span class="pyoperator">.</span><span class="pyname">zeroblob</span><span class=
775
"pyoperator">(</span><span class="pynumber">20000</span><span class="pyoperator">),))
776
</span><span class="pycomment"># Open a blob for writing. We need to know the rowid
777
</span><span class="pyname">rowid</span><span class="pyoperator">=</span><span class="pyname">cursor</span><span class=
778
"pyoperator">.</span><span class="pyname">execute</span><span class="pyoperator">(</span><span class=
779
"pystring">"select ROWID from blobby where x=1"</span><span class="pyoperator">).</span><span class=
780
"pyname">next</span><span class="pyoperator">()[</span><span class="pynumber">0</span><span class="pyoperator">]
781
</span><span class="pyname">blob</span><span class="pyoperator">=</span><span class=
782
"pyname">connection</span><span class="pyoperator">.</span><span class="pyname">blobopen</span><span class=
783
"pyoperator">(</span><span class="pystring">"main"</span><span class="pyoperator">, </span><span class=
784
"pystring">"blobby"</span><span class="pyoperator">, </span><span class="pystring">"y"</span><span class=
785
"pyoperator">, </span><span class="pyname">rowid</span><span class="pyoperator">, </span><span class=
786
"pynumber">1</span><span class="pyoperator">) </span><span class="pycomment"># 1 is for read/write
787
</span><span class="pyname">blob</span><span class="pyoperator">.</span><span class="pyname">write</span><span class=
788
"pyoperator">(</span><span class="pystring">"hello world"</span><span class="pyoperator">)
789
</span><span class="pyname">blob</span><span class="pyoperator">.</span><span class="pyname">seek</span><span class=
790
"pyoperator">(</span><span class="pynumber">2000</span><span class="pyoperator">)
791
</span><span class="pyname">blob</span><span class="pyoperator">.</span><span class="pyname">write</span><span class=
792
"pyoperator">(</span><span class="pystring">"hello world, again"</span><span class="pyoperator">)
793
</span><span class="pyname">blob</span><span class="pyoperator">.</span><span class="pyname">close</span><span class=
796
</span><span class="pycomment">###
796
797
### Virtual tables
799
800
# This virtual table stores information about files in a set of
800
801
# directories so you can execute SQL queries
802
</font><font color="#C00000">def </font>getfiledata<font color=
803
"#0000C0">(</font>directories<font color="#0000C0">):
804
</font>columns<font color="#0000C0">=</font>None
805
data<font color="#0000C0">=[]
806
</font>counter<font color="#0000C0">=</font><font color="#0080C0">1
807
</font><font color="#C00000">for </font>directory <font color=
808
"#C00000">in </font>directories<font color="#0000C0">:
809
</font><font color="#C00000">for </font>f <font color=
810
"#C00000">in </font>os<font color="#0000C0">.</font>listdir<font color=
811
"#0000C0">(</font>directory<font color="#0000C0">):
812
</font><font color="#C00000">if not </font>os<font color=
813
"#0000C0">.</font>path<font color="#0000C0">.</font>isfile<font color=
814
"#0000C0">(</font>os<font color="#0000C0">.</font>path<font color=
815
"#0000C0">.</font>join<font color="#0000C0">(</font>directory<font color=
816
"#0000C0">,</font>f<font color="#0000C0">)):
817
</font><font color="#C00000">continue
818
</font>counter<font color="#0000C0">+=</font><font color=
820
</font>st<font color="#0000C0">=</font>os<font color=
821
"#0000C0">.</font>stat<font color="#0000C0">(</font>os<font color=
822
"#0000C0">.</font>path<font color="#0000C0">.</font>join<font color=
823
"#0000C0">(</font>directory<font color="#0000C0">,</font>f<font color=
825
</font><font color="#C00000">if </font>columns <font color=
826
"#C00000">is </font>None<font color="#0000C0">:
827
</font>columns<font color="#0000C0">=[</font><font color=
828
"#004080">"rowid"</font><font color="#0000C0">, </font><font color=
829
"#004080">"name"</font><font color="#0000C0">, </font><font color=
830
"#004080">"directory"</font><font color="#0000C0">]+[</font>x <font color=
831
"#C00000">for </font>x <font color="#C00000">in </font>dir<font color=
832
"#0000C0">(</font>st<font color="#0000C0">) </font><font color=
833
"#C00000">if </font>x<font color="#0000C0">.</font>startswith<font color=
834
"#0000C0">(</font><font color="#004080">"st_"</font><font color="#0000C0">)]
835
</font>data<font color="#0000C0">.</font>append<font color=
836
"#0000C0">( [</font>counter<font color="#0000C0">, </font>f<font color=
837
"#0000C0">, </font>directory<font color=
838
"#0000C0">] + [</font>getattr<font color="#0000C0">(</font>st<font color=
839
"#0000C0">,</font>x<font color="#0000C0">) </font><font color=
840
"#C00000">for </font>x <font color="#C00000">in </font>columns<font color=
841
"#0000C0">[</font><font color="#0080C0">3</font><font color="#0000C0">:]] )
842
</font><font color="#C00000">return </font>columns<font color=
843
"#0000C0">, </font>data
845
<font color="#008000"># This gets registered with the Connection
846
</font><font color="#C00000">class </font>Source<font color="#0000C0">:
847
</font><font color="#C00000">def </font>Create<font color=
848
"#0000C0">(</font>self<font color="#0000C0">, </font>db<font color=
849
"#0000C0">, </font>modulename<font color="#0000C0">, </font>dbname<font color=
850
"#0000C0">, </font>tablename<font color="#0000C0">, *</font>args<font color=
852
</font>columns<font color="#0000C0">,</font>data<font color=
853
"#0000C0">=</font>getfiledata<font color="#0000C0">([</font>eval<font color=
854
"#0000C0">(</font>a<font color="#0000C0">) </font><font color=
855
"#C00000">for </font>a <font color="#C00000">in </font>args<font color=
856
"#0000C0">]) </font><font color="#008000"># eval strips off layer of quotes
857
</font>schema<font color="#0000C0">=</font><font color=
858
"#004080">"create table foo("</font><font color="#0000C0">+</font><font color=
859
"#004080">','</font><font color="#0000C0">.</font>join<font color=
860
"#0000C0">([</font><font color="#004080">"'%s'" </font><font color=
861
"#0000C0">% (</font>x<font color="#0000C0">,) </font><font color=
862
"#C00000">for </font>x <font color="#C00000">in </font>columns<font color=
863
"#0000C0">[</font><font color="#0080C0">1</font><font color=
864
"#0000C0">:]])+</font><font color="#004080">")"
865
</font><font color="#C00000">return </font>schema<font color=
866
"#0000C0">,</font>Table<font color="#0000C0">(</font>columns<font color=
867
"#0000C0">,</font>data<font color="#0000C0">)
868
</font>Connect<font color="#0000C0">=</font>Create
870
<font color="#008000"># Represents a table
871
</font><font color="#C00000">class </font>Table<font color="#0000C0">:
872
</font><font color="#C00000">def </font>__init__<font color=
873
"#0000C0">(</font>self<font color="#0000C0">, </font>columns<font color=
874
"#0000C0">, </font>data<font color="#0000C0">):
875
</font>self<font color="#0000C0">.</font>columns<font color=
876
"#0000C0">=</font>columns
877
self<font color="#0000C0">.</font>data<font color=
878
"#0000C0">=</font>data
880
<font color="#C00000">def </font>BestIndex<font color=
881
"#0000C0">(</font>self<font color="#0000C0">, *</font>args<font color=
883
</font><font color="#C00000">return </font>None
885
<font color="#C00000">def </font>Open<font color=
886
"#0000C0">(</font>self<font color="#0000C0">):
887
</font><font color="#C00000">return </font>Cursor<font color=
888
"#0000C0">(</font>self<font color="#0000C0">)
890
</font><font color="#C00000">def </font>Disconnect<font color=
891
"#0000C0">(</font>self<font color="#0000C0">):
892
</font><font color="#C00000">pass
894
</font>Destroy<font color="#0000C0">=</font>Disconnect
896
<font color="#008000"># Represents a cursor
897
</font><font color="#C00000">class </font>Cursor<font color="#0000C0">:
898
</font><font color="#C00000">def </font>__init__<font color=
899
"#0000C0">(</font>self<font color="#0000C0">, </font>table<font color=
901
</font>self<font color="#0000C0">.</font>table<font color=
902
"#0000C0">=</font>table
904
<font color="#C00000">def </font>Filter<font color=
905
"#0000C0">(</font>self<font color="#0000C0">, *</font>args<font color=
907
</font>self<font color="#0000C0">.</font>pos<font color=
908
"#0000C0">=</font><font color="#0080C0">0
910
</font><font color="#C00000">def </font>Eof<font color=
911
"#0000C0">(</font>self<font color="#0000C0">):
912
</font><font color="#C00000">return </font>self<font color=
913
"#0000C0">.</font>pos<font color="#0000C0">>=</font>len<font color=
914
"#0000C0">(</font>self<font color="#0000C0">.</font>table<font color=
915
"#0000C0">.</font>data<font color="#0000C0">)
917
</font><font color="#C00000">def </font>Rowid<font color=
918
"#0000C0">(</font>self<font color="#0000C0">):
919
</font><font color="#C00000">return </font>self<font color=
920
"#0000C0">.</font>table<font color="#0000C0">.</font>data<font color=
921
"#0000C0">[</font>self<font color="#0000C0">.</font>pos<font color=
922
"#0000C0">][</font><font color="#0080C0">0</font><font color="#0000C0">]
924
</font><font color="#C00000">def </font>Column<font color=
925
"#0000C0">(</font>self<font color="#0000C0">, </font>col<font color=
927
</font><font color="#C00000">return </font>self<font color=
928
"#0000C0">.</font>table<font color="#0000C0">.</font>data<font color=
929
"#0000C0">[</font>self<font color="#0000C0">.</font>pos<font color=
930
"#0000C0">][</font><font color="#0080C0">1</font><font color=
931
"#0000C0">+</font>col<font color="#0000C0">]
933
</font><font color="#C00000">def </font>Next<font color=
934
"#0000C0">(</font>self<font color="#0000C0">):
935
</font>self<font color="#0000C0">.</font>pos<font color=
936
"#0000C0">+=</font><font color="#0080C0">1
938
</font><font color="#C00000">def </font>Close<font color=
939
"#0000C0">(</font>self<font color="#0000C0">):
940
</font><font color="#C00000">pass
942
</font><font color="#008000"># Register the module as filesource
943
</font>connection<font color="#0000C0">.</font>createmodule<font color=
944
"#0000C0">(</font><font color="#004080">"filesource"</font><font color=
945
"#0000C0">, </font>Source<font color="#0000C0">())
948
"#008000"># Arguments to module - all directories in sys.path
949
</font>sysdirs<font color="#0000C0">=</font><font color=
950
"#004080">","</font><font color="#0000C0">.</font>join<font color=
951
"#0000C0">([</font><font color="#004080">"'%s'" </font><font color=
952
"#0000C0">% (</font>x<font color="#0000C0">,) </font><font color=
953
"#C00000">for </font>x <font color="#C00000">in </font>sys<font color=
954
"#0000C0">.</font>path<font color="#0000C0">[</font><font color=
955
"#0080C0">1</font><font color="#0000C0">:] </font><font color=
956
"#C00000">if </font>len<font color="#0000C0">(</font>x<font color=
957
"#0000C0">) </font><font color="#C00000">and </font>os<font color=
958
"#0000C0">.</font>path<font color="#0000C0">.</font>isdir<font color=
959
"#0000C0">(</font>x<font color="#0000C0">)])
960
</font>cursor<font color="#0000C0">.</font>execute<font color=
961
"#0000C0">(</font><font color=
962
"#004080">"create virtual table sysfiles using filesource("</font><font color=
963
"#0000C0">+</font>sysdirs<font color="#0000C0">+</font><font color=
964
"#004080">")"</font><font color="#0000C0">)
966
</font><font color="#008000"># Which 3 files are the biggest?
967
</font><font color="#C00000">for </font>size<font color=
968
"#0000C0">,</font>directory<font color="#0000C0">,</font>file <font color=
969
"#C00000">in </font>cursor<font color="#0000C0">.</font>execute<font color=
970
"#0000C0">(</font><font color=
971
"#004080">"select st_size,directory,name from sysfiles order by st_size desc limit 3"</font><font color="#0000C0">):
972
</font><font color="#C00000">print </font>size<font color=
973
"#0000C0">,</font>file<font color="#0000C0">,</font>directory
975
<font color="blue"> 1610924 apsw.so /usr/lib64/python2.4/site-packages
976
1527536 _lcms.so /usr/lib64/python2.4/site-packages
977
736616 lapack_lite.so /usr/lib64/python2.4/site-packages/Numeric
979
<font color="#008000"># Which 3 files are the oldest?
980
</font><font color="#C00000">for </font>ctime<font color=
981
"#0000C0">,</font>directory<font color="#0000C0">,</font>file <font color=
982
"#C00000">in </font>cursor<font color="#0000C0">.</font>execute<font color=
983
"#0000C0">(</font><font color=
984
"#004080">"select st_ctime,directory,name from sysfiles order by st_ctime limit 3"</font><font color="#0000C0">):
985
</font><font color="#C00000">print </font>ctime<font color=
986
"#0000C0">,</font>file<font color="#0000C0">,</font>directory
988
<font color="blue"> 1157247798 libcdemu.py /usr/lib64/python2.4/site-packages
989
1157247798 libcdemu.pyo /usr/lib64/python2.4/site-packages
990
1157247798 libcdemu.pyc /usr/lib64/python2.4/site-packages
992
<font color="#008000">###
803
</span><span class="pykeyword">def </span><span class="pyname">getfiledata</span><span class=
804
"pyoperator">(</span><span class="pyname">directories</span><span class="pyoperator">):
805
</span><span class="pyname">columns</span><span class="pyoperator">=</span><span class="pyname">None
806
data</span><span class="pyoperator">=[]
807
</span><span class="pyname">counter</span><span class="pyoperator">=</span><span class="pynumber">1
808
</span><span class="pykeyword">for </span><span class="pyname">directory </span><span class=
809
"pykeyword">in </span><span class="pyname">directories</span><span class="pyoperator">:
810
</span><span class="pykeyword">for </span><span class="pyname">f </span><span class=
811
"pykeyword">in </span><span class="pyname">os</span><span class="pyoperator">.</span><span class=
812
"pyname">listdir</span><span class="pyoperator">(</span><span class="pyname">directory</span><span class=
814
</span><span class="pykeyword">if not </span><span class="pyname">os</span><span class=
815
"pyoperator">.</span><span class="pyname">path</span><span class="pyoperator">.</span><span class=
816
"pyname">isfile</span><span class="pyoperator">(</span><span class="pyname">os</span><span class=
817
"pyoperator">.</span><span class="pyname">path</span><span class="pyoperator">.</span><span class=
818
"pyname">join</span><span class="pyoperator">(</span><span class="pyname">directory</span><span class=
819
"pyoperator">,</span><span class="pyname">f</span><span class="pyoperator">)):
820
</span><span class="pykeyword">continue
821
</span><span class="pyname">counter</span><span class="pyoperator">+=</span><span class="pynumber">1
822
</span><span class="pyname">st</span><span class="pyoperator">=</span><span class=
823
"pyname">os</span><span class="pyoperator">.</span><span class="pyname">stat</span><span class=
824
"pyoperator">(</span><span class="pyname">os</span><span class="pyoperator">.</span><span class=
825
"pyname">path</span><span class="pyoperator">.</span><span class="pyname">join</span><span class=
826
"pyoperator">(</span><span class="pyname">directory</span><span class="pyoperator">,</span><span class=
827
"pyname">f</span><span class="pyoperator">))
828
</span><span class="pykeyword">if </span><span class="pyname">columns </span><span class=
829
"pykeyword">is </span><span class="pyname">None</span><span class="pyoperator">:
830
</span><span class="pyname">columns</span><span class="pyoperator">=[</span><span class=
831
"pystring">"rowid"</span><span class="pyoperator">, </span><span class="pystring">"name"</span><span class=
832
"pyoperator">, </span><span class="pystring">"directory"</span><span class="pyoperator">]+[</span><span class=
833
"pyname">x </span><span class="pykeyword">for </span><span class="pyname">x </span><span class=
834
"pykeyword">in </span><span class="pyname">dir</span><span class="pyoperator">(</span><span class=
835
"pyname">st</span><span class="pyoperator">) </span><span class="pykeyword">if </span><span class=
836
"pyname">x</span><span class="pyoperator">.</span><span class="pyname">startswith</span><span class=
837
"pyoperator">(</span><span class="pystring">"st_"</span><span class="pyoperator">)]
838
</span><span class="pyname">data</span><span class="pyoperator">.</span><span class=
839
"pyname">append</span><span class="pyoperator">( [</span><span class="pyname">counter</span><span class=
840
"pyoperator">, </span><span class="pyname">f</span><span class="pyoperator">, </span><span class=
841
"pyname">directory</span><span class="pyoperator">] + [</span><span class="pyname">getattr</span><span class=
842
"pyoperator">(</span><span class="pyname">st</span><span class="pyoperator">,</span><span class=
843
"pyname">x</span><span class="pyoperator">) </span><span class="pykeyword">for </span><span class=
844
"pyname">x </span><span class="pykeyword">in </span><span class="pyname">columns</span><span class=
845
"pyoperator">[</span><span class="pynumber">3</span><span class="pyoperator">:]] )
846
</span><span class="pykeyword">return </span><span class="pyname">columns</span><span class=
847
"pyoperator">, </span><span class="pyname">data
849
</span><span class="pycomment"># This gets registered with the Connection
850
</span><span class="pykeyword">class </span><span class="pyname">Source</span><span class="pyoperator">:
851
</span><span class="pykeyword">def </span><span class="pyname">Create</span><span class=
852
"pyoperator">(</span><span class="pyname">self</span><span class="pyoperator">, </span><span class=
853
"pyname">db</span><span class="pyoperator">, </span><span class="pyname">modulename</span><span class=
854
"pyoperator">, </span><span class="pyname">dbname</span><span class="pyoperator">, </span><span class=
855
"pyname">tablename</span><span class="pyoperator">, *</span><span class="pyname">args</span><span class="pyoperator">):
856
</span><span class="pyname">columns</span><span class="pyoperator">,</span><span class=
857
"pyname">data</span><span class="pyoperator">=</span><span class="pyname">getfiledata</span><span class=
858
"pyoperator">([</span><span class="pyname">eval</span><span class="pyoperator">(</span><span class=
859
"pyname">a</span><span class="pyoperator">.</span><span class="pyname">replace</span><span class=
860
"pyoperator">(</span><span class="pystring">"\\"</span><span class="pyoperator">, </span><span class=
861
"pystring">"\\\\"</span><span class="pyoperator">)) </span><span class="pykeyword">for </span><span class=
862
"pyname">a </span><span class="pykeyword">in </span><span class="pyname">args</span><span class=
863
"pyoperator">]) </span><span class="pycomment"># eval strips off layer of quotes
864
</span><span class="pyname">schema</span><span class="pyoperator">=</span><span class=
865
"pystring">"create table foo("</span><span class="pyoperator">+</span><span class="pystring">','</span><span class=
866
"pyoperator">.</span><span class="pyname">join</span><span class="pyoperator">([</span><span class=
867
"pystring">"'%s'" </span><span class="pyoperator">% (</span><span class="pyname">x</span><span class=
868
"pyoperator">,) </span><span class="pykeyword">for </span><span class="pyname">x </span><span class=
869
"pykeyword">in </span><span class="pyname">columns</span><span class="pyoperator">[</span><span class=
870
"pynumber">1</span><span class="pyoperator">:]])+</span><span class="pystring">")"
871
</span><span class="pykeyword">return </span><span class="pyname">schema</span><span class=
872
"pyoperator">,</span><span class="pyname">Table</span><span class="pyoperator">(</span><span class=
873
"pyname">columns</span><span class="pyoperator">,</span><span class="pyname">data</span><span class="pyoperator">)
874
</span><span class="pyname">Connect</span><span class="pyoperator">=</span><span class="pyname">Create
876
</span><span class="pycomment"># Represents a table
877
</span><span class="pykeyword">class </span><span class="pyname">Table</span><span class="pyoperator">:
878
</span><span class="pykeyword">def </span><span class="pyname">__init__</span><span class=
879
"pyoperator">(</span><span class="pyname">self</span><span class="pyoperator">, </span><span class=
880
"pyname">columns</span><span class="pyoperator">, </span><span class="pyname">data</span><span class="pyoperator">):
881
</span><span class="pyname">self</span><span class="pyoperator">.</span><span class=
882
"pyname">columns</span><span class="pyoperator">=</span><span class="pyname">columns
883
self</span><span class="pyoperator">.</span><span class="pyname">data</span><span class=
884
"pyoperator">=</span><span class="pyname">data
886
</span><span class="pykeyword">def </span><span class="pyname">BestIndex</span><span class=
887
"pyoperator">(</span><span class="pyname">self</span><span class="pyoperator">, *</span><span class=
888
"pyname">args</span><span class="pyoperator">):
889
</span><span class="pykeyword">return </span><span class="pyname">None
891
</span><span class="pykeyword">def </span><span class="pyname">Open</span><span class=
892
"pyoperator">(</span><span class="pyname">self</span><span class="pyoperator">):
893
</span><span class="pykeyword">return </span><span class="pyname">Cursor</span><span class=
894
"pyoperator">(</span><span class="pyname">self</span><span class="pyoperator">)
896
</span><span class="pykeyword">def </span><span class="pyname">Disconnect</span><span class=
897
"pyoperator">(</span><span class="pyname">self</span><span class="pyoperator">):
898
</span><span class="pykeyword">pass
900
</span><span class="pyname">Destroy</span><span class="pyoperator">=</span><span class="pyname">Disconnect
902
</span><span class="pycomment"># Represents a cursor
903
</span><span class="pykeyword">class </span><span class="pyname">Cursor</span><span class="pyoperator">:
904
</span><span class="pykeyword">def </span><span class="pyname">__init__</span><span class=
905
"pyoperator">(</span><span class="pyname">self</span><span class="pyoperator">, </span><span class=
906
"pyname">table</span><span class="pyoperator">):
907
</span><span class="pyname">self</span><span class="pyoperator">.</span><span class=
908
"pyname">table</span><span class="pyoperator">=</span><span class="pyname">table
910
</span><span class="pykeyword">def </span><span class="pyname">Filter</span><span class=
911
"pyoperator">(</span><span class="pyname">self</span><span class="pyoperator">, *</span><span class=
912
"pyname">args</span><span class="pyoperator">):
913
</span><span class="pyname">self</span><span class="pyoperator">.</span><span class=
914
"pyname">pos</span><span class="pyoperator">=</span><span class="pynumber">0
916
</span><span class="pykeyword">def </span><span class="pyname">Eof</span><span class=
917
"pyoperator">(</span><span class="pyname">self</span><span class="pyoperator">):
918
</span><span class="pykeyword">return </span><span class="pyname">self</span><span class=
919
"pyoperator">.</span><span class="pyname">pos</span><span class="pyoperator">>=</span><span class=
920
"pyname">len</span><span class="pyoperator">(</span><span class="pyname">self</span><span class=
921
"pyoperator">.</span><span class="pyname">table</span><span class="pyoperator">.</span><span class=
922
"pyname">data</span><span class="pyoperator">)
924
</span><span class="pykeyword">def </span><span class="pyname">Rowid</span><span class=
925
"pyoperator">(</span><span class="pyname">self</span><span class="pyoperator">):
926
</span><span class="pykeyword">return </span><span class="pyname">self</span><span class=
927
"pyoperator">.</span><span class="pyname">table</span><span class="pyoperator">.</span><span class=
928
"pyname">data</span><span class="pyoperator">[</span><span class="pyname">self</span><span class=
929
"pyoperator">.</span><span class="pyname">pos</span><span class="pyoperator">][</span><span class=
930
"pynumber">0</span><span class="pyoperator">]
932
</span><span class="pykeyword">def </span><span class="pyname">Column</span><span class=
933
"pyoperator">(</span><span class="pyname">self</span><span class="pyoperator">, </span><span class=
934
"pyname">col</span><span class="pyoperator">):
935
</span><span class="pykeyword">return </span><span class="pyname">self</span><span class=
936
"pyoperator">.</span><span class="pyname">table</span><span class="pyoperator">.</span><span class=
937
"pyname">data</span><span class="pyoperator">[</span><span class="pyname">self</span><span class=
938
"pyoperator">.</span><span class="pyname">pos</span><span class="pyoperator">][</span><span class=
939
"pynumber">1</span><span class="pyoperator">+</span><span class="pyname">col</span><span class="pyoperator">]
941
</span><span class="pykeyword">def </span><span class="pyname">Next</span><span class=
942
"pyoperator">(</span><span class="pyname">self</span><span class="pyoperator">):
943
</span><span class="pyname">self</span><span class="pyoperator">.</span><span class=
944
"pyname">pos</span><span class="pyoperator">+=</span><span class="pynumber">1
946
</span><span class="pykeyword">def </span><span class="pyname">Close</span><span class=
947
"pyoperator">(</span><span class="pyname">self</span><span class="pyoperator">):
948
</span><span class="pykeyword">pass
950
</span><span class="pycomment"># Register the module as filesource
951
</span><span class="pyname">connection</span><span class="pyoperator">.</span><span class=
952
"pyname">createmodule</span><span class="pyoperator">(</span><span class="pystring">"filesource"</span><span class=
953
"pyoperator">, </span><span class="pyname">Source</span><span class="pyoperator">())
955
</span><span class="pycomment"># Arguments to module - all directories in sys.path
956
</span><span class="pyname">sysdirs</span><span class="pyoperator">=</span><span class=
957
"pystring">","</span><span class="pyoperator">.</span><span class="pyname">join</span><span class=
958
"pyoperator">([</span><span class="pystring">"'%s'" </span><span class="pyoperator">% (</span><span class=
959
"pyname">x</span><span class="pyoperator">,) </span><span class="pykeyword">for </span><span class=
960
"pyname">x </span><span class="pykeyword">in </span><span class="pyname">sys</span><span class=
961
"pyoperator">.</span><span class="pyname">path</span><span class="pyoperator">[</span><span class=
962
"pynumber">1</span><span class="pyoperator">:] </span><span class="pykeyword">if </span><span class=
963
"pyname">len</span><span class="pyoperator">(</span><span class="pyname">x</span><span class=
964
"pyoperator">) </span><span class="pykeyword">and </span><span class="pyname">os</span><span class=
965
"pyoperator">.</span><span class="pyname">path</span><span class="pyoperator">.</span><span class=
966
"pyname">isdir</span><span class="pyoperator">(</span><span class="pyname">x</span><span class="pyoperator">)])
967
</span><span class="pyname">cursor</span><span class="pyoperator">.</span><span class=
968
"pyname">execute</span><span class="pyoperator">(</span><span class=
969
"pystring">"create virtual table sysfiles using filesource("</span><span class="pyoperator">+</span><span class=
970
"pyname">sysdirs</span><span class="pyoperator">+</span><span class="pystring">")"</span><span class="pyoperator">)
972
</span><span class="pycomment"># Which 3 files are the biggest?
973
</span><span class="pykeyword">for </span><span class="pyname">size</span><span class="pyoperator">,</span><span class=
974
"pyname">directory</span><span class="pyoperator">,</span><span class="pyname">file </span><span class=
975
"pykeyword">in </span><span class="pyname">cursor</span><span class="pyoperator">.</span><span class=
976
"pyname">execute</span><span class="pyoperator">(</span><span class=
977
"pystring">"select st_size,directory,name from sysfiles order by st_size desc limit 3"</span><span class=
979
</span><span class="pykeyword">print </span><span class="pyname">size</span><span class=
980
"pyoperator">,</span><span class="pyname">file</span><span class="pyoperator">,</span><span class="pyname">directory
982
</span><span class="pyoutput"> 8625144 qt.so /usr/lib/python2.5/site-packages
983
786208 qtsql.so /usr/lib/python2.5/site-packages
984
481008 unicodedata.so /usr/lib/python2.5/lib-dynload
986
<span class="pycomment"># Which 3 files are the oldest?
987
</span><span class="pykeyword">for </span><span class="pyname">ctime</span><span class=
988
"pyoperator">,</span><span class="pyname">directory</span><span class="pyoperator">,</span><span class=
989
"pyname">file </span><span class="pykeyword">in </span><span class="pyname">cursor</span><span class=
990
"pyoperator">.</span><span class="pyname">execute</span><span class="pyoperator">(</span><span class=
991
"pystring">"select st_ctime,directory,name from sysfiles order by st_ctime limit 3"</span><span class="pyoperator">):
992
</span><span class="pykeyword">print </span><span class="pyname">ctime</span><span class=
993
"pyoperator">,</span><span class="pyname">file</span><span class="pyoperator">,</span><span class="pyname">directory
995
</span><span class="pyoutput"> 1194713443.0 GnuPGInterface-0.3.2.egg-info /var/lib/python-support/python2.5
996
1194713443.0 GnuPGInterface.py /var/lib/python-support/python2.5
997
1194713447.0 sexy.so /usr/lib/python2.5/site-packages/gtk-2.0
999
<span class="pycomment">###
1004
</span><span class="pykeyword">for </span><span class="pyname">limit </span><span class=
1005
"pykeyword">in </span><span class="pyoperator">(</span><span class="pystring">"LENGTH"</span><span class=
1006
"pyoperator">, </span><span class="pystring">"COLUMN"</span><span class="pyoperator">, </span><span class=
1007
"pystring">"ATTACHED"</span><span class="pyoperator">):
1008
</span><span class="pyname">name</span><span class="pyoperator">=</span><span class=
1009
"pystring">"SQLITE_LIMIT_"</span><span class="pyoperator">+</span><span class="pyname">limit
1010
maxname</span><span class="pyoperator">=</span><span class="pystring">"SQLITE_MAX_"</span><span class=
1011
"pyoperator">+</span><span class="pyname">limit </span><span class="pycomment"># compile time
1012
</span><span class="pyname">orig</span><span class="pyoperator">=</span><span class=
1013
"pyname">connection</span><span class="pyoperator">.</span><span class="pyname">limit</span><span class=
1014
"pyoperator">(</span><span class="pyname">getattr</span><span class="pyoperator">(</span><span class=
1015
"pyname">apsw</span><span class="pyoperator">, </span><span class="pyname">name</span><span class="pyoperator">))
1016
</span><span class="pykeyword">print </span><span class="pyname">name</span><span class=
1017
"pyoperator">, </span><span class="pyname">orig
1018
</span><span class="pycomment"># To get the maximum, set to 0x7fffffff and then read value back
1019
</span><span class="pyname">connection</span><span class="pyoperator">.</span><span class=
1020
"pyname">limit</span><span class="pyoperator">(</span><span class="pyname">getattr</span><span class=
1021
"pyoperator">(</span><span class="pyname">apsw</span><span class="pyoperator">, </span><span class=
1022
"pyname">name</span><span class="pyoperator">), </span><span class="pynumber">0x7fffffff</span><span class=
1024
</span><span class="pyname">max</span><span class="pyoperator">=</span><span class=
1025
"pyname">connection</span><span class="pyoperator">.</span><span class="pyname">limit</span><span class=
1026
"pyoperator">(</span><span class="pyname">getattr</span><span class="pyoperator">(</span><span class=
1027
"pyname">apsw</span><span class="pyoperator">, </span><span class="pyname">name</span><span class="pyoperator">))
1028
</span><span class="pykeyword">print </span><span class="pyname">maxname</span><span class=
1029
"pyoperator">, </span><span class="pyname">max
1031
</span><span class="pycomment"># Set limit for size of a string
1032
</span><span class="pyname">cursor</span><span class="pyoperator">.</span><span class=
1033
"pyname">execute</span><span class="pyoperator">(</span><span class=
1034
"pystring">"create table testlimit(s)"</span><span class="pyoperator">)
1035
</span><span class="pyname">cursor</span><span class="pyoperator">.</span><span class=
1036
"pyname">execute</span><span class="pyoperator">(</span><span class=
1037
"pystring">"insert into testlimit values(?)"</span><span class="pyoperator">, ( </span><span class=
1038
"pystring">"x"</span><span class="pyoperator">*</span><span class="pynumber">1024</span><span class=
1039
"pyoperator">, )) </span><span class="pycomment"># 1024 char string
1040
</span><span class="pyname">connection</span><span class="pyoperator">.</span><span class=
1041
"pyname">limit</span><span class="pyoperator">(</span><span class="pyname">apsw</span><span class=
1042
"pyoperator">.</span><span class="pyname">SQLITE_LIMIT_LENGTH</span><span class="pyoperator">, </span><span class=
1043
"pynumber">1023</span><span class="pyoperator">) </span><span class="pycomment"># limit is now 1023
1044
</span><span class="pykeyword">try</span><span class="pyoperator">:
1045
</span><span class="pyname">cursor</span><span class="pyoperator">.</span><span class=
1046
"pyname">execute</span><span class="pyoperator">(</span><span class=
1047
"pystring">"insert into testlimit values(?)"</span><span class="pyoperator">, ( </span><span class=
1048
"pystring">"y"</span><span class="pyoperator">*</span><span class="pynumber">1024</span><span class="pyoperator">, ))
1049
</span><span class="pykeyword">print </span><span class="pystring">"string exceeding limit was inserted"
1050
</span><span class="pykeyword">except </span><span class="pyname">apsw</span><span class=
1051
"pyoperator">.</span><span class="pyname">TooBigError</span><span class="pyoperator">:
1052
</span><span class="pykeyword">print </span><span class="pystring">"Caught toobig exception"
1055
</span><span class="pyoutput"> SQLITE_LIMIT_LENGTH 1000000000
1056
SQLITE_MAX_LENGTH 1000000000
1057
SQLITE_LIMIT_COLUMN 2000
1058
SQLITE_MAX_COLUMN 2000
1059
SQLITE_LIMIT_ATTACHED 10
1060
SQLITE_MAX_ATTACHED 10
1061
Caught toobig exception
1063
<span class="pycomment">###
996
# We must close connections
997
</font>connection<font color="#0000C0">.</font>close<font color=
998
"#0000C0">(</font>True<font color="#0000C0">) </font><font color=
999
"#008000"># force it since we want to exit</font>
1067
# We can close connections manually (useful if you want to catch exceptions)
1068
# but you don't have to
1069
</span><span class="pyname">connection</span><span class="pyoperator">.</span><span class=
1070
"pyname">close</span><span class="pyoperator">(</span><span class="pyname">True</span><span class=
1071
"pyoperator">) </span><span class="pycomment"># force it since we want to exit</span></font>
1000
1072
<!--sourceend-->