From: Alexey Terentev Date: Tue, 13 May 2014 09:10:39 +0000 (+0400) Subject: zero_indexes-param-for-postgresql-ARRAY-type X-Git-Tag: rel_0_9_5~52^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=57b6da9d402f164605c7bfe270654725cb604f1f;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git zero_indexes-param-for-postgresql-ARRAY-type --- diff --git a/lib/sqlalchemy/dialects/postgresql/base.py b/lib/sqlalchemy/dialects/postgresql/base.py index f69a6e0108..50918c31e3 100644 --- a/lib/sqlalchemy/dialects/postgresql/base.py +++ b/lib/sqlalchemy/dialects/postgresql/base.py @@ -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): diff --git a/test/dialect/postgresql/test_compiler.py b/test/dialect/postgresql/test_compiler.py index db6efa34ab..35f7b1199a 100644 --- a/test/dialect/postgresql/test_compiler.py +++ b/test/dialect/postgresql/test_compiler.py @@ -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)