neo-activerecord-jdbc-adapter 5.0.pre2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (187) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +33 -0
  3. data/.travis.yml +438 -0
  4. data/.yardopts +4 -0
  5. data/Appraisals +41 -0
  6. data/CONTRIBUTING.md +44 -0
  7. data/Gemfile +62 -0
  8. data/History.md +1191 -0
  9. data/LICENSE.txt +25 -0
  10. data/README.md +266 -0
  11. data/RUNNING_TESTS.md +88 -0
  12. data/Rakefile +100 -0
  13. data/Rakefile.jdbc +20 -0
  14. data/activerecord-jdbc-adapter.gemspec +42 -0
  15. data/lib/active_record/connection_adapters/as400_adapter.rb +2 -0
  16. data/lib/active_record/connection_adapters/db2_adapter.rb +1 -0
  17. data/lib/active_record/connection_adapters/derby_adapter.rb +1 -0
  18. data/lib/active_record/connection_adapters/firebird_adapter.rb +1 -0
  19. data/lib/active_record/connection_adapters/h2_adapter.rb +1 -0
  20. data/lib/active_record/connection_adapters/hsqldb_adapter.rb +1 -0
  21. data/lib/active_record/connection_adapters/informix_adapter.rb +1 -0
  22. data/lib/active_record/connection_adapters/jdbc_adapter.rb +1 -0
  23. data/lib/active_record/connection_adapters/jndi_adapter.rb +1 -0
  24. data/lib/active_record/connection_adapters/mariadb_adapter.rb +1 -0
  25. data/lib/active_record/connection_adapters/mssql_adapter.rb +1 -0
  26. data/lib/active_record/connection_adapters/mysql2_adapter.rb +1 -0
  27. data/lib/active_record/connection_adapters/mysql_adapter.rb +1 -0
  28. data/lib/active_record/connection_adapters/oracle_adapter.rb +1 -0
  29. data/lib/active_record/connection_adapters/postgresql_adapter.rb +1 -0
  30. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +1 -0
  31. data/lib/active_record/connection_adapters/sqlserver_adapter.rb +1 -0
  32. data/lib/activerecord-jdbc-adapter.rb +1 -0
  33. data/lib/arel/visitors/compat.rb +60 -0
  34. data/lib/arel/visitors/db2.rb +137 -0
  35. data/lib/arel/visitors/derby.rb +112 -0
  36. data/lib/arel/visitors/firebird.rb +79 -0
  37. data/lib/arel/visitors/h2.rb +25 -0
  38. data/lib/arel/visitors/hsqldb.rb +32 -0
  39. data/lib/arel/visitors/postgresql_jdbc.rb +6 -0
  40. data/lib/arel/visitors/sql_server.rb +225 -0
  41. data/lib/arel/visitors/sql_server/ng42.rb +293 -0
  42. data/lib/arjdbc.rb +19 -0
  43. data/lib/arjdbc/abstract/database_statements.rb +92 -0
  44. data/lib/arjdbc/abstract/transaction_support.rb +86 -0
  45. data/lib/arjdbc/common_jdbc_methods.rb +13 -0
  46. data/lib/arjdbc/db2.rb +4 -0
  47. data/lib/arjdbc/db2/adapter.rb +789 -0
  48. data/lib/arjdbc/db2/as400.rb +130 -0
  49. data/lib/arjdbc/db2/column.rb +167 -0
  50. data/lib/arjdbc/db2/connection_methods.rb +44 -0
  51. data/lib/arjdbc/derby.rb +3 -0
  52. data/lib/arjdbc/derby/active_record_patch.rb +13 -0
  53. data/lib/arjdbc/derby/adapter.rb +556 -0
  54. data/lib/arjdbc/derby/connection_methods.rb +20 -0
  55. data/lib/arjdbc/derby/schema_creation.rb +15 -0
  56. data/lib/arjdbc/discover.rb +115 -0
  57. data/lib/arjdbc/firebird.rb +4 -0
  58. data/lib/arjdbc/firebird/adapter.rb +434 -0
  59. data/lib/arjdbc/firebird/connection_methods.rb +23 -0
  60. data/lib/arjdbc/h2.rb +3 -0
  61. data/lib/arjdbc/h2/adapter.rb +303 -0
  62. data/lib/arjdbc/h2/connection_methods.rb +27 -0
  63. data/lib/arjdbc/hsqldb.rb +3 -0
  64. data/lib/arjdbc/hsqldb/adapter.rb +297 -0
  65. data/lib/arjdbc/hsqldb/connection_methods.rb +28 -0
  66. data/lib/arjdbc/hsqldb/explain_support.rb +35 -0
  67. data/lib/arjdbc/hsqldb/schema_creation.rb +11 -0
  68. data/lib/arjdbc/informix.rb +5 -0
  69. data/lib/arjdbc/informix/adapter.rb +162 -0
  70. data/lib/arjdbc/informix/connection_methods.rb +9 -0
  71. data/lib/arjdbc/jdbc.rb +59 -0
  72. data/lib/arjdbc/jdbc/adapter.rb +899 -0
  73. data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
  74. data/lib/arjdbc/jdbc/adapter_require.rb +46 -0
  75. data/lib/arjdbc/jdbc/base_ext.rb +44 -0
  76. data/lib/arjdbc/jdbc/callbacks.rb +51 -0
  77. data/lib/arjdbc/jdbc/column.rb +97 -0
  78. data/lib/arjdbc/jdbc/connection.rb +133 -0
  79. data/lib/arjdbc/jdbc/connection_methods.rb +36 -0
  80. data/lib/arjdbc/jdbc/driver.rb +43 -0
  81. data/lib/arjdbc/jdbc/extension.rb +59 -0
  82. data/lib/arjdbc/jdbc/java.rb +15 -0
  83. data/lib/arjdbc/jdbc/jdbc.rake +4 -0
  84. data/lib/arjdbc/jdbc/quoted_primary_key.rb +28 -0
  85. data/lib/arjdbc/jdbc/railtie.rb +2 -0
  86. data/lib/arjdbc/jdbc/rake_tasks.rb +3 -0
  87. data/lib/arjdbc/jdbc/serialized_attributes_helper.rb +3 -0
  88. data/lib/arjdbc/jdbc/type_cast.rb +166 -0
  89. data/lib/arjdbc/jdbc/type_converter.rb +142 -0
  90. data/lib/arjdbc/mimer.rb +3 -0
  91. data/lib/arjdbc/mimer/adapter.rb +142 -0
  92. data/lib/arjdbc/mssql.rb +7 -0
  93. data/lib/arjdbc/mssql/adapter.rb +808 -0
  94. data/lib/arjdbc/mssql/column.rb +200 -0
  95. data/lib/arjdbc/mssql/connection_methods.rb +79 -0
  96. data/lib/arjdbc/mssql/explain_support.rb +99 -0
  97. data/lib/arjdbc/mssql/limit_helpers.rb +231 -0
  98. data/lib/arjdbc/mssql/lock_methods.rb +77 -0
  99. data/lib/arjdbc/mssql/types.rb +343 -0
  100. data/lib/arjdbc/mssql/utils.rb +82 -0
  101. data/lib/arjdbc/mysql.rb +3 -0
  102. data/lib/arjdbc/mysql/adapter.rb +1006 -0
  103. data/lib/arjdbc/mysql/bulk_change_table.rb +150 -0
  104. data/lib/arjdbc/mysql/column.rb +162 -0
  105. data/lib/arjdbc/mysql/connection_methods.rb +145 -0
  106. data/lib/arjdbc/mysql/explain_support.rb +82 -0
  107. data/lib/arjdbc/mysql/schema_creation.rb +58 -0
  108. data/lib/arjdbc/oracle.rb +4 -0
  109. data/lib/arjdbc/oracle/adapter.rb +952 -0
  110. data/lib/arjdbc/oracle/column.rb +126 -0
  111. data/lib/arjdbc/oracle/connection_methods.rb +21 -0
  112. data/lib/arjdbc/postgresql.rb +3 -0
  113. data/lib/arjdbc/postgresql/_bc_time_cast_patch.rb +21 -0
  114. data/lib/arjdbc/postgresql/adapter.rb +825 -0
  115. data/lib/arjdbc/postgresql/base/array_decoder.rb +26 -0
  116. data/lib/arjdbc/postgresql/base/array_encoder.rb +25 -0
  117. data/lib/arjdbc/postgresql/base/array_parser.rb +95 -0
  118. data/lib/arjdbc/postgresql/base/pgconn.rb +11 -0
  119. data/lib/arjdbc/postgresql/column.rb +51 -0
  120. data/lib/arjdbc/postgresql/connection_methods.rb +54 -0
  121. data/lib/arjdbc/postgresql/name.rb +24 -0
  122. data/lib/arjdbc/postgresql/oid_types.rb +178 -0
  123. data/lib/arjdbc/railtie.rb +11 -0
  124. data/lib/arjdbc/sqlite3.rb +3 -0
  125. data/lib/arjdbc/sqlite3/adapter.rb +703 -0
  126. data/lib/arjdbc/sqlite3/connection_methods.rb +40 -0
  127. data/lib/arjdbc/sybase.rb +2 -0
  128. data/lib/arjdbc/sybase/adapter.rb +47 -0
  129. data/lib/arjdbc/tasks.rb +13 -0
  130. data/lib/arjdbc/tasks/database_tasks.rb +54 -0
  131. data/lib/arjdbc/tasks/databases.rake +91 -0
  132. data/lib/arjdbc/tasks/databases3.rake +215 -0
  133. data/lib/arjdbc/tasks/databases4.rake +39 -0
  134. data/lib/arjdbc/tasks/db2_database_tasks.rb +104 -0
  135. data/lib/arjdbc/tasks/derby_database_tasks.rb +95 -0
  136. data/lib/arjdbc/tasks/h2_database_tasks.rb +31 -0
  137. data/lib/arjdbc/tasks/hsqldb_database_tasks.rb +70 -0
  138. data/lib/arjdbc/tasks/jdbc_database_tasks.rb +169 -0
  139. data/lib/arjdbc/tasks/mssql_database_tasks.rb +46 -0
  140. data/lib/arjdbc/tasks/oracle/enhanced_structure_dump.rb +297 -0
  141. data/lib/arjdbc/tasks/oracle_database_tasks.rb +65 -0
  142. data/lib/arjdbc/util/quoted_cache.rb +60 -0
  143. data/lib/arjdbc/util/serialized_attributes.rb +98 -0
  144. data/lib/arjdbc/util/table_copier.rb +110 -0
  145. data/lib/arjdbc/version.rb +8 -0
  146. data/lib/generators/jdbc/USAGE +9 -0
  147. data/lib/generators/jdbc/jdbc_generator.rb +17 -0
  148. data/lib/jdbc_adapter.rb +2 -0
  149. data/lib/jdbc_adapter/rake_tasks.rb +4 -0
  150. data/lib/jdbc_adapter/version.rb +4 -0
  151. data/pom.xml +114 -0
  152. data/rails_generators/jdbc_generator.rb +15 -0
  153. data/rails_generators/templates/config/initializers/jdbc.rb +10 -0
  154. data/rails_generators/templates/lib/tasks/jdbc.rake +11 -0
  155. data/rakelib/01-tomcat.rake +51 -0
  156. data/rakelib/02-test.rake +121 -0
  157. data/rakelib/bundler_ext.rb +11 -0
  158. data/rakelib/compile.rake +62 -0
  159. data/rakelib/db.rake +58 -0
  160. data/rakelib/rails.rake +75 -0
  161. data/src/java/arjdbc/ArJdbcModule.java +178 -0
  162. data/src/java/arjdbc/db2/DB2Module.java +71 -0
  163. data/src/java/arjdbc/db2/DB2RubyJdbcConnection.java +142 -0
  164. data/src/java/arjdbc/derby/DerbyModule.java +179 -0
  165. data/src/java/arjdbc/derby/DerbyRubyJdbcConnection.java +164 -0
  166. data/src/java/arjdbc/firebird/FirebirdRubyJdbcConnection.java +190 -0
  167. data/src/java/arjdbc/h2/H2Module.java +44 -0
  168. data/src/java/arjdbc/h2/H2RubyJdbcConnection.java +67 -0
  169. data/src/java/arjdbc/hsqldb/HSQLDBModule.java +68 -0
  170. data/src/java/arjdbc/informix/InformixRubyJdbcConnection.java +75 -0
  171. data/src/java/arjdbc/jdbc/AdapterJavaService.java +45 -0
  172. data/src/java/arjdbc/jdbc/Callable.java +44 -0
  173. data/src/java/arjdbc/jdbc/JdbcConnectionFactory.java +45 -0
  174. data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +3616 -0
  175. data/src/java/arjdbc/jdbc/SQLBlock.java +54 -0
  176. data/src/java/arjdbc/mssql/MSSQLModule.java +102 -0
  177. data/src/java/arjdbc/mssql/MSSQLRubyJdbcConnection.java +195 -0
  178. data/src/java/arjdbc/mysql/MySQLModule.java +147 -0
  179. data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +397 -0
  180. data/src/java/arjdbc/oracle/OracleModule.java +75 -0
  181. data/src/java/arjdbc/oracle/OracleRubyJdbcConnection.java +465 -0
  182. data/src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java +752 -0
  183. data/src/java/arjdbc/sqlite3/SQLite3Module.java +78 -0
  184. data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +351 -0
  185. data/src/java/arjdbc/util/CallResultSet.java +826 -0
  186. data/src/java/arjdbc/util/QuotingUtils.java +111 -0
  187. metadata +255 -0
@@ -0,0 +1,46 @@
1
+ require 'arjdbc/tasks/jdbc_database_tasks'
2
+
3
+ module ArJdbc
4
+ module Tasks
5
+ class MSSQLDatabaseTasks < JdbcDatabaseTasks
6
+
7
+ def purge
8
+ test = deep_dup(configuration)
9
+ test_database = resolve_database(test)
10
+ test['database'] = 'master'
11
+ establish_connection(test)
12
+ connection.recreate_database!(test_database)
13
+ end
14
+
15
+ def structure_dump(filename)
16
+ config = config_from_url_if_needed
17
+ `smoscript -s #{config['host']} -d #{config['database']} -u #{config['username']} -p #{config['password']} -f #{filename} -A -U`
18
+ end
19
+
20
+ def structure_load(filename)
21
+ config = config_from_url_if_needed
22
+ `sqlcmd -S #{config['host']} -d #{config['database']} -U #{config['username']} -P #{config['password']} -i #{filename}`
23
+ end
24
+
25
+ private
26
+
27
+ def config_from_url_if_needed
28
+ config = self.config
29
+ if config['url'] && ! config.key?('database')
30
+ config = config_from_url(config['url'])
31
+ end
32
+ config
33
+ end
34
+
35
+ def deep_dup(hash)
36
+ dup = hash.dup
37
+ dup.each_pair do |k,v|
38
+ tv = dup[k]
39
+ dup[k] = tv.is_a?(Hash) && v.is_a?(Hash) ? deep_dup(tv) : v
40
+ end
41
+ dup
42
+ end
43
+
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,297 @@
1
+ # NOTE: kindly copy-pasted from Raimonds Simanovskis's oracle-enhanced adapter :
2
+ # https://github.com/rsim/oracle-enhanced/blob/master/lib/active_record/connection_adapters/oracle_enhanced_structure_dump.rb
3
+
4
+ module ActiveRecord #:nodoc:
5
+ module ConnectionAdapters #:nodoc:
6
+ module OracleEnhancedStructureDump #:nodoc:
7
+
8
+ # Statements separator used in structure dump to allow loading of structure dump also with SQL*Plus
9
+ STATEMENT_TOKEN = "\n\n/\n\n"
10
+
11
+ def structure_dump #:nodoc:
12
+ structure = select_values("SELECT sequence_name FROM user_sequences ORDER BY 1").map do |seq|
13
+ "CREATE SEQUENCE \"#{seq}\""
14
+ end
15
+ select_values("SELECT table_name FROM all_tables t
16
+ WHERE owner = SYS_CONTEXT('userenv', 'session_user') AND secondary = 'N'
17
+ AND NOT EXISTS (SELECT mv.mview_name FROM all_mviews mv WHERE mv.owner = t.owner AND mv.mview_name = t.table_name)
18
+ AND NOT EXISTS (SELECT mvl.log_table FROM all_mview_logs mvl WHERE mvl.log_owner = t.owner AND mvl.log_table = t.table_name)
19
+ ORDER BY 1").each do |table_name|
20
+ virtual_columns = virtual_columns_for(table_name)
21
+ ddl = "CREATE#{ ' GLOBAL TEMPORARY' if temporary_table?(table_name)} TABLE \"#{table_name}\" (\n"
22
+ cols = select_all(%Q{
23
+ SELECT column_name, data_type, data_length, char_used, char_length, data_precision, data_scale, data_default, nullable
24
+ FROM user_tab_columns
25
+ WHERE table_name = '#{table_name}'
26
+ ORDER BY column_id
27
+ }).map do |row|
28
+ if(v = virtual_columns.find {|col| col['column_name'] == row['column_name']})
29
+ structure_dump_virtual_column(row, v['data_default'])
30
+ else
31
+ structure_dump_column(row)
32
+ end
33
+ end
34
+ ddl << cols.join(",\n ")
35
+ ddl << structure_dump_primary_key(table_name)
36
+ ddl << "\n)"
37
+ structure << ddl
38
+ structure << structure_dump_indexes(table_name)
39
+ structure << structure_dump_unique_keys(table_name)
40
+ end
41
+
42
+ join_with_statement_token(structure) << structure_dump_fk_constraints
43
+ end
44
+
45
+ def structure_dump_column(column) #:nodoc:
46
+ col = "\"#{column['column_name']}\" #{column['data_type']}"
47
+ if column['data_type'] =='NUMBER' && ! column['data_precision'].blank?
48
+ col << "(#{column['data_precision'].to_i}"
49
+ col << ",#{column['data_scale'].to_i}" unless column['data_scale'].blank?
50
+ col << ')'
51
+ elsif column['data_type'].include?('CHAR')
52
+ length = column['char_used'] == 'C' ? column['char_length'].to_i : column['data_length'].to_i
53
+ col << "(#{length})"
54
+ end
55
+ col << " DEFAULT #{column['data_default']}" unless column['data_default'].blank?
56
+ col << ' NOT NULL' if column['nullable'] == 'N'
57
+ col
58
+ end
59
+
60
+ def structure_dump_virtual_column(column, data_default) #:nodoc:
61
+ data_default = data_default.gsub(/"/, '')
62
+ col = "\"#{column['column_name']}\" #{column['data_type']}"
63
+ if column['data_type'] =='NUMBER' && ! column['data_precision'].blank?
64
+ col << "(#{column['data_precision'].to_i}"
65
+ col << ",#{column['data_scale'].to_i}" unless column['data_scale'].blank?
66
+ col << ')'
67
+ elsif column['data_type'].include?('CHAR')
68
+ length = column['char_used'] == 'C' ? column['char_length'].to_i : column['data_length'].to_i
69
+ col << "(#{length})"
70
+ end
71
+ col << " GENERATED ALWAYS AS (#{data_default}) VIRTUAL"
72
+ end
73
+
74
+ def structure_dump_primary_key(table) #:nodoc:
75
+ opts = {:name => '', :cols => []}
76
+ pks = select_all(<<-SQL, "Primary Keys")
77
+ SELECT a.constraint_name, a.column_name, a.position
78
+ FROM user_cons_columns a
79
+ JOIN user_constraints c
80
+ ON a.constraint_name = c.constraint_name
81
+ WHERE c.table_name = '#{table.upcase}'
82
+ AND c.constraint_type = 'P'
83
+ AND c.owner = SYS_CONTEXT('userenv', 'session_user')
84
+ SQL
85
+ pks.each do |row|
86
+ opts[:name] = row['constraint_name']
87
+ opts[:cols][row['position']-1] = row['column_name']
88
+ end
89
+ opts[:cols].length > 0 ? ",\n CONSTRAINT #{opts[:name]} PRIMARY KEY (#{opts[:cols].join(',')})" : ''
90
+ end
91
+
92
+ def structure_dump_unique_keys(table) #:nodoc:
93
+ keys = {}
94
+ uks = select_all(<<-SQL, "Primary Keys")
95
+ SELECT a.constraint_name, a.column_name, a.position
96
+ FROM user_cons_columns a
97
+ JOIN user_constraints c
98
+ ON a.constraint_name = c.constraint_name
99
+ WHERE c.table_name = '#{table.upcase}'
100
+ AND c.constraint_type = 'U'
101
+ AND c.owner = SYS_CONTEXT('userenv', 'session_user')
102
+ SQL
103
+ uks.each do |uk|
104
+ keys[uk['constraint_name']] ||= []
105
+ keys[uk['constraint_name']][uk['position']-1] = uk['column_name']
106
+ end
107
+ keys.map do |k,v|
108
+ "ALTER TABLE #{table.upcase} ADD CONSTRAINT #{k} UNIQUE (#{v.join(',')})"
109
+ end
110
+ end
111
+
112
+ def structure_dump_indexes(table_name) #:nodoc:
113
+ indexes(table_name).map do |options|
114
+ column_names = options[:columns]
115
+ options = {:name => options[:name], :unique => options[:unique]}
116
+ index_name = index_name(table_name, :column => column_names)
117
+ if Hash === options # legacy support, since this param was a string
118
+ index_type = options[:unique] ? "UNIQUE" : ""
119
+ index_name = options[:name] || index_name
120
+ else
121
+ index_type = options
122
+ end
123
+ quoted_column_names = column_names.map { |e| quote_column_name_or_expression(e) }.join(", ")
124
+ "CREATE #{index_type} INDEX #{quote_column_name(index_name)} ON #{quote_table_name(table_name)} (#{quoted_column_names})"
125
+ end
126
+ end
127
+
128
+ def structure_dump_fk_constraints #:nodoc:
129
+ fks = select_all("SELECT table_name FROM all_tables WHERE owner = SYS_CONTEXT('userenv', 'session_user') ORDER BY 1").map do |table|
130
+ if respond_to?(:foreign_keys) && (foreign_keys = foreign_keys(table["table_name"])).any?
131
+ foreign_keys.map do |fk|
132
+ sql = "ALTER TABLE #{quote_table_name(fk.from_table)} ADD CONSTRAINT #{quote_column_name(fk.options[:name])} "
133
+ sql << "#{foreign_key_definition(fk.to_table, fk.options)}"
134
+ end
135
+ end
136
+ end.flatten.compact
137
+ join_with_statement_token(fks)
138
+ end
139
+
140
+ def dump_schema_information #:nodoc:
141
+ sm_table = ActiveRecord::Migrator.schema_migrations_table_name
142
+ migrated = select_values("SELECT version FROM #{sm_table} ORDER BY version")
143
+ join_with_statement_token(migrated.map{|v| "INSERT INTO #{sm_table} (version) VALUES ('#{v}')" })
144
+ end
145
+
146
+ # Extract all stored procedures, packages, synonyms and views.
147
+ def structure_dump_db_stored_code #:nodoc:
148
+ structure = []
149
+ select_all("SELECT DISTINCT name, type
150
+ FROM all_source
151
+ WHERE type IN ('PROCEDURE', 'PACKAGE', 'PACKAGE BODY', 'FUNCTION', 'TRIGGER', 'TYPE')
152
+ AND name NOT LIKE 'BIN$%'
153
+ AND owner = SYS_CONTEXT('userenv', 'session_user') ORDER BY type").each do |source|
154
+ ddl = "CREATE OR REPLACE \n"
155
+ select_all(%Q{
156
+ SELECT text
157
+ FROM all_source
158
+ WHERE name = '#{source['name']}'
159
+ AND type = '#{source['type']}'
160
+ AND owner = SYS_CONTEXT('userenv', 'session_user')
161
+ ORDER BY line
162
+ }).each do |row|
163
+ ddl << row['text']
164
+ end
165
+ ddl << ";" unless ddl.strip[-1,1] == ';'
166
+ structure << ddl
167
+ end
168
+
169
+ # export views
170
+ select_all("SELECT view_name, text FROM user_views").each do |view|
171
+ structure << "CREATE OR REPLACE VIEW #{view['view_name']} AS\n #{view['text']}"
172
+ end
173
+
174
+ # export synonyms
175
+ select_all("SELECT owner, synonym_name, table_name, table_owner
176
+ FROM all_synonyms
177
+ WHERE owner = SYS_CONTEXT('userenv', 'session_user') ").each do |synonym|
178
+ structure << "CREATE OR REPLACE #{synonym['owner'] == 'PUBLIC' ? 'PUBLIC' : '' } SYNONYM #{synonym['synonym_name']}"
179
+ structure << " FOR #{synonym['table_owner']}.#{synonym['table_name']}"
180
+ end
181
+
182
+ join_with_statement_token(structure)
183
+ end
184
+
185
+ def structure_drop #:nodoc:
186
+ statements = select_values("SELECT sequence_name FROM user_sequences ORDER BY 1").map do |seq|
187
+ "DROP SEQUENCE \"#{seq}\""
188
+ end
189
+ select_values("SELECT table_name from all_tables t
190
+ WHERE owner = SYS_CONTEXT('userenv', 'session_user') AND secondary = 'N'
191
+ AND NOT EXISTS (SELECT mv.mview_name FROM all_mviews mv WHERE mv.owner = t.owner AND mv.mview_name = t.table_name)
192
+ AND NOT EXISTS (SELECT mvl.log_table FROM all_mview_logs mvl WHERE mvl.log_owner = t.owner AND mvl.log_table = t.table_name)
193
+ ORDER BY 1").each do |table|
194
+ statements << "DROP TABLE \"#{table}\" CASCADE CONSTRAINTS"
195
+ end
196
+ join_with_statement_token(statements)
197
+ end
198
+
199
+ def temp_table_drop #:nodoc:
200
+ join_with_statement_token(select_values(
201
+ "SELECT table_name FROM all_tables
202
+ WHERE owner = SYS_CONTEXT('userenv', 'session_user') AND secondary = 'N' AND temporary = 'Y' ORDER BY 1").map do |table|
203
+ "DROP TABLE \"#{table}\" CASCADE CONSTRAINTS"
204
+ end)
205
+ end
206
+
207
+ def full_drop(preserve_tables=false) #:nodoc:
208
+ s = preserve_tables ? [] : [structure_drop]
209
+ s << temp_table_drop if preserve_tables
210
+ s << drop_sql_for_feature("view")
211
+ s << drop_sql_for_feature("materialized view")
212
+ s << drop_sql_for_feature("synonym")
213
+ s << drop_sql_for_feature("type")
214
+ s << drop_sql_for_object("package")
215
+ s << drop_sql_for_object("function")
216
+ s << drop_sql_for_object("procedure")
217
+ s.join
218
+ end
219
+
220
+ def add_column_options!(sql, options) #:nodoc:
221
+ type = options[:type] || ((column = options[:column]) && column.type)
222
+ type = type && type.to_sym
223
+ # handle case of defaults for CLOB columns, which would otherwise get "quoted" incorrectly
224
+ if options_include_default?(options)
225
+ if type == :text
226
+ sql << " DEFAULT #{quote(options[:default])}"
227
+ else
228
+ # from abstract adapter
229
+ sql << " DEFAULT #{quote(options[:default], options[:column])}"
230
+ end
231
+ end
232
+ # must explicitly add NULL or NOT NULL to allow change_column to work on migrations
233
+ if options[:null] == false
234
+ sql << " NOT NULL"
235
+ elsif options[:null] == true
236
+ sql << " NULL" unless type == :primary_key
237
+ end
238
+ # add AS expression for virtual columns
239
+ if options[:as].present?
240
+ sql << " AS (#{options[:as]})"
241
+ end
242
+ end
243
+
244
+ def execute_structure_dump(string)
245
+ string.split(STATEMENT_TOKEN).each do |ddl|
246
+ ddl.chop! if ddl[-1,1] == ';'
247
+ execute(ddl) unless ddl.blank?
248
+ end
249
+ end
250
+
251
+ private
252
+
253
+ # virtual columns are an 11g feature. This returns [] if feature is not
254
+ # present or none are found.
255
+ # return [{'column_name' => 'FOOS', 'data_default' => '...'}, ...]
256
+ def virtual_columns_for(table)
257
+ begin
258
+ select_all <<-SQL
259
+ SELECT column_name, data_default
260
+ FROM user_tab_cols
261
+ WHERE virtual_column = 'YES'
262
+ AND table_name = '#{table.upcase}'
263
+ SQL
264
+ # feature not supported previous to 11g
265
+ rescue ActiveRecord::StatementInvalid => e
266
+ []
267
+ end
268
+ end
269
+
270
+ def drop_sql_for_feature(type)
271
+ short_type = type == 'materialized view' ? 'mview' : type
272
+ join_with_statement_token(
273
+ select_values("SELECT #{short_type}_name FROM user_#{short_type.tableize}").map do |name|
274
+ "DROP #{type.upcase} \"#{name}\""
275
+ end)
276
+ end
277
+
278
+ def drop_sql_for_object(type)
279
+ join_with_statement_token(
280
+ select_values("SELECT object_name FROM user_objects WHERE object_type = '#{type.upcase}'").map do |name|
281
+ "DROP #{type.upcase} \"#{name}\""
282
+ end)
283
+ end
284
+
285
+ def join_with_statement_token(array)
286
+ string = array.join(STATEMENT_TOKEN)
287
+ string << STATEMENT_TOKEN unless string.blank?
288
+ string
289
+ end
290
+
291
+ end
292
+ end
293
+ end
294
+
295
+ ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter.class_eval do
296
+ include ActiveRecord::ConnectionAdapters::OracleEnhancedStructureDump
297
+ end
@@ -0,0 +1,65 @@
1
+ require 'arjdbc/tasks/jdbc_database_tasks'
2
+
3
+ module ArJdbc
4
+ module Tasks
5
+ class OracleDatabaseTasks < JdbcDatabaseTasks
6
+
7
+ def create
8
+ print "Please provide the SYSTEM password for your oracle installation\n>"
9
+ system_password = $stdin.gets.strip
10
+ establish_connection(config.merge('username' => 'SYSTEM', 'password' => system_password))
11
+ unless ( config = self.config ).key?('username')
12
+ config = config_from_url(config['url']) if config['url']
13
+ end
14
+ begin
15
+ connection.execute "CREATE USER #{config['username']} IDENTIFIED BY #{config['password']}"
16
+ rescue => e
17
+ if e.message =~ /ORA-01920/ # user name conflicts with another user or role name
18
+ connection.execute "ALTER USER #{config['username']} IDENTIFIED BY #{config['password']}"
19
+ else
20
+ raise e
21
+ end
22
+ end
23
+ connection.execute "GRANT unlimited tablespace TO #{config['username']}"
24
+ connection.execute "GRANT create session TO #{config['username']}"
25
+ connection.execute "GRANT create table TO #{config['username']}"
26
+ connection.execute "GRANT create sequence TO #{config['username']}"
27
+ end
28
+
29
+ def drop
30
+ self.class.load_enhanced_structure_dump
31
+ establish_connection(config)
32
+ connection.execute_structure_dump(connection.full_drop)
33
+ end
34
+
35
+ def purge
36
+ self.class.load_enhanced_structure_dump
37
+ establish_connection(:test)
38
+ connection.execute_structure_dump(connection.full_drop)
39
+ connection.execute("PURGE RECYCLEBIN") rescue nil
40
+ end
41
+
42
+ def structure_dump(filename)
43
+ self.class.load_enhanced_structure_dump
44
+ establish_connection(config)
45
+ File.open(filename, "w:utf-8") { |f| f << connection.structure_dump }
46
+ end
47
+
48
+ def structure_load(filename)
49
+ self.class.load_enhanced_structure_dump
50
+ establish_connection(config)
51
+ connection.execute_structure_dump(File.read(filename))
52
+ end
53
+
54
+ def self.load_enhanced_structure_dump
55
+ unless defined? ActiveRecord::ConnectionAdapters::OracleEnhancedAdapter
56
+ ActiveRecord::ConnectionAdapters.module_eval do
57
+ const_set :OracleEnhancedAdapter, ActiveRecord::ConnectionAdapters::OracleAdapter
58
+ end
59
+ end
60
+ require 'arjdbc/tasks/oracle/enhanced_structure_dump'
61
+ end
62
+
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,60 @@
1
+ module ArJdbc
2
+ module Util
3
+ # Caches table and column name (quoted) outcomes.
4
+ # Uses {ThreadSafe::Cache} as a concurrent lock free (on JRuby) cache backend.
5
+ # The thread_safe gem is a dependency since ActiveSupport 4.0, when using
6
+ # ActiveRecord <= 3.2 one should add `gem 'thread_safe'` into the *Gemfile*
7
+ # as it is not forced (currently) as an explicit gem dependency.
8
+ #
9
+ # Caching can also be disabled by setting the *arjdbc.quoted_cache.disabled*
10
+ # system property = 'true'.
11
+ module QuotedCache
12
+
13
+ # @private
14
+ DISABLED = Java::JavaLang::Boolean.getBoolean('arjdbc.quoted_cache.disabled')
15
+
16
+ def self.included(base)
17
+ # the thread_safe gem is an ActiveSupport dependency (since 4.0) :
18
+ begin; require 'thread_safe'; rescue LoadError; end unless DISABLED
19
+ if ! DISABLED && defined? ThreadSafe::Cache
20
+ base.const_set :QUOTED_TABLE_NAMES, ThreadSafe::Cache.new
21
+ base.const_set :QUOTED_COLUMN_NAMES, ThreadSafe::Cache.new
22
+ else
23
+ base.const_set :QUOTED_TABLE_NAMES, nil
24
+ base.const_set :QUOTED_COLUMN_NAMES, nil
25
+ end
26
+ end
27
+
28
+ # Caches quoted table names, the cache is stored in the class'
29
+ # `QUOTED_TABLE_NAMES` constant.
30
+ # @return [String]
31
+ def quote_table_name(name, *args)
32
+ if cache = self.class::QUOTED_TABLE_NAMES
33
+ unless quoted = cache[name]
34
+ quoted = super
35
+ cache.put_if_absent name, quoted.freeze
36
+ end
37
+ quoted
38
+ else
39
+ super
40
+ end
41
+ end
42
+
43
+ # Caches quoted table names, the cache is stored in the class'
44
+ # `QUOTED_COLUMN_NAMES` constant.
45
+ # @return [String]
46
+ def quote_column_name(name, *args)
47
+ if cache = self.class::QUOTED_COLUMN_NAMES
48
+ unless quoted = cache[name]
49
+ quoted = super
50
+ cache.put_if_absent name, quoted.freeze
51
+ end
52
+ quoted
53
+ else
54
+ super
55
+ end
56
+ end
57
+
58
+ end
59
+ end
60
+ end