activerecord-jdbc-adapter-onsite 1.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (228) hide show
  1. data/.gitignore +22 -0
  2. data/.travis.yml +14 -0
  3. data/Appraisals +16 -0
  4. data/Gemfile +11 -0
  5. data/Gemfile.lock +45 -0
  6. data/History.txt +488 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.rdoc +214 -0
  9. data/Rakefile +62 -0
  10. data/activerecord-jdbc-adapter.gemspec +23 -0
  11. data/bench/bench_attributes.rb +13 -0
  12. data/bench/bench_attributes_new.rb +14 -0
  13. data/bench/bench_create.rb +12 -0
  14. data/bench/bench_find_all.rb +12 -0
  15. data/bench/bench_find_all_mt.rb +25 -0
  16. data/bench/bench_model.rb +85 -0
  17. data/bench/bench_new.rb +12 -0
  18. data/bench/bench_new_valid.rb +12 -0
  19. data/bench/bench_valid.rb +13 -0
  20. data/gemfiles/rails23.gemfile +10 -0
  21. data/gemfiles/rails23.gemfile.lock +38 -0
  22. data/gemfiles/rails30.gemfile +9 -0
  23. data/gemfiles/rails30.gemfile.lock +33 -0
  24. data/gemfiles/rails31.gemfile +9 -0
  25. data/gemfiles/rails31.gemfile.lock +35 -0
  26. data/gemfiles/rails32.gemfile +9 -0
  27. data/gemfiles/rails32.gemfile.lock +35 -0
  28. data/lib/active_record/connection_adapters/derby_adapter.rb +1 -0
  29. data/lib/active_record/connection_adapters/h2_adapter.rb +1 -0
  30. data/lib/active_record/connection_adapters/hsqldb_adapter.rb +1 -0
  31. data/lib/active_record/connection_adapters/informix_adapter.rb +1 -0
  32. data/lib/active_record/connection_adapters/jdbc_adapter.rb +1 -0
  33. data/lib/active_record/connection_adapters/jndi_adapter.rb +1 -0
  34. data/lib/active_record/connection_adapters/mssql_adapter.rb +1 -0
  35. data/lib/active_record/connection_adapters/mysql2_adapter.rb +1 -0
  36. data/lib/active_record/connection_adapters/mysql_adapter.rb +1 -0
  37. data/lib/active_record/connection_adapters/oracle_adapter.rb +1 -0
  38. data/lib/active_record/connection_adapters/postgresql_adapter.rb +1 -0
  39. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +1 -0
  40. data/lib/activerecord-jdbc-adapter.rb +8 -0
  41. data/lib/arel/engines/sql/compilers/db2_compiler.rb +9 -0
  42. data/lib/arel/engines/sql/compilers/derby_compiler.rb +6 -0
  43. data/lib/arel/engines/sql/compilers/h2_compiler.rb +6 -0
  44. data/lib/arel/engines/sql/compilers/hsqldb_compiler.rb +15 -0
  45. data/lib/arel/engines/sql/compilers/jdbc_compiler.rb +6 -0
  46. data/lib/arel/engines/sql/compilers/mssql_compiler.rb +46 -0
  47. data/lib/arel/visitors/compat.rb +13 -0
  48. data/lib/arel/visitors/db2.rb +17 -0
  49. data/lib/arel/visitors/derby.rb +32 -0
  50. data/lib/arel/visitors/firebird.rb +24 -0
  51. data/lib/arel/visitors/hsqldb.rb +26 -0
  52. data/lib/arel/visitors/sql_server.rb +46 -0
  53. data/lib/arjdbc.rb +24 -0
  54. data/lib/arjdbc/db2.rb +2 -0
  55. data/lib/arjdbc/db2/adapter.rb +541 -0
  56. data/lib/arjdbc/derby.rb +7 -0
  57. data/lib/arjdbc/derby/adapter.rb +358 -0
  58. data/lib/arjdbc/derby/connection_methods.rb +19 -0
  59. data/lib/arjdbc/discover.rb +92 -0
  60. data/lib/arjdbc/firebird.rb +2 -0
  61. data/lib/arjdbc/firebird/adapter.rb +140 -0
  62. data/lib/arjdbc/h2.rb +4 -0
  63. data/lib/arjdbc/h2/adapter.rb +54 -0
  64. data/lib/arjdbc/h2/connection_methods.rb +13 -0
  65. data/lib/arjdbc/hsqldb.rb +4 -0
  66. data/lib/arjdbc/hsqldb/adapter.rb +184 -0
  67. data/lib/arjdbc/hsqldb/connection_methods.rb +15 -0
  68. data/lib/arjdbc/informix.rb +3 -0
  69. data/lib/arjdbc/informix/adapter.rb +142 -0
  70. data/lib/arjdbc/informix/connection_methods.rb +11 -0
  71. data/lib/arjdbc/jdbc.rb +2 -0
  72. data/lib/arjdbc/jdbc/adapter.rb +356 -0
  73. data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
  74. data/lib/arjdbc/jdbc/base_ext.rb +15 -0
  75. data/lib/arjdbc/jdbc/callbacks.rb +44 -0
  76. data/lib/arjdbc/jdbc/column.rb +47 -0
  77. data/lib/arjdbc/jdbc/compatibility.rb +51 -0
  78. data/lib/arjdbc/jdbc/connection.rb +134 -0
  79. data/lib/arjdbc/jdbc/connection_methods.rb +16 -0
  80. data/lib/arjdbc/jdbc/core_ext.rb +24 -0
  81. data/lib/arjdbc/jdbc/discover.rb +18 -0
  82. data/lib/arjdbc/jdbc/driver.rb +35 -0
  83. data/lib/arjdbc/jdbc/extension.rb +47 -0
  84. data/lib/arjdbc/jdbc/java.rb +14 -0
  85. data/lib/arjdbc/jdbc/jdbc.rake +131 -0
  86. data/lib/arjdbc/jdbc/missing_functionality_helper.rb +88 -0
  87. data/lib/arjdbc/jdbc/quoted_primary_key.rb +28 -0
  88. data/lib/arjdbc/jdbc/railtie.rb +9 -0
  89. data/lib/arjdbc/jdbc/rake_tasks.rb +10 -0
  90. data/lib/arjdbc/jdbc/require_driver.rb +16 -0
  91. data/lib/arjdbc/jdbc/type_converter.rb +126 -0
  92. data/lib/arjdbc/mimer.rb +2 -0
  93. data/lib/arjdbc/mimer/adapter.rb +142 -0
  94. data/lib/arjdbc/mssql.rb +4 -0
  95. data/lib/arjdbc/mssql/adapter.rb +477 -0
  96. data/lib/arjdbc/mssql/connection_methods.rb +31 -0
  97. data/lib/arjdbc/mssql/limit_helpers.rb +101 -0
  98. data/lib/arjdbc/mssql/lock_helpers.rb +72 -0
  99. data/lib/arjdbc/mssql/tsql_helper.rb +61 -0
  100. data/lib/arjdbc/mysql.rb +4 -0
  101. data/lib/arjdbc/mysql/adapter.rb +505 -0
  102. data/lib/arjdbc/mysql/connection_methods.rb +28 -0
  103. data/lib/arjdbc/oracle.rb +3 -0
  104. data/lib/arjdbc/oracle/adapter.rb +432 -0
  105. data/lib/arjdbc/oracle/connection_methods.rb +12 -0
  106. data/lib/arjdbc/postgresql.rb +4 -0
  107. data/lib/arjdbc/postgresql/adapter.rb +861 -0
  108. data/lib/arjdbc/postgresql/connection_methods.rb +23 -0
  109. data/lib/arjdbc/sqlite3.rb +4 -0
  110. data/lib/arjdbc/sqlite3/adapter.rb +389 -0
  111. data/lib/arjdbc/sqlite3/connection_methods.rb +35 -0
  112. data/lib/arjdbc/sybase.rb +2 -0
  113. data/lib/arjdbc/sybase/adapter.rb +46 -0
  114. data/lib/arjdbc/version.rb +8 -0
  115. data/lib/generators/jdbc/USAGE +10 -0
  116. data/lib/generators/jdbc/jdbc_generator.rb +9 -0
  117. data/lib/jdbc_adapter.rb +2 -0
  118. data/lib/jdbc_adapter/rake_tasks.rb +3 -0
  119. data/lib/jdbc_adapter/version.rb +3 -0
  120. data/lib/pg.rb +26 -0
  121. data/pom.xml +57 -0
  122. data/rails_generators/jdbc_generator.rb +15 -0
  123. data/rails_generators/templates/config/initializers/jdbc.rb +7 -0
  124. data/rails_generators/templates/lib/tasks/jdbc.rake +8 -0
  125. data/rakelib/bundler_ext.rb +11 -0
  126. data/rakelib/compile.rake +23 -0
  127. data/rakelib/db.rake +39 -0
  128. data/rakelib/rails.rake +41 -0
  129. data/src/java/arjdbc/db2/DB2RubyJdbcConnection.java +69 -0
  130. data/src/java/arjdbc/derby/DerbyModule.java +324 -0
  131. data/src/java/arjdbc/h2/H2RubyJdbcConnection.java +70 -0
  132. data/src/java/arjdbc/informix/InformixRubyJdbcConnection.java +74 -0
  133. data/src/java/arjdbc/jdbc/AdapterJavaService.java +68 -0
  134. data/src/java/arjdbc/jdbc/JdbcConnectionFactory.java +36 -0
  135. data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +1346 -0
  136. data/src/java/arjdbc/jdbc/SQLBlock.java +48 -0
  137. data/src/java/arjdbc/mssql/MssqlRubyJdbcConnection.java +127 -0
  138. data/src/java/arjdbc/mysql/MySQLModule.java +134 -0
  139. data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +161 -0
  140. data/src/java/arjdbc/oracle/OracleRubyJdbcConnection.java +85 -0
  141. data/src/java/arjdbc/postgresql/PostgresqlRubyJdbcConnection.java +82 -0
  142. data/src/java/arjdbc/sqlite3/Sqlite3RubyJdbcConnection.java +126 -0
  143. data/test/abstract_db_create.rb +135 -0
  144. data/test/activerecord/connection_adapters/type_conversion_test.rb +31 -0
  145. data/test/activerecord/connections/native_jdbc_mysql/connection.rb +25 -0
  146. data/test/activerecord/jall.sh +7 -0
  147. data/test/activerecord/jtest.sh +3 -0
  148. data/test/db/db2.rb +11 -0
  149. data/test/db/derby.rb +12 -0
  150. data/test/db/h2.rb +11 -0
  151. data/test/db/hsqldb.rb +13 -0
  152. data/test/db/informix.rb +11 -0
  153. data/test/db/jdbc.rb +12 -0
  154. data/test/db/jndi_config.rb +40 -0
  155. data/test/db/logger.rb +3 -0
  156. data/test/db/mssql.rb +9 -0
  157. data/test/db/mysql.rb +10 -0
  158. data/test/db/oracle.rb +34 -0
  159. data/test/db/postgres.rb +18 -0
  160. data/test/db/sqlite3.rb +11 -0
  161. data/test/db2_reset_column_information_test.rb +8 -0
  162. data/test/db2_simple_test.rb +66 -0
  163. data/test/derby_migration_test.rb +68 -0
  164. data/test/derby_multibyte_test.rb +12 -0
  165. data/test/derby_reset_column_information_test.rb +8 -0
  166. data/test/derby_row_locking_test.rb +9 -0
  167. data/test/derby_simple_test.rb +139 -0
  168. data/test/generic_jdbc_connection_test.rb +29 -0
  169. data/test/h2_change_column_test.rb +68 -0
  170. data/test/h2_simple_test.rb +41 -0
  171. data/test/has_many_through.rb +79 -0
  172. data/test/helper.rb +108 -0
  173. data/test/hsqldb_simple_test.rb +6 -0
  174. data/test/informix_simple_test.rb +48 -0
  175. data/test/jdbc_common.rb +28 -0
  176. data/test/jndi_callbacks_test.rb +36 -0
  177. data/test/jndi_test.rb +25 -0
  178. data/test/manualTestDatabase.rb +191 -0
  179. data/test/models/add_not_null_column_to_table.rb +9 -0
  180. data/test/models/auto_id.rb +15 -0
  181. data/test/models/custom_pk_name.rb +14 -0
  182. data/test/models/data_types.rb +30 -0
  183. data/test/models/entry.rb +40 -0
  184. data/test/models/mixed_case.rb +22 -0
  185. data/test/models/reserved_word.rb +15 -0
  186. data/test/models/string_id.rb +17 -0
  187. data/test/models/thing.rb +16 -0
  188. data/test/models/validates_uniqueness_of_string.rb +19 -0
  189. data/test/mssql_db_create_test.rb +26 -0
  190. data/test/mssql_identity_insert_test.rb +19 -0
  191. data/test/mssql_ignore_system_views_test.rb +27 -0
  192. data/test/mssql_legacy_types_test.rb +58 -0
  193. data/test/mssql_limit_offset_test.rb +136 -0
  194. data/test/mssql_multibyte_test.rb +18 -0
  195. data/test/mssql_null_test.rb +14 -0
  196. data/test/mssql_reset_column_information_test.rb +8 -0
  197. data/test/mssql_row_locking_sql_test.rb +159 -0
  198. data/test/mssql_row_locking_test.rb +9 -0
  199. data/test/mssql_simple_test.rb +55 -0
  200. data/test/mysql_db_create_test.rb +27 -0
  201. data/test/mysql_index_length_test.rb +58 -0
  202. data/test/mysql_info_test.rb +123 -0
  203. data/test/mysql_multibyte_test.rb +10 -0
  204. data/test/mysql_nonstandard_primary_key_test.rb +42 -0
  205. data/test/mysql_reset_column_information_test.rb +8 -0
  206. data/test/mysql_simple_test.rb +125 -0
  207. data/test/oracle_reset_column_information_test.rb +8 -0
  208. data/test/oracle_simple_test.rb +18 -0
  209. data/test/oracle_specific_test.rb +83 -0
  210. data/test/postgres_db_create_test.rb +32 -0
  211. data/test/postgres_drop_db_test.rb +16 -0
  212. data/test/postgres_information_schema_leak_test.rb +29 -0
  213. data/test/postgres_mixed_case_test.rb +29 -0
  214. data/test/postgres_native_type_mapping_test.rb +93 -0
  215. data/test/postgres_nonseq_pkey_test.rb +38 -0
  216. data/test/postgres_reserved_test.rb +22 -0
  217. data/test/postgres_reset_column_information_test.rb +8 -0
  218. data/test/postgres_schema_search_path_test.rb +48 -0
  219. data/test/postgres_simple_test.rb +168 -0
  220. data/test/postgres_table_alias_length_test.rb +15 -0
  221. data/test/postgres_type_conversion_test.rb +34 -0
  222. data/test/row_locking.rb +90 -0
  223. data/test/simple.rb +731 -0
  224. data/test/sqlite3_reset_column_information_test.rb +8 -0
  225. data/test/sqlite3_simple_test.rb +316 -0
  226. data/test/sybase_jtds_simple_test.rb +28 -0
  227. data/test/sybase_reset_column_information_test.rb +8 -0
  228. metadata +288 -0
@@ -0,0 +1,12 @@
1
+ class ActiveRecord::Base
2
+ class << self
3
+ def oracle_connection(config)
4
+ config[:port] ||= 1521
5
+ config[:url] ||= "jdbc:oracle:thin:@#{config[:host]}:#{config[:port]}:#{config[:database]}"
6
+ config[:driver] ||= "oracle.jdbc.driver.OracleDriver"
7
+ config[:adapter_spec] = ::ArJdbc::Oracle
8
+ jdbc_connection(config)
9
+ end
10
+ end
11
+ end
12
+
@@ -0,0 +1,4 @@
1
+ require 'arjdbc/jdbc'
2
+ jdbc_require_driver 'jdbc/postgres'
3
+ require 'arjdbc/postgresql/connection_methods'
4
+ require 'arjdbc/postgresql/adapter'
@@ -0,0 +1,861 @@
1
+ module ActiveRecord::ConnectionAdapters
2
+ PostgreSQLAdapter = Class.new(AbstractAdapter) unless const_defined?(:PostgreSQLAdapter)
3
+ end
4
+
5
+ module ::ArJdbc
6
+ module PostgreSQL
7
+ def self.extended(mod)
8
+ (class << mod; self; end).class_eval do
9
+ alias_chained_method :columns, :query_cache, :pg_columns
10
+ end
11
+ end
12
+
13
+ def self.column_selector
14
+ [/postgre/i, lambda {|cfg,col| col.extend(::ArJdbc::PostgreSQL::Column)}]
15
+ end
16
+
17
+ def self.jdbc_connection_class
18
+ ::ActiveRecord::ConnectionAdapters::PostgresJdbcConnection
19
+ end
20
+
21
+ # column behavior based on postgresql_adapter in rails project
22
+ # https://github.com/rails/rails/blob/3-1-stable/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb#L41
23
+ module Column
24
+ def self.included(base)
25
+ class << base
26
+ attr_accessor :money_precision
27
+ def string_to_time(string)
28
+ return string unless String === string
29
+
30
+ case string
31
+ when 'infinity' then 1.0 / 0.0
32
+ when '-infinity' then -1.0 / 0.0
33
+ else
34
+ super
35
+ end
36
+ end
37
+ end
38
+ end
39
+
40
+ private
41
+ # Extracts the value from a Postgresql column default definition
42
+ def default_value(default)
43
+ case default
44
+ # This is a performance optimization for Ruby 1.9.2 in development.
45
+ # If the value is nil, we return nil straight away without checking
46
+ # the regular expressions. If we check each regular expression,
47
+ # Regexp#=== will call NilClass#to_str, which will trigger
48
+ # method_missing (defined by whiny nil in ActiveSupport) which
49
+ # makes this method very very slow.
50
+ when NilClass
51
+ nil
52
+ # Numeric types
53
+ when /\A\(?(-?\d+(\.\d*)?\)?)\z/
54
+ $1
55
+ # Character types
56
+ when /\A'(.*)'::(?:character varying|bpchar|text)\z/m
57
+ $1
58
+ # Character types (8.1 formatting)
59
+ when /\AE'(.*)'::(?:character varying|bpchar|text)\z/m
60
+ $1.gsub(/\\(\d\d\d)/) { $1.oct.chr }
61
+ # Binary data types
62
+ when /\A'(.*)'::bytea\z/m
63
+ $1
64
+ # Date/time types
65
+ when /\A'(.+)'::(?:time(?:stamp)? with(?:out)? time zone|date)\z/
66
+ $1
67
+ when /\A'(.*)'::interval\z/
68
+ $1
69
+ # Boolean type
70
+ when 'true'
71
+ true
72
+ when 'false'
73
+ false
74
+ # Geometric types
75
+ when /\A'(.*)'::(?:point|line|lseg|box|"?path"?|polygon|circle)\z/
76
+ $1
77
+ # Network address types
78
+ when /\A'(.*)'::(?:cidr|inet|macaddr)\z/
79
+ $1
80
+ # Bit string types
81
+ when /\AB'(.*)'::"?bit(?: varying)?"?\z/
82
+ $1
83
+ # XML type
84
+ when /\A'(.*)'::xml\z/m
85
+ $1
86
+ # Arrays
87
+ when /\A'(.*)'::"?\D+"?\[\]\z/
88
+ $1
89
+ # Object identifier types
90
+ when /\A-?\d+\z/
91
+ $1
92
+ else
93
+ # Anything else is blank, some user type, or some function
94
+ # and we can't know the value of that, so return nil.
95
+ nil
96
+ end
97
+ end
98
+
99
+ def extract_limit(sql_type)
100
+ case sql_type
101
+ when /^bigint/i then 8
102
+ when /^smallint/i then 2
103
+ else super
104
+ end
105
+ end
106
+
107
+ # Extracts the scale from PostgreSQL-specific data types.
108
+ def extract_scale(sql_type)
109
+ # Money type has a fixed scale of 2.
110
+ sql_type =~ /^money/ ? 2 : super
111
+ end
112
+
113
+ # Extracts the precision from PostgreSQL-specific data types.
114
+ def extract_precision(sql_type)
115
+ if sql_type == 'money'
116
+ self.class.money_precision
117
+ else
118
+ super
119
+ end
120
+ end
121
+
122
+ # Maps PostgreSQL-specific data types to logical Rails types.
123
+ def simplified_type(field_type)
124
+ case field_type
125
+ # Numeric and monetary types
126
+ when /^(?:real|double precision)$/ then :float
127
+ # Monetary types
128
+ when 'money' then :decimal
129
+ # Character types
130
+ when /^(?:character varying|bpchar)(?:\(\d+\))?$/ then :string
131
+ # Binary data types
132
+ when 'bytea' then :binary
133
+ # Date/time types
134
+ when /^timestamp with(?:out)? time zone$/ then :datetime
135
+ when 'interval' then :string
136
+ # Geometric types
137
+ when /^(?:point|line|lseg|box|"?path"?|polygon|circle)$/ then :string
138
+ # Network address types
139
+ when /^(?:cidr|inet|macaddr)$/ then :string
140
+ # Bit strings
141
+ when /^bit(?: varying)?(?:\(\d+\))?$/ then :string
142
+ # XML type
143
+ when 'xml' then :xml
144
+ # tsvector type
145
+ when 'tsvector' then :tsvector
146
+ # Arrays
147
+ when /^\D+\[\]$/ then :string
148
+ # Object identifier types
149
+ when 'oid' then :integer
150
+ # UUID type
151
+ when 'uuid' then :string
152
+ # Small and big integer types
153
+ when /^(?:small|big)int$/ then :integer
154
+ # Pass through all types that are not specific to PostgreSQL.
155
+ else
156
+ super
157
+ end
158
+ end
159
+ end
160
+
161
+ # constants taken from postgresql_adapter in rails project
162
+ ADAPTER_NAME = 'PostgreSQL'
163
+
164
+ NATIVE_DATABASE_TYPES = {
165
+ :primary_key => "serial primary key",
166
+ :string => { :name => "character varying", :limit => 255 },
167
+ :text => { :name => "text" },
168
+ :integer => { :name => "integer" },
169
+ :float => { :name => "float" },
170
+ :decimal => { :name => "decimal" },
171
+ :datetime => { :name => "timestamp" },
172
+ :timestamp => { :name => "timestamp" },
173
+ :time => { :name => "time" },
174
+ :date => { :name => "date" },
175
+ :binary => { :name => "bytea" },
176
+ :boolean => { :name => "boolean" },
177
+ :xml => { :name => "xml" },
178
+ :tsvector => { :name => "tsvector" }
179
+ }
180
+
181
+ def adapter_name #:nodoc:
182
+ ADAPTER_NAME
183
+ end
184
+
185
+ def self.arel2_visitors(config)
186
+ {}.tap {|v| %w(postgresql pg jdbcpostgresql).each {|a| v[a] = ::Arel::Visitors::PostgreSQL } }
187
+ end
188
+
189
+ def postgresql_version
190
+ @postgresql_version ||=
191
+ begin
192
+ value = select_value('SELECT version()')
193
+ if value =~ /PostgreSQL (\d+)\.(\d+)\.(\d+)/
194
+ ($1.to_i * 10000) + ($2.to_i * 100) + $3.to_i
195
+ else
196
+ 0
197
+ end
198
+ end
199
+ end
200
+
201
+ def native_database_types
202
+ NATIVE_DATABASE_TYPES
203
+ end
204
+
205
+ # Does PostgreSQL support migrations?
206
+ def supports_migrations?
207
+ true
208
+ end
209
+
210
+ # Does PostgreSQL support standard conforming strings?
211
+ def supports_standard_conforming_strings?
212
+ # Temporarily set the client message level above error to prevent unintentional
213
+ # error messages in the logs when working on a PostgreSQL database server that
214
+ # does not support standard conforming strings.
215
+ client_min_messages_old = client_min_messages
216
+ self.client_min_messages = 'panic'
217
+
218
+ # postgres-pr does not raise an exception when client_min_messages is set higher
219
+ # than error and "SHOW standard_conforming_strings" fails, but returns an empty
220
+ # PGresult instead.
221
+ has_support = select('SHOW standard_conforming_strings').to_a[0][0] rescue false
222
+ self.client_min_messages = client_min_messages_old
223
+ has_support
224
+ end
225
+
226
+ def supports_insert_with_returning?
227
+ postgresql_version >= 80200
228
+ end
229
+
230
+ def supports_ddl_transactions?
231
+ true
232
+ end
233
+
234
+ def supports_savepoints?
235
+ true
236
+ end
237
+
238
+ def create_savepoint
239
+ execute("SAVEPOINT #{current_savepoint_name}")
240
+ end
241
+
242
+ def rollback_to_savepoint
243
+ execute("ROLLBACK TO SAVEPOINT #{current_savepoint_name}")
244
+ end
245
+
246
+ def release_savepoint
247
+ execute("RELEASE SAVEPOINT #{current_savepoint_name}")
248
+ end
249
+
250
+ # Returns the configured supported identifier length supported by PostgreSQL,
251
+ # or report the default of 63 on PostgreSQL 7.x.
252
+ def table_alias_length
253
+ @table_alias_length ||= (postgresql_version >= 80000 ? select_one('SHOW max_identifier_length')['max_identifier_length'].to_i : 63)
254
+ end
255
+
256
+ def default_sequence_name(table_name, pk = nil)
257
+ default_pk, default_seq = pk_and_sequence_for(table_name)
258
+ default_seq || "#{table_name}_#{pk || default_pk || 'id'}_seq"
259
+ end
260
+
261
+ # Resets sequence to the max value of the table's pk if present.
262
+ def reset_pk_sequence!(table, pk = nil, sequence = nil) #:nodoc:
263
+ unless pk and sequence
264
+ default_pk, default_sequence = pk_and_sequence_for(table)
265
+ pk ||= default_pk
266
+ sequence ||= default_sequence
267
+ end
268
+ if pk
269
+ if sequence
270
+ quoted_sequence = quote_column_name(sequence)
271
+
272
+ select_value <<-end_sql, 'Reset sequence'
273
+ SELECT setval('#{quoted_sequence}', (SELECT COALESCE(MAX(#{quote_column_name pk})+(SELECT increment_by FROM #{quoted_sequence}), (SELECT min_value FROM #{quoted_sequence})) FROM #{quote_table_name(table)}), false)
274
+ end_sql
275
+ else
276
+ @logger.warn "#{table} has primary key #{pk} with no default sequence" if @logger
277
+ end
278
+ end
279
+ end
280
+
281
+ # Find a table's primary key and sequence.
282
+ def pk_and_sequence_for(table) #:nodoc:
283
+ # First try looking for a sequence with a dependency on the
284
+ # given table's primary key.
285
+ result = select(<<-end_sql, 'PK and serial sequence')[0]
286
+ SELECT attr.attname, seq.relname
287
+ FROM pg_class seq,
288
+ pg_attribute attr,
289
+ pg_depend dep,
290
+ pg_namespace name,
291
+ pg_constraint cons
292
+ WHERE seq.oid = dep.objid
293
+ AND seq.relkind = 'S'
294
+ AND attr.attrelid = dep.refobjid
295
+ AND attr.attnum = dep.refobjsubid
296
+ AND attr.attrelid = cons.conrelid
297
+ AND attr.attnum = cons.conkey[1]
298
+ AND cons.contype = 'p'
299
+ AND dep.refobjid = '#{quote_table_name(table)}'::regclass
300
+ end_sql
301
+
302
+ if result.nil? or result.empty?
303
+ # If that fails, try parsing the primary key's default value.
304
+ # Support the 7.x and 8.0 nextval('foo'::text) as well as
305
+ # the 8.1+ nextval('foo'::regclass).
306
+ result = select(<<-end_sql, 'PK and custom sequence')[0]
307
+ SELECT attr.attname,
308
+ CASE
309
+ WHEN split_part(def.adsrc, '''', 2) ~ '.' THEN
310
+ substr(split_part(def.adsrc, '''', 2),
311
+ strpos(split_part(def.adsrc, '''', 2), '.')+1)
312
+ ELSE split_part(def.adsrc, '''', 2)
313
+ END as relname
314
+ FROM pg_class t
315
+ JOIN pg_attribute attr ON (t.oid = attrelid)
316
+ JOIN pg_attrdef def ON (adrelid = attrelid AND adnum = attnum)
317
+ JOIN pg_constraint cons ON (conrelid = adrelid AND adnum = conkey[1])
318
+ WHERE t.oid = '#{quote_table_name(table)}'::regclass
319
+ AND cons.contype = 'p'
320
+ AND def.adsrc ~* 'nextval'
321
+ end_sql
322
+ end
323
+
324
+ [result["attname"], result["relname"]]
325
+ rescue
326
+ nil
327
+ end
328
+
329
+ # Insert logic for pre-AR-3.1 adapters
330
+ def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = [])
331
+ # Extract the table from the insert sql. Yuck.
332
+ table = sql.split(" ", 4)[2].gsub('"', '')
333
+
334
+ # Try an insert with 'returning id' if available (PG >= 8.2)
335
+ if supports_insert_with_returning? && id_value.nil?
336
+ pk, sequence_name = *pk_and_sequence_for(table) unless pk
337
+ if pk
338
+ sql = substitute_binds(sql, binds)
339
+ id_value = select_value("#{sql} RETURNING #{quote_column_name(pk)}")
340
+ clear_query_cache #FIXME: Why now?
341
+ return id_value
342
+ end
343
+ end
344
+
345
+ # Otherwise, plain insert
346
+ execute(sql, name, binds)
347
+
348
+ # Don't need to look up id_value if we already have it.
349
+ # (and can't in case of non-sequence PK)
350
+ unless id_value
351
+ # If neither pk nor sequence name is given, look them up.
352
+ unless pk || sequence_name
353
+ pk, sequence_name = *pk_and_sequence_for(table)
354
+ end
355
+
356
+ # If a pk is given, fallback to default sequence name.
357
+ # Don't fetch last insert id for a table without a pk.
358
+ if pk && sequence_name ||= default_sequence_name(table, pk)
359
+ id_value = last_insert_id(table, sequence_name)
360
+ end
361
+ end
362
+ id_value
363
+ end
364
+
365
+ def primary_key(table)
366
+ pk_and_sequence = pk_and_sequence_for(table)
367
+ pk_and_sequence && pk_and_sequence.first
368
+ end
369
+
370
+ # taken from rails postgresql adapter
371
+ # https://github.com/gfmurphy/rails/blob/master/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb#L611
372
+ def sql_for_insert(sql, pk, id_value, sequence_name, binds)
373
+ unless pk
374
+ table_ref = extract_table_ref_from_insert_sql(sql)
375
+ pk = primary_key(table_ref) if table_ref
376
+ end
377
+
378
+ sql = "#{sql} RETURNING #{quote_column_name(pk)}" if pk
379
+
380
+ [sql, binds]
381
+ end
382
+
383
+ def pg_columns(table_name, name=nil)
384
+ column_definitions(table_name).map do |row|
385
+ ::ActiveRecord::ConnectionAdapters::PostgreSQLColumn.new(
386
+ row["column_name"], row["column_default"], row["column_type"],
387
+ row["column_not_null"] == "f")
388
+ end
389
+ end
390
+
391
+ # current database name
392
+ def current_database
393
+ exec_query("select current_database() as database").
394
+ first["database"]
395
+ end
396
+
397
+ # current database encoding
398
+ def encoding
399
+ exec_query(<<-end_sql).first["encoding"]
400
+ SELECT pg_encoding_to_char(pg_database.encoding) as encoding
401
+ FROM pg_database
402
+ WHERE pg_database.datname LIKE '#{current_database}'
403
+ end_sql
404
+ end
405
+
406
+ # Sets the maximum number columns postgres has, default 32
407
+ def multi_column_index_limit=(limit)
408
+ @multi_column_index_limit = limit
409
+ end
410
+
411
+ # Gets the maximum number columns postgres has, default 32
412
+ def multi_column_index_limit
413
+ defined?(@multi_column_index_limit) && @multi_column_index_limit || 32
414
+ end
415
+
416
+ # Based on postgresql_adapter.rb
417
+ def indexes(table_name, name = nil)
418
+ schema_search_path = @config[:schema_search_path] || select_rows('SHOW search_path')[0][0]
419
+ schemas = schema_search_path.split(/,/).map { |p| quote(p) }.join(',')
420
+ result = select_rows(<<-SQL, name)
421
+ SELECT i.relname, d.indisunique, a.attname, a.attnum, d.indkey
422
+ FROM pg_class t, pg_class i, pg_index d, pg_attribute a,
423
+ generate_series(0,#{multi_column_index_limit - 1}) AS s(i)
424
+ WHERE i.relkind = 'i'
425
+ AND d.indexrelid = i.oid
426
+ AND d.indisprimary = 'f'
427
+ AND t.oid = d.indrelid
428
+ AND t.relname = '#{table_name}'
429
+ AND i.relnamespace IN (SELECT oid FROM pg_namespace WHERE nspname IN (#{schemas}) )
430
+ AND a.attrelid = t.oid
431
+ AND d.indkey[s.i]=a.attnum
432
+ ORDER BY i.relname
433
+ SQL
434
+
435
+ current_index = nil
436
+ indexes = []
437
+
438
+ insertion_order = []
439
+ index_order = nil
440
+
441
+ result.each do |row|
442
+ if current_index != row[0]
443
+
444
+ (index_order = row[4].split(' ')).each_with_index{ |v, i| index_order[i] = v.to_i }
445
+ indexes << ::ActiveRecord::ConnectionAdapters::IndexDefinition.new(table_name, row[0], row[1] == "t", [])
446
+ current_index = row[0]
447
+ end
448
+ insertion_order = row[3]
449
+ ind = index_order.index(insertion_order)
450
+ indexes.last.columns[ind] = row[2]
451
+ end
452
+
453
+ indexes
454
+ end
455
+
456
+ # take id from result of insert query
457
+ def last_inserted_id(result)
458
+ if result.is_a? Fixnum
459
+ result
460
+ else
461
+ result.first.first[1]
462
+ end
463
+ end
464
+
465
+ def last_insert_id(table, sequence_name)
466
+ Integer(select_value("SELECT currval('#{sequence_name}')"))
467
+ end
468
+
469
+ def recreate_database(name)
470
+ drop_database(name)
471
+ create_database(name)
472
+ end
473
+
474
+ def create_database(name, options = {})
475
+ execute "CREATE DATABASE \"#{name}\" ENCODING='#{options[:encoding] || 'utf8'}'"
476
+ end
477
+
478
+ def drop_database(name)
479
+ execute "DROP DATABASE IF EXISTS \"#{name}\""
480
+ end
481
+
482
+ def create_schema(schema_name, pg_username)
483
+ execute("CREATE SCHEMA \"#{schema_name}\" AUTHORIZATION \"#{pg_username}\"")
484
+ end
485
+
486
+ def drop_schema(schema_name)
487
+ execute("DROP SCHEMA \"#{schema_name}\"")
488
+ end
489
+
490
+ def all_schemas
491
+ select('select nspname from pg_namespace').map {|r| r["nspname"] }
492
+ end
493
+
494
+ def structure_dump
495
+ database = @config[:database]
496
+ if database.nil?
497
+ if @config[:url] =~ /\/([^\/]*)$/
498
+ database = $1
499
+ else
500
+ raise "Could not figure out what database this url is for #{@config["url"]}"
501
+ end
502
+ end
503
+
504
+ ENV['PGHOST'] = @config[:host] if @config[:host]
505
+ ENV['PGPORT'] = @config[:port].to_s if @config[:port]
506
+ ENV['PGPASSWORD'] = @config[:password].to_s if @config[:password]
507
+ search_path = @config[:schema_search_path]
508
+ search_path = "--schema=#{search_path}" if search_path
509
+
510
+ @connection.connection.close
511
+ begin
512
+ definition = `pg_dump -i -U "#{@config[:username]}" -s -x -O #{search_path} #{database}`
513
+ raise "Error dumping database" if $?.exitstatus == 1
514
+
515
+ # need to patch away any references to SQL_ASCII as it breaks the JDBC driver
516
+ definition.gsub(/SQL_ASCII/, 'UNICODE')
517
+ ensure
518
+ reconnect!
519
+ end
520
+ end
521
+
522
+ # SELECT DISTINCT clause for a given set of columns and a given ORDER BY clause.
523
+ #
524
+ # PostgreSQL requires the ORDER BY columns in the select list for distinct queries, and
525
+ # requires that the ORDER BY include the distinct column.
526
+ #
527
+ # distinct("posts.id", "posts.created_at desc")
528
+ def distinct(columns, orders) #:nodoc:
529
+ return "DISTINCT #{columns}" if orders.empty?
530
+
531
+ # Construct a clean list of column names from the ORDER BY clause, removing
532
+ # any ASC/DESC modifiers
533
+ order_columns = orders.collect { |s| s.gsub(/\s+(ASC|DESC)\s*/i, '') }.
534
+ reject(&:blank?)
535
+ order_columns = order_columns.
536
+ zip((0...order_columns.size).to_a).map { |s,i| "#{s} AS alias_#{i}" }
537
+
538
+ "DISTINCT #{columns}, #{order_columns * ', '}"
539
+ end
540
+
541
+ # ORDER BY clause for the passed order option.
542
+ #
543
+ # PostgreSQL does not allow arbitrary ordering when using DISTINCT ON, so we work around this
544
+ # by wrapping the sql as a sub-select and ordering in that query.
545
+ def add_order_by_for_association_limiting!(sql, options)
546
+ return sql if options[:order].blank?
547
+
548
+ order = options[:order].split(',').collect { |s| s.strip }.reject(&:blank?)
549
+ order.map! { |s| 'DESC' if s =~ /\bdesc$/i }
550
+ order = order.zip((0...order.size).to_a).map { |s,i| "id_list.alias_#{i} #{s}" }.join(', ')
551
+
552
+ sql.replace "SELECT * FROM (#{sql}) AS id_list ORDER BY #{order}"
553
+ end
554
+
555
+ # from postgres_adapter.rb in rails project
556
+ # https://github.com/rails/rails/blob/3-1-stable/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb#L412
557
+ # Quotes PostgreSQL-specific data types for SQL input.
558
+ def quote(value, column = nil) #:nodoc:
559
+ return super unless column
560
+
561
+ case value
562
+ when Float
563
+ return super unless value.infinite? && column.type == :datetime
564
+ "'#{value.to_s.downcase}'"
565
+ when Numeric
566
+ return super unless column.sql_type == 'money'
567
+ # Not truly string input, so doesn't require (or allow) escape string syntax.
568
+ "'#{value}'"
569
+ when String
570
+ case column.sql_type
571
+ when 'bytea' then "'#{escape_bytea(value)}'"
572
+ when 'xml' then "xml '#{quote_string(value)}'"
573
+ when /^bit/
574
+ case value
575
+ when /^[01]*$/ then "B'#{value}'" # Bit-string notation
576
+ when /^[0-9A-F]*$/i then "X'#{value}'" # Hexadecimal notation
577
+ end
578
+ else
579
+ super
580
+ end
581
+ else
582
+ super
583
+ end
584
+ end
585
+
586
+ def escape_bytea(s)
587
+ if s
588
+ result = ''
589
+ s.each_byte { |c| result << sprintf('\\\\%03o', c) }
590
+ result
591
+ end
592
+ end
593
+
594
+ def quote_table_name(name)
595
+ schema, name_part = extract_pg_identifier_from_name(name.to_s)
596
+
597
+ unless name_part
598
+ quote_column_name(schema)
599
+ else
600
+ table_name, name_part = extract_pg_identifier_from_name(name_part)
601
+ "#{quote_column_name(schema)}.#{quote_column_name(table_name)}"
602
+ end
603
+ end
604
+
605
+ def quote_column_name(name)
606
+ %("#{name.to_s.gsub("\"", "\"\"")}")
607
+ end
608
+
609
+ def quoted_date(value) #:nodoc:
610
+ if value.acts_like?(:time) && value.respond_to?(:usec)
611
+ "#{super}.#{sprintf("%06d", value.usec)}"
612
+ else
613
+ super
614
+ end
615
+ end
616
+
617
+ def disable_referential_integrity(&block) #:nodoc:
618
+ execute(tables.collect { |name| "ALTER TABLE #{quote_table_name(name)} DISABLE TRIGGER ALL" }.join(";"))
619
+ yield
620
+ ensure
621
+ execute(tables.collect { |name| "ALTER TABLE #{quote_table_name(name)} ENABLE TRIGGER ALL" }.join(";"))
622
+ end
623
+
624
+ def rename_table(name, new_name)
625
+ execute "ALTER TABLE #{name} RENAME TO #{new_name}"
626
+ end
627
+
628
+ # Adds a new column to the named table.
629
+ # See TableDefinition#column for details of the options you can use.
630
+ def add_column(table_name, column_name, type, options = {})
631
+ default = options[:default]
632
+ notnull = options[:null] == false
633
+
634
+ # Add the column.
635
+ execute("ALTER TABLE #{quote_table_name(table_name)} ADD COLUMN #{quote_column_name(column_name)} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}")
636
+
637
+ change_column_default(table_name, column_name, default) if options_include_default?(options)
638
+ change_column_null(table_name, column_name, false, default) if notnull
639
+ end
640
+
641
+ # Changes the column of a table.
642
+ def change_column(table_name, column_name, type, options = {})
643
+ quoted_table_name = quote_table_name(table_name)
644
+
645
+ begin
646
+ execute "ALTER TABLE #{quoted_table_name} ALTER COLUMN #{quote_column_name(column_name)} TYPE #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}"
647
+ rescue ActiveRecord::StatementInvalid => e
648
+ raise e if postgresql_version > 80000
649
+ # This is PostgreSQL 7.x, so we have to use a more arcane way of doing it.
650
+ begin
651
+ begin_db_transaction
652
+ tmp_column_name = "#{column_name}_ar_tmp"
653
+ add_column(table_name, tmp_column_name, type, options)
654
+ execute "UPDATE #{quoted_table_name} SET #{quote_column_name(tmp_column_name)} = CAST(#{quote_column_name(column_name)} AS #{type_to_sql(type, options[:limit], options[:precision], options[:scale])})"
655
+ remove_column(table_name, column_name)
656
+ rename_column(table_name, tmp_column_name, column_name)
657
+ commit_db_transaction
658
+ rescue
659
+ rollback_db_transaction
660
+ end
661
+ end
662
+
663
+ change_column_default(table_name, column_name, options[:default]) if options_include_default?(options)
664
+ change_column_null(table_name, column_name, options[:null], options[:default]) if options.key?(:null)
665
+ end
666
+
667
+ # Changes the default value of a table column.
668
+ def change_column_default(table_name, column_name, default)
669
+ execute "ALTER TABLE #{quote_table_name(table_name)} ALTER COLUMN #{quote_column_name(column_name)} SET DEFAULT #{quote(default)}"
670
+ end
671
+
672
+ def change_column_null(table_name, column_name, null, default = nil)
673
+ unless null || default.nil?
674
+ execute("UPDATE #{quote_table_name(table_name)} SET #{quote_column_name(column_name)}=#{quote(default)} WHERE #{quote_column_name(column_name)} IS NULL")
675
+ end
676
+ execute("ALTER TABLE #{quote_table_name(table_name)} ALTER #{quote_column_name(column_name)} #{null ? 'DROP' : 'SET'} NOT NULL")
677
+ end
678
+
679
+ def rename_column(table_name, column_name, new_column_name) #:nodoc:
680
+ execute "ALTER TABLE #{quote_table_name(table_name)} RENAME COLUMN #{quote_column_name(column_name)} TO #{quote_column_name(new_column_name)}"
681
+ end
682
+
683
+ def remove_index!(table_name, index_name) #:nodoc:
684
+ execute "DROP INDEX #{quote_table_name(index_name)}"
685
+ end
686
+
687
+ def index_name_length
688
+ 63
689
+ end
690
+
691
+ # Maps logical Rails types to PostgreSQL-specific data types.
692
+ def type_to_sql(type, limit = nil, precision = nil, scale = nil)
693
+ return super unless type.to_s == 'integer'
694
+ return 'integer' unless limit
695
+
696
+ case limit
697
+ when 1, 2; 'smallint'
698
+ when 3, 4; 'integer'
699
+ when 5..8; 'bigint'
700
+ else raise(ActiveRecordError, "No integer type has byte size #{limit}. Use a numeric with precision 0 instead.")
701
+ end
702
+ end
703
+
704
+ def tables(name = nil)
705
+ exec_query(<<-SQL, 'SCHEMA').map { |row| row["tablename"] }
706
+ SELECT tablename
707
+ FROM pg_tables
708
+ WHERE schemaname = ANY (current_schemas(false))
709
+ SQL
710
+ end
711
+
712
+ def table_exists?(name)
713
+ schema, table = extract_schema_and_table(name.to_s)
714
+ return false unless table # Abstract classes is having nil table name
715
+
716
+ binds = [[nil, table.gsub(/(^"|"$)/,'')]]
717
+ binds << [nil, schema] if schema
718
+
719
+ exec_query(<<-SQL, 'SCHEMA', binds).first["table_count"] > 0
720
+ SELECT COUNT(*) as table_count
721
+ FROM pg_tables
722
+ WHERE tablename = ?
723
+ AND schemaname = #{schema ? "?" : "ANY (current_schemas(false))"}
724
+ SQL
725
+ end
726
+
727
+ # Extracts the table and schema name from +name+
728
+ def extract_schema_and_table(name)
729
+ schema, table = name.split('.', 2)
730
+
731
+ unless table # A table was provided without a schema
732
+ table = schema
733
+ schema = nil
734
+ end
735
+
736
+ if name =~ /^"/ # Handle quoted table names
737
+ table = name
738
+ schema = nil
739
+ end
740
+ [schema, table]
741
+ end
742
+
743
+ private
744
+ def translate_exception(exception, message)
745
+ case exception.message
746
+ when /duplicate key value violates unique constraint/
747
+ ::ActiveRecord::RecordNotUnique.new(message, exception)
748
+ when /violates foreign key constraint/
749
+ ::ActiveRecord::InvalidForeignKey.new(message, exception)
750
+ else
751
+ super
752
+ end
753
+ end
754
+
755
+ # Returns the list of a table's column names, data types, and default values.
756
+ #
757
+ # The underlying query is roughly:
758
+ # SELECT column.name, column.type, default.value
759
+ # FROM column LEFT JOIN default
760
+ # ON column.table_id = default.table_id
761
+ # AND column.num = default.column_num
762
+ # WHERE column.table_id = get_table_id('table_name')
763
+ # AND column.num > 0
764
+ # AND NOT column.is_dropped
765
+ # ORDER BY column.num
766
+ #
767
+ # If the table name is not prefixed with a schema, the database will
768
+ # take the first match from the schema search path.
769
+ #
770
+ # Query implementation notes:
771
+ # - format_type includes the column size constraint, e.g. varchar(50)
772
+ # - ::regclass is a function that gives the id for a table name
773
+ def column_definitions(table_name) #:nodoc:
774
+ exec_query(<<-end_sql, 'SCHEMA')
775
+ SELECT a.attname as column_name, format_type(a.atttypid, a.atttypmod) as column_type, d.adsrc as column_default, a.attnotnull as column_not_null
776
+ FROM pg_attribute a LEFT JOIN pg_attrdef d
777
+ ON a.attrelid = d.adrelid AND a.attnum = d.adnum
778
+ WHERE a.attrelid = '#{quote_table_name(table_name)}'::regclass
779
+ AND a.attnum > 0 AND NOT a.attisdropped
780
+ ORDER BY a.attnum
781
+ end_sql
782
+ end
783
+
784
+ def extract_pg_identifier_from_name(name)
785
+ match_data = name[0,1] == '"' ? name.match(/\"([^\"]+)\"/) : name.match(/([^\.]+)/)
786
+
787
+ if match_data
788
+ rest = name[match_data[0].length..-1]
789
+ rest = rest[1..-1] if rest[0,1] == "."
790
+ [match_data[1], (rest.length > 0 ? rest : nil)]
791
+ end
792
+ end
793
+
794
+ # from rails postgresl_adapter
795
+ def extract_table_ref_from_insert_sql(sql)
796
+ sql[/into\s+([^\(]*).*values\s*\(/i]
797
+ $1.strip if $1
798
+ end
799
+ end
800
+ end
801
+
802
+ module ActiveRecord::ConnectionAdapters
803
+ remove_const(:PostgreSQLAdapter) if const_defined?(:PostgreSQLAdapter)
804
+
805
+ class PostgreSQLColumn < JdbcColumn
806
+ include ArJdbc::PostgreSQL::Column
807
+
808
+ def initialize(name, *args)
809
+ if Hash === name
810
+ super
811
+ else
812
+ super(nil, name, *args)
813
+ end
814
+ end
815
+
816
+ def call_discovered_column_callbacks(*)
817
+ end
818
+ end
819
+
820
+ class PostgresJdbcConnection < JdbcConnection
821
+ alias :java_native_database_types :set_native_database_types
822
+
823
+ # override to prevent connection from loading hash from jdbc
824
+ # metadata, which can be expensive. We can do this since
825
+ # native_database_types is defined in the adapter to use a static hash
826
+ # not relying on the driver's metadata
827
+ def set_native_database_types
828
+ @native_types = {}
829
+ end
830
+ end
831
+
832
+ class PostgreSQLAdapter < JdbcAdapter
833
+ include ArJdbc::PostgreSQL
834
+
835
+ class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition
836
+ def xml(*args)
837
+ options = args.extract_options!
838
+ column(args[0], "xml", options)
839
+ end
840
+
841
+ def tsvector(*args)
842
+ options = args.extract_options!
843
+ column(args[0], "tsvector", options)
844
+ end
845
+ end
846
+
847
+ def table_definition
848
+ TableDefinition.new(self)
849
+ end
850
+
851
+ def jdbc_connection_class(spec)
852
+ ::ArJdbc::PostgreSQL.jdbc_connection_class
853
+ end
854
+
855
+ def jdbc_column_class
856
+ ActiveRecord::ConnectionAdapters::PostgreSQLColumn
857
+ end
858
+
859
+ alias_chained_method :columns, :query_cache, :pg_columns
860
+ end
861
+ end