--- /dev/null
+.. change::
+ :tags: bug, sql
+ :tickets: 11526
+
+ A warning is emitted when using the standalone :func:`_.sql.distinct`
+ function in a :func:`_sql.select` columns list outside of an aggregate
+ function; this function is not intended as a replacement for the use of
+ :meth:`.Select.distinct`. Pull request courtesy bekapono.
text: str
+ kwargs["within_aggregate_function"] = True
+
if disp:
text = disp(func, **kwargs)
else:
kw["add_to_result_map"] = add_to_result_map
kw["result_map_targets"] = result_map_targets
+ if unary.operator is operators.distinct_op and not kw.get(
+ "within_aggregate_function", False
+ ):
+ util.warn(
+ "Column-expression-level unary distinct() "
+ "should not be used outside of an aggregate "
+ "function. For general 'SELECT DISTINCT' support"
+ "use select().distinct()."
+ )
+
if unary.operator:
if unary.modifier:
raise exc.CompileError(
.all(),
)
+ @testing.emits_warning("Column-expression-level unary distinct")
def test_basic_standalone(self):
User = self.classes.User
- # issue 6008. the UnaryExpression now places itself into the
+ # issue #6008. the UnaryExpression now places itself into the
# result map so that it can be matched positionally without the need
# for any label.
q = fixture_session().query(distinct(User.id)).order_by(User.id)
)
eq_([(7,), (8,), (9,), (10,)], q.all())
+ @testing.emits_warning("Column-expression-level unary distinct")
def test_standalone_w_subquery(self):
+ # additional test for #6008
User = self.classes.User
- q = fixture_session().query(distinct(User.id))
+ q = fixture_session().query(distinct(User.id))
subq = q.subquery()
q = fixture_session().query(subq).order_by(subq.c[0])
eq_([(7,), (8,), (9,), (10,)], q.all())
dialect=default.DefaultDialect(supports_native_boolean=True),
)
- def test_distinct(self):
+ def test_distinct_select_modifier(self):
self.assert_compile(
- select(table1.c.myid.distinct()),
- "SELECT DISTINCT mytable.myid FROM mytable",
- )
-
- self.assert_compile(
- select(distinct(table1.c.myid)),
+ select(table1.c.myid).distinct(),
"SELECT DISTINCT mytable.myid FROM mytable",
)
self.assert_compile(
- select(distinct(table1.c.myid)).set_label_style(
- LABEL_STYLE_TABLENAME_PLUS_COL
- ),
- "SELECT DISTINCT mytable.myid FROM mytable",
+ select(table1.c.myid)
+ .distinct()
+ .set_label_style(LABEL_STYLE_TABLENAME_PLUS_COL),
+ "SELECT DISTINCT mytable.myid AS mytable_myid FROM mytable",
)
+ @testing.emits_warning("Column-expression-level unary distinct")
+ def test_distinct_function_6008(self):
# the bug fixed here as part of #6008 is the same bug that's
# in 1.3 as well, producing
# "SELECT anon_2.anon_1 FROM (SELECT distinct mytable.myid
)
self.assert_compile(
- select(table1.c.myid).distinct(),
- "SELECT DISTINCT mytable.myid FROM mytable",
+ select(select(table1.c.myid.distinct()).subquery()),
+ "SELECT anon_2.anon_1 FROM (SELECT "
+ "DISTINCT mytable.myid AS anon_1 FROM mytable) AS anon_2",
+ )
+
+ def test_distinct_function(self):
+ self.assert_compile(
+ select(func.sum(distinct(table1.c.myid))),
+ "SELECT sum(DISTINCT mytable.myid) AS sum_1 FROM mytable",
)
self.assert_compile(
"SELECT count(DISTINCT mytable.myid) AS count_1 FROM mytable",
)
+ def test_distinct_function_warn_outside_aggregate(self):
+ with testing.expect_warnings(
+ "Column-expression-level unary distinct.*SELECT DISTINCT"
+ ):
+ self.assert_compile(
+ select(distinct(table1.c.myid)),
+ "SELECT DISTINCT mytable.myid FROM mytable",
+ )
+
+ with testing.expect_warnings(
+ "Column-expression-level unary distinct.*SELECT DISTINCT"
+ ):
+ self.assert_compile(
+ select(table1.c.myid.distinct()),
+ "SELECT DISTINCT mytable.myid FROM mytable",
+ )
+
def test_distinct_on(self):
with testing.expect_deprecated(
"Passing expression to",
argnames="py_op, sql_op",
)
@testing.variation("named", ["column", "unnamed", "label"])
+ @testing.emits_warning("Column-expression-level unary distinct")
def test_wraps_named_column_heuristic(self, py_op, sql_op, named):
"""test for #12681"""
select(expr),
f"SELECT {sql_op}q",
)
-
elif named.unnamed:
expr = py_op(literal("x", Integer))
assert isinstance(expr, UnaryExpression)
not_in("user_name", r._mapping)
eq_(list(r._fields), ["users.user_id", "users.user_name"])
+ @testing.emits_warning("Column-expression-level unary distinct")
def test_column_accessor_unary(self, connection):
users = self.tables.users
def test_distinct(self, connection):
test_table = self.tables.test
+ s = select(test_table.c.avalue).distinct()
+ eq_(connection.execute(s).scalar(), 25)
- s = select(distinct(test_table.c.avalue))
+ s = select(func.sum(test_table.c.avalue.distinct()))
eq_(connection.execute(s).scalar(), 25)
- s = select(test_table.c.avalue.distinct())
+ s = select(func.sum(distinct(test_table.c.avalue)))
eq_(connection.execute(s).scalar(), 25)
assert distinct(test_table.c.data).type == test_table.c.data.type