summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/util
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2018-12-21 11:04:14 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2018-12-21 13:53:16 -0500
commit0b0a4c8ba2465fce5fa1954a0d31b44840f1b4b8 (patch)
tree0ef7a440172532f626b613632626c2c78784f0db /lib/sqlalchemy/util
parentb5592de30ecc986c1862261513ab99f43de885b4 (diff)
downloadsqlalchemy-0b0a4c8ba2465fce5fa1954a0d31b44840f1b4b8.tar.gz
Handle PostgreSQL enums in remote schemas
Fixed issue where a :class:`.postgresql.ENUM` or a custom domain present in a remote schema would not be recognized within column reflection if the name of the enum/domain or the name of the schema required quoting. A new parsing scheme now fully parses out quoted or non-quoted tokens including support for SQL-escaped quotes. Fixed issue where multiple :class:`.postgresql.ENUM` objects referred to by the same :class:`.MetaData` object would fail to be created if multiple objects had the same name under different schema names. The internal memoization the Postgresql dialect uses to track if it has created a particular :class:`.postgresql.ENUM` in the database during a DDL creation sequence now takes schema name into account. Fixes: #4416 Change-Id: I8cf03069e10b12f409e9b6796e24fc5850979955
Diffstat (limited to 'lib/sqlalchemy/util')
-rw-r--r--lib/sqlalchemy/util/__init__.py2
-rw-r--r--lib/sqlalchemy/util/langhelpers.py45
2 files changed, 46 insertions, 1 deletions
diff --git a/lib/sqlalchemy/util/__init__.py b/lib/sqlalchemy/util/__init__.py
index 031376d78..9229d0797 100644
--- a/lib/sqlalchemy/util/__init__.py
+++ b/lib/sqlalchemy/util/__init__.py
@@ -34,7 +34,7 @@ from .langhelpers import iterate_attributes, class_hierarchy, \
classproperty, set_creation_order, warn_exception, warn, NoneType,\
constructor_copy, methods_equivalent, chop_traceback, asint,\
generic_repr, counter, PluginLoader, hybridproperty, hybridmethod, \
- safe_reraise,\
+ safe_reraise, quoted_token_parser,\
get_callable_argspec, only_once, attrsetter, ellipses_string, \
warn_limited, map_bits, MemoizedSlots, EnsureKWArgType, wrap_callable
diff --git a/lib/sqlalchemy/util/langhelpers.py b/lib/sqlalchemy/util/langhelpers.py
index 8815ed837..6a1db7a98 100644
--- a/lib/sqlalchemy/util/langhelpers.py
+++ b/lib/sqlalchemy/util/langhelpers.py
@@ -1422,3 +1422,48 @@ def wrap_callable(wrapper, fn):
_f.__doc__ = fn.__doc__
return _f
+
+
+def quoted_token_parser(value):
+ """Parse a dotted identifier with accomodation for quoted names.
+
+ Includes support for SQL-style double quotes as a literal character.
+
+ E.g.::
+
+ >>> quoted_token_parser("name")
+ ["name"]
+ >>> quoted_token_parser("schema.name")
+ ["schema", "name"]
+ >>> quoted_token_parser('"Schema"."Name"')
+ ['Schema', 'Name']
+ >>> quoted_token_parser('"Schema"."Name""Foo"')
+ ['Schema', 'Name""Foo']
+
+ """
+
+ if '"' not in value:
+ return value.split(".")
+
+ # 0 = outside of quotes
+ # 1 = inside of quotes
+ state = 0
+ result = [[]]
+ idx = 0
+ lv = len(value)
+ while idx < lv:
+ char = value[idx]
+ if char == '"':
+ if state == 1 and idx < lv - 1 and value[idx + 1] == '"':
+ result[-1].append('"')
+ idx += 1
+ else:
+ state ^= 1
+ elif char == "." and state == 0:
+ result.append([])
+ else:
+ result[-1].append(char)
+ idx += 1
+
+ return ["".join(token) for token in result]
+