20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
|
# File 'lib/schema_plus_pg_indexes/middleware/postgresql/schema.rb', line 20
def implement(env)
result = env.connection.query(" SELECT distinct i.relname, d.indisunique, d.indkey, pg_get_indexdef(d.indexrelid), t.oid,\n m.amname, pg_get_expr(d.indpred, t.oid) as conditions, pg_get_expr(d.indexprs, t.oid) as expression,\n d.indclass\n FROM pg_class t\n INNER JOIN pg_index d ON t.oid = d.indrelid\n INNER JOIN pg_class i ON d.indexrelid = i.oid\n INNER JOIN pg_am m ON i.relam = m.oid\n WHERE i.relkind = 'i'\n AND d.indisprimary = 'f'\n AND t.relname = '\#{table_name_without_namespace(env.table_name)}'\n AND i.relnamespace IN (SELECT oid FROM pg_namespace WHERE nspname = \#{namespace_sql(env.table_name)} )\n ORDER BY i.relname\n SQL\n\n env.index_definitions += result.map do |(index_name, unique, indkey, inddef, oid, using, conditions, expression, indclass)|\n index_keys = indkey.split(\" \")\n opclasses = indclass.split(\" \")\n\n rows = env.connection.query(<<-SQL, 'SCHEMA')\n SELECT CAST(a.attnum as VARCHAR), a.attname, t.typname\n FROM pg_attribute a\n INNER JOIN pg_type t ON a.atttypid = t.oid\n WHERE a.attrelid = \#{oid}\n SQL\n columns = {}\n types = {}\n rows.each do |num, name, type|\n columns[num] = name\n types[name] = type\n end\n\n column_names = columns.values_at(*index_keys).compact\n case_sensitive = true\n\n # extract column names from the expression, for a\n # case-insensitive index.\n # only applies to character, character varying, and text\n if expression\n rexp_lower = %r{\\blower\\(\\(?([^)]+)(\\)::text)?\\)}\n if expression.match /\\A\#{rexp_lower}(?:, \#{rexp_lower})*\\z/i\n case_insensitive_columns = expression.scan(rexp_lower).map(&:first).select{|column| %W[char varchar text].include? types[column]}\n if case_insensitive_columns.any?\n case_sensitive = false\n column_names = index_keys.map { |index_key|\n index_key == '0' ? case_insensitive_columns.shift : columns[index_key]\n }.compact | column_names\n end\n end\n end\n\n get_opclass_names(env, opclasses)\n operator_classes = Hash[\n index_keys.zip(opclasses).map { |index_key, opclass| [columns[index_key], @opclass_names[opclass]] }\n ]\n operator_classes.delete_if{|k,v| v.nil?}\n\n # add info on sort order for columns (only desc order is explicitly specified, asc is the default)\n desc_order_columns = inddef.scan(/(\\w+) DESC/).flatten\n orders = desc_order_columns.any? ? Hash[column_names.map {|column| [column, desc_order_columns.include?(column) ? :desc : :asc]}] : {}\n\n ::ActiveRecord::ConnectionAdapters::IndexDefinition.new(env.table_name, column_names,\n :name => index_name,\n :unique => (unique == 't'),\n :orders => orders,\n :where => conditions,\n :case_sensitive => case_sensitive,\n :using => using.downcase == \"btree\" ? nil : using.to_sym,\n :operator_classes => operator_classes,\n :expression => expression)\n end\nend\n", 'SCHEMA')
|