# use server-side cursors:
# http://lists.initd.org/pipermail/psycopg/2007-January/005251.html
ident = "c" + hex(random.randint(0, 65535))[2:]
- return self.connection.connection.cursor(ident)
+ return self._connection.connection.cursor(ident)
else:
- return self.connection.connection.cursor()
+ return self._connection.connection.cursor()
def get_result_proxy(self):
if self._is_server_side():
ExecutionContext should have these datamembers:
connection
- Connection object which initiated the call to the
- dialect to create this ExecutionContext.
+ Connection object which can be freely used by default value generators
+ to execute SQL. This Connection should reference the same underlying
+ connection/transactional resources of root_connection.
+
+ root_connection
+ Connection object which is the source of this ExecutionContext. This
+ Connection may have close_with_result=True set, in which case it can
+ only be used once.
dialect
dialect which created this ExecutionContext.
The Connection object is **not** threadsafe.
"""
- def __init__(self, engine, connection=None, close_with_result=False):
+ def __init__(self, engine, connection=None, close_with_result=False, _branch=False):
self.__engine = engine
self.__connection = connection or engine.raw_connection()
self.__transaction = None
self.__close_with_result = close_with_result
self.__savepoint_seq = 0
+ self.__branch = _branch
def _get_connection(self):
try:
def _branch(self):
"""return a new Connection which references this Connection's
- engine and connection; but does not have close_with_result enabled."""
+ engine and connection; but does not have close_with_result enabled,
+ and also whose close() method does nothing.
+
+ This is used to execute "sub" statements within a single execution,
+ usually an INSERT statement.
+ """
- return Connection(self.__engine, self.__connection)
+ return Connection(self.__engine, self.__connection, _branch=True)
engine = property(lambda s:s.__engine, doc="The Engine with which this Connection is associated.")
dialect = property(lambda s:s.__engine.dialect, doc="Dialect used by this Connection.")
c = self.__connection
except AttributeError:
return
- self.__connection.close()
+ if not self.__branch:
+ self.__connection.close()
self.__connection = None
del self.__connection
else:
self.__execute(context)
self._autocommit(context.statement)
-
+
def __execute(self, context):
if context.parameters is None:
if context.dialect.positional:
self._rowcount = context.get_rowcount()
self.close()
- connection = property(lambda self:self.context.connection)
+ connection = property(lambda self:self.context.root_connection)
+
def _get_rowcount(self):
if self._rowcount is not None:
return self._rowcount
def __init__(self, context):
self.context = context
- # branch the connection so it doesnt close after result
- self.connection = context.connection._branch()
-
+ self.connection = self.context._connection._branch()
dialect = property(lambda self:self.context.dialect)
def get_column_default(self, column):
class DefaultExecutionContext(base.ExecutionContext):
def __init__(self, dialect, connection, compiled=None, statement=None, parameters=None):
self.dialect = dialect
- self.connection = connection
+ self._connection = connection
self.compiled = compiled
self._postfetch_cols = util.Set()
self.statement = self.statement.encode(self.dialect.encoding)
self.cursor = self.create_cursor()
-
+
engine = property(lambda s:s.connection.engine)
isinsert = property(lambda s:s.compiled and s.compiled.isinsert)
isupdate = property(lambda s:s.compiled and s.compiled.isupdate)
+ connection = property(lambda s:s._connection._branch())
+
+ root_connection = property(lambda s:s._connection)
+
def __encode_param_keys(self, params):
"""apply string encoding to the keys of dictionary-based bind parameters"""
if self.dialect.positional or self.dialect.supports_unicode_statements():
return re.match(r'SELECT', self.statement.lstrip(), re.I) is not None
def create_cursor(self):
- return self.connection.connection.cursor()
+ return self._connection.connection.cursor()
def pre_execution(self):
self.pre_exec()
x['x'] += 1
return x['x']
- def mydefault_with_ctx(ctx):
- return ctx.compiled_parameters['col1'] + 10
-
def myupdate_with_ctx(ctx):
return len(ctx.compiled_parameters['col2'])
+
+ def mydefault_using_connection(ctx):
+ conn = ctx.connection
+ try:
+ if db.engine.name == 'oracle':
+ return conn.execute("select 12 from dual").scalar()
+ else:
+ return conn.execute("select 12").scalar()
+ finally:
+ # ensure a "close()" on this connection does nothing,
+ # since its a "branched" connection
+ conn.close()
use_function_defaults = db.engine.name == 'postgres' or db.engine.name == 'oracle'
is_oracle = db.engine.name == 'oracle'
Column('boolcol2', Boolean, default=False),
# python function which uses ExecutionContext
- Column('col7', Integer, default=mydefault_with_ctx, onupdate=myupdate_with_ctx),
+ Column('col7', Integer, default=mydefault_using_connection, onupdate=myupdate_with_ctx),
# python builtin
Column('col8', Date, default=datetime.date.today, onupdate=datetime.date.today)
print "Currenttime "+ repr(ctexec)
l = t.select().execute()
today = datetime.date.today()
- self.assert_(l.fetchall() == [(51, 'imthedefault', f, ts, ts, ctexec, True, False, 61, today), (52, 'imthedefault', f, ts, ts, ctexec, True, False, 62, today), (53, 'imthedefault', f, ts, ts, ctexec, True, False, 63, today)])
+ self.assert_(l.fetchall() == [(51, 'imthedefault', f, ts, ts, ctexec, True, False, 12, today), (52, 'imthedefault', f, ts, ts, ctexec, True, False, 12, today), (53, 'imthedefault', f, ts, ts, ctexec, True, False, 12, today)])
def testinsertvalues(self):
t.insert(values={'col3':50}).execute()
nonai_table = Table("aitest", meta,
Column('id', Integer, autoincrement=False, primary_key=True),
Column('data', String(20)))
- nonai_table.create()
+ nonai_table.create(checkfirst=True)
try:
try:
# postgres will fail on first row, mysql fails on second row
table = Table("aitest", meta,
Column('id', Integer, primary_key=True),
Column('data', String(20)))
- table.create()
+ table.create(checkfirst=True)
try:
table.insert().execute(data='row 1')
table.insert().execute(data='row 2')
table = Table("aitest", meta,
Column('id', Integer, primary_key=True),
Column('data', String(20)))
- table.create()
+ table.create(checkfirst=True)
try:
# simulate working on a table that doesn't already exist