diff options
Diffstat (limited to 'lib/sqlalchemy/dialects')
-rw-r--r-- | lib/sqlalchemy/dialects/mysql/base.py | 15 | ||||
-rw-r--r-- | lib/sqlalchemy/dialects/postgresql/base.py | 30 | ||||
-rw-r--r-- | lib/sqlalchemy/dialects/sqlite/base.py | 20 |
3 files changed, 65 insertions, 0 deletions
diff --git a/lib/sqlalchemy/dialects/mysql/base.py b/lib/sqlalchemy/dialects/mysql/base.py index 9d856e271..2642b5fdc 100644 --- a/lib/sqlalchemy/dialects/mysql/base.py +++ b/lib/sqlalchemy/dialects/mysql/base.py @@ -2212,6 +2212,21 @@ class MySQLDialect(default.DefaultDialect): return indexes @reflection.cache + def get_unique_constraints(self, connection, table_name, + schema=None, **kw): + parsed_state = self._parsed_state_or_create( + connection, table_name, schema, **kw) + + return [ + { + 'name': key['name'], + 'column_names': [col[0] for col in key['columns']] + } + for key in parsed_state.keys + if key['type'] == 'UNIQUE' + ] + + @reflection.cache def get_view_definition(self, connection, view_name, schema=None, **kw): charset = self._connection_charset diff --git a/lib/sqlalchemy/dialects/postgresql/base.py b/lib/sqlalchemy/dialects/postgresql/base.py index 00d0acc2c..0810e0384 100644 --- a/lib/sqlalchemy/dialects/postgresql/base.py +++ b/lib/sqlalchemy/dialects/postgresql/base.py @@ -1950,6 +1950,36 @@ class PGDialect(default.DefaultDialect): index_d['unique'] = unique return indexes + @reflection.cache + def get_unique_constraints(self, connection, table_name, + schema=None, **kw): + table_oid = self.get_table_oid(connection, table_name, schema, + info_cache=kw.get('info_cache')) + + UNIQUE_SQL = """ + SELECT + cons.conname as name, + ARRAY_AGG(a.attname) as column_names + FROM + pg_catalog.pg_constraint cons + left outer join pg_attribute a + on cons.conrelid = a.attrelid and a.attnum = ANY(cons.conkey) + WHERE + cons.conrelid = :table_oid AND + cons.contype = 'u' + GROUP BY + cons.conname + """ + + t = sql.text(UNIQUE_SQL, + typemap={'column_names': ARRAY(sqltypes.Unicode)}) + c = connection.execute(t, table_oid=table_oid) + + return [ + {'name': row.name, 'column_names': row.column_names} + for row in c.fetchall() + ] + def _load_enums(self, connection): if not self.supports_native_enum: return {} diff --git a/lib/sqlalchemy/dialects/sqlite/base.py b/lib/sqlalchemy/dialects/sqlite/base.py index c7e09b164..3e2a158a0 100644 --- a/lib/sqlalchemy/dialects/sqlite/base.py +++ b/lib/sqlalchemy/dialects/sqlite/base.py @@ -917,6 +917,26 @@ class SQLiteDialect(default.DefaultDialect): cols.append(row[2]) return indexes + @reflection.cache + def get_unique_constraints(self, connection, table_name, + schema=None, **kw): + UNIQUE_SQL = """ + SELECT sql + FROM + sqlite_master + WHERE + type='table' AND + name=:table_name + """ + c = connection.execute(UNIQUE_SQL, table_name=table_name) + table_data = c.fetchone()[0] + + UNIQUE_PATTERN = 'CONSTRAINT (\w+) UNIQUE \(([^\)]+)\)' + return [ + {'name': name, 'column_names': [c.strip() for c in cols.split(',')]} + for name, cols in re.findall(UNIQUE_PATTERN, table_data) + ] + def _pragma_cursor(cursor): """work around SQLite issue whereby cursor.description |