activerecord-odbc-adapter 2.0

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 (74) hide show
  1. data/AUTHORS +16 -0
  2. data/COPYING +21 -0
  3. data/ChangeLog +139 -0
  4. data/LICENSE +5 -0
  5. data/NEWS +25 -0
  6. data/README +229 -0
  7. data/lib/active_record/connection_adapters/odbc_adapter.rb +1950 -0
  8. data/lib/active_record/vendor/odbcext_db2.rb +87 -0
  9. data/lib/active_record/vendor/odbcext_informix.rb +144 -0
  10. data/lib/active_record/vendor/odbcext_informix_col.rb +45 -0
  11. data/lib/active_record/vendor/odbcext_ingres.rb +156 -0
  12. data/lib/active_record/vendor/odbcext_microsoftsqlserver.rb +216 -0
  13. data/lib/active_record/vendor/odbcext_microsoftsqlserver_col.rb +40 -0
  14. data/lib/active_record/vendor/odbcext_mysql.rb +174 -0
  15. data/lib/active_record/vendor/odbcext_oracle.rb +219 -0
  16. data/lib/active_record/vendor/odbcext_postgresql.rb +158 -0
  17. data/lib/active_record/vendor/odbcext_progress.rb +139 -0
  18. data/lib/active_record/vendor/odbcext_progress89.rb +259 -0
  19. data/lib/active_record/vendor/odbcext_sqlanywhere.rb +115 -0
  20. data/lib/active_record/vendor/odbcext_sqlanywhere_col.rb +49 -0
  21. data/lib/active_record/vendor/odbcext_sybase.rb +213 -0
  22. data/lib/active_record/vendor/odbcext_sybase_col.rb +49 -0
  23. data/lib/active_record/vendor/odbcext_virtuoso.rb +158 -0
  24. data/lib/odbc_adapter.rb +28 -0
  25. data/support/lib/active_record/connection_adapters/abstract/schema_definitions.rb +259 -0
  26. data/support/odbc_rails.diff +367 -0
  27. data/support/pack_odbc.rb +119 -0
  28. data/support/rake/rails_plugin_package_task.rb +212 -0
  29. data/support/rake_fixes/README +6 -0
  30. data/support/rake_fixes/databases.dif +13 -0
  31. data/support/test/base_test.rb +1765 -0
  32. data/support/test/migration_test.rb +1007 -0
  33. data/test/connections/native_odbc/connection.rb +137 -0
  34. data/test/fixtures/db_definitions/db2.drop.sql +33 -0
  35. data/test/fixtures/db_definitions/db2.sql +237 -0
  36. data/test/fixtures/db_definitions/db22.drop.sql +2 -0
  37. data/test/fixtures/db_definitions/db22.sql +5 -0
  38. data/test/fixtures/db_definitions/informix.drop.sql +33 -0
  39. data/test/fixtures/db_definitions/informix.sql +223 -0
  40. data/test/fixtures/db_definitions/informix2.drop.sql +2 -0
  41. data/test/fixtures/db_definitions/informix2.sql +5 -0
  42. data/test/fixtures/db_definitions/ingres.drop.sql +68 -0
  43. data/test/fixtures/db_definitions/ingres.sql +252 -0
  44. data/test/fixtures/db_definitions/ingres2.drop.sql +2 -0
  45. data/test/fixtures/db_definitions/ingres2.sql +5 -0
  46. data/test/fixtures/db_definitions/mysql.drop.sql +33 -0
  47. data/test/fixtures/db_definitions/mysql.sql +238 -0
  48. data/test/fixtures/db_definitions/mysql2.drop.sql +2 -0
  49. data/test/fixtures/db_definitions/mysql2.sql +5 -0
  50. data/test/fixtures/db_definitions/oracle_odbc.drop.sql +72 -0
  51. data/test/fixtures/db_definitions/oracle_odbc.sql +296 -0
  52. data/test/fixtures/db_definitions/oracle_odbc2.drop.sql +2 -0
  53. data/test/fixtures/db_definitions/oracle_odbc2.sql +6 -0
  54. data/test/fixtures/db_definitions/postgresql.drop.sql +38 -0
  55. data/test/fixtures/db_definitions/postgresql.sql +267 -0
  56. data/test/fixtures/db_definitions/postgresql2.drop.sql +2 -0
  57. data/test/fixtures/db_definitions/postgresql2.sql +5 -0
  58. data/test/fixtures/db_definitions/progress.drop.sql +67 -0
  59. data/test/fixtures/db_definitions/progress.sql +255 -0
  60. data/test/fixtures/db_definitions/progress2.drop.sql +2 -0
  61. data/test/fixtures/db_definitions/progress2.sql +6 -0
  62. data/test/fixtures/db_definitions/sqlserver.drop.sql +35 -0
  63. data/test/fixtures/db_definitions/sqlserver.sql +247 -0
  64. data/test/fixtures/db_definitions/sqlserver2.drop.sql +2 -0
  65. data/test/fixtures/db_definitions/sqlserver2.sql +5 -0
  66. data/test/fixtures/db_definitions/sybase.drop.sql +35 -0
  67. data/test/fixtures/db_definitions/sybase.sql +222 -0
  68. data/test/fixtures/db_definitions/sybase2.drop.sql +4 -0
  69. data/test/fixtures/db_definitions/sybase2.sql +5 -0
  70. data/test/fixtures/db_definitions/virtuoso.drop.sql +33 -0
  71. data/test/fixtures/db_definitions/virtuoso.sql +218 -0
  72. data/test/fixtures/db_definitions/virtuoso2.drop.sql +2 -0
  73. data/test/fixtures/db_definitions/virtuoso2.sql +5 -0
  74. metadata +166 -0
@@ -0,0 +1,40 @@
1
+ #
2
+ # $Id: odbcext_microsoftsqlserver_col.rb,v 1.1 2006/12/06 14:42:11 source Exp $
3
+ #
4
+ # OpenLink ODBC Adapter for Ruby on Rails
5
+ # Copyright (C) 2006 OpenLink Software
6
+ #
7
+ # Permission is hereby granted, free of charge, to any person obtaining
8
+ # a copy of this software and associated documentation files (the
9
+ # "Software"), to deal in the Software without restriction, including
10
+ # without limitation the rights to use, copy, modify, merge, publish,
11
+ # distribute, sublicense, and/or sell copies of the Software, and to
12
+ # permit persons to whom the Software is furnished to do so, subject
13
+ # to the following conditions:
14
+ #
15
+ # The above copyright notice and this permission notice shall be
16
+ # included in all copies or substantial portions of the Software.
17
+ #
18
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21
+ # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
22
+ # ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
23
+ # CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
+ #
26
+
27
+ module ODBCColumnExt
28
+
29
+ # Is the column a numeric autoincrementing column?
30
+ def auto_unique?
31
+ @autounique
32
+ end
33
+
34
+ private
35
+
36
+ def autoUnique?
37
+ @nativeType =~ /\bidentity\b/i
38
+ end
39
+
40
+ end # module
@@ -0,0 +1,174 @@
1
+ #
2
+ # $Id: odbcext_mysql.rb,v 1.3 2008/04/13 22:46:09 source Exp $
3
+ #
4
+ # OpenLink ODBC Adapter for Ruby on Rails
5
+ # Copyright (C) 2006 OpenLink Software
6
+ #
7
+ # Permission is hereby granted, free of charge, to any person obtaining
8
+ # a copy of this software and associated documentation files (the
9
+ # "Software"), to deal in the Software without restriction, including
10
+ # without limitation the rights to use, copy, modify, merge, publish,
11
+ # distribute, sublicense, and/or sell copies of the Software, and to
12
+ # permit persons to whom the Software is furnished to do so, subject
13
+ # to the following conditions:
14
+ #
15
+ # The above copyright notice and this permission notice shall be
16
+ # included in all copies or substantial portions of the Software.
17
+ #
18
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21
+ # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
22
+ # ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
23
+ # CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
+ #
26
+ module ODBCExt
27
+
28
+ # ------------------------------------------------------------------------
29
+ # Mandatory methods
30
+ #
31
+ # The ODBCAdapter core doesn't not implement these methods
32
+
33
+ # #last_insert_id must be implemented for any database which returns
34
+ # false from #prefetch_primary_key?
35
+ #
36
+ # This method assumes that the table inserted into has a primary key defined
37
+ # as INT AUTOINCREMENT
38
+ def last_insert_id(table, sequence_name, stmt = nil)
39
+ @logger.unknown("ODBCAdapter#last_insert_id>") if @trace
40
+ select_value("select LAST_INSERT_ID()", 'last_insert_id')
41
+ end
42
+
43
+ # ------------------------------------------------------------------------
44
+ # Optional methods
45
+ #
46
+ # These are supplied for a DBMS only if necessary.
47
+ # ODBCAdapter tests for optional methods using Object#respond_to?
48
+
49
+ # Pre action for ODBCAdapter#insert
50
+ # def pre_insert(sql, name, pk, id_value, sequence_name)
51
+ # end
52
+
53
+ # Post action for ODBCAdapter#insert
54
+ # def post_insert(sql, name, pk, id_value, sequence_name)
55
+ # end
56
+
57
+ # ------------------------------------------------------------------------
58
+ # Method redefinitions
59
+ #
60
+ # DBMS specific methods which override the default implementation
61
+ # provided by the ODBCAdapter core.
62
+
63
+ def quote_string(string)
64
+ @logger.unknown("ODBCAdapter#quote_string>") if @trace
65
+
66
+ # MySQL requires backslashes to be escaped
67
+ string.gsub(/\\/, '\&\&').gsub(/'/, "''")
68
+ end
69
+
70
+ def create_database(name)
71
+ @logger.unknown("ODBCAdapter#create_database>") if @trace
72
+ @logger.unknown("args=[#{name}]") if @trace
73
+ execute "CREATE DATABASE `#{name}`"
74
+ rescue Exception => e
75
+ @logger.unknown("exception=#{e}") if @trace
76
+ raise
77
+ end
78
+
79
+ def drop_database(name)
80
+ @logger.unknown("ODBCAdapter#drop_database>") if @trace
81
+ @logger.unknown("args=[#{name}]") if @trace
82
+ execute "DROP DATABASE IF EXISTS `#{name}`"
83
+ rescue Exception => e
84
+ @logger.unknown("exception=#{e}") if @trace
85
+ raise
86
+ end
87
+
88
+ def create_table(name, options = {})
89
+ @logger.unknown("ODBCAdapter#create_table>") if @trace
90
+ super(name, {:options => "ENGINE=InnoDB"}.merge(options))
91
+ rescue Exception => e
92
+ @logger.unknown("exception=#{e}") if @trace
93
+ raise
94
+ end
95
+
96
+ def rename_table(name, new_name)
97
+ @logger.unknown("ODBCAdapter#rename_table>") if @trace
98
+ execute "RENAME TABLE #{name} TO #{new_name}"
99
+ rescue Exception => e
100
+ @logger.unknown("exception=#{e}") if @trace
101
+ raise
102
+ end
103
+
104
+ def change_column(table_name, column_name, type, options = {})
105
+ @logger.unknown("ODBCAdapter#change_column>") if @trace
106
+ # column_name.to_s used in case column_name is a symbol
107
+ unless options_include_default?(options)
108
+ options[:default] = columns(table_name).find { |c| c.name == column_name.to_s }.default
109
+ end
110
+ change_column_sql = "ALTER TABLE #{table_name} CHANGE #{column_name} #{column_name} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}"
111
+ add_column_options!(change_column_sql, options)
112
+ execute(change_column_sql)
113
+ rescue Exception => e
114
+ @logger.unknown("exception=#{e}") if @trace
115
+ raise
116
+ end
117
+
118
+ def rename_column(table_name, column_name, new_column_name)
119
+ @logger.unknown("ODBCAdapter#rename_column>") if @trace
120
+ col = columns(table_name).find{ |c| c.name == column_name.to_s }
121
+ current_type = col.sql_type
122
+ current_type << "(#{col.limit})" if col.limit
123
+ execute "ALTER TABLE #{table_name} CHANGE #{column_name} #{new_column_name} #{current_type}"
124
+ rescue Exception => e
125
+ @logger.unknown("exception=#{e}") if @trace
126
+ raise
127
+ end
128
+
129
+ def change_column_default(table_name, column_name, default)
130
+ @logger.unknown("ODBCAdapter#change_column_default>") if @trace
131
+ col = columns(table_name).find{ |c| c.name == column_name.to_s }
132
+ change_column(table_name, column_name, col.type, :default => default,
133
+ :limit => col.limit, :precision => col.precision, :scale => col.scale)
134
+ rescue Exception => e
135
+ @logger.unknown("exception=#{e}") if @trace
136
+ raise
137
+ end
138
+
139
+ def indexes(table_name, name = nil)
140
+ # Skip primary key indexes
141
+ super(table_name, name).delete_if { |i| i.unique && i.name =~ /^PRIMARY$/ }
142
+ end
143
+
144
+ def options_include_default?(options)
145
+ # MySQL 5.x doesn't allow DEFAULT NULL for first timestamp column in a table
146
+ if options.include?(:default) && options[:default].nil?
147
+ if options.include?(:column) && options[:column].sql_type =~ /timestamp/i
148
+ options.delete(:default)
149
+ end
150
+ end
151
+ super(options)
152
+ end
153
+
154
+ def disable_referential_integrity(&block) #:nodoc:
155
+ old = select_value("SELECT @@FOREIGN_KEY_CHECKS")
156
+ begin
157
+ update("SET FOREIGN_KEY_CHECKS = 0")
158
+ yield
159
+ ensure
160
+ update("SET FOREIGN_KEY_CHECKS = #{old}")
161
+ end
162
+ end
163
+
164
+ def structure_dump
165
+ @logger.unknown("ODBCAdapter#structure_dump>") if @trace
166
+ select_all("SHOW TABLES").inject("") do |structure, table|
167
+ structure += select_one("SHOW CREATE TABLE #{table.to_a.first.last}")["Create Table"] + ";\n\n"
168
+ end
169
+ rescue Exception => e
170
+ @logger.unknown("exception=#{e}") if @trace
171
+ raise
172
+ end
173
+
174
+ end
@@ -0,0 +1,219 @@
1
+ #
2
+ # $Id: odbcext_oracle.rb,v 1.3 2008/04/13 22:46:09 source Exp $
3
+ #
4
+ # OpenLink ODBC Adapter for Ruby on Rails
5
+ # Copyright (C) 2006 OpenLink Software
6
+ #
7
+ # Permission is hereby granted, free of charge, to any person obtaining
8
+ # a copy of this software and associated documentation files (the
9
+ # "Software"), to deal in the Software without restriction, including
10
+ # without limitation the rights to use, copy, modify, merge, publish,
11
+ # distribute, sublicense, and/or sell copies of the Software, and to
12
+ # permit persons to whom the Software is furnished to do so, subject
13
+ # to the following conditions:
14
+ #
15
+ # The above copyright notice and this permission notice shall be
16
+ # included in all copies or substantial portions of the Software.
17
+ #
18
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21
+ # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
22
+ # ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
23
+ # CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
+ #
26
+
27
+ module ODBCExt
28
+
29
+ # ------------------------------------------------------------------------
30
+ # Mandatory methods
31
+ #
32
+
33
+ # #last_insert_id must be implemented for any database which returns
34
+ # false from #prefetch_primary_key?
35
+ # (This adapter returns true for Oracle)
36
+
37
+ #def last_insert_id(table, sequence_name, stmt = nil)
38
+ #end
39
+
40
+ # #next_sequence_value must be implemented for any database which returns
41
+ # true from #prefetch_primary_key?
42
+ #
43
+ # Returns the next sequence value from a sequence generator. Not generally
44
+ # called directly; used by ActiveRecord to get the next primary key value
45
+ # when inserting a new database record (see #prefetch_primary_key?).
46
+ def next_sequence_value(sequence_name)
47
+ @logger.unknown("ODBCAdapter#next_sequence_value>") if @trace
48
+ #@logger.unknown("args=[#{sequence_name}]") if @trace
49
+ select_one("select #{sequence_name}.nextval id from dual")['id']
50
+ end
51
+
52
+ # ------------------------------------------------------------------------
53
+ # Optional methods
54
+ #
55
+ # These are supplied for a DBMS only if necessary.
56
+ # ODBCAdapter tests for optional methods using Object#respond_to?
57
+
58
+ # Pre action for ODBCAdapter#insert
59
+ # def pre_insert(sql, name, pk, id_value, sequence_name)
60
+ # end
61
+
62
+ # Post action for ODBCAdapter#insert
63
+ # def post_insert(sql, name, pk, id_value, sequence_name)
64
+ # end
65
+
66
+ # ------------------------------------------------------------------------
67
+ # Method redefinitions
68
+ #
69
+ # DBMS specific methods which override the default implementation
70
+ # provided by the ODBCAdapter core.
71
+
72
+ def quoted_date(value)
73
+ @logger.unknown("ODBCAdapter#quoted_date>") if @trace
74
+ # Ideally, we'd return an ODBC date or timestamp literal escape
75
+ # sequence, but not all ODBC drivers support them.
76
+ if value.acts_like?(:time) # Time, DateTime
77
+ #%Q!{ts '#{value.strftime("%Y-%m-%d %H:%M:%S")}'}!
78
+ "to_timestamp(\'#{value.strftime("%Y-%m-%d %H:%M:%S")}\', \'YYYY-MM-DD HH24:MI:SS\')"
79
+ else # Date
80
+ #%Q!{d '#{value.strftime("%Y-%m-%d")}'}!
81
+ "to_timestamp(\'#{value.strftime("%Y-%m-%d")}\', \'YYYY-MM-DD\')"
82
+ end
83
+ end
84
+
85
+ def create_table(name, options = {})
86
+ @logger.unknown("ODBCAdapter#create_table>") if @trace
87
+ super(name, options)
88
+ # Some ActiveRecord tests insert using an explicit id value. Starting the
89
+ # primary key sequence from 10000 eliminates collisions (and subsequent
90
+ # complaints from Oracle of integrity constraint violations) between id's
91
+ # generated from the sequence and explicitly supplied ids.
92
+ # Using explicit and generated id's together should be avoided.
93
+ execute "CREATE SEQUENCE #{name}_seq START WITH 10000" unless options[:id] == false
94
+ rescue Exception => e
95
+ @logger.unknown("exception=#{e}") if @trace
96
+ raise
97
+ end
98
+
99
+ def rename_table(name, new_name)
100
+ @logger.unknown("ODBCAdapter#rename_table>") if @trace
101
+ execute "RENAME #{name} TO #{new_name}"
102
+ execute "RENAME #{name}_seq TO #{new_name}_seq"
103
+ rescue Exception => e
104
+ @logger.unknown("exception=#{e}") if @trace
105
+ raise
106
+ end
107
+
108
+ def drop_table(name, options = {})
109
+ @logger.unknown("ODBCAdapter#drop_table>") if @trace
110
+ super(name, options)
111
+ execute "DROP SEQUENCE #{name}_seq"
112
+ rescue Exception => e
113
+ if e.message !~ /ORA-02289/i
114
+ # Error "ORA-02289: sequence does not exist" will be generated
115
+ # if the table was created with options[:id] == false
116
+ @logger.unknown("exception=#{e}") if @trace
117
+ raise
118
+ end
119
+ end
120
+
121
+ def remove_column(table_name, column_name)
122
+ @logger.unknown("ODBCAdapter#remove_column>") if @trace
123
+ execute "ALTER TABLE #{quote_table_name(table_name)} DROP COLUMN #{quote_column_name(column_name)}"
124
+ rescue Exception => e
125
+ @logger.unknown("exception=#{e}") if @trace
126
+ raise
127
+ end
128
+
129
+ def change_column(table_name, column_name, type, options = {})
130
+ @logger.unknown("ODBCAdapter#change_column>") if @trace
131
+ change_column_sql = "ALTER TABLE #{table_name} MODIFY #{column_name} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}"
132
+ add_column_options!(change_column_sql, options)
133
+ execute(change_column_sql)
134
+ rescue Exception => e
135
+ @logger.unknown("exception=#{e}") if @trace
136
+ raise
137
+ end
138
+
139
+ def change_column_default(table_name, column_name, default)
140
+ @logger.unknown("ODBCAdapter#change_column_default>") if @trace
141
+ execute "ALTER TABLE #{table_name} MODIFY #{column_name} DEFAULT #{quote(default)}"
142
+ rescue Exception => e
143
+ @logger.unknown("exception=#{e}") if @trace
144
+ raise
145
+ end
146
+
147
+ def rename_column(table_name, column_name, new_column_name)
148
+ @logger.unknown("ODBCAdapter#rename_column>") if @trace
149
+ execute "ALTER TABLE #{table_name} RENAME COLUMN #{column_name} to #{new_column_name}"
150
+ rescue Exception => e
151
+ @logger.unknown("exception=#{e}") if @trace
152
+ raise
153
+ end
154
+
155
+ def remove_index(table_name, options = {})
156
+ @logger.unknown("ODBCAdapter#remove_index>") if @trace
157
+ execute "DROP INDEX #{quote_column_name(index_name(table_name, options))}"
158
+ rescue Exception => e
159
+ @logger.unknown("exception=#{e}") if @trace
160
+ raise
161
+ end
162
+
163
+ def tables(name = nil)
164
+ # Hide dropped tables in Oracle's recyclebin.
165
+ super(name).delete_if {|t| t =~ /^BIN\$/i }
166
+ end
167
+
168
+ def indexes(table_name, name = nil)
169
+ # Oracle creates a unique index for a table's primary key.
170
+ # Hide any such index. Oracle uses system-generated names
171
+ # beginning with "SYS_" for implicitly generated schema objects.
172
+ #
173
+ # If this isn't done...
174
+ # Rails' 'rake test_units' attempts to create this index explicitly,
175
+ # but Oracle rejects this as the index has already been created
176
+ # automatically when the table was defined.
177
+ super(table_name, name).delete_if { |i| i.unique && i.name =~ /^SYS_/i }
178
+ end
179
+
180
+ def structure_dump
181
+ @logger.unknown("ODBCAdapter#structure_dump>") if @trace
182
+ s = select_all("select sequence_name from user_sequences").inject("") do |structure, seq|
183
+ structure << "create sequence #{seq.to_a.first.last};\n\n"
184
+ end
185
+
186
+ select_all("select table_name from user_tables").inject(s) do |structure, table|
187
+ ddl = "create table #{table.to_a.first.last} (\n "
188
+ cols = select_all(%Q{
189
+ select column_name, data_type, data_length, data_precision, data_scale, data_default, nullable
190
+ from user_tab_columns
191
+ where table_name = '#{table.to_a.first.last}'
192
+ order by column_id
193
+ }).map do |row|
194
+ col = "#{row['column_name'].downcase} #{row['data_type'].downcase}"
195
+ if row['data_type'] =='NUMBER' and !row['data_precision'].nil?
196
+ col << "(#{row['data_precision'].to_i}"
197
+ col << ",#{row['data_scale'].to_i}" if !row['data_scale'].nil?
198
+ col << ')'
199
+ elsif row['data_type'].include?('CHAR')
200
+ col << "(#{row['data_length'].to_i})"
201
+ end
202
+ col << " default #{row['data_default']}" if !row['data_default'].nil?
203
+ col << ' not null' if row['nullable'] == 'N'
204
+ col
205
+ end
206
+ ddl << cols.join(",\n ")
207
+ ddl << ");\n\n"
208
+ structure << ddl
209
+ end
210
+ rescue Exception => e
211
+ @logger.unknown("exception=#{e}") if @trace
212
+ raise
213
+ end
214
+
215
+ # ------------------------------------------------------------------------
216
+ # Private methods to support methods above
217
+ #
218
+
219
+ end # module
@@ -0,0 +1,158 @@
1
+ #
2
+ # $Id: odbcext_postgresql.rb,v 1.4 2008/04/13 22:46:09 source Exp $
3
+ #
4
+ # OpenLink ODBC Adapter for Ruby on Rails
5
+ # Copyright (C) 2006 OpenLink Software
6
+ #
7
+ # Permission is hereby granted, free of charge, to any person obtaining
8
+ # a copy of this software and associated documentation files (the
9
+ # "Software"), to deal in the Software without restriction, including
10
+ # without limitation the rights to use, copy, modify, merge, publish,
11
+ # distribute, sublicense, and/or sell copies of the Software, and to
12
+ # permit persons to whom the Software is furnished to do so, subject
13
+ # to the following conditions:
14
+ #
15
+ # The above copyright notice and this permission notice shall be
16
+ # included in all copies or substantial portions of the Software.
17
+ #
18
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21
+ # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
22
+ # ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
23
+ # CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
+ #
26
+
27
+ module ODBCExt
28
+
29
+ # ------------------------------------------------------------------------
30
+ # Mandatory methods
31
+ #
32
+
33
+ # #last_insert_id must be implemented for any database which returns
34
+ # false from #prefetch_primary_key?
35
+
36
+ def last_insert_id(table, sequence_name, stmt = nil)
37
+ select_value("select currval('#{sequence_name}')", 'last_insert_id')
38
+ end
39
+
40
+ # ------------------------------------------------------------------------
41
+ # Optional methods
42
+ #
43
+ # These are supplied for a DBMS only if necessary.
44
+ # ODBCAdapter tests for optional methods using Object#respond_to?
45
+
46
+ # Filter for ODBCAdapter#tables
47
+ # Omits table from #tables if table_filter returns true
48
+ def table_filter(schemaName, tblName, tblType)
49
+ ["information_schema", "pg_catalog"].include?(schemaName) || tblType !~ /TABLE/i
50
+ end
51
+
52
+ # Pre action for ODBCAdapter#insert
53
+ # def pre_insert(sql, name, pk, id_value, sequence_name)
54
+ # end
55
+
56
+ # Post action for ODBCAdapter#insert
57
+ # def post_insert(sql, name, pk, id_value, sequence_name)
58
+ # end
59
+
60
+ def string_to_binary(value)
61
+ # Escape data prior to insert into a bytea column
62
+ if value
63
+ res = ''
64
+ value.each_byte { |b| res << sprintf('\\\\%03o', b) }
65
+ res
66
+ end
67
+ end
68
+
69
+ # ------------------------------------------------------------------------
70
+ # Method redefinitions
71
+ #
72
+ # DBMS specific methods which override the default implementation
73
+ # provided by the ODBCAdapter core.
74
+
75
+ def quoted_true
76
+ "'t'"
77
+ end
78
+
79
+ def quoted_false
80
+ "'f'"
81
+ end
82
+
83
+ def quote_string(string)
84
+ @logger.unknown("ODBCAdapter#quote_string>") if @trace
85
+ string.gsub(/\\/, '\&\&').gsub(/'/, "''")
86
+ end
87
+
88
+ def default_sequence_name(table, column)
89
+ @logger.unknown("ODBCAdapter#default_sequence_name>") if @trace
90
+ @logger.unknown("args=[#{table}|#{column}]") if @trace
91
+ "#{table}_#{column}_seq"
92
+ end
93
+
94
+ def indexes(table_name, name = nil)
95
+ # Exclude primary key indexes
96
+ super(table_name, name).delete_if { |i| i.unique && i.name =~ /_pkey$/i }
97
+ end
98
+
99
+ def rename_table(name, new_name)
100
+ @logger.unknown("ODBCAdapter#rename_table>") if @trace
101
+ execute "ALTER TABLE #{name} RENAME TO #{new_name}"
102
+ rescue Exception => e
103
+ @logger.unknown("exception=#{e}") if @trace
104
+ raise
105
+ end
106
+
107
+ def add_column(table_name, column_name, type, options = {})
108
+ @logger.unknown("ODBCAdapter#add_column>") if @trace
109
+ sql = "ALTER TABLE #{table_name} ADD #{column_name} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}"
110
+ sql << " NOT NULL" if options[:null] == false
111
+ sql << " DEFAULT #{quote(options[:default])}" if options[:default]
112
+ execute(sql)
113
+ rescue Exception => e
114
+ @logger.unknown("exception=#{e}") if @trace
115
+ raise
116
+ end
117
+
118
+ def change_column(table_name, column_name, type, options = {})
119
+ @logger.unknown("ODBCAdapter#change_column>") if @trace
120
+ execute "ALTER TABLE #{table_name} ALTER #{column_name} TYPE #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}"
121
+ change_column_default(table_name, column_name, options[:default]) if options_include_default?(options)
122
+ rescue Exception => e
123
+ @logger.unknown("exception=#{e}") if @trace
124
+ raise
125
+ end
126
+
127
+ def change_column_default(table_name, column_name, default)
128
+ @logger.unknown("ODBCAdapter#change_column_default>") if @trace
129
+ execute "ALTER TABLE #{table_name} ALTER COLUMN #{column_name} SET DEFAULT #{quote(default)}"
130
+ rescue Exception => e
131
+ @logger.unknown("exception=#{e}") if @trace
132
+ raise
133
+ end
134
+
135
+ def rename_column(table_name, column_name, new_column_name)
136
+ @logger.unknown("ODBCAdapter#rename_column>") if @trace
137
+ execute "ALTER TABLE #{table_name} RENAME #{column_name} TO #{new_column_name}"
138
+ rescue Exception => e
139
+ @logger.unknown("exception=#{e}") if @trace
140
+ raise
141
+ end
142
+
143
+ def remove_index(table_name, options = {})
144
+ @logger.unknown("ODBCAdapter#remove_index>") if @trace
145
+ execute "DROP INDEX #{index_name(table_name, options)}"
146
+ rescue Exception => e
147
+ @logger.unknown("exception=#{e}") if @trace
148
+ raise
149
+ end
150
+
151
+ def disable_referential_integrity(&block) #:nodoc:
152
+ execute(tables.collect { |name| "ALTER TABLE #{quote_table_name(name)} DISABLE TRIGGER ALL" }.join(";"))
153
+ yield
154
+ ensure
155
+ execute(tables.collect { |name| "ALTER TABLE #{quote_table_name(name)} ENABLE TRIGGER ALL" }.join(";"))
156
+ end
157
+
158
+ end # module