odbc-rails 1.2
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 +89 -0
- data/LICENSE +5 -0
- data/NEWS +12 -0
- data/README +282 -0
- data/lib/active_record/connection_adapters/odbc_adapter.rb +1792 -0
- data/lib/active_record/vendor/odbcext_db2.rb +87 -0
- data/lib/active_record/vendor/odbcext_informix.rb +132 -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 +185 -0
- data/lib/active_record/vendor/odbcext_microsoftsqlserver_col.rb +40 -0
- data/lib/active_record/vendor/odbcext_mysql.rb +136 -0
- data/lib/active_record/vendor/odbcext_oracle.rb +220 -0
- data/lib/active_record/vendor/odbcext_postgresql.rb +179 -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_sybase.rb +212 -0
- data/lib/active_record/vendor/odbcext_sybase_col.rb +49 -0
- data/lib/active_record/vendor/odbcext_virtuoso.rb +146 -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 +707 -0
- data/support/pack_odbc.rb +119 -0
- data/support/rake/rails_plugin_package_task.rb +212 -0
- data/support/test/base_test.rb +1349 -0
- data/support/test/migration_test.rb +566 -0
- data/test/connections/native_odbc/connection.rb +95 -0
- data/test/fixtures/db_definitions/db2.drop.sql +30 -0
- data/test/fixtures/db_definitions/db2.sql +217 -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 +30 -0
- data/test/fixtures/db_definitions/informix.sql +205 -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 +62 -0
- data/test/fixtures/db_definitions/ingres.sql +232 -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 +30 -0
- data/test/fixtures/db_definitions/mysql.sql +219 -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 +64 -0
- data/test/fixtures/db_definitions/oracle_odbc.sql +257 -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/progress.drop.sql +61 -0
- data/test/fixtures/db_definitions/progress.sql +234 -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 +30 -0
- data/test/fixtures/db_definitions/sqlserver.sql +203 -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 +31 -0
- data/test/fixtures/db_definitions/sybase.sql +204 -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 +30 -0
- data/test/fixtures/db_definitions/virtuoso.sql +200 -0
- data/test/fixtures/db_definitions/virtuoso2.drop.sql +2 -0
- data/test/fixtures/db_definitions/virtuoso2.sql +5 -0
- metadata +149 -0
@@ -0,0 +1,87 @@
|
|
1
|
+
#
|
2
|
+
# $Id: odbcext_db2.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 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
|
+
@logger.unknown("ODBCAdapter#last_insert_id>") if @trace
|
38
|
+
@logger.unknown("args=[#{table}]") if @trace
|
39
|
+
select_value("VALUES IDENTITY_VAL_LOCAL()", 'last_insert_id')
|
40
|
+
end
|
41
|
+
|
42
|
+
# ------------------------------------------------------------------------
|
43
|
+
# Method redefinitions
|
44
|
+
#
|
45
|
+
# DBMS specific methods which override the default implementation
|
46
|
+
# provided by the ODBCAdapter core.
|
47
|
+
|
48
|
+
def rename_table(name, new_name)
|
49
|
+
@logger.unknown("ODBCAdapter#rename_table>") if @trace
|
50
|
+
@logger.unknown("args=[#{name}|#{new_name}]") if @trace
|
51
|
+
execute "RENAME TABLE #{name} TO #{new_name}"
|
52
|
+
rescue Exception => e
|
53
|
+
@logger.unknown("exception=#{e}") if @trace
|
54
|
+
raise ActiveRecord::ActiveRecordError, e.message
|
55
|
+
end
|
56
|
+
|
57
|
+
def change_column_default(table_name, column_name, default)
|
58
|
+
@logger.unknown("ODBCAdapter#change_column_default>") if @trace
|
59
|
+
@logger.unknown("args=[#{table_name}|#{column_name}]") if @trace
|
60
|
+
execute "ALTER TABLE #{table_name} ALTER #{column_name} SET DEFAULT #{quote(default)}"
|
61
|
+
rescue Exception => e
|
62
|
+
@logger.unknown("exception=#{e}") if @trace
|
63
|
+
raise ActiveRecord::ActiveRecordError, e.message
|
64
|
+
end
|
65
|
+
|
66
|
+
def remove_column(table_name, column_name)
|
67
|
+
@logger.unknown("ODBCAdapter#remove_column>\n" +
|
68
|
+
"args=[#{table_name}|#{column_name}]\n" +
|
69
|
+
"exception=remove_column is not supported") if @trace
|
70
|
+
raise ActiveRecord::ActiveRecordError, "remove_column is not supported"
|
71
|
+
end
|
72
|
+
|
73
|
+
def remove_index(table_name, options = {})
|
74
|
+
@logger.unknown("ODBCAdapter#remove_index>") if @trace
|
75
|
+
@logger.unknown("args=[#{table_name}]") if @trace
|
76
|
+
execute "DROP INDEX #{quote_column_name(index_name(table_name, options))}"
|
77
|
+
rescue Exception => e
|
78
|
+
@logger.unknown("exception=#{e}") if @trace
|
79
|
+
raise ActiveRecord::ActiveRecordError, e.message
|
80
|
+
end
|
81
|
+
|
82
|
+
def indexes(table_name, name = nil)
|
83
|
+
# Hide primary key indexes
|
84
|
+
super(table_name, name).delete_if { |i| i.unique && i.name =~ /^sql\d+$/ }
|
85
|
+
end
|
86
|
+
|
87
|
+
end # module
|
@@ -0,0 +1,132 @@
|
|
1
|
+
#
|
2
|
+
# $Id: odbcext_informix.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 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
|
+
@logger.unknown("ODBCAdapter#last_insert_id>") if @trace
|
38
|
+
@logger.unknown("args=[#{table}]") if @trace
|
39
|
+
# 1049 (SQL_LASTSERIAL) is an ODBC extension for SQLGetStmtOption
|
40
|
+
stmt.get_option(1049)
|
41
|
+
end
|
42
|
+
|
43
|
+
# ------------------------------------------------------------------------
|
44
|
+
# Method redefinitions
|
45
|
+
#
|
46
|
+
# DBMS specific methods which override the default implementation
|
47
|
+
# provided by the ODBCAdapter core.
|
48
|
+
|
49
|
+
def quoted_date(value)
|
50
|
+
@logger.unknown("ODBCAdapter#quoted_date>") if @trace
|
51
|
+
@logger.unknown("args=[#{value}]") if @trace
|
52
|
+
# Informix's DBTIME and DBDATE environment variables should be set to:
|
53
|
+
# DBTIME=%Y-%m-%d %H:%M:%S
|
54
|
+
# DBDATE=Y4MD-
|
55
|
+
case value
|
56
|
+
when Time, DateTime
|
57
|
+
%Q!'#{value.strftime("%Y-%m-%d %H:%M:%S.")}'!
|
58
|
+
when Date
|
59
|
+
%Q!'#{value.strftime("%Y-%m-%d")}'!
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def rename_table(name, new_name)
|
64
|
+
@logger.unknown("ODBCAdapter#rename_table>") if @trace
|
65
|
+
@logger.unknown("args=[#{name}|#{new_name}]") if @trace
|
66
|
+
execute "RENAME TABLE #{name} TO #{new_name}"
|
67
|
+
rescue Exception => e
|
68
|
+
@logger.unknown("exception=#{e}") if @trace
|
69
|
+
raise ActiveRecord::ActiveRecordError, e.message
|
70
|
+
end
|
71
|
+
|
72
|
+
def change_column(table_name, column_name, type, options = {})
|
73
|
+
@logger.unknown("ODBCAdapter#change_column>") if @trace
|
74
|
+
@logger.unknown("args=[#{table_name}|#{column_name}|#{type}]") if @trace
|
75
|
+
change_column_sql = "ALTER TABLE #{table_name} MODIFY #{column_name} " +
|
76
|
+
"#{type_to_sql(type)}"
|
77
|
+
# Add any :null and :default options
|
78
|
+
add_column_options!(change_column_sql, options)
|
79
|
+
execute(change_column_sql)
|
80
|
+
rescue Exception => e
|
81
|
+
@logger.unknown("exception=#{e}") if @trace
|
82
|
+
raise ActiveRecord::ActiveRecordError, e.message
|
83
|
+
end
|
84
|
+
|
85
|
+
def change_column_default(table_name, column_name, default)
|
86
|
+
@logger.unknown("ODBCAdapter#change_column_default>") if @trace
|
87
|
+
@logger.unknown("args=[#{table_name}|#{column_name}]") if @trace
|
88
|
+
change_column(table_name, column_name, nil, {:default => default})
|
89
|
+
rescue Exception => e
|
90
|
+
@logger.unknown("exception=#{e}") if @trace
|
91
|
+
raise ActiveRecord::ActiveRecordError, e.message
|
92
|
+
end
|
93
|
+
|
94
|
+
def rename_column(table_name, column_name, new_column_name)
|
95
|
+
@logger.unknown("ODBCAdapter#rename_column>") if @trace
|
96
|
+
@logger.unknown("args=[#{table_name}|#{column_name}|#{new_column_name}]") if @trace
|
97
|
+
execute "RENAME COLUMN #{table_name}.#{column_name} TO #{new_column_name}"
|
98
|
+
rescue Exception => e
|
99
|
+
@logger.unknown("exception=#{e}") if @trace
|
100
|
+
raise ActiveRecord::ActiveRecordError, e.message
|
101
|
+
end
|
102
|
+
|
103
|
+
def remove_index(table_name, options = {})
|
104
|
+
@logger.unknown("ODBCAdapter#remove_index>") if @trace
|
105
|
+
@logger.unknown("args=[#{table_name}]") if @trace
|
106
|
+
execute "DROP INDEX #{quote_column_name(index_name(table_name, options))}"
|
107
|
+
rescue Exception => e
|
108
|
+
@logger.unknown("exception=#{e}") if @trace
|
109
|
+
raise ActiveRecord::ActiveRecordError, e.message
|
110
|
+
end
|
111
|
+
|
112
|
+
def tables(name = nil)
|
113
|
+
# Hide the system tables. Some contain columns which don't have an
|
114
|
+
# equivalent ODBC SQL type which causes problems with #columns.
|
115
|
+
super(name).delete_if {|t| t =~ /^sys/i }
|
116
|
+
end
|
117
|
+
|
118
|
+
def indexes(table_name, name = nil)
|
119
|
+
# Informix creates a unique index for a table's primary key.
|
120
|
+
# Hide any such index. The index name takes the form ddd_ddd.
|
121
|
+
# (Indexes created through 'CREATE INDEX' must have a name starting
|
122
|
+
# with a letter or an # underscore.)
|
123
|
+
#
|
124
|
+
# If this isn't done...
|
125
|
+
# Rails' 'rake test_units' attempts to create primary key indexes
|
126
|
+
# explicitly when creating the test database schema. Informix rejects
|
127
|
+
# the resulting 'CREATE UNIQUE INDEX ddd_ddd' commands with a syntax
|
128
|
+
# error.
|
129
|
+
super(table_name, name).delete_if { |i| i.unique && i.name =~ /\d+_\d+/ }
|
130
|
+
end
|
131
|
+
|
132
|
+
end # module
|
@@ -0,0 +1,45 @@
|
|
1
|
+
#
|
2
|
+
# $Id: odbcext_informix_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
|
+
#private
|
30
|
+
|
31
|
+
def default_preprocess(nativeType, default)
|
32
|
+
return default if default.nil?
|
33
|
+
if ["INTEGER", "SMALLINT"].include?(nativeType)
|
34
|
+
# Literal default value is encoded in two parts, space separated
|
35
|
+
# Strip off first part
|
36
|
+
dflt = default.strip
|
37
|
+
if (indx = dflt.index(" "))
|
38
|
+
dflt = dflt[(indx + 1)...dflt.length]
|
39
|
+
default.replace(dflt)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
default
|
43
|
+
end
|
44
|
+
|
45
|
+
end # module
|
@@ -0,0 +1,156 @@
|
|
1
|
+
#
|
2
|
+
# $Id: odbcext_ingres.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
|
+
require 'active_record/connection_adapters/abstract_adapter'
|
28
|
+
|
29
|
+
module ODBCExt
|
30
|
+
|
31
|
+
# ------------------------------------------------------------------------
|
32
|
+
# Mandatory methods
|
33
|
+
#
|
34
|
+
|
35
|
+
# #last_insert_id must be implemented for any database which returns
|
36
|
+
# false from #prefetch_primary_key?
|
37
|
+
# (This adapter returns true for Ingres)
|
38
|
+
|
39
|
+
#def last_insert_id(table, sequence_name, stmt = nil)
|
40
|
+
#end
|
41
|
+
|
42
|
+
# #next_sequence_value must be implemented for any database which returns
|
43
|
+
# true from #prefetch_primary_key?
|
44
|
+
#
|
45
|
+
# Returns the next sequence value from a sequence generator. Not generally
|
46
|
+
# called directly; used by ActiveRecord to get the next primary key value
|
47
|
+
# when inserting a new database record (see #prefetch_primary_key?).
|
48
|
+
def next_sequence_value(sequence_name)
|
49
|
+
@logger.unknown("ODBCAdapter#next_sequence_value>") if @trace
|
50
|
+
@logger.unknown("args=[#{sequence_name}]") if @trace
|
51
|
+
select_one("select #{sequence_name}.nextval id")['id']
|
52
|
+
end
|
53
|
+
|
54
|
+
# ------------------------------------------------------------------------
|
55
|
+
# Optional methods
|
56
|
+
#
|
57
|
+
# These are supplied for a DBMS only if necessary.
|
58
|
+
# ODBCAdapter tests for optional methods using Object#respond_to?
|
59
|
+
|
60
|
+
# Pre action for ODBCAdapter#insert
|
61
|
+
# def pre_insert(sql, name, pk, id_value, sequence_name)
|
62
|
+
# end
|
63
|
+
|
64
|
+
# Post action for ODBCAdapter#insert
|
65
|
+
# def post_insert(sql, name, pk, id_value, sequence_name)
|
66
|
+
# end
|
67
|
+
|
68
|
+
# ------------------------------------------------------------------------
|
69
|
+
# Method redefinitions
|
70
|
+
#
|
71
|
+
# DBMS specific methods which override the default implementation
|
72
|
+
# provided by the ODBCAdapter core.
|
73
|
+
|
74
|
+
def create_table(name, options = {})
|
75
|
+
@logger.unknown("ODBCAdapter#create_table>") if @trace
|
76
|
+
@logger.unknown("args=[#{name}]") if @trace
|
77
|
+
#ALTER TABLE ADD COLUMN not allowed with default page size of 2K
|
78
|
+
super(name, {:options => "WITH PAGE_SIZE=8192"}.merge(options))
|
79
|
+
execute "CREATE SEQUENCE #{name}_seq"
|
80
|
+
rescue Exception => e
|
81
|
+
@logger.unknown("exception=#{e}") if @trace
|
82
|
+
raise ActiveRecord::ActiveRecordError, e.message
|
83
|
+
end
|
84
|
+
|
85
|
+
def drop_table(name)
|
86
|
+
@logger.unknown("ODBCAdapter#drop_table>") if @trace
|
87
|
+
@logger.unknown("args=[#{name}]") if @trace
|
88
|
+
super
|
89
|
+
execute "DROP SEQUENCE #{name}_seq"
|
90
|
+
rescue Exception => e
|
91
|
+
@logger.unknown("exception=#{e}") if @trace
|
92
|
+
raise ActiveRecord::ActiveRecordError, e.message
|
93
|
+
end
|
94
|
+
|
95
|
+
def add_column(table_name, column_name, type, options = {})
|
96
|
+
@logger.unknown("ODBCAdapter#add_column>") if @trace
|
97
|
+
@logger.unknown("args=[#{table_name}|#{column_name}]") if @trace
|
98
|
+
|
99
|
+
sql = "ALTER TABLE #{table_name} ADD #{quote_column_name(column_name)} #{type_to_sql(type, options[:limit])}"
|
100
|
+
sql << " DEFAULT #{quote(options[:default], options[:column])}" unless options[:default].nil?
|
101
|
+
|
102
|
+
# Ingres requires that if 'ALTER TABLE table ADD column' specifies a NOT NULL constraint,
|
103
|
+
# then 'WITH DEFAULT' must also be specified *without* a default value.
|
104
|
+
# Ingres will report an error if both options[:null] == false && options[:default]
|
105
|
+
if options[:null] == false
|
106
|
+
sql << " NOT NULL"
|
107
|
+
sql << " WITH DEFAULT" if options[:default].nil?
|
108
|
+
end
|
109
|
+
execute(sql)
|
110
|
+
rescue Exception => e
|
111
|
+
@logger.unknown("exception=#{e}") if @trace
|
112
|
+
raise ActiveRecord::ActiveRecordError, e.message
|
113
|
+
end
|
114
|
+
|
115
|
+
def remove_column(table_name, column_name)
|
116
|
+
@logger.unknown("ODBCAdapter#remove_column>") if @trace
|
117
|
+
@logger.unknown("args=[#{table_name}|#{column_name}]") if @trace
|
118
|
+
execute "ALTER TABLE #{table_name} DROP #{quote_column_name(column_name)} RESTRICT"
|
119
|
+
rescue Exception => e
|
120
|
+
@logger.unknown("exception=#{e}") if @trace
|
121
|
+
raise ActiveRecord::ActiveRecordError, e.message
|
122
|
+
end
|
123
|
+
|
124
|
+
def change_column(table_name, column_name, type, options = {})
|
125
|
+
@logger.unknown("ODBCAdapter#change_column>") if @trace
|
126
|
+
@logger.unknown("args=[#{table_name}|#{column_name}|#{type}]") if @trace
|
127
|
+
change_column_sql = "ALTER TABLE #{table_name} ALTER #{column_name} " +
|
128
|
+
"#{type_to_sql(type)}"
|
129
|
+
# Add any :null and :default options
|
130
|
+
add_column_options!(change_column_sql, options)
|
131
|
+
execute(change_column_sql)
|
132
|
+
rescue Exception => e
|
133
|
+
@logger.unknown("exception=#{e}") if @trace
|
134
|
+
raise ActiveRecord::ActiveRecordError, e.message
|
135
|
+
end
|
136
|
+
|
137
|
+
def remove_index(table_name, options = {})
|
138
|
+
@logger.unknown("ODBCAdapter#remove_index>") if @trace
|
139
|
+
@logger.unknown("args=[#{table_name}]") if @trace
|
140
|
+
execute "DROP INDEX #{quote_column_name(index_name(table_name, options))}"
|
141
|
+
rescue Exception => e
|
142
|
+
@logger.unknown("exception=#{e}") if @trace
|
143
|
+
raise ActiveRecord::ActiveRecordError, e.message
|
144
|
+
end
|
145
|
+
|
146
|
+
def tables(name = nil)
|
147
|
+
# Hide system tables
|
148
|
+
super(name).delete_if {|t| t =~ /^ii/i }
|
149
|
+
end
|
150
|
+
|
151
|
+
def indexes(table_name, name = nil)
|
152
|
+
# Hide internally generated indexes used to support primary keys.
|
153
|
+
super(table_name, name).delete_if { |i| i.unique && i.name =~ /^\$/ }
|
154
|
+
end
|
155
|
+
|
156
|
+
end # module
|
@@ -0,0 +1,185 @@
|
|
1
|
+
#
|
2
|
+
# $Id: odbcext_microsoftsqlserver.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 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
|
+
def last_insert_id(table, sequence_name, stmt = nil)
|
36
|
+
@logger.unknown("ODBCAdapter#last_insert_id>") if @trace
|
37
|
+
select_value("select @@IDENTITY", '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
|
+
# Pre action for ODBCAdapter#insert
|
47
|
+
def pre_insert(sql, name, pk, id_value, sequence_name)
|
48
|
+
@iiTable = get_table_name(sql)
|
49
|
+
@iiCol = get_autounique_column(@iiTable)
|
50
|
+
@iiEnabled = false
|
51
|
+
|
52
|
+
if @iiCol != nil
|
53
|
+
if query_contains_autounique_col(sql, @iiCol)
|
54
|
+
begin
|
55
|
+
@connection.do(enable_identity_insert(@iiTable, true))
|
56
|
+
@iiEnabled = true
|
57
|
+
rescue Exception => e
|
58
|
+
raise ActiveRecordError, "IDENTITY_INSERT could not be turned on"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
# Post action for ODBCAdapter#insert
|
65
|
+
def post_insert(sql, name, pk, id_value, sequence_name)
|
66
|
+
if @iiEnabled
|
67
|
+
begin
|
68
|
+
@connection.do(enable_identity_insert(@iiTable, false))
|
69
|
+
rescue Exception => e
|
70
|
+
raise ActiveRecordError, "IDENTITY_INSERT could not be turned off"
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# ------------------------------------------------------------------------
|
76
|
+
# Method redefinitions
|
77
|
+
#
|
78
|
+
# DBMS specific methods which override the default implementation
|
79
|
+
# provided by the ODBCAdapter core.
|
80
|
+
|
81
|
+
def rename_table(name, new_name)
|
82
|
+
@logger.unknown("ODBCAdapter#rename_table>") if @trace
|
83
|
+
execute "EXEC sp_rename '#{name}', '#{new_name}'"
|
84
|
+
rescue Exception => e
|
85
|
+
@logger.unknown("exception=#{e}") if @trace
|
86
|
+
raise
|
87
|
+
end
|
88
|
+
|
89
|
+
def remove_column(table_name, column_name)
|
90
|
+
@logger.unknown("ODBCAdapter#remove_column>") if @trace
|
91
|
+
# Remove default constraints first
|
92
|
+
defaults = select_all "select def.name from sysobjects def, syscolumns col, sysobjects tab where col.cdefault = def.id and col.name = '#{column_name}' and tab.name = '#{table_name}' and col.id = tab.id"
|
93
|
+
defaults.each {|constraint|
|
94
|
+
execute "ALTER TABLE #{table_name} DROP CONSTRAINT #{constraint["name"]}"
|
95
|
+
}
|
96
|
+
execute "ALTER TABLE #{table_name} DROP COLUMN #{quote_column_name(column_name)}"
|
97
|
+
rescue Exception => e
|
98
|
+
@logger.unknown("exception=#{e}") if @trace
|
99
|
+
raise
|
100
|
+
end
|
101
|
+
|
102
|
+
def change_column(table_name, column_name, type, options = {})
|
103
|
+
@logger.unknown("ODBCAdapter#change_column>") if @trace
|
104
|
+
sql_commands = ["ALTER TABLE #{table_name} ALTER COLUMN #{column_name} #{type_to_sql(type, options[:limit])}"]
|
105
|
+
if options[:default]
|
106
|
+
# Remove default constraints first
|
107
|
+
defaults = select_all "select def.name from sysobjects def, syscolumns col, sysobjects tab where col.cdefault = def.id and col.name = '#{column_name}' and tab.name = '#{table_name}' and col.id = tab.id"
|
108
|
+
defaults.each {|constraint|
|
109
|
+
execute "ALTER TABLE #{table_name} DROP CONSTRAINT #{constraint["name"]}"
|
110
|
+
}
|
111
|
+
sql_commands << "ALTER TABLE #{table_name} ADD CONSTRAINT DF_#{table_name}_#{column_name} DEFAULT #{options[:default]} FOR #{column_name}"
|
112
|
+
end
|
113
|
+
sql_commands.each {|c|
|
114
|
+
execute(c)
|
115
|
+
}
|
116
|
+
rescue Exception => e
|
117
|
+
@logger.unknown("exception=#{e}") if @trace
|
118
|
+
raise
|
119
|
+
end
|
120
|
+
|
121
|
+
def rename_column(table_name, column_name, new_column_name)
|
122
|
+
@logger.unknown("ODBCAdapter#rename_column>") if @trace
|
123
|
+
execute "EXEC sp_rename '#{table_name}.#{column_name}', '#{new_column_name}'"
|
124
|
+
rescue Exception => e
|
125
|
+
@logger.unknown("exception=#{e}") if @trace
|
126
|
+
raise
|
127
|
+
end
|
128
|
+
|
129
|
+
def remove_index(table_name, options = {})
|
130
|
+
@logger.unknown("ODBCAdapter#remove_index>") if @trace
|
131
|
+
execute "DROP INDEX #{table_name}.#{quote_column_name(index_name(table_name, options))}"
|
132
|
+
rescue Exception => e
|
133
|
+
@logger.unknown("exception=#{e}") if @trace
|
134
|
+
raise
|
135
|
+
end
|
136
|
+
|
137
|
+
def tables(name = nil)
|
138
|
+
# Hide system tables.
|
139
|
+
super(name).delete_if {|t| t =~ /^sys/ }
|
140
|
+
end
|
141
|
+
|
142
|
+
def indexes(table_name, name = nil)
|
143
|
+
# Hide primary key indexes.
|
144
|
+
super(table_name, name).delete_if { |i| i.name =~ /^PK_/ }
|
145
|
+
end
|
146
|
+
|
147
|
+
# ------------------------------------------------------------------------
|
148
|
+
# Private methods to support methods above
|
149
|
+
#
|
150
|
+
private
|
151
|
+
|
152
|
+
def get_table_name(sql)
|
153
|
+
if sql =~ /^\s*insert\s+into\s+([^\(\s]+)\s*|^\s*update\s+([^\(\s]+)\s*/i
|
154
|
+
$1
|
155
|
+
elsif sql =~ /from\s+([^\(\s]+)\s*/i
|
156
|
+
$1
|
157
|
+
else
|
158
|
+
nil
|
159
|
+
end end
|
160
|
+
|
161
|
+
def get_autounique_column(table_name)
|
162
|
+
@table_columns = {} unless @table_columns
|
163
|
+
@table_columns[table_name] = columns(table_name) if @table_columns[table_name] == nil
|
164
|
+
@table_columns[table_name].each do |col|
|
165
|
+
return col.name if col.auto_unique?
|
166
|
+
end
|
167
|
+
|
168
|
+
return nil
|
169
|
+
end
|
170
|
+
|
171
|
+
def query_contains_autounique_col(sql, col)
|
172
|
+
sql =~ /(\[#{col}\])|("#{col}")/
|
173
|
+
end
|
174
|
+
|
175
|
+
def enable_identity_insert(table_name, enable = true)
|
176
|
+
if has_autounique_column(table_name)
|
177
|
+
"SET IDENTITY_INSERT #{table_name} #{enable ? 'ON' : 'OFF'}"
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
def has_autounique_column(table_name)
|
182
|
+
!get_autounique_column(table_name).nil?
|
183
|
+
end
|
184
|
+
|
185
|
+
end # module
|