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.
- data/AUTHORS +16 -0
- data/COPYING +21 -0
- data/ChangeLog +139 -0
- data/LICENSE +5 -0
- data/NEWS +25 -0
- data/README +229 -0
- data/lib/active_record/connection_adapters/odbc_adapter.rb +1950 -0
- data/lib/active_record/vendor/odbcext_db2.rb +87 -0
- data/lib/active_record/vendor/odbcext_informix.rb +144 -0
- data/lib/active_record/vendor/odbcext_informix_col.rb +45 -0
- data/lib/active_record/vendor/odbcext_ingres.rb +156 -0
- data/lib/active_record/vendor/odbcext_microsoftsqlserver.rb +216 -0
- data/lib/active_record/vendor/odbcext_microsoftsqlserver_col.rb +40 -0
- data/lib/active_record/vendor/odbcext_mysql.rb +174 -0
- data/lib/active_record/vendor/odbcext_oracle.rb +219 -0
- data/lib/active_record/vendor/odbcext_postgresql.rb +158 -0
- data/lib/active_record/vendor/odbcext_progress.rb +139 -0
- data/lib/active_record/vendor/odbcext_progress89.rb +259 -0
- data/lib/active_record/vendor/odbcext_sqlanywhere.rb +115 -0
- data/lib/active_record/vendor/odbcext_sqlanywhere_col.rb +49 -0
- data/lib/active_record/vendor/odbcext_sybase.rb +213 -0
- data/lib/active_record/vendor/odbcext_sybase_col.rb +49 -0
- data/lib/active_record/vendor/odbcext_virtuoso.rb +158 -0
- data/lib/odbc_adapter.rb +28 -0
- data/support/lib/active_record/connection_adapters/abstract/schema_definitions.rb +259 -0
- data/support/odbc_rails.diff +367 -0
- data/support/pack_odbc.rb +119 -0
- data/support/rake/rails_plugin_package_task.rb +212 -0
- data/support/rake_fixes/README +6 -0
- data/support/rake_fixes/databases.dif +13 -0
- data/support/test/base_test.rb +1765 -0
- data/support/test/migration_test.rb +1007 -0
- data/test/connections/native_odbc/connection.rb +137 -0
- data/test/fixtures/db_definitions/db2.drop.sql +33 -0
- data/test/fixtures/db_definitions/db2.sql +237 -0
- data/test/fixtures/db_definitions/db22.drop.sql +2 -0
- data/test/fixtures/db_definitions/db22.sql +5 -0
- data/test/fixtures/db_definitions/informix.drop.sql +33 -0
- data/test/fixtures/db_definitions/informix.sql +223 -0
- data/test/fixtures/db_definitions/informix2.drop.sql +2 -0
- data/test/fixtures/db_definitions/informix2.sql +5 -0
- data/test/fixtures/db_definitions/ingres.drop.sql +68 -0
- data/test/fixtures/db_definitions/ingres.sql +252 -0
- data/test/fixtures/db_definitions/ingres2.drop.sql +2 -0
- data/test/fixtures/db_definitions/ingres2.sql +5 -0
- data/test/fixtures/db_definitions/mysql.drop.sql +33 -0
- data/test/fixtures/db_definitions/mysql.sql +238 -0
- data/test/fixtures/db_definitions/mysql2.drop.sql +2 -0
- data/test/fixtures/db_definitions/mysql2.sql +5 -0
- data/test/fixtures/db_definitions/oracle_odbc.drop.sql +72 -0
- data/test/fixtures/db_definitions/oracle_odbc.sql +296 -0
- data/test/fixtures/db_definitions/oracle_odbc2.drop.sql +2 -0
- data/test/fixtures/db_definitions/oracle_odbc2.sql +6 -0
- data/test/fixtures/db_definitions/postgresql.drop.sql +38 -0
- data/test/fixtures/db_definitions/postgresql.sql +267 -0
- data/test/fixtures/db_definitions/postgresql2.drop.sql +2 -0
- data/test/fixtures/db_definitions/postgresql2.sql +5 -0
- data/test/fixtures/db_definitions/progress.drop.sql +67 -0
- data/test/fixtures/db_definitions/progress.sql +255 -0
- data/test/fixtures/db_definitions/progress2.drop.sql +2 -0
- data/test/fixtures/db_definitions/progress2.sql +6 -0
- data/test/fixtures/db_definitions/sqlserver.drop.sql +35 -0
- data/test/fixtures/db_definitions/sqlserver.sql +247 -0
- data/test/fixtures/db_definitions/sqlserver2.drop.sql +2 -0
- data/test/fixtures/db_definitions/sqlserver2.sql +5 -0
- data/test/fixtures/db_definitions/sybase.drop.sql +35 -0
- data/test/fixtures/db_definitions/sybase.sql +222 -0
- data/test/fixtures/db_definitions/sybase2.drop.sql +4 -0
- data/test/fixtures/db_definitions/sybase2.sql +5 -0
- data/test/fixtures/db_definitions/virtuoso.drop.sql +33 -0
- data/test/fixtures/db_definitions/virtuoso.sql +218 -0
- data/test/fixtures/db_definitions/virtuoso2.drop.sql +2 -0
- data/test/fixtures/db_definitions/virtuoso2.sql +5 -0
- 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
|