forked from jruby/activerecord-jdbc-adapter
/
adapter.rb
182 lines (154 loc) · 5.38 KB
/
adapter.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
module ::ArJdbc
module HSQLDB
def self.column_selector
[/hsqldb|\.h2\./i, lambda {|cfg,col| col.extend(::ArJdbc::HSQLDB::Column)}]
end
module Column
private
def simplified_type(field_type)
case field_type
when /longvarchar/i then :text
when /tinyint/i then :boolean
when /real/i then :float
when /decimal/i then :decimal
else
super
end
end
# Override of ActiveRecord::ConnectionAdapters::Column
def extract_limit(sql_type)
# HSQLDB appears to return "LONGVARCHAR(0)" for :text columns, which
# for AR purposes should be interpreted as "no limit"
return nil if sql_type =~ /\(0\)/
super
end
# Post process default value from JDBC into a Rails-friendly format (columns{-internal})
def default_value(value)
# jdbc returns column default strings with actual single quotes around the value.
return $1 if value =~ /^'(.*)'$/
value
end
end
def adapter_name #:nodoc:
'Hsqldb'
end
def arel2_visitors
require 'arel/visitors/hsqldb'
{'hsqldb' => ::Arel::Visitors::HSQLDB, 'jdbchsqldb' => ::Arel::Visitors::HSQLDB}
end
def modify_types(tp)
tp[:primary_key] = "INTEGER GENERATED BY DEFAULT AS IDENTITY(START WITH 0) PRIMARY KEY"
tp[:integer][:limit] = nil
tp[:boolean][:limit] = nil
# set text and float limits so we don't see odd scales tacked on
# in migrations
tp[:boolean] = { :name => "tinyint" }
tp[:text][:limit] = nil
tp[:float][:limit] = 17 if defined?(::Jdbc::H2)
tp[:string][:limit] = 255
tp[:datetime] = { :name => "DATETIME" }
tp[:timestamp] = { :name => "DATETIME" }
tp[:time] = { :name => "TIME" }
tp[:date] = { :name => "DATE" }
tp
end
def quote(value, column = nil) # :nodoc:
return value.quoted_id if value.respond_to?(:quoted_id)
case value
when String
if respond_to?(:h2_adapter) && value.empty?
"''"
elsif column && column.type == :binary
"'#{value.unpack("H*")}'"
elsif column && (column.type == :integer ||
column.respond_to?(:primary) && column.primary && column.klass != String)
value.to_i.to_s
else
"'#{quote_string(value)}'"
end
else
super
end
end
def quote_column_name(name) #:nodoc:
name = name.to_s
if name =~ /[-]/
%Q{"#{name.upcase}"}
else
name
end
end
def quote_string(str)
str.gsub(/'/, "''")
end
def quoted_true
'1'
end
def quoted_false
'0'
end
def add_column(table_name, column_name, type, options = {})
add_column_sql = "ALTER TABLE #{quote_table_name(table_name)} ADD #{quote_column_name(column_name)} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}"
add_column_options!(add_column_sql, options)
execute(add_column_sql)
end
def change_column(table_name, column_name, type, options = {}) #:nodoc:
execute "ALTER TABLE #{table_name} ALTER COLUMN #{column_name} #{type_to_sql(type, options[:limit])}"
end
def change_column_default(table_name, column_name, default) #:nodoc:
execute "ALTER TABLE #{table_name} ALTER COLUMN #{column_name} SET DEFAULT #{quote(default)}"
end
def rename_column(table_name, column_name, new_column_name) #:nodoc:
execute "ALTER TABLE #{table_name} ALTER COLUMN #{column_name} RENAME TO #{new_column_name}"
end
# Maps logical Rails types to MySQL-specific data types.
def type_to_sql(type, limit = nil, precision = nil, scale = nil)
return super if defined?(::Jdbc::H2) || type.to_s != 'integer' || limit == nil
type
end
def rename_table(name, new_name)
execute "ALTER TABLE #{name} RENAME TO #{new_name}"
end
def last_insert_id
Integer(select_value("CALL IDENTITY()"))
end
def _execute(sql, name = nil)
result = super
ActiveRecord::ConnectionAdapters::JdbcConnection::insert?(sql) ? last_insert_id : result
end
def add_limit_offset!(sql, options) #:nodoc:
if sql =~ /^select/i
offset = options[:offset] || 0
bef = sql[7..-1]
if limit = options[:limit]
sql.replace "SELECT LIMIT #{offset} #{limit} #{bef}"
elsif offset > 0
sql.replace "SELECT LIMIT #{offset} 0 #{bef}"
end
end
end
# override to filter out system tables that otherwise end
# up in db/schema.rb during migrations. JdbcConnection#tables
# now takes an optional block filter so we can screen out
# rows corresponding to system tables. HSQLDB names its
# system tables SYSTEM.*, but H2 seems to name them without
# any kind of convention
def tables
@connection.tables.select {|row| row.to_s !~ /^system_/i }
end
def remove_index(table_name, options = {})
execute "DROP INDEX #{quote_column_name(index_name(table_name, options))}"
end
def recreate_database(name)
drop_database(name)
end
# do nothing since database gets created upon connection. However
# this method gets called by rails db rake tasks so now we're
# avoiding method_missing error
def create_database(name)
end
def drop_database(name)
execute("DROP ALL OBJECTS")
end
end
end