activerecord-odbc-adapter 2.0

Sign up to get free protection for your applications and to get access to all the features.
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