162
161
<div class="section" id="examples">
163
162
<span id="examples-toplevel"></span><h1>Examples<a class="headerlink" href="#examples" title="Permalink to this headline">¶</a></h1>
164
<p>The SQLAlchemy distribution includes a variety of code examples illustrating a select set of patterns, some typical and some not so typical. All are runnable and can be found in the <tt class="docutils literal"><span class="pre">/examples</span></tt> directory of the distribution. Each example contains a README in its <tt class="docutils literal"><span class="pre">__init__.py</span></tt> file, each of which are listed below.</p>
165
<p>Additional SQLAlchemy examples, some user contributed, are available on the wiki at <a class="reference external" href="http://www.sqlalchemy.org/trac/wiki/UsageRecipes">http://www.sqlalchemy.org/trac/wiki/UsageRecipes</a>.</p>
163
<p>The SQLAlchemy distribution includes a variety of code examples illustrating
164
a select set of patterns, some typical and some not so typical. All are
165
runnable and can be found in the <tt class="docutils literal"><span class="pre">/examples</span></tt> directory of the
166
distribution. Each example contains a README in its <tt class="docutils literal"><span class="pre">__init__.py</span></tt> file,
167
each of which are listed below.</p>
168
<p>Additional SQLAlchemy examples, some user contributed, are available on the
169
wiki at <a class="reference external" href="http://www.sqlalchemy.org/trac/wiki/UsageRecipes">http://www.sqlalchemy.org/trac/wiki/UsageRecipes</a>.</p>
166
170
<div class="section" id="adjacency-list">
167
171
<span id="examples-adjacencylist"></span><h2>Adjacency List<a class="headerlink" href="#adjacency-list" title="Permalink to this headline">¶</a></h2>
168
172
<p>Location: /examples/adjacency_list/</p>
201
205
<div class="section" id="attribute-instrumentation">
202
206
<span id="examples-instrumentation"></span><h2>Attribute Instrumentation<a class="headerlink" href="#attribute-instrumentation" title="Permalink to this headline">¶</a></h2>
203
207
<p>Location: /examples/custom_attributes/</p>
204
<span class="target" id="module-custom_attributes"></span><p>Two examples illustrating modifications to SQLAlchemy’s attribute management system.</p>
205
<p><tt class="docutils literal"><span class="pre">listen_for_events.py</span></tt> illustrates the usage of <a class="reference internal" href="deprecated.html#sqlalchemy.orm.interfaces.AttributeExtension" title="sqlalchemy.orm.interfaces.AttributeExtension"><tt class="xref py py-class docutils literal"><span class="pre">AttributeExtension</span></tt></a> to intercept attribute events. It additionally illustrates a way to automatically attach these listeners to all class attributes using a <a class="reference internal" href="events.html#sqlalchemy.orm.interfaces.InstrumentationManager" title="sqlalchemy.orm.interfaces.InstrumentationManager"><tt class="xref py py-class docutils literal"><span class="pre">InstrumentationManager</span></tt></a>.</p>
206
<p><tt class="docutils literal"><span class="pre">custom_management.py</span></tt> illustrates much deeper usage of <a class="reference internal" href="events.html#sqlalchemy.orm.interfaces.InstrumentationManager" title="sqlalchemy.orm.interfaces.InstrumentationManager"><tt class="xref py py-class docutils literal"><span class="pre">InstrumentationManager</span></tt></a> as well as collection adaptation, to completely change the underlying method used to store state on an object. This example was developed to illustrate techniques which would be used by other third party object instrumentation systems to interact with SQLAlchemy’s event system and is only intended for very intricate framework integrations.</p>
208
<span class="target" id="module-custom_attributes"></span><p>Two examples illustrating modifications to SQLAlchemy’s attribute management
210
<p><tt class="docutils literal"><span class="pre">listen_for_events.py</span></tt> illustrates the usage of
211
<a class="reference internal" href="deprecated.html#sqlalchemy.orm.interfaces.AttributeExtension" title="sqlalchemy.orm.interfaces.AttributeExtension"><tt class="xref py py-class docutils literal"><span class="pre">AttributeExtension</span></tt></a> to intercept attribute
212
events. It additionally illustrates a way to automatically attach these
213
listeners to all class attributes using a
214
<a class="reference internal" href="extensions/instrumentation.html#sqlalchemy.ext.instrumentation.InstrumentationManager" title="sqlalchemy.ext.instrumentation.InstrumentationManager"><tt class="xref py py-class docutils literal"><span class="pre">InstrumentationManager</span></tt></a>.</p>
215
<p><tt class="docutils literal"><span class="pre">custom_management.py</span></tt> illustrates much deeper usage of
216
<a class="reference internal" href="extensions/instrumentation.html#sqlalchemy.ext.instrumentation.InstrumentationManager" title="sqlalchemy.ext.instrumentation.InstrumentationManager"><tt class="xref py py-class docutils literal"><span class="pre">InstrumentationManager</span></tt></a> as well as
217
collection adaptation, to completely change the underlying method used to
218
store state on an object. This example was developed to illustrate
219
techniques which would be used by other third party object instrumentation
220
systems to interact with SQLAlchemy’s event system and is only intended for
221
very intricate framework integrations.</p>
208
<div class="section" id="beaker-caching">
209
<span id="examples-caching"></span><h2>Beaker Caching<a class="headerlink" href="#beaker-caching" title="Permalink to this headline">¶</a></h2>
210
<p>Location: /examples/beaker_caching/</p>
211
<span class="target" id="module-beaker_caching"></span><p>Illustrates how to embed Beaker cache functionality within
212
the Query object, allowing full cache control as well as the
223
<div class="section" id="dogpile-caching">
224
<span id="examples-caching"></span><h2>Dogpile Caching<a class="headerlink" href="#dogpile-caching" title="Permalink to this headline">¶</a></h2>
225
<p>Location: /examples/dogpile_caching/</p>
226
<span class="target" id="module-dogpile_caching"></span><p>Illustrates how to embed <a class="reference external" href="http://dogpilecache.readthedocs.org/">dogpile.cache</a>
228
the <a class="reference internal" href="query.html#sqlalchemy.orm.query.Query" title="sqlalchemy.orm.query.Query"><tt class="xref py py-class docutils literal"><span class="pre">Query</span></tt></a> object, allowing full cache control as well as the
213
229
ability to pull “lazy loaded” attributes from long term cache
231
<p class="versionchanged">
232
<span class="versionmodified">Changed in version 0.8: </span>The example was modernized to use
233
dogpile.cache, replacing Beaker as the caching library in
215
235
<p>In this demo, the following techniques are illustrated:</p>
216
236
<ul class="simple">
217
<li>Using custom subclasses of Query</li>
237
<li>Using custom subclasses of <a class="reference internal" href="query.html#sqlalchemy.orm.query.Query" title="sqlalchemy.orm.query.Query"><tt class="xref py py-class docutils literal"><span class="pre">Query</span></tt></a></li>
218
238
<li>Basic technique of circumventing Query to pull from a
219
239
custom cache source instead of the database.</li>
220
<li>Rudimental caching with Beaker, using “regions” which allow
240
<li>Rudimental caching with dogpile.cache, using “regions” which allow
221
241
global control over a fixed set of configurations.</li>
222
<li>Using custom MapperOption objects to configure options on
242
<li>Using custom <tt class="xref py py-class docutils literal"><span class="pre">MapperOption</span></tt> objects to configure options on
223
243
a Query, including the ability to invoke the options
224
244
deep within an object graph when lazy loads occur.</li>
227
247
<div class="highlight-python"><div class="highlight"><pre><span class="c"># query for Person objects, specifying cache</span>
228
<span class="n">q</span> <span class="o">=</span> <span class="n">Session</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="n">Person</span><span class="p">)</span><span class="o">.</span><span class="n">options</span><span class="p">(</span><span class="n">FromCache</span><span class="p">(</span><span class="s">"default"</span><span class="p">,</span> <span class="s">"all_people"</span><span class="p">))</span>
248
<span class="n">q</span> <span class="o">=</span> <span class="n">Session</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="n">Person</span><span class="p">)</span><span class="o">.</span><span class="n">options</span><span class="p">(</span><span class="n">FromCache</span><span class="p">(</span><span class="s">"default"</span><span class="p">))</span>
230
250
<span class="c"># specify that each Person's "addresses" collection comes from</span>
231
251
<span class="c"># cache too</span>
232
<span class="n">q</span> <span class="o">=</span> <span class="n">q</span><span class="o">.</span><span class="n">options</span><span class="p">(</span><span class="n">RelationshipCache</span><span class="p">(</span><span class="s">"default"</span><span class="p">,</span> <span class="s">"by_person"</span><span class="p">,</span> <span class="n">Person</span><span class="o">.</span><span class="n">addresses</span><span class="p">))</span>
252
<span class="n">q</span> <span class="o">=</span> <span class="n">q</span><span class="o">.</span><span class="n">options</span><span class="p">(</span><span class="n">RelationshipCache</span><span class="p">(</span><span class="n">Person</span><span class="o">.</span><span class="n">addresses</span><span class="p">,</span> <span class="s">"default"</span><span class="p">))</span>
234
254
<span class="c"># query</span>
235
255
<span class="k">print</span> <span class="n">q</span><span class="o">.</span><span class="n">all</span><span class="p">()</span></pre></div>
237
<p>To run, both SQLAlchemy and Beaker (1.4 or greater) must be
257
<p>To run, both SQLAlchemy and dogpile.cache must be
238
258
installed or on the current PYTHONPATH. The demo will create a local
239
259
directory for datafiles, insert initial data, and run. Running the
240
260
demo a second time will utilize the cache files already present, and
242
262
displayed result however will utilize dozens of lazyloads that all
243
263
pull from cache.</p>
244
264
<p>The demo scripts themselves, in order of complexity, are run as follows:</p>
245
<div class="highlight-python"><pre>python examples/beaker_caching/helloworld.py
247
python examples/beaker_caching/relationship_caching.py
249
python examples/beaker_caching/advanced.py
251
python examples/beaker_caching/local_session_caching.py</pre>
265
<div class="highlight-python"><pre>python examples/dogpile_caching/helloworld.py
267
python examples/dogpile_caching/relationship_caching.py
269
python examples/dogpile_caching/advanced.py
271
python examples/dogpile_caching/local_session_caching.py</pre>
253
273
<p>Listing of files:</p>
255
<div><p>environment.py - Establish the Session, the Beaker cache
256
manager, data / cache file paths, and configurations,
275
<div><p>environment.py - Establish the Session, a dictionary
276
of “regions”, a sample cache region against a .dbm
277
file, data / cache file paths, and configurations,
257
278
bootstrap fixture data if necessary.</p>
258
279
<p>caching_query.py - Represent functions and classes
259
which allow the usage of Beaker caching with SQLAlchemy.
280
which allow the usage of Dogpile caching with SQLAlchemy.
260
281
Introduces a query option called FromCache.</p>
261
282
<p>model.py - The datamodel, which represents Person that has multiple
262
283
Address objects, each with PostalCode, City, Country</p>
268
289
<p>advanced.py - Further examples of how to use FromCache. Combines
269
290
techniques from the first two scripts.</p>
270
291
<p>local_session_caching.py - Grok everything so far ? This example
271
creates a new Beaker container that will persist data in a dictionary
292
creates a new dogpile.cache backend that will persist data in a dictionary
272
293
which is local to the current session. remove() the session
273
294
and the cache is gone.</p>
274
295
</div></blockquote>
276
<div class="section" id="declarative-reflection">
277
<span id="examples-declarative-reflection"></span><h2>Declarative Reflection<a class="headerlink" href="#declarative-reflection" title="Permalink to this headline">¶</a></h2>
278
<p>Location: /examples/declarative_reflection</p>
279
<span class="target" id="module-declarative_reflection"></span><p>Illustrates how to mix table reflection with Declarative, such that
280
the reflection process itself can take place <strong>after</strong> all classes
281
are defined. Declarative classes can also override column
282
definitions loaded from the database.</p>
283
<p>At the core of this example is the ability to change how Declarative
284
assigns mappings to classes. The <tt class="docutils literal"><span class="pre">__mapper_cls__</span></tt> special attribute
285
is overridden to provide a function that gathers mapping requirements
286
as they are established, without actually creating the mapping.
287
Then, a second class-level method <tt class="docutils literal"><span class="pre">prepare()</span></tt> is used to iterate
288
through all mapping configurations collected, reflect the tables
289
named within and generate the actual mappers.</p>
290
<p class="versionadded">
291
<span class="versionmodified">New in version 0.7.5: </span>This new example makes usage of the new
292
<tt class="docutils literal"><span class="pre">autoload_replace</span></tt> flag on <a class="reference internal" href="../core/schema.html#sqlalchemy.schema.Table" title="sqlalchemy.schema.Table"><tt class="xref py py-class docutils literal"><span class="pre">Table</span></tt></a> to allow declared
293
classes to override reflected columns.</p>
294
<p>Usage example:</p>
295
<div class="highlight-python"><div class="highlight"><pre><span class="n">Base</span> <span class="o">=</span> <span class="n">declarative_base</span><span class="p">(</span><span class="n">cls</span><span class="o">=</span><span class="n">DeclarativeReflectedBase</span><span class="p">)</span>
297
<span class="k">class</span> <span class="nc">Foo</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
298
<span class="n">__tablename__</span> <span class="o">=</span> <span class="s">'foo'</span>
299
<span class="n">bars</span> <span class="o">=</span> <span class="n">relationship</span><span class="p">(</span><span class="s">"Bar"</span><span class="p">)</span>
301
<span class="k">class</span> <span class="nc">Bar</span><span class="p">(</span><span class="n">Base</span><span class="p">):</span>
302
<span class="n">__tablename__</span> <span class="o">=</span> <span class="s">'bar'</span>
304
<span class="c"># illustrate overriding of "bar.foo_id" to have</span>
305
<span class="c"># a foreign key constraint otherwise not</span>
306
<span class="c"># reflected, such as when using MySQL</span>
307
<span class="n">foo_id</span> <span class="o">=</span> <span class="n">Column</span><span class="p">(</span><span class="n">Integer</span><span class="p">,</span> <span class="n">ForeignKey</span><span class="p">(</span><span class="s">'foo.id'</span><span class="p">))</span>
309
<span class="n">Base</span><span class="o">.</span><span class="n">prepare</span><span class="p">(</span><span class="n">e</span><span class="p">)</span>
311
<span class="n">s</span> <span class="o">=</span> <span class="n">Session</span><span class="p">(</span><span class="n">e</span><span class="p">)</span>
313
<span class="n">s</span><span class="o">.</span><span class="n">add_all</span><span class="p">([</span>
314
<span class="n">Foo</span><span class="p">(</span><span class="n">bars</span><span class="o">=</span><span class="p">[</span><span class="n">Bar</span><span class="p">(</span><span class="n">data</span><span class="o">=</span><span class="s">'b1'</span><span class="p">),</span> <span class="n">Bar</span><span class="p">(</span><span class="n">data</span><span class="o">=</span><span class="s">'b2'</span><span class="p">)],</span> <span class="n">data</span><span class="o">=</span><span class="s">'f1'</span><span class="p">),</span>
315
<span class="n">Foo</span><span class="p">(</span><span class="n">bars</span><span class="o">=</span><span class="p">[</span><span class="n">Bar</span><span class="p">(</span><span class="n">data</span><span class="o">=</span><span class="s">'b3'</span><span class="p">),</span> <span class="n">Bar</span><span class="p">(</span><span class="n">data</span><span class="o">=</span><span class="s">'b4'</span><span class="p">)],</span> <span class="n">data</span><span class="o">=</span><span class="s">'f2'</span><span class="p">)</span>
316
<span class="p">])</span>
317
<span class="n">s</span><span class="o">.</span><span class="n">commit</span><span class="p">()</span></pre></div>
320
297
<div class="section" id="directed-graphs">
321
298
<h2>Directed Graphs<a class="headerlink" href="#directed-graphs" title="Permalink to this headline">¶</a></h2>
322
299
<p>Location: /examples/graphs/</p>
323
<span class="target" id="module-graphs"></span><p>An example of persistence for a directed graph structure. The graph is stored as a collection of edges, each referencing both a “lower” and an “upper” node in a table of nodes. Basic persistence and querying for lower- and upper- neighbors are illustrated:</p>
300
<span class="target" id="module-graphs"></span><p>An example of persistence for a directed graph structure. The
301
graph is stored as a collection of edges, each referencing both a
302
“lower” and an “upper” node in a table of nodes. Basic persistence
303
and querying for lower- and upper- neighbors are illustrated:</p>
324
304
<div class="highlight-python"><div class="highlight"><pre><span class="n">n2</span> <span class="o">=</span> <span class="n">Node</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
325
305
<span class="n">n5</span> <span class="o">=</span> <span class="n">Node</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span>
326
306
<span class="n">n2</span><span class="o">.</span><span class="n">add_neighbor</span><span class="p">(</span><span class="n">n5</span><span class="p">)</span>
330
310
<div class="section" id="dynamic-relations-as-dictionaries">
331
311
<h2>Dynamic Relations as Dictionaries<a class="headerlink" href="#dynamic-relations-as-dictionaries" title="Permalink to this headline">¶</a></h2>
332
312
<p>Location: /examples/dynamic_dict/</p>
333
<span class="target" id="module-dynamic_dict"></span><p>Illustrates how to place a dictionary-like facade on top of a “dynamic” relation, so
334
that dictionary operations (assuming simple string keys) can operate upon a large
335
collection without loading the full collection at once.</p>
313
<span class="target" id="module-dynamic_dict"></span><p>Illustrates how to place a dictionary-like facade on top of a
314
“dynamic” relation, so that dictionary operations (assuming simple
315
string keys) can operate upon a large collection without loading the
316
full collection at once.</p>
337
318
<div class="section" id="generic-associations">
338
319
<span id="examples-generic-associations"></span><h2>Generic Associations<a class="headerlink" href="#generic-associations" title="Permalink to this headline">¶</a></h2>
390
372
<div class="section" id="inheritance-mappings">
391
373
<h2>Inheritance Mappings<a class="headerlink" href="#inheritance-mappings" title="Permalink to this headline">¶</a></h2>
392
374
<p>Location: /examples/inheritance/</p>
393
<span class="target" id="module-inheritance"></span><p>Working examples of single-table, joined-table, and concrete-table inheritance as described in <em class="xref std std-ref">datamapping_inheritance</em>.</p>
375
<span class="target" id="module-inheritance"></span><p>Working examples of single-table, joined-table, and concrete-table
376
inheritance as described in <em class="xref std std-ref">datamapping_inheritance</em>.</p>
395
378
<div class="section" id="large-collections">
396
379
<h2>Large Collections<a class="headerlink" href="#large-collections" title="Permalink to this headline">¶</a></h2>
397
380
<p>Location: /examples/large_collection/</p>
398
381
<span class="target" id="module-large_collection"></span><p>Large collection example.</p>
399
<p>Illustrates the options to use with <a class="reference internal" href="relationships.html#sqlalchemy.orm.relationship" title="sqlalchemy.orm.relationship"><tt class="xref py py-func docutils literal"><span class="pre">relationship()</span></tt></a> when the list of related objects is very large, including:</p>
382
<p>Illustrates the options to use with
383
<a class="reference internal" href="relationships.html#sqlalchemy.orm.relationship" title="sqlalchemy.orm.relationship"><tt class="xref py py-func docutils literal"><span class="pre">relationship()</span></tt></a> when the list of related
384
objects is very large, including:</p>
400
385
<ul class="simple">
401
386
<li>“dynamic” relationships which query slices of data as accessed</li>
402
<li>how to use ON DELETE CASCADE in conjunction with <tt class="docutils literal"><span class="pre">passive_deletes=True</span></tt> to greatly improve the performance of related collection deletion.</li>
387
<li>how to use ON DELETE CASCADE in conjunction with
388
<tt class="docutils literal"><span class="pre">passive_deletes=True</span></tt> to greatly improve the performance of
389
related collection deletion.</li>
405
392
<div class="section" id="nested-sets">
406
393
<h2>Nested Sets<a class="headerlink" href="#nested-sets" title="Permalink to this headline">¶</a></h2>
407
394
<p>Location: /examples/nested_sets/</p>
408
<span class="target" id="module-nested_sets"></span><p>Illustrates a rudimentary way to implement the “nested sets” pattern for hierarchical data using the SQLAlchemy ORM.</p>
395
<span class="target" id="module-nested_sets"></span><p>Illustrates a rudimentary way to implement the “nested sets”
396
pattern for hierarchical data using the SQLAlchemy ORM.</p>
410
398
<div class="section" id="polymorphic-associations">
411
399
<h2>Polymorphic Associations<a class="headerlink" href="#polymorphic-associations" title="Permalink to this headline">¶</a></h2>
412
400
<p>See <a class="reference internal" href="#examples-generic-associations"><em>Generic Associations</em></a> for a modern version of polymorphic associations.</p>
414
402
<div class="section" id="postgis-integration">
415
<h2>PostGIS Integration<a class="headerlink" href="#postgis-integration" title="Permalink to this headline">¶</a></h2>
403
<span id="examples-postgis"></span><h2>PostGIS Integration<a class="headerlink" href="#postgis-integration" title="Permalink to this headline">¶</a></h2>
416
404
<p>Location: /examples/postgis</p>
417
405
<span class="target" id="module-postgis"></span><p>A naive example illustrating techniques to help
418
406
embed PostGIS functionality.</p>
419
<p>This example was originally developed in the hopes that it would be extrapolated into a comprehensive PostGIS integration layer. We are pleased to announce that this has come to fruition as <a class="reference external" href="http://www.geoalchemy.org/">GeoAlchemy</a>.</p>
407
<p>This example was originally developed in the hopes that it would be
408
extrapolated into a comprehensive PostGIS integration layer. We are
409
pleased to announce that this has come to fruition as <a class="reference external" href="http://www.geoalchemy.org/">GeoAlchemy</a>.</p>
420
410
<p>The example illustrates:</p>
421
411
<ul class="simple">
422
412
<li>a DDL extension which allows CREATE/DROP to work in
499
490
<h2>Vertical Attribute Mapping<a class="headerlink" href="#vertical-attribute-mapping" title="Permalink to this headline">¶</a></h2>
500
491
<p>Location: /examples/vertical</p>
501
492
<span class="target" id="module-vertical"></span><p>Illustrates “vertical table” mappings.</p>
502
<p>A “vertical table” refers to a technique where individual attributes of an object are stored as distinct rows in a table.
503
The “vertical table” technique is used to persist objects which can have a varied set of attributes, at the expense of simple query control and brevity. It is commonly found in content/document management systems in order to represent user-created structures flexibly.</p>
504
<p>Two variants on the approach are given. In the second, each row references a “datatype” which contains information about the type of information stored in the attribute, such as integer, string, or date.</p>
493
<p>A “vertical table” refers to a technique where individual attributes
494
of an object are stored as distinct rows in a table. The “vertical
495
table” technique is used to persist objects which can have a varied
496
set of attributes, at the expense of simple query control and brevity.
497
It is commonly found in content/document management systems in order
498
to represent user-created structures flexibly.</p>
499
<p>Two variants on the approach are given. In the second, each row
500
references a “datatype” which contains information about the type of
501
information stored in the attribute, such as integer, string, or date.</p>
506
503
<div class="highlight-python"><div class="highlight"><pre><span class="n">shrew</span> <span class="o">=</span> <span class="n">Animal</span><span class="p">(</span><span class="s">u'shrew'</span><span class="p">)</span>
507
504
<span class="n">shrew</span><span class="p">[</span><span class="s">u'cuteness'</span><span class="p">]</span> <span class="o">=</span> <span class="mi">5</span>
530
527
xpath-like strings is illustrated as well.</p>
531
528
<p>In order of complexity:</p>
532
529
<ul class="simple">
533
<li><tt class="docutils literal"><span class="pre">pickle.py</span></tt> - Quick and dirty, serialize the whole DOM into a BLOB column. While the example
534
is very brief, it has very limited functionality.</li>
535
<li><tt class="docutils literal"><span class="pre">adjacency_list.py</span></tt> - Each DOM node is stored in an individual table row, with attributes
536
represented in a separate table. The nodes are associated in a hierarchy using an adjacency list
537
structure. A query function is introduced which can search for nodes along any path with a given
538
structure of attributes, basically a (very narrow) subset of xpath.</li>
539
<li><tt class="docutils literal"><span class="pre">optimized_al.py</span></tt> - Uses the same strategy as <tt class="docutils literal"><span class="pre">adjacency_list.py</span></tt>, but associates each
540
DOM row with its owning document row, so that a full document of DOM nodes can be
541
loaded using O(1) queries - the construction of the “hierarchy” is performed after
542
the load in a non-recursive fashion and is much more efficient.</li>
530
<li><tt class="docutils literal"><span class="pre">pickle.py</span></tt> - Quick and dirty, serialize the whole DOM into a BLOB
531
column. While the example is very brief, it has very limited
533
<li><tt class="docutils literal"><span class="pre">adjacency_list.py</span></tt> - Each DOM node is stored in an individual
534
table row, with attributes represented in a separate table. The
535
nodes are associated in a hierarchy using an adjacency list
536
structure. A query function is introduced which can search for nodes
537
along any path with a given structure of attributes, basically a
538
(very narrow) subset of xpath.</li>
539
<li><tt class="docutils literal"><span class="pre">optimized_al.py</span></tt> - Uses the same strategy as
540
<tt class="docutils literal"><span class="pre">adjacency_list.py</span></tt>, but associates each DOM row with its owning
541
document row, so that a full document of DOM nodes can be loaded
542
using O(1) queries - the construction of the “hierarchy” is performed
543
after the load in a non-recursive fashion and is much more
545
547
<div class="highlight-python"><div class="highlight"><pre><span class="c"># parse an XML file and persist in the database</span>