mirror of
https://github.com/sqlalchemy/sqlalchemy.git
synced 2026-05-17 06:07:27 -04:00
- fix to oracle table aliasing
- added select.prefix_with(), adds arbitrary prefixes to a SELECT's columns clause, [ticket:504]
This commit is contained in:
@@ -181,6 +181,8 @@
|
||||
- select(scalar=True) argument is deprecated; use select(..).as_scalar().
|
||||
the resulting object obeys the full "column" interface and plays better
|
||||
within expressions
|
||||
- added select().with_prefix('foo') allowing any set of keywords to be
|
||||
placed before the columns clause of the SELECT [ticket:504]
|
||||
- result sets make a better attempt at matching the DBAPI types present
|
||||
in cursor.description to the TypeEngine objects defined by the dialect,
|
||||
which are then used for result-processing. Note this only takes effect
|
||||
|
||||
@@ -527,7 +527,7 @@ class ANSICompiler(engine.Compiled):
|
||||
|
||||
collist = string.join(inner_columns.difference(util.Set([None])), ', ')
|
||||
|
||||
text = "SELECT "
|
||||
text = " ".join(["SELECT"] + [self.process(x) for x in select._prefixes]) + " "
|
||||
text += self.get_select_precolumns(select)
|
||||
text += collist
|
||||
|
||||
|
||||
@@ -526,9 +526,9 @@ class OracleCompiler(ansisql.ANSICompiler):
|
||||
"""Oracle doesn't like ``FROM table AS alias``. Is the AS standard SQL??"""
|
||||
|
||||
if asfrom:
|
||||
return self.process(alias.original) + " " + alias.name
|
||||
return self.process(alias.original, asfrom=asfrom, **kwargs) + " " + alias.name
|
||||
else:
|
||||
return self.process(alias.original)
|
||||
return self.process(alias.original, **kwargs)
|
||||
|
||||
def visit_insert(self, insert):
|
||||
"""``INSERT`` s are required to have the primary keys be explicitly present.
|
||||
|
||||
+32
-10
@@ -752,6 +752,14 @@ def _literal_as_text(element):
|
||||
else:
|
||||
return element
|
||||
|
||||
def _literal_as_column(element):
|
||||
if isinstance(element, Operators):
|
||||
return element.clause_element()
|
||||
elif _is_literal(element):
|
||||
return literal_column(str(element))
|
||||
else:
|
||||
return element
|
||||
|
||||
def _literal_as_binds(element, name='literal', type_=None):
|
||||
if isinstance(element, Operators):
|
||||
return element.clause_element()
|
||||
@@ -1285,16 +1293,16 @@ class _CompareMixin(ColumnOperators):
|
||||
def __compare(self, op, obj, negate=None):
|
||||
if obj is None or isinstance(obj, _Null):
|
||||
if op == operator.eq:
|
||||
return _BinaryExpression(self.clause_element(), null(), Operators.is_, negate=Operators.isnot)
|
||||
return _BinaryExpression(self.expression_element(), null(), Operators.is_, negate=Operators.isnot)
|
||||
elif op == operator.ne:
|
||||
return _BinaryExpression(self.clause_element(), null(), Operators.isnot, negate=Operators.is_)
|
||||
return _BinaryExpression(self.expression_element(), null(), Operators.isnot, negate=Operators.is_)
|
||||
else:
|
||||
raise exceptions.ArgumentError("Only '='/'!=' operators can be used with NULL")
|
||||
else:
|
||||
obj = self._check_literal(obj)
|
||||
|
||||
|
||||
return _BinaryExpression(self.clause_element(), obj, op, type_=sqltypes.Boolean, negate=negate)
|
||||
return _BinaryExpression(self.expression_element(), obj, op, type_=sqltypes.Boolean, negate=negate)
|
||||
|
||||
def __operate(self, op, obj):
|
||||
obj = self._check_literal(obj)
|
||||
@@ -1305,7 +1313,7 @@ class _CompareMixin(ColumnOperators):
|
||||
if op == operator.add and isinstance(type_, (sqltypes.Concatenable)):
|
||||
op = ColumnOperators.concat_op
|
||||
|
||||
return _BinaryExpression(self.clause_element(), obj, op, type_=type_)
|
||||
return _BinaryExpression(self.expression_element(), obj, op, type_=type_)
|
||||
|
||||
operators = {
|
||||
operator.add : (__operate,),
|
||||
@@ -1413,6 +1421,11 @@ class _CompareMixin(ColumnOperators):
|
||||
return other
|
||||
|
||||
def clause_element(self):
|
||||
"""Allow ``_CompareMixins`` to return the underlying ``ClauseElement``, for non-``ClauseElement`` ``_CompareMixins``."""
|
||||
|
||||
return self
|
||||
|
||||
def expression_element(self):
|
||||
"""Allow ``_CompareMixins`` to return the appropriate object to be used in expressions."""
|
||||
|
||||
return self
|
||||
@@ -2547,9 +2560,9 @@ class _Label(ColumnElement):
|
||||
_label = property(lambda s: s.name)
|
||||
orig_set = property(lambda s:s.obj.orig_set)
|
||||
|
||||
def clause_element(self):
|
||||
def expression_element(self):
|
||||
return self.obj
|
||||
|
||||
|
||||
def _copy_internals(self):
|
||||
self.obj = self.obj._clone()
|
||||
|
||||
@@ -2923,7 +2936,7 @@ class Select(_SelectBaseMixin, FromClause):
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, columns, whereclause=None, from_obj=None, distinct=False, having=None, correlate=True, **kwargs):
|
||||
def __init__(self, columns, whereclause=None, from_obj=None, distinct=False, having=None, correlate=True, prefixes=None, **kwargs):
|
||||
"""construct a Select object.
|
||||
|
||||
The public constructor for Select is the [sqlalchemy.sql#select()] function;
|
||||
@@ -2938,6 +2951,7 @@ class Select(_SelectBaseMixin, FromClause):
|
||||
self._froms = util.OrderedSet()
|
||||
self._whereclause = None
|
||||
self._having = None
|
||||
self._prefixes = []
|
||||
|
||||
if columns is not None:
|
||||
for c in columns:
|
||||
@@ -3148,6 +3162,11 @@ class Select(_SelectBaseMixin, FromClause):
|
||||
s.distinct = True
|
||||
return s
|
||||
|
||||
def prefix_with(self, clause):
|
||||
s = self._generate()
|
||||
s.append_prefix(clause)
|
||||
return s
|
||||
|
||||
def select_from(self, fromclause):
|
||||
s = self._generate()
|
||||
s.append_from(fromclause)
|
||||
@@ -3171,14 +3190,17 @@ class Select(_SelectBaseMixin, FromClause):
|
||||
self.__correlate.add(fromclause)
|
||||
|
||||
def append_column(self, column):
|
||||
if _is_literal(column):
|
||||
column = literal_column(str(column))
|
||||
column = _literal_as_column(column)
|
||||
|
||||
if isinstance(column, _ScalarSelect):
|
||||
column = column.self_group(against=ColumnOperators.comma_op)
|
||||
|
||||
self._raw_columns.append(column)
|
||||
|
||||
|
||||
def append_prefix(self, clause):
|
||||
clause = _literal_as_text(clause)
|
||||
self._prefixes.append(clause)
|
||||
|
||||
def append_whereclause(self, whereclause):
|
||||
if self._whereclause is not None:
|
||||
self._whereclause = and_(self._whereclause, _literal_as_text(whereclause))
|
||||
|
||||
+16
-5
@@ -414,13 +414,18 @@ sq.myothertable_othername AS sq_myothertable_othername FROM (" + sqstring + ") A
|
||||
def testalias(self):
|
||||
# test the alias for a table1. column names stay the same, table name "changes" to "foo".
|
||||
self.runtest(
|
||||
select([alias(table1, 'foo')])
|
||||
select([table1.alias('foo')])
|
||||
,"SELECT foo.myid, foo.name, foo.description FROM mytable AS foo")
|
||||
|
||||
|
||||
for dialect in (firebird.dialect(), oracle.dialect()):
|
||||
self.runtest(
|
||||
select([table1.alias('foo')])
|
||||
,"SELECT foo.myid, foo.name, foo.description FROM mytable foo"
|
||||
,dialect=dialect)
|
||||
|
||||
self.runtest(
|
||||
select([alias(table1, 'foo')])
|
||||
,"SELECT foo.myid, foo.name, foo.description FROM mytable foo"
|
||||
,dialect=firebird.dialect())
|
||||
select([table1.alias()])
|
||||
,"SELECT mytable_1.myid, mytable_1.name, mytable_1.description FROM mytable AS mytable_1")
|
||||
|
||||
# create a select for a join of two tables. use_labels means the column names will have
|
||||
# labels tablename_columnname, which become the column keys accessible off the Selectable object.
|
||||
@@ -441,6 +446,12 @@ myothertable.otherid AS myothertable_otherid FROM mytable, myothertable \
|
||||
WHERE mytable.myid = myothertable.otherid) AS t2view WHERE t2view.mytable_myid = :t2view_mytable_myid"
|
||||
)
|
||||
|
||||
|
||||
def test_prefixes(self):
|
||||
self.runtest(table1.select().prefix_with("SQL_CALC_FOUND_ROWS").prefix_with("SQL_SOME_WEIRD_MYSQL_THING"),
|
||||
"SELECT SQL_CALC_FOUND_ROWS SQL_SOME_WEIRD_MYSQL_THING mytable.myid, mytable.name, mytable.description FROM mytable"
|
||||
)
|
||||
|
||||
def testtext(self):
|
||||
self.runtest(
|
||||
text("select * from foo where lala = bar") ,
|
||||
|
||||
Reference in New Issue
Block a user