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