]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- Added support for the SQL-standard function :class:`.array_agg`,
authorMike Bayer <mike_mp@zzzcomputing.com>
Wed, 26 Aug 2015 19:15:45 +0000 (15:15 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Wed, 26 Aug 2015 19:15:55 +0000 (15:15 -0400)
which automatically returns an :class:`.Array` of the correct type
and supports index / slice operations.   As arrays are only
supported on Postgresql at the moment, only actually works on
Postgresql. fixes #3132

doc/build/changelog/changelog_11.rst
lib/sqlalchemy/sql/functions.py
test/dialect/postgresql/test_types.py
test/sql/test_functions.py

index 2c14731aa582213b20620a3deec965d0401f9c27..0a6543575242db009bcb5c6c406b2bef411a5045 100644 (file)
 .. changelog::
     :version: 1.1.0b1
 
+    .. change::
+        :tags: feature, sql, postgresql
+        :tickets: 3132
+
+        Added support for the SQL-standard function :class:`.array_agg`,
+        which automatically returns an :class:`.Array` of the correct type
+        and supports index / slice operations.   As arrays are only
+        supported on Postgresql at the moment, only actually works on
+        Postgresql.
+
     .. change::
         :tags: feature, sql
         :tickets: 3516
index 80ee31b0fd16aa21728a23195c59c98aa336af87..d536c300887295c2161b1390dcd962662adb47ea 100644 (file)
@@ -626,3 +626,25 @@ class sysdate(AnsiFunction):
 
 class user(AnsiFunction):
     type = sqltypes.String
+
+
+class array_agg(GenericFunction):
+    """support for the ARRAY_AGG function.
+
+    The ``func.array_agg(expr)`` construct returns an expression of
+    type :class:`.Array`.
+
+    e.g.
+
+        stmt = select([func.array_agg(table.c.values)[2:5]])
+
+    .. versionadded:: 1.1
+
+    """
+
+    def __init__(self, *args, **kwargs):
+        args = [_literal_as_binds(c) for c in args]
+        kwargs.setdefault('type_', sqltypes.Array(_type_from_args(args)))
+        kwargs['_parsed_args'] = args
+        GenericFunction.__init__(self, *args, **kwargs)
+
index 2d5c2aaa11fe98f1ca1362aa05824b1429245a53..da45c2f2afb31599f10bae0a652c5df54bb0dc8d 100644 (file)
@@ -916,6 +916,33 @@ class ArrayRoundTripTest(fixtures.TablesTest, AssertsExecutionResults):
         assert isinstance(tbl.c.intarr.type.item_type, Integer)
         assert isinstance(tbl.c.strarr.type.item_type, String)
 
+    @testing.provide_metadata
+    def test_array_agg(self):
+        values_table = Table('values', self.metadata, Column('value', Integer))
+        self.metadata.create_all(testing.db)
+        testing.db.execute(
+            values_table.insert(),
+            [{'value': i} for i in range(1, 10)]
+        )
+
+        stmt = select([func.array_agg(values_table.c.value)])
+        eq_(
+            testing.db.execute(stmt).scalar(),
+            list(range(1, 10))
+        )
+
+        stmt = select([func.array_agg(values_table.c.value)[3]])
+        eq_(
+            testing.db.execute(stmt).scalar(),
+            3
+        )
+
+        stmt = select([func.array_agg(values_table.c.value)[2:4]])
+        eq_(
+            testing.db.execute(stmt).scalar(),
+            [2, 3, 4]
+        )
+
     def test_array_index_slice_exprs(self):
         """test a variety of expressions that sometimes need parenthesizing"""
 
index ccc9b2dcdb2d6eba854c4df41365402410cf713e..f080046ff849ffed5f1851e2797008ce698c7976 100644 (file)
@@ -1,8 +1,8 @@
-from sqlalchemy.testing import eq_
+from sqlalchemy.testing import eq_, is_
 import datetime
 from sqlalchemy import func, select, Integer, literal, DateTime, Table, \
     Column, Sequence, MetaData, extract, Date, String, bindparam, \
-    literal_column
+    literal_column, Array
 from sqlalchemy.sql import table, column
 from sqlalchemy import sql, util
 from sqlalchemy.sql.compiler import BIND_TEMPLATES
@@ -489,6 +489,14 @@ class CompileTest(fixtures.TestBase, AssertsCompiledSQL):
             MissingType().compile
         )
 
+    def test_array_agg(self):
+        m = MetaData()
+        t = Table('t', m, Column('data', Integer))
+        expr = func.array_agg(t.c.data)
+        is_(expr.type._type_affinity, Array)
+        is_(expr.type.item_type._type_affinity, Integer)
+
+
 
 class ExecuteTest(fixtures.TestBase):