allow clause elements inside of in_ clauses

Issue #476 resolved
Mike Bayer repo owner created an issue

right now, cant do:

>>> from sqlalchemy import *
>>> t = table('foo', column('hi'))
>>> t.c.hi.in_(bindparam("x"), bindparam("y")).__str__()
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "build/bdist.darwin-8.8.0-Power_Macintosh/egg/sqlalchemy/sql.py", line 552, in in_
AttributeError: 'module' object has no attribute 'InvalidRequestException'

Comments (10)

  1. Former user Account Deleted

    (original author: svilen) Here a sort-of patch + test. Have a look / run. i'm walking the args (if expressions) and checking for allowed/disallowed node-types.

    IMO the checks should be only defensive, i.e. disable only impossibly-wrong stuff, and pass all else down - to be decided by sql-server. e.g. if some dialect/server may accept t.col1 IN (t.col2, t.col3+abc), let it be so.

    This one is still trying to mime the current checks. The vis4check.py is separate because of its own test; the reason of it to be a generated and not a plain visitor-class, is maintainability - no need to change it if more methods appear in base ClauseVisitor. it's up to you, such node-check may or may not be needed.

  2. Former user Account Deleted

    (original author: svilen) on a second thought, seeing what sql/89 and sql/92 says, just drop all visitor-stuff and use (_isliteral(arg) or isinstance(arg, _CompareMixin)). Or, better, only make strong difference between a subquery and plain list of arguments (without / with parens). Let the sql-server complain - GIGO (garbage-in -> garbage-out).

  3. Former user Account Deleted

    (original author: svil) e.g. ` def in_(self, *other): if len(other) == 0: return self.eq(None) elif len(other) == 1: o = other0 if sql._is_literal(o) or isinstance( o, sql._CompareMixin): return self.eq( o) #single item -> == else: #subquery assert hasattr( o, '_selectable') #XXX better check? return self._compare( 'IN', o, negate='NOT IN') #single subquery

        args = []
        for o in other:
            if sql._is_literal(o):
                o = self._bind_param(o)
            else:
                if not isinstance( o, sql._CompareMixin):
                    raise sql.exceptions.InvalidRequestError( "in() function accepts only multiple literal values, or a single selectable as an argument: "+repr(o) )
            args.append(o)
        return self._compare( 'IN', sql.ClauseList( parens=True, *args), negate='NOT IN')
    

    `

  4. Mike Bayer reporter

    yes, i was going to drop the visitor stuff. i usually favor sending whatever over to the SQL server. this is a really small fix i just have too many other things to deal wtih right now. if you can convert your unit test to a function that we can stick into test/sql/select.py, and provide a patch for everything (i.e. using svn diff) that would help.

  5. Former user Account Deleted

    (original author: svil) ok, forget it by now, i'll do that after several days, not a hurry.

  6. Log in to comment