summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/dialects/postgresql/base.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/sqlalchemy/dialects/postgresql/base.py')
-rw-r--r--lib/sqlalchemy/dialects/postgresql/base.py136
1 files changed, 47 insertions, 89 deletions
diff --git a/lib/sqlalchemy/dialects/postgresql/base.py b/lib/sqlalchemy/dialects/postgresql/base.py
index b16a82e04..855b77fb6 100644
--- a/lib/sqlalchemy/dialects/postgresql/base.py
+++ b/lib/sqlalchemy/dialects/postgresql/base.py
@@ -1356,6 +1356,7 @@ class PGDDLCompiler(compiler.DDLCompiler):
class PGTypeCompiler(compiler.GenericTypeCompiler):
+
def visit_TSVECTOR(self, type, **kw):
return "TSVECTOR"
@@ -2329,110 +2330,64 @@ class PGDialect(default.DefaultDialect):
table_oid = self.get_table_oid(connection, table_name, schema,
info_cache=kw.get('info_cache'))
- # cast indkey as varchar since it's an int2vector,
- # returned as a list by some drivers such as pypostgresql
-
- if self.server_version_info < (8, 5):
- IDX_SQL = """
- SELECT
- i.relname as relname,
- ix.indisunique, ix.indexprs, ix.indpred,
- a.attname, a.attnum, NULL, ix.indkey%s,
- %s, am.amname
- FROM
- pg_class t
- join pg_index ix on t.oid = ix.indrelid
- join pg_class i on i.oid = ix.indexrelid
- left outer join
- pg_attribute a
- on t.oid = a.attrelid and %s
- left outer join
- pg_am am
- on i.relam = am.oid
- WHERE
- t.relkind IN ('r', 'v', 'f', 'm')
- and t.oid = :table_oid
- and ix.indisprimary = 'f'
- ORDER BY
- t.relname,
- i.relname
- """ % (
- # version 8.3 here was based on observing the
- # cast does not work in PG 8.2.4, does work in 8.3.0.
- # nothing in PG changelogs regarding this.
- "::varchar" if self.server_version_info >= (8, 3) else "",
- "i.reloptions" if self.server_version_info >= (8, 2)
- else "NULL",
- self._pg_index_any("a.attnum", "ix.indkey")
- )
- else:
- IDX_SQL = """
- SELECT
- i.relname as relname,
- ix.indisunique, ix.indexprs, ix.indpred,
- a.attname, a.attnum, c.conrelid, ix.indkey::varchar,
- i.reloptions, am.amname
- FROM
- pg_class t
- join pg_index ix on t.oid = ix.indrelid
- join pg_class i on i.oid = ix.indexrelid
- left outer join
- pg_attribute a
- on t.oid = a.attrelid and a.attnum = ANY(ix.indkey)
- left outer join
- pg_constraint c
- on (ix.indrelid = c.conrelid and
- ix.indexrelid = c.conindid and
- c.contype in ('p', 'u', 'x'))
- left outer join
- pg_am am
- on i.relam = am.oid
- WHERE
- t.relkind IN ('r', 'v', 'f', 'm')
- and t.oid = :table_oid
- and ix.indisprimary = 'f'
- ORDER BY
- t.relname,
- i.relname
- """
+ IDX_SQL = """
+ SELECT
+ i.relname as relname,
+ ix.indisunique,
+ pg_get_indexdef(i.oid, s.i + 1, false),
+ s.i,
+ pg_get_expr(ix.indpred, ix.indrelid),
+ c.conrelid,
+ %s,
+ am.amname
+ FROM
+ pg_class t
+ join pg_index ix on t.oid = ix.indrelid
+ join pg_class i on i.oid = ix.indexrelid
+ join generate_series(0, current_setting('max_index_keys')::int - 1) s(i)
+ on ix.indkey[s.i] is NOT NULL
+ left outer join
+ pg_constraint c
+ on (ix.indrelid = c.conrelid and
+ ix.indexrelid = c.conindid and
+ c.contype in ('p', 'u', 'x'))
+ left outer join
+ pg_am am
+ on i.relam = am.oid
+ WHERE
+ t.relkind IN ('r', 'v', 'f', 'm')
+ and t.oid = :table_oid
+ and ix.indisprimary = 'f'
+ ORDER BY
+ t.relname,
+ i.relname,
+ s.i
+ """ % (
+ "i.reloptions" if self.server_version_info >= (8, 2) else "NULL"
+ )
t = sql.text(IDX_SQL, typemap={'attname': sqltypes.Unicode})
c = connection.execute(t, table_oid=table_oid)
- indexes = defaultdict(lambda: defaultdict(dict))
+ indexes = defaultdict(lambda: defaultdict(list))
sv_idx_name = None
for row in c.fetchall():
- (idx_name, unique, expr, prd, col,
- col_num, conrelid, idx_key, options, amname) = row
-
- if expr:
- if idx_name != sv_idx_name:
- util.warn(
- "Skipped unsupported reflection of "
- "expression-based index %s"
- % idx_name)
- sv_idx_name = idx_name
- continue
-
- if prd and not idx_name == sv_idx_name:
- util.warn(
- "Predicate of partial index %s ignored during reflection"
- % idx_name)
- sv_idx_name = idx_name
+ (idx_name, unique, col, col_num, prd, conrelid, options, amname) = row
has_idx = idx_name in indexes
index = indexes[idx_name]
if col is not None:
- index['cols'][col_num] = col
+ index['cols'].append(col.strip('"'))
if not has_idx:
- index['key'] = [int(k.strip()) for k in idx_key.split()]
index['unique'] = unique
if conrelid is not None:
index['duplicates_constraint'] = idx_name
if options:
index['options'] = dict(
[option.split("=") for option in options])
+ if prd:
+ index['where'] = prd
# it *might* be nice to include that this is 'btree' in the
# reflection info. But we don't want an Index object
@@ -2446,16 +2401,19 @@ class PGDialect(default.DefaultDialect):
entry = {
'name': name,
'unique': idx['unique'],
- 'column_names': [idx['cols'][i] for i in idx['key']]
+ 'column_names': idx['cols']
}
if 'duplicates_constraint' in idx:
entry['duplicates_constraint'] = idx['duplicates_constraint']
if 'options' in idx:
entry.setdefault(
- 'dialect_options', {})["postgresql_with"] = idx['options']
+ 'dialect_options', {})['postgresql_with'] = idx['options']
if 'amname' in idx:
entry.setdefault(
- 'dialect_options', {})["postgresql_using"] = idx['amname']
+ 'dialect_options', {})['postgresql_using'] = idx['amname']
+ if 'where' in idx:
+ entry.setdefault(
+ 'dialect_options', {})['postgresql_where'] = idx['where']
result.append(entry)
return result