]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
zero_indexes-param-for-postgresql-ARRAY-type
authorAlexey Terentev <alexey@terentyev.su>
Tue, 13 May 2014 09:10:39 +0000 (13:10 +0400)
committerAlexey Terentev <alexey@terentyev.su>
Tue, 13 May 2014 11:48:29 +0000 (15:48 +0400)
lib/sqlalchemy/dialects/postgresql/base.py
test/dialect/postgresql/test_compiler.py

index f69a6e01085f7824c63b39c1c4167719a6702aa2..50918c31e3a724e3caf1d50fa35f5b7239b6280d 100644 (file)
@@ -702,11 +702,20 @@ class ARRAY(sqltypes.Concatenable, sqltypes.TypeEngine):
         """Define comparison operations for :class:`.ARRAY`."""
 
         def __getitem__(self, index):
+            shift_indexes = 1 if self.expr.type.zero_indexes else 0
             if isinstance(index, slice):
+                if shift_indexes:
+                    index = slice(
+                        index.start + shift_indexes,
+                        index.stop + shift_indexes,
+                        index.step
+                    )
                 index = _Slice(index, self)
                 return_type = self.type
             else:
+                index += shift_indexes
                 return_type = self.type.item_type
+
             return self._binary_operate(self.expr, operators.getitem, index,
                             result_type=return_type)
 
@@ -797,7 +806,8 @@ class ARRAY(sqltypes.Concatenable, sqltypes.TypeEngine):
 
     comparator_factory = Comparator
 
-    def __init__(self, item_type, as_tuple=False, dimensions=None):
+    def __init__(self, item_type, as_tuple=False, dimensions=None,
+                 zero_indexes=False):
         """Construct an ARRAY.
 
         E.g.::
@@ -824,6 +834,10 @@ class ARRAY(sqltypes.Concatenable, sqltypes.TypeEngine):
          meaning they can store any number of dimensions no matter how
          they were declared.
 
+         :param zero_indexes=False: True allow to work with field like with
+          python's list - use indexes starts with zero, but not starts with
+          1 like in ARRAY
+
         """
         if isinstance(item_type, ARRAY):
             raise ValueError("Do not nest ARRAY types; ARRAY(basetype) "
@@ -833,6 +847,7 @@ class ARRAY(sqltypes.Concatenable, sqltypes.TypeEngine):
         self.item_type = item_type
         self.as_tuple = as_tuple
         self.dimensions = dimensions
+        self.zero_indexes = zero_indexes
 
     @property
     def python_type(self):
index db6efa34ab37aed0a7381abfaadbf523001ba963..35f7b1199af19b3cc80753fee3c6d988e0d2f074 100644 (file)
@@ -428,6 +428,59 @@ class CompileTest(fixtures.TestBase, AssertsCompiledSQL):
             checkparams={'param_1': 7}
         )
 
+    def test_array_shift_indexes(self):
+        c = Column('x', postgresql.ARRAY(Integer, zero_indexes=True))
+
+        self.assert_compile(
+            cast(c, postgresql.ARRAY(Integer, zero_indexes=True)),
+            "CAST(x AS INTEGER[])"
+        )
+        self.assert_compile(
+            c[5],
+            "x[%(x_1)s]",
+            checkparams={'x_1': 6}
+        )
+
+        self.assert_compile(
+            c[5:7],
+            "x[%(x_1)s:%(x_2)s]",
+            checkparams={'x_2': 8, 'x_1': 6}
+        )
+        self.assert_compile(
+            c[5:7][2:3],
+            "x[%(x_1)s:%(x_2)s][%(param_1)s:%(param_2)s]",
+            checkparams={'x_2': 8, 'x_1': 6, 'param_1': 3, 'param_2': 4}
+        )
+        self.assert_compile(
+            c[5:7][3],
+            "x[%(x_1)s:%(x_2)s][%(param_1)s]",
+            checkparams={'x_2': 8, 'x_1': 6, 'param_1': 4}
+        )
+
+        c = Column('x', postgresql.ARRAY(Integer, zero_indexes=False))
+
+        self.assert_compile(
+            c[5],
+            "x[%(x_1)s]",
+            checkparams={'x_1': 5}
+        )
+
+        self.assert_compile(
+            c[5:7],
+            "x[%(x_1)s:%(x_2)s]",
+            checkparams={'x_2': 7, 'x_1': 5}
+        )
+        self.assert_compile(
+            c[5:7][2:3],
+            "x[%(x_1)s:%(x_2)s][%(param_1)s:%(param_2)s]",
+            checkparams={'x_2': 7, 'x_1': 5, 'param_1': 2, 'param_2': 3}
+        )
+        self.assert_compile(
+            c[5:7][3],
+            "x[%(x_1)s:%(x_2)s][%(param_1)s]",
+            checkparams={'x_2': 7, 'x_1': 5, 'param_1': 3}
+        )
+
     def test_array_literal_type(self):
         is_(postgresql.array([1, 2]).type._type_affinity, postgresql.ARRAY)
         is_(postgresql.array([1, 2]).type.item_type._type_affinity, Integer)