activerecord-cubrid2-adapter 0.0.1
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.
- 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
|