[Sqlalchemy-commits] [1091] sqlalchemy/trunk/test: making sequences, column defaults independently e
Brought to you by:
zzzeek
From: <co...@sq...> - 2006-03-04 19:30:44
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head><style type="text/css"><!-- #msg dl { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; } #msg dt { float: left; width: 6em; font-weight: bold; } #msg dt:after { content:':';} #msg dl, #msg dt, #msg ul, #msg li { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; } #msg dl a { font-weight: bold} #msg dl a:link { color:#fc3; } #msg dl a:active { color:#ff0; } #msg dl a:visited { color:#cc6; } h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; } #msg pre { overflow: auto; background: #ffc; border: 1px #fc0 solid; padding: 6px; } #msg ul, pre { overflow: auto; } #patch { width: 100%; } #patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;} #patch .propset h4, #patch .binary h4 {margin:0;} #patch pre {padding:0;line-height:1.2em;margin:0;} #patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;} #patch .propset .diff, #patch .binary .diff {padding:10px 0;} #patch span {display:block;padding:0 10px;} #patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;} #patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;} #patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;} #patch .lines, .info {color:#888;background:#fff;} --></style> <title>[1091] sqlalchemy/trunk/test: making sequences, column defaults independently executeable</title> </head> <body> <div id="msg"> <dl> <dt>Revision</dt> <dd>1091</dd> <dt>Author</dt> <dd>zzzeek</dd> <dt>Date</dt> <dd>2006-03-04 13:26:23 -0600 (Sat, 04 Mar 2006)</dd> </dl> <h3>Log Message</h3> <pre>making sequences, column defaults independently executeable</pre> <h3>Modified Paths</h3> <ul> <li><a href="#sqlalchemytrunklibsqlalchemydatabasespostgrespy">sqlalchemy/trunk/lib/sqlalchemy/databases/postgres.py</a></li> <li><a href="#sqlalchemytrunklibsqlalchemyenginepy">sqlalchemy/trunk/lib/sqlalchemy/engine.py</a></li> <li><a href="#sqlalchemytrunklibsqlalchemyschemapy">sqlalchemy/trunk/lib/sqlalchemy/schema.py</a></li> <li><a href="#sqlalchemytrunktestquerypy">sqlalchemy/trunk/test/query.py</a></li> <li><a href="#sqlalchemytrunktestsequencepy">sqlalchemy/trunk/test/sequence.py</a></li> </ul> </div> <div id="patch"> <h3>Diff</h3> <a id="sqlalchemytrunklibsqlalchemydatabasespostgrespy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/databases/postgres.py (1090 => 1091)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/databases/postgres.py 2006-03-04 18:53:35 UTC (rev 1090) +++ sqlalchemy/trunk/lib/sqlalchemy/databases/postgres.py 2006-03-04 19:26:23 UTC (rev 1091) </span><span class="lines">@@ -218,7 +218,7 @@ </span><span class="cx"> def schemadropper(self, **params): </span><span class="cx"> return PGSchemaDropper(self, **params) </span><span class="cx"> </span><del>- def defaultrunner(self, proxy): </del><ins>+ def defaultrunner(self, proxy=None): </ins><span class="cx"> return PGDefaultRunner(self, proxy) </span><span class="cx"> </span><span class="cx"> def get_default_schema_name(self): </span><span class="lines">@@ -346,7 +346,7 @@ </span><span class="cx"> self.execute() </span><span class="cx"> </span><span class="cx"> class PGDefaultRunner(ansisql.ANSIDefaultRunner): </span><del>- def get_column_default(self, column): </del><ins>+ def get_column_default(self, column, isinsert=True): </ins><span class="cx"> if column.primary_key: </span><span class="cx"> # passive defaults on primary keys have to be overridden </span><span class="cx"> if isinstance(column.default, schema.PassiveDefault): </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemyenginepy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/engine.py (1090 => 1091)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/engine.py 2006-03-04 18:53:35 UTC (rev 1090) +++ sqlalchemy/trunk/lib/sqlalchemy/engine.py 2006-03-04 19:26:23 UTC (rev 1091) </span><span class="lines">@@ -265,7 +265,7 @@ </span><span class="cx"> """ </span><span class="cx"> raise NotImplementedError() </span><span class="cx"> </span><del>- def defaultrunner(self, proxy): </del><ins>+ def defaultrunner(self, proxy=None): </ins><span class="cx"> """Returns a schema.SchemaVisitor instance that can execute the default values on a column. </span><span class="cx"> The base class for this visitor is the DefaultRunner class inside this module. </span><span class="cx"> This visitor will typically only receive schema.DefaultGenerator schema objects. The given </span><span class="lines">@@ -275,7 +275,7 @@ </span><span class="cx"> </span><span class="cx"> defaultrunner is called within the context of the execute_compiled() method.""" </span><span class="cx"> return DefaultRunner(self, proxy) </span><del>- </del><ins>+ </ins><span class="cx"> def compiler(self, statement, parameters): </span><span class="cx"> """returns a sql.ClauseVisitor which will produce a string representation of the given </span><span class="cx"> ClauseElement and parameter dictionary. This object is usually a subclass of </span><span class="lines">@@ -529,7 +529,7 @@ </span><span class="cx"> self.post_exec(proxy, compiled, parameters, **kwargs) </span><span class="cx"> return ResultProxy(cursor, self, typemap=compiled.typemap) </span><span class="cx"> </span><del>- def execute(self, statement, parameters, connection=None, cursor=None, echo=None, typemap=None, commit=False, return_raw=False, **kwargs): </del><ins>+ def execute(self, statement, parameters=None, connection=None, cursor=None, echo=None, typemap=None, commit=False, return_raw=False, **kwargs): </ins><span class="cx"> """executes the given string-based SQL statement with the given parameters. </span><span class="cx"> </span><span class="cx"> The parameters can be a dictionary or a list, or a list of dictionaries or lists, depending </span></span></pre></div> <a id="sqlalchemytrunklibsqlalchemyschemapy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/lib/sqlalchemy/schema.py (1090 => 1091)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/lib/sqlalchemy/schema.py 2006-03-04 18:53:35 UTC (rev 1090) +++ sqlalchemy/trunk/lib/sqlalchemy/schema.py 2006-03-04 19:26:23 UTC (rev 1091) </span><span class="lines">@@ -434,11 +434,12 @@ </span><span class="cx"> self.parent.table.foreign_keys.append(self) </span><span class="cx"> </span><span class="cx"> class DefaultGenerator(SchemaItem): </span><del>- """Base class for column "default" values, which can be a plain default - or a Sequence.""" </del><ins>+ """Base class for column "default" values.""" </ins><span class="cx"> def _set_parent(self, column): </span><span class="cx"> self.column = column </span><span class="cx"> self.column.default = self </span><ins>+ def execute(self): + return self.accept_schema_visitor(self.engine.defaultrunner(self.engine.execute)) </ins><span class="cx"> def __repr__(self): </span><span class="cx"> return "DefaultGenerator()" </span><span class="cx"> </span><span class="lines">@@ -464,17 +465,27 @@ </span><span class="cx"> </span><span class="cx"> class Sequence(DefaultGenerator): </span><span class="cx"> """represents a sequence, which applies to Oracle and Postgres databases.""" </span><del>- def __init__(self, name, start = None, increment = None, optional=False): </del><ins>+ def __init__(self, name, start = None, increment = None, optional=False, engine=None): </ins><span class="cx"> self.name = name </span><span class="cx"> self.start = start </span><span class="cx"> self.increment = increment </span><span class="cx"> self.optional=optional </span><ins>+ self.engine = engine </ins><span class="cx"> def __repr__(self): </span><span class="cx"> return "Sequence(%s)" % string.join( </span><span class="cx"> [repr(self.name)] + </span><span class="cx"> ["%s=%s" % (k, repr(getattr(self, k))) for k in ['start', 'increment', 'optional']] </span><span class="cx"> , ',') </span><del>- </del><ins>+ def _set_parent(self, column): + super(Sequence, self)._set_parent(column) + column.sequence = self + if self.engine is None: + self.engine = column.table.engine + def create(self): + self.engine.create(self) + return self + def drop(self): + self.engine.drop(self) </ins><span class="cx"> def accept_schema_visitor(self, visitor): </span><span class="cx"> """calls the visit_seauence method on the given visitor.""" </span><span class="cx"> return visitor.visit_sequence(self) </span></span></pre></div> <a id="sqlalchemytrunktestquerypy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/test/query.py (1090 => 1091)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/test/query.py 2006-03-04 18:53:35 UTC (rev 1090) +++ sqlalchemy/trunk/test/query.py 2006-03-04 19:26:23 UTC (rev 1091) </span><span class="lines">@@ -5,7 +5,7 @@ </span><span class="cx"> import sqlalchemy.databases.sqlite as sqllite </span><span class="cx"> </span><span class="cx"> db = testbase.db </span><del>-db.echo='debug' </del><ins>+#db.echo='debug' </ins><span class="cx"> from sqlalchemy import * </span><span class="cx"> from sqlalchemy.engine import ResultProxy, RowProxy </span><span class="cx"> </span><span class="lines">@@ -90,63 +90,7 @@ </span><span class="cx"> finally: </span><span class="cx"> test_table.drop() </span><span class="cx"> </span><del>- def testdefaults(self): - x = {'x':50} - def mydefault(): - x['x'] += 1 - return x['x'] - - use_function_defaults = db.engine.name == 'postgres' or db.engine.name == 'oracle' - is_oracle = db.engine.name == 'oracle' - - # select "count(1)" from the DB which returns different results - # on different DBs - if is_oracle: - f = select([func.count(1) + 5], engine=db, from_obj=['DUAL']).scalar() - ts = select([func.sysdate()], engine=db, from_obj=['DUAL']).scalar() - def1 = func.sysdate() - def2 = text("sysdate") - deftype = Date - elif use_function_defaults: - f = select([func.count(1) + 5], engine=db).scalar() - def1 = func.current_date() - def2 = text("current_date") - deftype = Date - ts = select([func.current_date()], engine=db).scalar() - else: - f = select([func.count(1) + 5], engine=db).scalar() - def1 = def2 = "3" - ts = 3 - deftype = Integer - - t = Table('default_test1', db, - # python function - Column('col1', Integer, primary_key=True, default=mydefault), - - # python literal - Column('col2', String(20), default="imthedefault"), - - # preexecute expression - Column('col3', Integer, default=func.count(1) + 5), - - # SQL-side default from sql expression - Column('col4', deftype, PassiveDefault(def1)), - - # SQL-side default from literal expression - Column('col5', deftype, PassiveDefault(def2)) - ) - t.create() - try: - t.insert().execute() - self.assert_(t.engine.lastrow_has_defaults()) - t.insert().execute() - t.insert().execute() </del><span class="cx"> </span><del>- l = t.select().execute() - self.assert_(l.fetchall() == [(51, 'imthedefault', f, ts, ts), (52, 'imthedefault', f, ts, ts), (53, 'imthedefault', f, ts, ts)]) - finally: - t.drop() - </del><span class="cx"> def testdelete(self): </span><span class="cx"> c = db.connection() </span><span class="cx"> </span></span></pre></div> <a id="sqlalchemytrunktestsequencepy"></a> <div class="modfile"><h4>Modified: sqlalchemy/trunk/test/sequence.py (1090 => 1091)</h4> <pre class="diff"><span> <span class="info">--- sqlalchemy/trunk/test/sequence.py 2006-03-04 18:53:35 UTC (rev 1090) +++ sqlalchemy/trunk/test/sequence.py 2006-03-04 19:26:23 UTC (rev 1091) </span><span class="lines">@@ -6,30 +6,106 @@ </span><span class="cx"> from sqlalchemy import * </span><span class="cx"> import sqlalchemy </span><span class="cx"> </span><ins>+db = testbase.db </ins><span class="cx"> </span><ins>+class DefaultTest(PersistTest): + + def testdefaults(self): + x = {'x':50} + def mydefault(): + x['x'] += 1 + return x['x'] + + use_function_defaults = db.engine.name == 'postgres' or db.engine.name == 'oracle' + is_oracle = db.engine.name == 'oracle' + + # select "count(1)" from the DB which returns different results + # on different DBs + if is_oracle: + f = select([func.count(1) + 5], engine=db, from_obj=['DUAL']).scalar() + ts = select([func.sysdate()], engine=db, from_obj=['DUAL']).scalar() + def1 = func.sysdate() + def2 = text("sysdate") + deftype = Date + elif use_function_defaults: + f = select([func.count(1) + 5], engine=db).scalar() + def1 = func.current_date() + def2 = text("current_date") + deftype = Date + ts = select([func.current_date()], engine=db).scalar() + else: + f = select([func.count(1) + 5], engine=db).scalar() + def1 = def2 = "3" + ts = 3 + deftype = Integer + + t = Table('default_test1', db, + # python function + Column('col1', Integer, primary_key=True, default=mydefault), + + # python literal + Column('col2', String(20), default="imthedefault"), + + # preexecute expression + Column('col3', Integer, default=func.count(1) + 5), + + # SQL-side default from sql expression + Column('col4', deftype, PassiveDefault(def1)), + + # SQL-side default from literal expression + Column('col5', deftype, PassiveDefault(def2)) + ) + t.create() + try: + t.insert().execute() + self.assert_(t.engine.lastrow_has_defaults()) + t.insert().execute() + t.insert().execute() + + l = t.select().execute() + self.assert_(l.fetchall() == [(51, 'imthedefault', f, ts, ts), (52, 'imthedefault', f, ts, ts), (53, 'imthedefault', f, ts, ts)]) + finally: + t.drop() + </ins><span class="cx"> class SequenceTest(PersistTest): </span><span class="cx"> </span><del>- def setUp(self): - db = sqlalchemy.engine.create_engine('postgres', {'database':'test', 'host':'127.0.0.1', 'user':'scott', 'password':'tiger'}, echo=testbase.echo) - #db = sqlalchemy.engine.create_engine('oracle', {'dsn':os.environ['DSN'], 'user':os.environ['USER'], 'password':os.environ['PASSWORD']}, echo=testbase.echo) - - self.table = Table("cartitems", db, </del><ins>+ def setUpAll(self): + if testbase.db.engine.name != 'postgres' and testbase.db.engine.name != 'oracle': + return + global cartitems + cartitems = Table("cartitems", db, </ins><span class="cx"> Column("cart_id", Integer, Sequence('cart_id_seq'), primary_key=True), </span><span class="cx"> Column("description", String(40)), </span><span class="cx"> Column("createdate", DateTime()) </span><span class="cx"> ) </span><span class="cx"> </span><del>- self.table.create() </del><ins>+ cartitems.create() </ins><span class="cx"> </span><span class="cx"> def testsequence(self): </span><del>- self.table.insert().execute(description='hi') - self.table.insert().execute(description='there') - self.table.insert().execute(description='lala') </del><ins>+ cartitems.insert().execute(description='hi') + cartitems.insert().execute(description='there') + cartitems.insert().execute(description='lala') </ins><span class="cx"> </span><del>- self.table.select().execute().fetchall() </del><ins>+ cartitems.select().execute().fetchall() </ins><span class="cx"> </span><del>- def tearDown(self): - self.table.drop() </del><ins>+ + def teststandalone(self): + s = Sequence("my_sequence", engine=db) + s.create() + try: + x =s.execute() + self.assert_(x == 1) + finally: + s.drop() + + def teststandalone2(self): + x = cartitems.c.cart_id.sequence.execute() + self.assert_(1 <= x <= 4) + + def tearDownAll(self): + if testbase.db.engine.name != 'postgres' and testbase.db.engine.name != 'oracle': + return + cartitems.drop() </ins><span class="cx"> </span><span class="cx"> if __name__ == "__main__": </span><span class="cx"> unittest.main() </span></span></pre> </div> </div> </body> </html> |