Edgewall Software

Changes between Initial Version and Version 1 of TracDev/DatabaseApi


Ignore:
Timestamp:
May 27, 2005, 8:43:07 AM (19 years ago)
Author:
Christopher Lenz
Comment:

Started documenting the Trac database "API"

Legend:

Unmodified
Added
Removed
Modified
  • TracDev/DatabaseApi

    v1 v1  
     1= Trac SQL Database API =
     2
     3Trac uses a very thin layer on top of the standard [http://www.python.org/peps/pep-0249.html Python Database API 2.0] for interfacing with supported relational database systems such as [http://sqlite.org/ SQLite] or [http://www.postgresql.org/ PostgreSQL].
     4
     5 ''Note that Trac prior to version 0.9 used the PySQLite APIs directly, and has no support for other database systems. This document describes the thin DB API abstraction layer introduced in version 0.9.''
     6
     7You can find the specifics of the database API in the [source:/trunk/trac/db.py#latest trac.db] module. This module provides:
     8 * Simple pooling of database connections
     9 * Iterable cursors
     10 * Selection of DB modules based of connection URIs.
     11
     12== Accessing to the Database ==
     13
     14Code accessing the database in Trac go through this layer simply by using the {{{Environment}}} method {{{get_db_cnx()}}}:
     15
     16
     17{{{
     18#!python
     19from trac.env import Environment
     20
     21env = Environment('/path/to/projenv')
     22db = env.get_db_cnx()
     23cursor = db.cursor()
     24# Execute some SQL statements
     25db.commit()
     26}}}
     27
     28The {{{get_db_cnx}}} method looks at the value of the {{{database}}} configuration option in [wiki:TracIni trac.ini], which should contain a database connection URI. The default value for this option tells Trac to use an SQLite database inside the environment directory:
     29
     30{{{
     31[trac]
     32database = sqlite:db/trac.db
     33}}}
     34
     35 ''The connection URI syntax has been designed to be compatible with that provided by [http://sqlobject.org/docs/SQLObject.html#declaring-the-class SQLObject] (see also the Wiki page on SQLObject [http://wiki.sqlobject.org/connections.html connections]). The only supported URI schemes at this point are {{{sqlite}}} and {{{postgres}}}.''
     36
     37== Rules for DB API Usage ==
     38
     39Different DB API modules have different ways to pass parameters to the cursors' {{{execute}}} method, and different ways to access query results. To keep the database API as thin as possible, the Trac team has decided to use a relatively common subset in all database code.
     40
     41=== Parameter passing ===
     42
     43Always use the "format" parameter style, and always with {{{%s}}} (because that's the only type that pyPgSQL supports). Statement parameters always need to be passed into execute as an actual sequence (list or tuple).
     44
     45So the following statements are okay:
     46{{{
     47#!python
     48cursor.execute("SELECT author,ipnr,comment FROM wiki WHERE name=%s", [thename])
     49cursor.execute("SELECT id FROM ticket WHERE time>=%s AND time<=%s", (start, stop))
     50}}}
     51
     52The following uses are '''not''' okay:
     53{{{
     54#!python
     55cursor.execute("SELECT author,ipnr,comment FROM wiki WHERE name=?", thename)
     56cursor.execute("SELECT id FROM ticket WHERE time>=%i AND time<=%i", start, stop)
     57}}}
     58
     59=== Retrieving results ===
     60
     61For convenience, cursors returned by the database connection object are iterable after having executed an SQL query. Individual fields in result rows may only be accessed using integer indices:
     62{{{
     63#!python
     64cursor.execute("SELECT author,ipnr,comment FROM wiki WHERE name=%s", (thename,))
     65for row in cursor:
     66    print 'Author: %s (%s)' % (row[0], row[1])
     67    print row[2]
     68}}}
     69
     70Accessing fields using the column names is not supported by all database modules, so it should not be used. Automatically unpacking rows into tuples of named variables often provides better readability:
     71{{{
     72#!python
     73cursor.execute("SELECT author,ipnr,comment FROM wiki WHERE name=%s", (thename,))
     74for author, ipnr, comment in cursor:
     75    print 'Author: %s (%s)' % (author, ipnr)
     76    print comment
     77}}}
     78
     79== Guidelines for SQL Statements ==
     80
     81As you probably, support for SQL varies among different database systems. The requirements of Trac are relatively trivial, so we try to stick to a common subset that is supported by the majority of databases.
     82
     83 ''TODO: Need content''
     84
     85----
     86See also: TracDev, TracDev/DatabaseSchema, TracDev/DatabaseUpgrades, TracDev/CodingStyle