From: Mike Bayer Date: Thu, 20 Jan 2022 20:01:47 +0000 (-0500) Subject: restore empty list logic to ARRAY of ENUM parsing X-Git-Tag: rel_2_0_0b1~529 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=dda5c43cab88daad02bc871cf40bf4984e94a031;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git restore empty list logic to ARRAY of ENUM parsing Fixed regression where the change in :ticket:`7148` to repair ENUM handling in PostgreSQL broke the use case of an empty ARRAY of ENUM, preventing rows that contained an empty array from being handled correctly when fetching results. Fixes: #7590 Change-Id: I43a35ef25281a6e0a26b698efebef6ba12a63e8c --- diff --git a/doc/build/changelog/unreleased_14/7590.rst b/doc/build/changelog/unreleased_14/7590.rst new file mode 100644 index 0000000000..822adf6dd0 --- /dev/null +++ b/doc/build/changelog/unreleased_14/7590.rst @@ -0,0 +1,8 @@ +.. change:: + :tags: bug, postgresql, regression + :tickets: 7590 + + Fixed regression where the change in :ticket:`7148` to repair ENUM handling + in PostgreSQL broke the use case of an empty ARRAY of ENUM, preventing rows + that contained an empty array from being handled correctly when fetching + results. diff --git a/lib/sqlalchemy/dialects/postgresql/array.py b/lib/sqlalchemy/dialects/postgresql/array.py index abe17ea35e..74643c4d92 100644 --- a/lib/sqlalchemy/dialects/postgresql/array.py +++ b/lib/sqlalchemy/dialects/postgresql/array.py @@ -385,9 +385,10 @@ class ARRAY(sqltypes.ARRAY): def _split_enum_values(array_string): + if '"' not in array_string: # no escape char is present so it can just split on the comma - return array_string.split(",") + return array_string.split(",") if array_string else [] # handles quoted strings from: # r'abc,"quoted","also\\\\quoted", "quoted, comma", "esc \" quot", qpr' diff --git a/test/dialect/postgresql/test_types.py b/test/dialect/postgresql/test_types.py index 991b0ed9d4..0c00c76333 100644 --- a/test/dialect/postgresql/test_types.py +++ b/test/dialect/postgresql/test_types.py @@ -1911,7 +1911,7 @@ class ArrayRoundTripTest: t.drop(connection) eq_(inspect(connection).get_enums(), []) - def _type_combinations(exclude_json=False): + def _type_combinations(exclude_json=False, exclude_empty_lists=False): def str_values(x): return ["one", "two: %s" % x, "three", "four", "five"] @@ -1945,6 +1945,9 @@ class ArrayRoundTripTest: AnEnum.Foo, ] + def empty_list(x): + return [] + class inet_str(str): def __eq__(self, other): return str(self) == str(other) @@ -2078,6 +2081,15 @@ class ArrayRoundTripTest: ), ] + if not exclude_empty_lists: + elements.extend( + [ + (postgresql.ENUM(AnEnum), empty_list), + (sqltypes.Enum(AnEnum, native_enum=True), empty_list), + (sqltypes.Enum(AnEnum, native_enum=False), empty_list), + (postgresql.ENUM(AnEnum, native_enum=True), empty_list), + ] + ) if not exclude_json: elements.extend( [ @@ -2166,7 +2178,7 @@ class ArrayRoundTripTest: connection.scalar(select(table.c.bar).where(table.c.id == 2)), ) - @_type_combinations() + @_type_combinations(exclude_empty_lists=True) def test_type_specific_slice_update( self, type_specific_fixture, connection, type_, gen ): @@ -2193,7 +2205,7 @@ class ArrayRoundTripTest: eq_(rows, [(gen(1),), (sliced_gen,)]) - @_type_combinations(exclude_json=True) + @_type_combinations(exclude_json=True, exclude_empty_lists=True) def test_type_specific_value_delete( self, type_specific_fixture, connection, type_, gen ):