<&formatting.myt:poplink&>c = users.select(users.c.user_name.in_('jack', 'ed', 'fred')).execute()
<&|formatting.myt:codepopper, link="sql" &>
SELECT users.user_id, users.user_name, users.password
-FROM users WHERE users.user_name IN ('jack', 'ed', 'fred')
+FROM users WHERE users.user_name
+IN (:users_user_name, :users_user_name_1, :users_user_name_2)
+{'users_user_name': 'jack', 'users_user_name_1': 'ed',
+ 'users_user_name_2': 'fred'}
</&>
# join users and addresses together
{'users_user_name': 'fred'}
</&>
</&>
+
+ <P>Select statements can also generate a WHERE clause based on the parameters you give it. If a given parameter, which matches the name of a column or its "label" (the combined tablename + "_" + column name), and does not already correspond to a bind parameter in the select object, it will be added as a comparison against that column. This is a shortcut to creating a full WHERE clause:</p>
+ <&|formatting.myt:code&>
+ # specify a match for the "user_name" column
+ <&formatting.myt:poplink&>c = users.select().execute(user_name='ed')
+<&|formatting.myt:codepopper, link="sql" &>
+SELECT users.user_id, users.user_name, users.password
+FROM users WHERE users.user_name = :users_user_name
+{'users_user_name': 'ed'}
+</&>
+ # specify a full where clause for the "user_name" column, as well as a
+ # comparison for the "user_id" column
+ <&formatting.myt:poplink&>c = users.select(users.c.user_name=='ed').execute(user_id=10)
+<&|formatting.myt:codepopper, link="sql" &>
+SELECT users.user_id, users.user_name, users.password
+FROM users WHERE users.user_name = :users_user_name AND users.user_id = :users_user_id
+{'users_user_name': 'ed', 'users_user_id': 10}
+</&>
+ </&>
<&|doclib.myt:item, name="operators", description="Operators" &>
<p>Supported column operators so far are all the numerical comparison operators, i.e. '==', '>', '>=', etc., as well as like(), startswith(), endswith(), and in(). Boolean operators include not_(), and_() and or_(), which also can be used inline via '~', '&', and '|'. Math operators are '+', '-', '*', '/'.</p>
<&|formatting.myt:code &>
+ # "like" operator
users.select(users.c.user_name.like('%ter'))
+
+ # equality operator
users.select(users.c.user_name == 'jane')
+
+ # in opertator
users.select(users.c.user_id.in_(1,2,3))
+
+ # and_, endswith, equality operators
users.select(and_(addresses.c.street.endswith('green street'), addresses.c.zip=='11234'))
+
+ # & operator subsituting for 'and_'
users.select(addresses.c.street.endswith('green street') & (addresses.c.zip=='11234'))
+
+ # + concatenation operator
select([users.c.user_name + '_name'])
+
+ # NOT operator
users.select(~(addresses.c.street == 'Green Street'))
</&>
</&>
whereclause = select.whereclause
- # TODO: look at our own parameters, see if they
+ # look at our own parameters, see if they
# are all present in the form of BindParamClauses. if
# not, then append to the above whereclause column conditions
# matching those keys
-
+ if self.parameters is not None:
+ revisit = False
+ for c in inner_columns:
+ if self.parameters.has_key(c.key) and not self.binds.has_key(c.key):
+ value = self.parameters[c.key]
+ elif self.parameters.has_key(c.label) and not self.binds.has_key(c.label):
+ value = self.parameters[c.label]
+ else:
+ continue
+ clause = c==value
+ clause.accept_visitor(self)
+ whereclause = sql.and_(clause, whereclause)
+ self.visit_compound(whereclause)
+
froms = []
for f in select.froms:
return parameters
def get_colparams(self, parameters):
+ """this is used by the ANSICompiler to determine the VALUES or SET clause based on the arguments
+ specified to the execute() or compile() method of the INSERT or UPDATE clause:
+
+ insert(mytable).execute(col1='foo', col2='bar')
+ mytable.update().execute(col2='foo', col3='bar')
+
+ in the above examples, the insert() and update() methods have no "values" sent to them
+ at all, so compiling them with no arguments would yield an insert for all table columns,
+ or an update with no SET clauses. but the parameters sent indicate a set of per-compilation
+ arguments that result in a differently compiled INSERT or UPDATE object compared to the
+ original. The "values" parameter to the insert/update is figured as well if present,
+ but the incoming "parameters" sent here take precedence.
+ """
# case one: no parameters in the statement, no parameters in the
# compiled params - just return binds for all the table columns
if parameters is None and self.parameters is None:
self.runtest(select([table], table.c.id.in_(select([table2.c.id]))),
"SELECT mytable.myid, mytable.name, mytable.description FROM mytable WHERE mytable.myid IN (SELECT myothertable.otherid FROM myothertable)")
+ def testlateargs(self):
+ """tests that a SELECT clause will have extra "WHERE" clauses added to it at compile time if extra arguments
+ are sent"""
+ self.runtest(table.select(), "SELECT mytable.myid, mytable.name, mytable.description FROM mytable WHERE mytable.name = :mytable_name AND mytable.myid = :mytable_myid", params={'id':'3', 'name':'jack'})
+
+ self.runtest(table.select(table.c.name=='jack'), "SELECT mytable.myid, mytable.name, mytable.description FROM mytable WHERE mytable.myid = :mytable_myid AND mytable.name = :mytable_name", params={'id':'3'})
+
+ self.runtest(table.select(table.c.name=='jack'), "SELECT mytable.myid, mytable.name, mytable.description FROM mytable WHERE mytable.myid = :mytable_myid AND mytable.name = :mytable_name", params={'id':'3', 'name':'fred'})
class CRUDTest(SQLTest):
def testinsert(self):