activerecord-cubrid2-adapter 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/LICENSE +21 -0
- data/README.md +63 -0
- data/Rakefile +11 -0
- data/VERSION +1 -0
- data/activerecord-cubrid2-adapter.gemspec +26 -0
- data/lib/active_record/connection_adapters/abstract_cubrid2_adapter.rb +750 -0
- data/lib/active_record/connection_adapters/cubrid2/column.rb +28 -0
- data/lib/active_record/connection_adapters/cubrid2/database_statements.rb +192 -0
- data/lib/active_record/connection_adapters/cubrid2/explain_pretty_printer.rb +71 -0
- data/lib/active_record/connection_adapters/cubrid2/quoting.rb +118 -0
- data/lib/active_record/connection_adapters/cubrid2/schema_creation.rb +98 -0
- data/lib/active_record/connection_adapters/cubrid2/schema_definitions.rb +81 -0
- data/lib/active_record/connection_adapters/cubrid2/schema_dumper.rb +31 -0
- data/lib/active_record/connection_adapters/cubrid2/schema_statements.rb +276 -0
- data/lib/active_record/connection_adapters/cubrid2/type_metadata.rb +31 -0
- data/lib/active_record/connection_adapters/cubrid2/version.rb +7 -0
- data/lib/active_record/connection_adapters/cubrid2_adapter.rb +169 -0
- data/lib/activerecord-cubrid2-adapter.rb +4 -0
- data/lib/arel/visitors/cubrid.rb +67 -0
- data/lib/cubrid2/client.rb +93 -0
- data/lib/cubrid2/console.rb +5 -0
- data/lib/cubrid2/error.rb +86 -0
- data/lib/cubrid2/field.rb +3 -0
- data/lib/cubrid2/result.rb +7 -0
- data/lib/cubrid2/statement.rb +11 -0
- data/lib/cubrid2/version.rb +3 -0
- data/lib/cubrid2.rb +76 -0
- data/tests/Gemfile +10 -0
- data/tests/test_activerecord.rb +109 -0
- metadata +102 -0
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module ConnectionAdapters
|
5
|
+
module Cubrid2
|
6
|
+
class Column < ConnectionAdapters::Column # :nodoc:
|
7
|
+
delegate :extra, to: :sql_type_metadata, allow_nil: true
|
8
|
+
|
9
|
+
def unsigned?
|
10
|
+
false
|
11
|
+
end
|
12
|
+
|
13
|
+
def case_sensitive?
|
14
|
+
collation && !collation.end_with?('_ci')
|
15
|
+
end
|
16
|
+
|
17
|
+
def auto_increment?
|
18
|
+
!respond_to?(:extra) && extra == 'auto_increment'
|
19
|
+
end
|
20
|
+
|
21
|
+
def virtual?
|
22
|
+
# /\b(?:VIRTUAL|STORED|PERSISTENT)\b/.match?(extra)
|
23
|
+
false
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,192 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module ConnectionAdapters
|
5
|
+
module Cubrid2
|
6
|
+
module DatabaseStatements
|
7
|
+
# Returns an ActiveRecord::Result instance.
|
8
|
+
def select_all(*param1, **param2) # :nodoc:
|
9
|
+
if ExplainRegistry.collect? && prepared_statements
|
10
|
+
unprepared_statement { super }
|
11
|
+
else
|
12
|
+
super
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def query(sql, name = nil) # :nodoc:
|
17
|
+
execute(sql, name)
|
18
|
+
end
|
19
|
+
|
20
|
+
def query_values(sql, name = nil) # :nodoc:
|
21
|
+
res = exec_query(sql, name)
|
22
|
+
res&.rows&.map(&:first)
|
23
|
+
end
|
24
|
+
|
25
|
+
def query_value(sql, name = nil) # :nodoc:
|
26
|
+
_single_value_from_rows(query(sql, name))
|
27
|
+
end
|
28
|
+
|
29
|
+
READ_QUERY = ActiveRecord::ConnectionAdapters::AbstractAdapter.build_read_query_regexp(
|
30
|
+
:begin, :commit, :explain, :select, :set, :show, :release, :savepoint, :rollback, :describe, :desc, :with
|
31
|
+
) # :nodoc:
|
32
|
+
private_constant :READ_QUERY
|
33
|
+
|
34
|
+
def write_query?(sql) # :nodoc:
|
35
|
+
!READ_QUERY.match?(sql)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Executes the SQL statement in the context of this connection.
|
39
|
+
def execute(sql, name = nil)
|
40
|
+
if preventing_writes? && write_query?(sql)
|
41
|
+
raise ActiveRecord::ReadOnlyError, "Write query attempted while in readonly mode: #{sql}"
|
42
|
+
end
|
43
|
+
|
44
|
+
# make sure we carry over any changes to ActiveRecord::Base.default_timezone that have been
|
45
|
+
# made since we established the connection
|
46
|
+
@connection.query_options[:database_timezone] = ActiveRecord::Base.default_timezone
|
47
|
+
# @connection.query_options[:database_timezone] = ActiveRecord.default_timezone
|
48
|
+
|
49
|
+
super
|
50
|
+
end
|
51
|
+
|
52
|
+
def exec_query(sql, name = 'SQL', binds = [], prepare: false)
|
53
|
+
if without_prepared_statement?(binds)
|
54
|
+
execute_and_free(sql, name) do |result|
|
55
|
+
_build_stmt_result(result)
|
56
|
+
end
|
57
|
+
else
|
58
|
+
exec_stmt_and_free(sql, name, binds, cache_stmt: prepare) do |_, result|
|
59
|
+
_build_stmt_result(result)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def exec_delete(sql, name = nil, binds = [])
|
65
|
+
if without_prepared_statement?(binds)
|
66
|
+
@lock.synchronize do
|
67
|
+
execute_and_free(sql, name) { |stmt| stmt.affected_rows }
|
68
|
+
end
|
69
|
+
else
|
70
|
+
exec_stmt_and_free(sql, name, binds) { |stmt| stmt.affected_rows }
|
71
|
+
end
|
72
|
+
end
|
73
|
+
alias exec_update exec_delete
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
def is_conn_utf8?
|
78
|
+
charset == 'utf8' && collation =~ /^utf8/
|
79
|
+
end
|
80
|
+
|
81
|
+
def _build_stmt_result(stmt)
|
82
|
+
columns = stmt.column_info.map { |col| col['name'] }
|
83
|
+
rows = is_conn_utf8? ? _extract_rows_from_stmt__utf8(stmt) : _extract_rows_from_stmt__raw(stmt)
|
84
|
+
build_result(columns: columns, rows: rows)
|
85
|
+
end
|
86
|
+
|
87
|
+
def _extract_rows_from_stmt__raw(stmt, as_hash: false)
|
88
|
+
rows = []
|
89
|
+
if as_hash
|
90
|
+
while row = stmt.fetch_hash
|
91
|
+
rows << row
|
92
|
+
end
|
93
|
+
else
|
94
|
+
while row = stmt.fetch
|
95
|
+
rows << row
|
96
|
+
end
|
97
|
+
end
|
98
|
+
rows
|
99
|
+
end
|
100
|
+
|
101
|
+
def _extract_rows_from_stmt__utf8(stmt, as_hash: false)
|
102
|
+
rows = []
|
103
|
+
if as_hash
|
104
|
+
while row = stmt.fetch_hash
|
105
|
+
rows << row.map do |x|
|
106
|
+
[x[0], _as_utf8(x[1])]
|
107
|
+
end.to_h
|
108
|
+
end
|
109
|
+
else
|
110
|
+
while row = stmt.fetch
|
111
|
+
rows << row.map { |x| _as_utf8(x) }
|
112
|
+
end
|
113
|
+
end
|
114
|
+
rows
|
115
|
+
end
|
116
|
+
|
117
|
+
def _as_utf8(val)
|
118
|
+
if val.is_a?(String)
|
119
|
+
val.force_encoding('UTF-8')
|
120
|
+
else
|
121
|
+
val
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
def _single_value_from_rows(rows)
|
126
|
+
row = rows.fetch
|
127
|
+
row && row.first
|
128
|
+
end
|
129
|
+
|
130
|
+
def execute_batch(statements, name = nil)
|
131
|
+
combine_multi_statements(statements).each do |statement|
|
132
|
+
execute(statement, name)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def default_insert_value(column)
|
137
|
+
super unless column.auto_increment?
|
138
|
+
end
|
139
|
+
|
140
|
+
def last_inserted_id(_result)
|
141
|
+
stmt = query('SELECT LAST_INSERT_ID() as val_')
|
142
|
+
row = stmt.fetch
|
143
|
+
row[0]&.to_i
|
144
|
+
end
|
145
|
+
|
146
|
+
def supports_set_server_option?
|
147
|
+
@connection.respond_to?(:set_server_option)
|
148
|
+
end
|
149
|
+
|
150
|
+
def exec_stmt_and_free(sql, name, binds, cache_stmt: false)
|
151
|
+
if preventing_writes? && write_query?(sql)
|
152
|
+
raise ActiveRecord::ReadOnlyError, "Write query attempted while in readonly mode: #{sql}"
|
153
|
+
end
|
154
|
+
|
155
|
+
materialize_transactions
|
156
|
+
|
157
|
+
# make sure we carry over any changes to ActiveRecord::Base.default_timezone that have been
|
158
|
+
# made since we established the connection
|
159
|
+
@connection.query_options[:database_timezone] = ActiveRecord::Base.default_timezone
|
160
|
+
|
161
|
+
type_casted_binds = type_casted_binds(binds)
|
162
|
+
|
163
|
+
log(sql, name, binds, type_casted_binds) do
|
164
|
+
stmt = if cache_stmt
|
165
|
+
@statements[sql] ||= @connection.prepare(sql)
|
166
|
+
else
|
167
|
+
@connection.prepare(sql)
|
168
|
+
end
|
169
|
+
|
170
|
+
begin
|
171
|
+
result = ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
|
172
|
+
stmt.execute(*type_casted_binds)
|
173
|
+
end
|
174
|
+
rescue Cubrid2::Error => e
|
175
|
+
if cache_stmt
|
176
|
+
@statements.delete(sql)
|
177
|
+
else
|
178
|
+
stmt.close
|
179
|
+
end
|
180
|
+
raise e
|
181
|
+
end
|
182
|
+
|
183
|
+
ret = yield stmt, result
|
184
|
+
result.free if result
|
185
|
+
stmt.close unless cache_stmt
|
186
|
+
ret
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module ConnectionAdapters
|
5
|
+
module Cubrid2
|
6
|
+
class ExplainPrettyPrinter # :nodoc:
|
7
|
+
# Pretty prints the result of an query that resembles Cubrid shell:
|
8
|
+
#
|
9
|
+
# Field Type Null Key Default Extra
|
10
|
+
# ====================================================================================================================================
|
11
|
+
# 'host_year' 'INTEGER' 'NO' 'PRI' NULL ''
|
12
|
+
# 'event_code' 'INTEGER' 'NO' 'MUL' NULL ''
|
13
|
+
# 'athlete_code' 'INTEGER' 'NO' 'MUL' NULL ''
|
14
|
+
# 'stadium_code' 'INTEGER' 'NO' '' NULL ''
|
15
|
+
# 'nation_code' 'CHAR(3)' 'YES' '' NULL ''
|
16
|
+
# 'medal' 'CHAR(1)' 'YES' '' NULL ''
|
17
|
+
# 'game_date' 'DATE' 'YES' '' NULL ''
|
18
|
+
#
|
19
|
+
# 7 rows selected. (0.010673 sec)
|
20
|
+
#
|
21
|
+
def pp(result, elapsed)
|
22
|
+
widths = compute_column_widths(result) + 4
|
23
|
+
separator = build_separator(widths)
|
24
|
+
|
25
|
+
pp = []
|
26
|
+
|
27
|
+
pp << build_cells(result.columns, widths)
|
28
|
+
pp << separator
|
29
|
+
|
30
|
+
result.rows.each do |row|
|
31
|
+
pp << build_cells(row, widths)
|
32
|
+
end
|
33
|
+
|
34
|
+
pp << build_footer(result.rows.length, elapsed)
|
35
|
+
|
36
|
+
pp.join("\n") + "\n"
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def compute_column_widths(result)
|
42
|
+
[].tap do |widths|
|
43
|
+
result.columns.each_with_index do |column, i|
|
44
|
+
cells_in_column = [column] + result.rows.map { |r| r[i].nil? ? 'NULL' : r[i].to_s }
|
45
|
+
widths << cells_in_column.map(&:length).max
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def build_separator(widths)
|
51
|
+
'=' * widths
|
52
|
+
end
|
53
|
+
|
54
|
+
def build_cells(items, widths)
|
55
|
+
cells = []
|
56
|
+
items.each_with_index do |item, i|
|
57
|
+
item = 'NULL' if item.nil?
|
58
|
+
justifier = item.is_a?(Numeric) ? 'rjust' : 'ljust'
|
59
|
+
cells << item.to_s.send(justifier, widths[i])
|
60
|
+
end
|
61
|
+
' ' + cells.join(' ') + ' '
|
62
|
+
end
|
63
|
+
|
64
|
+
def build_footer(nrows, elapsed)
|
65
|
+
rows_label = nrows == 1 ? 'row' : 'rows'
|
66
|
+
"#{nrows} #{rows_label} selected. (%.2f sec)" % elapsed
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module ConnectionAdapters
|
5
|
+
module Cubrid2
|
6
|
+
module Quoting # :nodoc:
|
7
|
+
# def quote_string(s)
|
8
|
+
# super
|
9
|
+
# end
|
10
|
+
|
11
|
+
def quote_column_name(name)
|
12
|
+
self.class.quoted_column_names[name] ||= "`#{super.gsub('`', '``')}`"
|
13
|
+
end
|
14
|
+
|
15
|
+
def quote_table_name(name)
|
16
|
+
self.class.quoted_table_names[name] ||= super.gsub(".", "`.`").freeze
|
17
|
+
end
|
18
|
+
|
19
|
+
# def quote_table_name(name) # :nodoc:
|
20
|
+
# schema, name = extract_schema_qualified_name(name.to_s)
|
21
|
+
|
22
|
+
# self.class.quoted_table_names[name] ||= "`#{quote_string(schema)}`.`#{quote_string(name)}`".freeze
|
23
|
+
# end
|
24
|
+
|
25
|
+
# Quotes schema names for use in SQL queries.
|
26
|
+
def quote_schema_name(name)
|
27
|
+
quote_table_name(name)
|
28
|
+
end
|
29
|
+
|
30
|
+
def quote_table_name_for_assignment(_table, attr)
|
31
|
+
quote_column_name(attr)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Quotes column names for use in SQL queries.
|
35
|
+
#def quote_column_name(name) # :nodoc:
|
36
|
+
#self.class.quoted_column_names[name] ||= quote(super).freeze
|
37
|
+
#pp "## quote_column_name: #{name}"
|
38
|
+
#self.class.quoted_column_names[name] ||= quote_string(name).freeze
|
39
|
+
#end
|
40
|
+
|
41
|
+
# def visit_Arel_Attributes_Attribute(o, collector)
|
42
|
+
# join_name = o.relation.table_alias || o.relation.name
|
43
|
+
# collector << quote_table_name(join_name) << "." << quote_column_name(o.name)
|
44
|
+
# end
|
45
|
+
|
46
|
+
def unquoted_true
|
47
|
+
1
|
48
|
+
end
|
49
|
+
|
50
|
+
def unquoted_false
|
51
|
+
0
|
52
|
+
end
|
53
|
+
|
54
|
+
def quoted_date(value)
|
55
|
+
if supports_datetime_with_precision?
|
56
|
+
super
|
57
|
+
else
|
58
|
+
super.sub(/\.\d{6}\z/, '')
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def quoted_binary(value)
|
63
|
+
# https://www.cubrid.org/manual/ko/11.2/sql/literal.html#id5
|
64
|
+
"X'#{value.hex}'"
|
65
|
+
end
|
66
|
+
|
67
|
+
def column_name_matcher
|
68
|
+
COLUMN_NAME
|
69
|
+
end
|
70
|
+
|
71
|
+
def column_name_with_order_matcher
|
72
|
+
COLUMN_NAME_WITH_ORDER
|
73
|
+
end
|
74
|
+
|
75
|
+
COLUMN_NAME = /
|
76
|
+
\A
|
77
|
+
(
|
78
|
+
(?:
|
79
|
+
# `table_name`.`column_name` | function(one or no argument)
|
80
|
+
# "table_name"."column_name" | function(one or no argument)
|
81
|
+
# [table_name].[column_name] | function(one or no argument)
|
82
|
+
((?:\w+\.|[`"\[]\w+[`"\]]\.)?(?:\w+|[`"\[]\w+[`"\]])) | \w+\((?:|\g<2>)\)
|
83
|
+
)
|
84
|
+
(?:\s+AS\s+(?:\w+|`\w+`))?
|
85
|
+
)
|
86
|
+
(?:\s*,\s*\g<1>)*
|
87
|
+
\z
|
88
|
+
/ix
|
89
|
+
|
90
|
+
COLUMN_NAME_WITH_ORDER = /
|
91
|
+
\A
|
92
|
+
(
|
93
|
+
(?:
|
94
|
+
# `table_name`.`column_name` | function(one or no argument)
|
95
|
+
# "table_name"."column_name" | function(one or no argument)
|
96
|
+
# [table_name].[column_name] | function(one or no argument)
|
97
|
+
((?:\w+\.|[`"\[]\w+[`"\]]\.)?(?:\w+|[`"\[]\w+[`"\]])) | \w+\((?:|\g<2>)\)
|
98
|
+
)
|
99
|
+
(?:\s+ASC|\s+DESC)?
|
100
|
+
)
|
101
|
+
(?:\s*,\s*\g<1>)*
|
102
|
+
\z
|
103
|
+
/ix
|
104
|
+
|
105
|
+
private_constant :COLUMN_NAME, :COLUMN_NAME_WITH_ORDER
|
106
|
+
|
107
|
+
private
|
108
|
+
|
109
|
+
def _type_cast(value)
|
110
|
+
case value
|
111
|
+
when Date, Time then value
|
112
|
+
else super
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module ConnectionAdapters
|
5
|
+
module Cubrid2
|
6
|
+
class SchemaCreation < ActiveRecord::ConnectionAdapters::SchemaCreation # :nodoc:
|
7
|
+
delegate :add_sql_comment!, to: :@conn, private: true
|
8
|
+
|
9
|
+
private
|
10
|
+
|
11
|
+
# def visit_DropForeignKey(name)
|
12
|
+
# "DROP FOREIGN KEY #{name}"
|
13
|
+
# end
|
14
|
+
|
15
|
+
def visit_DropCheckConstraint(name)
|
16
|
+
"DROP CONSTRAINT #{name}"
|
17
|
+
end
|
18
|
+
|
19
|
+
def visit_AddColumnDefinition(o)
|
20
|
+
add_column_position!(super, column_options(o.column))
|
21
|
+
end
|
22
|
+
|
23
|
+
def visit_ChangeColumnDefinition(o)
|
24
|
+
change_column_sql = +"CHANGE #{quote_column_name(o.name)} #{accept(o.column)}"
|
25
|
+
add_column_position!(change_column_sql, column_options(o.column))
|
26
|
+
end
|
27
|
+
|
28
|
+
def visit_CreateIndexDefinition(o)
|
29
|
+
sql = visit_IndexDefinition(o.index, true)
|
30
|
+
sql
|
31
|
+
end
|
32
|
+
|
33
|
+
def visit_IndexDefinition(o, create = false)
|
34
|
+
index_type = o.type&.to_s&.upcase || o.unique && "UNIQUE"
|
35
|
+
|
36
|
+
sql = create ? ["CREATE"] : []
|
37
|
+
sql << index_type if index_type
|
38
|
+
sql << "INDEX"
|
39
|
+
sql << quote_column_name(o.name)
|
40
|
+
#sql << "USING #{o.using}" if o.using
|
41
|
+
sql << "ON #{quote_table_name(o.table)}" if create
|
42
|
+
sql << "(#{quoted_columns(o)})"
|
43
|
+
|
44
|
+
add_sql_comment!(sql.join(" "), o.comment)
|
45
|
+
end
|
46
|
+
|
47
|
+
def add_table_options!(create_sql, options)
|
48
|
+
add_sql_comment!(super, options[:comment])
|
49
|
+
end
|
50
|
+
|
51
|
+
def add_column_options!(sql, options)
|
52
|
+
# In cubrid, default value of timestamp follows system parameter 'return_null_on_function_errors'
|
53
|
+
# if return_null_on_function_errors == 'no', timestamp null means error.
|
54
|
+
# https://www.cubrid.org/manual/en/10.1/sql/datatype.html#date-time-type
|
55
|
+
if /\Atimestamp\b/.match?(options[:column].sql_type) && !options[:primary_key] &&
|
56
|
+
!(options[:null] == false || options_include_default?(options))
|
57
|
+
sql << ' NULL'
|
58
|
+
end
|
59
|
+
|
60
|
+
if charset = options[:charset]
|
61
|
+
sql << " CHARSET #{charset}"
|
62
|
+
end
|
63
|
+
|
64
|
+
if collation = options[:collation]
|
65
|
+
sql << " COLLATE #{collation}"
|
66
|
+
end
|
67
|
+
|
68
|
+
if as = options[:as]
|
69
|
+
sql << " AS (#{as})"
|
70
|
+
end
|
71
|
+
|
72
|
+
add_sql_comment!(super, options[:comment])
|
73
|
+
end
|
74
|
+
|
75
|
+
def add_column_position!(sql, options)
|
76
|
+
if options[:first]
|
77
|
+
sql << ' FIRST'
|
78
|
+
elsif options[:after]
|
79
|
+
sql << " AFTER #{quote_column_name(options[:after])}"
|
80
|
+
end
|
81
|
+
|
82
|
+
sql
|
83
|
+
end
|
84
|
+
|
85
|
+
def index_in_create(table_name, column_name, options)
|
86
|
+
index_def, algorithm, if_not_exists = @conn.add_index_options(table_name, column_name, **options)
|
87
|
+
index_name = index_def.name
|
88
|
+
index_columns = index_def.columns.map { |x| quote_column_name(x) }.join(', ')
|
89
|
+
index_type = index_def.unique ? 'UNIQUE' : ''
|
90
|
+
comment = index_def.comment
|
91
|
+
add_sql_comment!(
|
92
|
+
+"#{index_type} INDEX #{quote_column_name(index_name)} (#{index_columns})", comment
|
93
|
+
)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module ConnectionAdapters
|
5
|
+
module Cubrid2
|
6
|
+
module ColumnMethods
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
included do
|
9
|
+
define_column_methods :blob, :clob, :nchar
|
10
|
+
|
11
|
+
alias_method :char, :nchar
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition
|
16
|
+
include ColumnMethods
|
17
|
+
|
18
|
+
def new_column_definition(name, type, **options) # :nodoc:
|
19
|
+
case type
|
20
|
+
when :primary_key
|
21
|
+
type = :integer
|
22
|
+
options[:limit] ||= 8
|
23
|
+
options[:primary_key] = true
|
24
|
+
end
|
25
|
+
|
26
|
+
super
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def aliased_types(_name, fallback)
|
32
|
+
fallback
|
33
|
+
end
|
34
|
+
|
35
|
+
def integer_like_primary_key_type(type, options)
|
36
|
+
options[:auto_increment] = true
|
37
|
+
type
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class Table < ActiveRecord::ConnectionAdapters::Table
|
42
|
+
include ColumnMethods
|
43
|
+
end
|
44
|
+
|
45
|
+
class IndexDefinition < ActiveRecord::ConnectionAdapters::IndexDefinition
|
46
|
+
attr_reader :null, :visible
|
47
|
+
|
48
|
+
def initialize(table, name, unique = false, columns = [], **options)
|
49
|
+
options.tap do |o|
|
50
|
+
o[:lengths] ||= {}
|
51
|
+
o[:orders] ||= {}
|
52
|
+
o[:opclasses] ||= {}
|
53
|
+
end
|
54
|
+
|
55
|
+
# get rise to error
|
56
|
+
@visible = options.delete(:visible)
|
57
|
+
@null = options.delete(:null)
|
58
|
+
|
59
|
+
super(table, name, unique, columns, **options)
|
60
|
+
end
|
61
|
+
|
62
|
+
def column_options
|
63
|
+
super.tap { |o|
|
64
|
+
o[:null] = @null
|
65
|
+
o[:visible] = @visible
|
66
|
+
}
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def concise_options(options)
|
72
|
+
if columns.size == options.size && options.values.uniq.size == 1
|
73
|
+
options.values.first
|
74
|
+
else
|
75
|
+
options
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module ConnectionAdapters
|
5
|
+
module Cubrid2
|
6
|
+
class SchemaDumper < ConnectionAdapters::SchemaDumper # :nodoc:
|
7
|
+
private
|
8
|
+
|
9
|
+
def prepare_column_options(column)
|
10
|
+
spec = super
|
11
|
+
spec[:auto_increment] = 'true' if column.auto_increment?
|
12
|
+
spec
|
13
|
+
end
|
14
|
+
|
15
|
+
def column_spec_for_primary_key(column)
|
16
|
+
spec = super
|
17
|
+
spec.delete(:auto_increment) if column.type == :integer && column.auto_increment?
|
18
|
+
spec
|
19
|
+
end
|
20
|
+
|
21
|
+
def default_primary_key?(column)
|
22
|
+
super && column.auto_increment?
|
23
|
+
end
|
24
|
+
|
25
|
+
def explicit_primary_key_default?(column)
|
26
|
+
column.type == :integer && !column.auto_increment?
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|