summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2008-12-06 18:27:04 +0000
committerMike Bayer <mike_mp@zzzcomputing.com>2008-12-06 18:27:04 +0000
commit994ab27aa38dfd3dc627083338509519247b7e20 (patch)
treea40d7755146c9f102fa05143ed7793c862aed028 /lib/sqlalchemy
parentde4ed96ec01d5c5da064001691357f987a6e8892 (diff)
downloadsqlalchemy-994ab27aa38dfd3dc627083338509519247b7e20.tar.gz
- postgres docstring
- insert/update/delete are documented generatively - values({}) is no longer deprecated, thus enabling unicode/Columns as keys
Diffstat (limited to 'lib/sqlalchemy')
-rw-r--r--lib/sqlalchemy/databases/oracle.py43
-rw-r--r--lib/sqlalchemy/databases/postgres.py82
-rw-r--r--lib/sqlalchemy/sql/expression.py73
3 files changed, 148 insertions, 50 deletions
diff --git a/lib/sqlalchemy/databases/oracle.py b/lib/sqlalchemy/databases/oracle.py
index d71b129d1..72a0bb265 100644
--- a/lib/sqlalchemy/databases/oracle.py
+++ b/lib/sqlalchemy/databases/oracle.py
@@ -8,39 +8,44 @@
Oracle version 8 through current (11g at the time of this writing) are supported.
Driver
+------
The Oracle dialect uses the cx_oracle driver, available at
-http://python.net/crew/atuining/cx_Oracle/ . The dialect has several behaviors
+http://cx-oracle.sourceforge.net/ . The dialect has several behaviors
which are specifically tailored towards compatibility with this module.
Connecting
+----------
Connecting with create_engine() uses the standard URL approach of
-oracle://user:pass@host:port/dbname[?key=value&key=value...]. If dbname is present, the
+``oracle://user:pass@host:port/dbname[?key=value&key=value...]``. If dbname is present, the
host, port, and dbname tokens are converted to a TNS name using the cx_oracle
-makedsn() function. Otherwise, the host token is taken directly as a TNS name.
+:func:`makedsn()` function. Otherwise, the host token is taken directly as a TNS name.
Additional arguments which may be specified either as query string arguments on the
-URL, or as keyword arguments to create_engine() include:
+URL, or as keyword arguments to :func:`~sqlalchemy.create_engine()` are:
- mode - This is given the string value of SYSDBA or SYSOPER, or alternatively an
- integer value. This value is only available as a URL query string argument.
+* *allow_twophase* - enable two-phase transactions. Defaults to ``True``.
- allow_twophase - enable two-phase transactions. This feature is not yet supported.
+* *auto_convert_lobs* - defaults to True, see the section on LOB objects.
- threaded - defaults to True with SQLAlchemy, enable multithreaded access to
- cx_oracle connections.
+* *auto_setinputsizes* - the cx_oracle.setinputsizes() call is issued for all bind parameters.
+ This is required for LOB datatypes but can be disabled to reduce overhead. Defaults
+ to ``True``.
- use_ansi - defaults to True, use ANSI JOIN constructs (see the section on Oracle 8).
+* *mode* - This is given the string value of SYSDBA or SYSOPER, or alternatively an
+ integer value. This value is only available as a URL query string argument.
- auto_convert_lobs - defaults to True, see the section on LOB objects.
+* *threaded* - enable multithreaded access to cx_oracle connections. Defaults
+ to ``True``. Note that this is the opposite default of cx_oracle itself.
- auto_setinputsizes - the cx_oracle.setinputsizes() call is issued for all bind parameters.
- This is required for LOB datatypes but can be disabled to reduce overhead.
+* *use_ansi* - Use ANSI JOIN constructs (see the section on Oracle 8). Defaults
+ to ``True``. If ``False``, Oracle-8 compatible constructs are used for joins.
- optimize_limits - defaults to False, see the section on LIMIT/OFFSET.
+* *optimize_limits* - defaults to ``False``. see the section on LIMIT/OFFSET.
Auto Increment Behavior
+-----------------------
SQLAlchemy Table objects which include integer primary keys are usually assumed to have
"autoincrementing" behavior, meaning they can generate their own primary key values upon
@@ -63,6 +68,7 @@ This step is also required when using table reflection, i.e. autoload=True::
)
LOB Objects
+-----------
cx_oracle presents some challenges when fetching LOB objects. A LOB object in a result set
is presented by cx_oracle as a cx_oracle.LOB object which has a read() method. By default,
@@ -84,6 +90,7 @@ without raising cursor errors. The conversion of LOB in all cases, as well as t
of LOB objects, can be disabled using auto_convert_lobs=False.
LIMIT/OFFSET Support
+--------------------
Oracle has no support for the LIMIT or OFFSET keywords. Whereas previous versions of SQLAlchemy
used the "ROW NUMBER OVER..." construct to simulate LIMIT/OFFSET, SQLAlchemy 0.5 now uses
@@ -94,18 +101,20 @@ this was stepping into the bounds of optimization that is better left on the DBA
prefix can be added by enabling the optimize_limits=True flag on create_engine().
Two Phase Transaction Support
+-----------------------------
-Two Phase transactions are partially implemented using XA transactions but at the time of this
-writing have not been successfully tested. The author of cx_oracle also stated that he's never
-seen them work so this may be a cx_oracle issue.
+Two Phase transactions are implemented using XA transactions. Success has been reported of them
+working successfully but this should be regarded as an experimental feature.
Oracle 8 Compatibility
+----------------------
When using Oracle 8, a "use_ansi=False" flag is available which converts all
JOIN phrases into the WHERE clause, and in the case of LEFT OUTER JOIN
makes use of Oracle's (+) operator.
Synonym/DBLINK Reflection
+-------------------------
When using reflection with Table objects, the dialect can optionally search for tables
indicated by synonyms that reference DBLINK-ed tables by passing the flag
diff --git a/lib/sqlalchemy/databases/postgres.py b/lib/sqlalchemy/databases/postgres.py
index 57620c007..320c749bc 100644
--- a/lib/sqlalchemy/databases/postgres.py
+++ b/lib/sqlalchemy/databases/postgres.py
@@ -6,17 +6,87 @@
"""Support for the PostgreSQL database.
-PostgreSQL supports partial indexes. To create them pass a posgres_where
+Driver
+------
+
+The psycopg2 driver is supported, available at http://pypi.python.org/pypi/psycopg2/ .
+The dialect has several behaviors which are specifically tailored towards compatibility
+with this module.
+
+Note that psycopg1 is **not** supported.
+
+Connecting
+----------
+
+URLs are of the form `postgres://user@password@host:port/dbname[?key=value&key=value...]`.
+
+Postgres-specific keyword arguments which are accepted by :func:`~sqlalchemy.create_engine()` are:
+
+* *server_side_cursors* - Enable the usage of "server side cursors" for SQL statements which support
+ this feature. What this essentially means from a psycopg2 point of view is that the cursor is
+ created using a name, e.g. `connection.cursor('some name')`, which has the effect that result rows
+ are not immediately pre-fetched and buffered after statement execution, but are instead left
+ on the server and only retrieved as needed. SQLAlchemy's :class:`~sqlalchemy.engine.base.ResultProxy`
+ uses special row-buffering behavior when this feature is enabled, such that groups of 100 rows
+ at a time are fetched over the wire to reduce conversational overhead.
+
+Sequences/SERIAL
+----------------
+
+Postgres supports sequences, and SQLAlchemy uses these as the default means of creating
+new primary key values for integer-based primary key columns. When creating tables,
+SQLAlchemy will issue the ``SERIAL`` datatype for integer-based primary key columns,
+which generates a sequence corresponding to the column and associated with it based on
+a naming convention.
+
+To specify a specific named sequence to be used for primary key generation, use the
+:func:`~sqlalchemy.schema.Sequence` construct::
+
+ Table('sometable', metadata,
+ Column('id', Integer, Sequence('some_id_seq'), primary_key=True)
+ )
+
+Currently, when SQLAlchemy issues a single insert statement, to fulfill the contract of
+having the "last insert identifier" available, the sequence is executed independently
+beforehand and the new value is retrieved, to be used in the subsequent insert. Note
+that when an :func:`~sqlalchemy.sql.expression.insert()` construct is executed using
+"executemany" semantics, the sequence is not pre-executed and normal PG SERIAL behavior
+is used.
+
+Postgres 8.3 supports an ``INSERT...RETURNING`` syntax which SQLAlchemy supports
+as well. A future release of SQLA will use this feature by default in lieu of
+sequence pre-execution in order to retrieve new primary key values, when available.
+
+INSERT/UPDATE...RETURNING
+-------------------------
+
+The dialect supports PG 8.3's ``INSERT..RETURNING`` and ``UPDATE..RETURNING`` syntaxes,
+but must be explicitly enabled on a per-statement basis::
+
+ # INSERT..RETURNING
+ result = table.insert(postgres_returning=[table.c.col1, table.c.col2]).\\
+ values(name='foo')
+ print result.fetchall()
+
+ # UPDATE..RETURNING
+ result = table.update(postgres_returning=[table.c.col1, table.c.col2]).\\
+ where(table.c.name=='foo').values(name='bar')
+ print result.fetchall()
+
+Indexes
+-------
+
+PostgreSQL supports partial indexes. To create them pass a postgres_where
option to the Index constructor::
Index('my_index', my_table.c.id, postgres_where=tbl.c.value > 10)
-PostgreSQL 8.2+ supports returning a result set from inserts and updates.
-To use this pass the column/expression list to the postgres_returning
-parameter when creating the queries::
+Transactions
+------------
+
+The Postgres dialect fully supports SAVEPOINT and two-phase commit operations.
+
- raises = tbl.update(empl.c.sales > 100, values=dict(salary=empl.c.salary * 1.1),
- postgres_returning=[empl.c.id, empl.c.salary]).execute().fetchall()
"""
import decimal, random, re, string
diff --git a/lib/sqlalchemy/sql/expression.py b/lib/sqlalchemy/sql/expression.py
index 4a1fab166..8d2e7f811 100644
--- a/lib/sqlalchemy/sql/expression.py
+++ b/lib/sqlalchemy/sql/expression.py
@@ -268,23 +268,21 @@ def insert(table, values=None, inline=False, **kwargs):
Similar functionality is available via the ``insert()`` method on
:class:`~sqlalchemy.schema.Table`.
- table
- The table to be inserted into.
+ :param table: The table to be inserted into.
- values
- A dictionary which specifies the column specifications of the
+ :param values: A dictionary which specifies the column specifications of the
``INSERT``, and is optional. If left as None, the column
specifications are determined from the bind parameters used
during the compile phase of the ``INSERT`` statement. If the
bind parameters also are None during the compile phase, then the
column specifications will be generated from the full list of
- table columns.
+ table columns. Note that the :meth:`~Insert.values()` generative method
+ may also be used for this.
- prefixes
- A list of modifier keywords to be inserted between INSERT and INTO,
- see ``Insert.prefix_with``.
+ :param prefixes: A list of modifier keywords to be inserted between INSERT and INTO.
+ Alternatively, the :meth:`~Insert.prefix_with` generative method may be used.
- inline
+ :param inline:
if True, SQL defaults will be compiled 'inline' into the statement
and not pre-executed.
@@ -312,27 +310,26 @@ def update(table, whereclause=None, values=None, inline=False, **kwargs):
Similar functionality is available via the ``update()`` method on
:class:`~sqlalchemy.schema.Table`.
- table
- The table to be updated.
+ :param table: The table to be updated.
- whereclause
- A ``ClauseElement`` describing the ``WHERE`` condition of the
- ``UPDATE`` statement.
+ :param whereclause: A ``ClauseElement`` describing the ``WHERE`` condition of the
+ ``UPDATE`` statement. Note that the :meth:`~Update.where()` generative
+ method may also be used for this.
- values
+ :param values:
A dictionary which specifies the ``SET`` conditions of the
``UPDATE``, and is optional. If left as None, the ``SET``
conditions are determined from the bind parameters used during
the compile phase of the ``UPDATE`` statement. If the bind
parameters also are None during the compile phase, then the
``SET`` conditions will be generated from the full list of table
- columns.
+ columns. Note that the :meth:`~Update.values()` generative method may
+ also be used for this.
- inline
+ :param inline:
if True, SQL defaults will be compiled 'inline' into the statement
and not pre-executed.
-
If both `values` and compile-time bind parameters are present, the
compile-time bind parameters override the information specified
within `values` on a per-key basis.
@@ -357,12 +354,11 @@ def delete(table, whereclause = None, **kwargs):
Similar functionality is available via the ``delete()`` method on
:class:`~sqlalchemy.schema.Table`.
- table
- The table to be updated.
+ :param table: The table to be updated.
- whereclause
- A ``ClauseElement`` describing the ``WHERE`` condition of the
- ``UPDATE`` statement.
+ :param whereclause: A :class:`ClauseElement` describing the ``WHERE`` condition of the
+ ``UPDATE`` statement. Note that the :meth:`~Delete.where()` generative method
+ may be used instead.
"""
return Delete(table, whereclause, **kwargs)
@@ -522,15 +518,15 @@ def exists(*args, **kwargs):
Calling styles are of the following forms::
# use on an existing select()
- s = select([<columns>]).where(<criterion>)
+ s = select([table.c.col1]).where(table.c.col2==5)
s = exists(s)
# construct a select() at once
- exists(['*'], **select_arguments).where(<criterion>)
+ exists(['*'], **select_arguments).where(criterion)
# columns argument is optional, generates "EXISTS (SELECT *)"
# by default.
- exists().where(<criterion>)
+ exists().where(table.c.col2==5)
"""
return _Exists(*args, **kwargs)
@@ -2841,12 +2837,18 @@ class TableClause(_Immutable, FromClause):
return select([func.count(col).label('tbl_row_count')], whereclause, from_obj=[self], **params)
def insert(self, values=None, inline=False, **kwargs):
+ """Genrate an :func:`insert()` construct."""
+
return insert(self, values=values, inline=inline, **kwargs)
def update(self, whereclause=None, values=None, inline=False, **kwargs):
+ """Genrate an :func:`update()` construct."""
+
return update(self, whereclause=whereclause, values=values, inline=inline, **kwargs)
def delete(self, whereclause=None, **kwargs):
+ """Genrate a :func:`delete()` construct."""
+
return delete(self, whereclause, **kwargs)
@property
@@ -3487,7 +3489,8 @@ class _ValuesBase(_UpdateBase):
key=<somevalue> arguments
\*args
- deprecated. A single dictionary can be sent as the first positional argument.
+ A single dictionary can be sent as the first positional argument. This allows
+ non-string based keys, such as Column objects, to be used.
"""
if args:
@@ -3504,6 +3507,11 @@ class _ValuesBase(_UpdateBase):
self.parameters.update(kwargs)
class Insert(_ValuesBase):
+ """Represent an INSERT construct.
+
+ The ``Insert`` object is created using the :func:`insert()` function.
+
+ """
def __init__(self, table, values=None, inline=False, bind=None, prefixes=None, **kwargs):
_ValuesBase.__init__(self, table, values)
self._bind = bind
@@ -3537,6 +3545,11 @@ class Insert(_ValuesBase):
self._prefixes = self._prefixes + [clause]
class Update(_ValuesBase):
+ """Represent an Update construct.
+
+ The ``Update`` object is created using the :func:`update()` function.
+
+ """
def __init__(self, table, whereclause, values=None, inline=False, bind=None, **kwargs):
_ValuesBase.__init__(self, table, values)
self._bind = bind
@@ -3570,6 +3583,12 @@ class Update(_ValuesBase):
class Delete(_UpdateBase):
+ """Represent a DELETE construct.
+
+ The ``Delete`` object is created using the :func:`delete()` function.
+
+ """
+
def __init__(self, table, whereclause, bind=None, **kwargs):
self._bind = bind
self.table = table