activerecord-jdbc-alt-adapter 61.0.0-java → 70.0.0.rc1-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +273 -0
- data/.gitignore +1 -0
- data/Gemfile +8 -6
- data/README.md +2 -1
- data/Rakefile +1 -1
- data/activerecord-jdbc-adapter.gemspec +2 -2
- data/activerecord-jdbc-alt-adapter.gemspec +2 -2
- data/lib/arel/visitors/compat.rb +5 -33
- data/lib/arel/visitors/h2.rb +1 -13
- data/lib/arel/visitors/hsqldb.rb +1 -21
- data/lib/arel/visitors/sql_server.rb +2 -103
- data/lib/arjdbc/abstract/core.rb +8 -9
- data/lib/arjdbc/abstract/database_statements.rb +4 -4
- data/lib/arjdbc/discover.rb +0 -67
- data/lib/arjdbc/hsqldb/adapter.rb +2 -2
- data/lib/arjdbc/jdbc/adapter.rb +3 -3
- data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
- data/lib/arjdbc/jdbc/adapter_require.rb +3 -1
- data/lib/arjdbc/jdbc/column.rb +1 -26
- data/lib/arjdbc/jdbc/type_cast.rb +2 -2
- data/lib/arjdbc/jdbc.rb +0 -7
- data/lib/arjdbc/mssql/adapter.rb +134 -105
- data/lib/arjdbc/mssql/quoting.rb +26 -27
- data/lib/arjdbc/mssql/schema_creation.rb +1 -1
- data/lib/arjdbc/mssql/schema_definitions.rb +32 -17
- data/lib/arjdbc/mssql/schema_dumper.rb +13 -1
- data/lib/arjdbc/mssql/schema_statements.rb +61 -36
- data/lib/arjdbc/mssql/transaction.rb +2 -2
- data/lib/arjdbc/mssql/types/date_and_time_types.rb +6 -6
- data/lib/arjdbc/mssql/types/numeric_types.rb +2 -2
- data/lib/arjdbc/mssql.rb +1 -1
- data/lib/arjdbc/mysql/adapter.rb +2 -1
- data/lib/arjdbc/oracle/adapter.rb +4 -23
- data/lib/arjdbc/postgresql/adapter.rb +64 -1
- data/lib/arjdbc/postgresql/oid_types.rb +68 -47
- data/lib/arjdbc/sqlite3/adapter.rb +132 -88
- data/lib/arjdbc/tasks/database_tasks.rb +0 -12
- data/lib/arjdbc/util/serialized_attributes.rb +0 -22
- data/lib/arjdbc/util/table_copier.rb +2 -1
- data/lib/arjdbc/version.rb +1 -1
- data/rakelib/02-test.rake +3 -18
- data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +17 -2
- data/src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java +14 -1
- data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +33 -0
- metadata +8 -40
- data/lib/active_record/connection_adapters/as400_adapter.rb +0 -2
- data/lib/active_record/connection_adapters/db2_adapter.rb +0 -1
- data/lib/active_record/connection_adapters/derby_adapter.rb +0 -1
- data/lib/active_record/connection_adapters/informix_adapter.rb +0 -1
- data/lib/arel/visitors/db2.rb +0 -137
- data/lib/arel/visitors/derby.rb +0 -112
- data/lib/arel/visitors/firebird.rb +0 -79
- data/lib/arjdbc/db2/adapter.rb +0 -808
- data/lib/arjdbc/db2/as400.rb +0 -142
- data/lib/arjdbc/db2/column.rb +0 -131
- data/lib/arjdbc/db2/connection_methods.rb +0 -48
- data/lib/arjdbc/db2.rb +0 -4
- data/lib/arjdbc/derby/active_record_patch.rb +0 -13
- data/lib/arjdbc/derby/adapter.rb +0 -521
- data/lib/arjdbc/derby/connection_methods.rb +0 -20
- data/lib/arjdbc/derby/schema_creation.rb +0 -15
- data/lib/arjdbc/derby.rb +0 -3
- data/lib/arjdbc/firebird/adapter.rb +0 -413
- data/lib/arjdbc/firebird/connection_methods.rb +0 -23
- data/lib/arjdbc/firebird.rb +0 -4
- data/lib/arjdbc/informix/adapter.rb +0 -139
- data/lib/arjdbc/informix/connection_methods.rb +0 -9
- data/lib/arjdbc/sybase/adapter.rb +0 -47
- data/lib/arjdbc/sybase.rb +0 -2
- data/lib/arjdbc/tasks/db2_database_tasks.rb +0 -104
- data/lib/arjdbc/tasks/derby_database_tasks.rb +0 -95
- data/src/java/arjdbc/derby/DerbyModule.java +0 -178
- data/src/java/arjdbc/derby/DerbyRubyJdbcConnection.java +0 -152
- data/src/java/arjdbc/firebird/FirebirdRubyJdbcConnection.java +0 -174
- data/src/java/arjdbc/informix/InformixRubyJdbcConnection.java +0 -75
@@ -14,80 +14,95 @@ module ActiveRecord
|
|
14
14
|
|
15
15
|
# datetime with seconds always zero (:00) and without fractional seconds
|
16
16
|
def smalldatetime(*args, **options)
|
17
|
-
args.each { |name| column(name, :smalldatetime, options) }
|
17
|
+
args.each { |name| column(name, :smalldatetime, **options) }
|
18
18
|
end
|
19
19
|
|
20
20
|
# this is the old sql server datetime type, the precision is as follow
|
21
21
|
# xx1, xx3, and xx7
|
22
22
|
def datetime_basic(*args, **options)
|
23
|
-
args.each { |name| column(name, :datetime_basic, options) }
|
23
|
+
args.each { |name| column(name, :datetime_basic, **options) }
|
24
24
|
end
|
25
25
|
|
26
26
|
def real(*args, **options)
|
27
|
-
args.each { |name| column(name, :real, options) }
|
27
|
+
args.each { |name| column(name, :real, **options) }
|
28
28
|
end
|
29
29
|
|
30
30
|
def money(*args, **options)
|
31
|
-
args.each { |name| column(name, :money, options) }
|
31
|
+
args.each { |name| column(name, :money, **options) }
|
32
32
|
end
|
33
33
|
|
34
34
|
def smallmoney(*args, **options)
|
35
|
-
args.each { |name| column(name, :smallmoney, options) }
|
35
|
+
args.each { |name| column(name, :smallmoney, **options) }
|
36
36
|
end
|
37
37
|
|
38
38
|
def char(*args, **options)
|
39
|
-
args.each { |name| column(name, :char, options) }
|
39
|
+
args.each { |name| column(name, :char, **options) }
|
40
40
|
end
|
41
41
|
|
42
42
|
def varchar(*args, **options)
|
43
|
-
args.each { |name| column(name, :varchar, options) }
|
43
|
+
args.each { |name| column(name, :varchar, **options) }
|
44
44
|
end
|
45
45
|
|
46
46
|
def varchar_max(*args, **options)
|
47
|
-
args.each { |name| column(name, :varchar_max, options) }
|
47
|
+
args.each { |name| column(name, :varchar_max, **options) }
|
48
48
|
end
|
49
49
|
|
50
50
|
def text_basic(*args, **options)
|
51
|
-
args.each { |name| column(name, :text_basic, options) }
|
51
|
+
args.each { |name| column(name, :text_basic, **options) }
|
52
52
|
end
|
53
53
|
|
54
54
|
def nchar(*args, **options)
|
55
|
-
args.each { |name| column(name, :nchar, options) }
|
55
|
+
args.each { |name| column(name, :nchar, **options) }
|
56
56
|
end
|
57
57
|
|
58
58
|
def ntext(*args, **options)
|
59
|
-
args.each { |name| column(name, :ntext, options) }
|
59
|
+
args.each { |name| column(name, :ntext, **options) }
|
60
60
|
end
|
61
61
|
|
62
62
|
def binary_basic(*args, **options)
|
63
|
-
args.each { |name| column(name, :binary_basic, options) }
|
63
|
+
args.each { |name| column(name, :binary_basic, **options) }
|
64
64
|
end
|
65
65
|
|
66
66
|
def varbinary(*args, **options)
|
67
|
-
args.each { |name| column(name, :varbinary, options) }
|
67
|
+
args.each { |name| column(name, :varbinary, **options) }
|
68
68
|
end
|
69
69
|
|
70
70
|
def uuid(*args, **options)
|
71
|
-
args.each { |name| column(name, :uniqueidentifier, options) }
|
71
|
+
args.each { |name| column(name, :uniqueidentifier, **options) }
|
72
72
|
end
|
73
73
|
end
|
74
74
|
|
75
75
|
class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition
|
76
76
|
include ColumnMethods
|
77
77
|
|
78
|
+
def column(name, type, index: nil, **options)
|
79
|
+
# TODO: remove this when the below changed is released
|
80
|
+
# Fix erroneous nil default precision on virtual datetime columns #46110
|
81
|
+
# https://github.com/rails/rails/pull/46110
|
82
|
+
#
|
83
|
+
if @conn.supports_datetime_with_precision?
|
84
|
+
if type == :datetime && !options.key?(:precision)
|
85
|
+
options[:precision] = 7
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
super
|
90
|
+
end
|
91
|
+
|
92
|
+
|
78
93
|
def new_column_definition(name, type, **options)
|
79
94
|
case type
|
80
95
|
when :primary_key
|
81
96
|
options[:is_identity] = true
|
97
|
+
when :datetime
|
98
|
+
options[:precision] = 7 if !options.key?(:precision) && @conn.supports_datetime_with_precision?
|
82
99
|
end
|
83
100
|
|
84
101
|
super
|
85
102
|
end
|
86
103
|
|
87
104
|
def timestamps(**options)
|
88
|
-
if !options.key?(:precision) && @conn.supports_datetime_with_precision?
|
89
|
-
options[:precision] = 7
|
90
|
-
end
|
105
|
+
options[:precision] = 7 if !options.key?(:precision) && @conn.supports_datetime_with_precision?
|
91
106
|
|
92
107
|
super
|
93
108
|
end
|
@@ -28,11 +28,23 @@ module ActiveRecord
|
|
28
28
|
super && column.identity?
|
29
29
|
end
|
30
30
|
|
31
|
+
def schema_precision(column)
|
32
|
+
case column.type
|
33
|
+
when :datetime
|
34
|
+
if column.precision == 7
|
35
|
+
nil
|
36
|
+
else
|
37
|
+
column.precision.inspect
|
38
|
+
end
|
39
|
+
else
|
40
|
+
super
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
31
44
|
# def schema_collation(column)
|
32
45
|
# return unless column.collation
|
33
46
|
# column.collation if column.collation != collation
|
34
47
|
# end
|
35
|
-
|
36
48
|
end
|
37
49
|
end
|
38
50
|
end
|
@@ -7,36 +7,36 @@ module ActiveRecord
|
|
7
7
|
|
8
8
|
NATIVE_DATABASE_TYPES = {
|
9
9
|
# Logical Rails types to SQL Server types
|
10
|
-
primary_key:
|
11
|
-
integer:
|
12
|
-
boolean:
|
13
|
-
decimal:
|
14
|
-
float:
|
15
|
-
date:
|
16
|
-
time:
|
17
|
-
datetime:
|
18
|
-
string:
|
19
|
-
text:
|
20
|
-
binary:
|
10
|
+
primary_key: 'bigint NOT NULL IDENTITY(1,1) PRIMARY KEY',
|
11
|
+
integer: { name: 'int', limit: 4 },
|
12
|
+
boolean: { name: 'bit' },
|
13
|
+
decimal: { name: 'decimal' },
|
14
|
+
float: { name: 'float' },
|
15
|
+
date: { name: 'date' },
|
16
|
+
time: { name: 'time' },
|
17
|
+
datetime: { name: 'datetime2' },
|
18
|
+
string: { name: 'nvarchar', limit: 4000 },
|
19
|
+
text: { name: 'nvarchar(max)' },
|
20
|
+
binary: { name: 'varbinary(max)' },
|
21
21
|
# Other types or SQL Server specific
|
22
|
-
bigint:
|
23
|
-
smalldatetime:
|
22
|
+
bigint: { name: 'bigint' },
|
23
|
+
smalldatetime: { name: 'smalldatetime' },
|
24
24
|
datetime_basic: { name: 'datetime' },
|
25
|
-
timestamp:
|
26
|
-
real:
|
27
|
-
money:
|
28
|
-
smallmoney:
|
29
|
-
char:
|
30
|
-
nchar:
|
31
|
-
varchar:
|
32
|
-
varchar_max:
|
33
|
-
uuid:
|
34
|
-
binary_basic:
|
35
|
-
varbinary:
|
25
|
+
timestamp: { name: 'datetime' },
|
26
|
+
real: { name: 'real' },
|
27
|
+
money: { name: 'money' },
|
28
|
+
smallmoney: { name: 'smallmoney' },
|
29
|
+
char: { name: 'char' },
|
30
|
+
nchar: { name: 'nchar' },
|
31
|
+
varchar: { name: 'varchar', limit: 8000 },
|
32
|
+
varchar_max: { name: 'varchar(max)' },
|
33
|
+
uuid: { name: 'uniqueidentifier' },
|
34
|
+
binary_basic: { name: 'binary' },
|
35
|
+
varbinary: { name: 'varbinary', limit: 8000 },
|
36
36
|
# Deprecated SQL Server types
|
37
|
-
image:
|
38
|
-
ntext:
|
39
|
-
text_basic:
|
37
|
+
image: { name: 'image' },
|
38
|
+
ntext: { name: 'ntext' },
|
39
|
+
text_basic: { name: 'text' }
|
40
40
|
}.freeze
|
41
41
|
|
42
42
|
def native_database_types
|
@@ -127,9 +127,17 @@ module ActiveRecord
|
|
127
127
|
create_database(name, options)
|
128
128
|
end
|
129
129
|
|
130
|
-
def
|
131
|
-
|
130
|
+
def remove_columns(table_name, *column_names, type: nil, **options)
|
131
|
+
if column_names.empty?
|
132
|
+
raise ArgumentError.new('You must specify at least one column name. Example: remove_columns(:people, :first_name)')
|
133
|
+
end
|
134
|
+
|
135
|
+
column_names.each do |column_name|
|
136
|
+
remove_column(table_name, column_name, type, **options)
|
137
|
+
end
|
138
|
+
end
|
132
139
|
|
140
|
+
def remove_column(table_name, column_name, _type = nil, **options)
|
133
141
|
return if options[:if_exists] == true && !column_exists?(table_name, column_name)
|
134
142
|
|
135
143
|
remove_check_constraints(table_name, column_name)
|
@@ -138,7 +146,7 @@ module ActiveRecord
|
|
138
146
|
execute "ALTER TABLE #{quote_table_name(table_name)} DROP COLUMN #{quote_column_name(column_name)}"
|
139
147
|
end
|
140
148
|
|
141
|
-
def drop_table(table_name, options
|
149
|
+
def drop_table(table_name, **options)
|
142
150
|
# mssql cannot recreate referenced table with force: :cascade
|
143
151
|
# https://docs.microsoft.com/en-us/sql/t-sql/statements/drop-table-transact-sql?view=sql-server-2017
|
144
152
|
if options[:force] == :cascade
|
@@ -248,7 +256,7 @@ module ActiveRecord
|
|
248
256
|
(order_columns << super).join(', ')
|
249
257
|
end
|
250
258
|
|
251
|
-
def add_timestamps(table_name, options
|
259
|
+
def add_timestamps(table_name, **options)
|
252
260
|
if !options.key?(:precision) && supports_datetime_with_precision?
|
253
261
|
options[:precision] = 7
|
254
262
|
end
|
@@ -256,6 +264,16 @@ module ActiveRecord
|
|
256
264
|
super
|
257
265
|
end
|
258
266
|
|
267
|
+
def add_column(table_name, column_name, type, **options)
|
268
|
+
if supports_datetime_with_precision?
|
269
|
+
if type == :datetime && !options.key?(:precision)
|
270
|
+
options[:precision] = 7
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
super
|
275
|
+
end
|
276
|
+
|
259
277
|
def create_schema_dumper(options)
|
260
278
|
MSSQL::SchemaDumper.create(self, options)
|
261
279
|
end
|
@@ -323,16 +341,20 @@ module ActiveRecord
|
|
323
341
|
quoted_table = quote_table_name(table_name)
|
324
342
|
quoted_column = quote_column_name(column_name)
|
325
343
|
quoted_default = quote(default)
|
344
|
+
|
326
345
|
unless null || default.nil?
|
327
346
|
execute("UPDATE #{quoted_table} SET #{quoted_column}=#{quoted_default} WHERE #{quoted_column} IS NULL")
|
328
347
|
end
|
348
|
+
|
349
|
+
options = { limit: column.limit, precision: column.precision, scale: column.scale }
|
350
|
+
|
329
351
|
sql_alter = [
|
330
352
|
"ALTER TABLE #{quoted_table}",
|
331
|
-
"ALTER COLUMN #{quoted_column} #{type_to_sql(column.type,
|
332
|
-
('
|
353
|
+
"ALTER COLUMN #{quoted_column} #{type_to_sql(column.type, **options)}",
|
354
|
+
('NOT NULL' unless null)
|
333
355
|
]
|
334
356
|
|
335
|
-
execute(sql_alter.join(' '))
|
357
|
+
execute(sql_alter.compact.join(' '))
|
336
358
|
end
|
337
359
|
|
338
360
|
def update_table_definition(table_name, base) #:nodoc:
|
@@ -345,11 +367,14 @@ module ActiveRecord
|
|
345
367
|
MSSQL::SchemaCreation.new(self)
|
346
368
|
end
|
347
369
|
|
348
|
-
def create_table_definition(
|
349
|
-
MSSQL::TableDefinition.new(self,
|
370
|
+
def create_table_definition(name, **options)
|
371
|
+
MSSQL::TableDefinition.new(self, name, **options)
|
350
372
|
end
|
351
373
|
|
352
374
|
def new_column_from_field(table_name, field)
|
375
|
+
# NOTE: this method is used by the columns method in the abstract Class
|
376
|
+
# to map column_definitions. It would be good if column_definitions is
|
377
|
+
# implemented in ruby
|
353
378
|
field
|
354
379
|
end
|
355
380
|
|
@@ -27,10 +27,10 @@ module ActiveRecord
|
|
27
27
|
module RealTransactionExt
|
28
28
|
attr_reader :initial_transaction_isolation
|
29
29
|
|
30
|
-
def initialize(connection,
|
30
|
+
def initialize(connection, isolation: nil, joinable: true, run_commit_callbacks: false)
|
31
31
|
@connection = connection
|
32
32
|
|
33
|
-
if
|
33
|
+
if isolation
|
34
34
|
@initial_transaction_isolation = current_transaction_isolation
|
35
35
|
end
|
36
36
|
|
@@ -13,9 +13,9 @@ module ActiveRecord
|
|
13
13
|
return %("#{value}") if value.acts_like?(:string)
|
14
14
|
|
15
15
|
if value.usec > 0
|
16
|
-
%("#{value.
|
16
|
+
%("#{value.to_fs(:db)}.#{value.usec.to_s.remove(/0+$/)}")
|
17
17
|
else
|
18
|
-
%("#{value.
|
18
|
+
%("#{value.to_fs(:db)}")
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
@@ -54,9 +54,9 @@ module ActiveRecord
|
|
54
54
|
return %("#{value}") if value.acts_like?(:string)
|
55
55
|
|
56
56
|
if value.usec > 0
|
57
|
-
%("#{value.
|
57
|
+
%("#{value.to_fs(:db)}.#{value.usec.to_s.remove(/0+$/)}")
|
58
58
|
else
|
59
|
-
%("#{value.
|
59
|
+
%("#{value.to_fs(:db)}")
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
@@ -100,9 +100,9 @@ module ActiveRecord
|
|
100
100
|
return %("#{value}") if value.acts_like?(:string)
|
101
101
|
|
102
102
|
if value.usec > 0
|
103
|
-
%("#{value.
|
103
|
+
%("#{value.to_fs(:db)}.#{value.usec.to_s.remove(/0+$/)}")
|
104
104
|
else
|
105
|
-
%("#{value.
|
105
|
+
%("#{value.to_fs(:db)}")
|
106
106
|
end
|
107
107
|
end
|
108
108
|
|
@@ -35,7 +35,7 @@ module ActiveRecord
|
|
35
35
|
end
|
36
36
|
|
37
37
|
class Money < Decimal
|
38
|
-
def initialize(
|
38
|
+
def initialize(precision: nil, limit: nil, scale: nil)
|
39
39
|
super
|
40
40
|
@precision = 19
|
41
41
|
@scale = 4
|
@@ -46,7 +46,7 @@ module ActiveRecord
|
|
46
46
|
end
|
47
47
|
|
48
48
|
class SmallMoney < Decimal
|
49
|
-
def initialize(
|
49
|
+
def initialize(precision: nil, limit: nil, scale: nil)
|
50
50
|
super
|
51
51
|
@precision = 10
|
52
52
|
@scale = 4
|
data/lib/arjdbc/mssql.rb
CHANGED
data/lib/arjdbc/mysql/adapter.rb
CHANGED
@@ -40,7 +40,7 @@ module ArJdbc
|
|
40
40
|
return if @@_initialized; @@_initialized = true
|
41
41
|
|
42
42
|
require 'arjdbc/util/serialized_attributes'
|
43
|
-
Util::SerializedAttributes.setup
|
43
|
+
Util::SerializedAttributes.setup %r{LOB\(|LOB$}i, 'after_save_with_oracle_lob'
|
44
44
|
|
45
45
|
unless ActiveRecord::ConnectionAdapters::AbstractAdapter.
|
46
46
|
instance_methods(false).detect { |m| m.to_s == "prefetch_primary_key?" }
|
@@ -285,7 +285,7 @@ module ArJdbc
|
|
285
285
|
execute "ALTER TABLE #{quote_table_name(table_name)} ADD CONSTRAINT #{quote_column_name(index_name)} #{index_type} (#{quoted_column_names})"
|
286
286
|
end
|
287
287
|
end
|
288
|
-
end
|
288
|
+
end
|
289
289
|
|
290
290
|
# @private
|
291
291
|
def add_index_options(table_name, column_name, options = {})
|
@@ -309,7 +309,7 @@ module ArJdbc
|
|
309
309
|
|
310
310
|
quoted_column_names = column_names.map { |e| quote_column_name_or_expression(e) }.join(", ")
|
311
311
|
[ index_name, index_type, quoted_column_names, tablespace, index_options ]
|
312
|
-
end
|
312
|
+
end
|
313
313
|
|
314
314
|
# @override
|
315
315
|
def remove_index(table_name, options = {})
|
@@ -327,12 +327,7 @@ module ArJdbc
|
|
327
327
|
end
|
328
328
|
execute "ALTER TABLE #{quote_table_name(table_name)} DROP CONSTRAINT #{quote_column_name(index_name)}" rescue nil
|
329
329
|
execute "DROP INDEX #{quote_column_name(index_name)}"
|
330
|
-
end
|
331
|
-
|
332
|
-
# @private
|
333
|
-
def remove_index(table_name, options = {})
|
334
|
-
execute "DROP INDEX #{index_name(table_name, options)}"
|
335
|
-
end unless AR42
|
330
|
+
end
|
336
331
|
|
337
332
|
def change_column_default(table_name, column_name, default)
|
338
333
|
execute "ALTER TABLE #{quote_table_name(table_name)} MODIFY #{quote_column_name(column_name)} DEFAULT #{quote(default)}"
|
@@ -361,25 +356,11 @@ module ArJdbc
|
|
361
356
|
"RENAME COLUMN #{quote_column_name(column_name)} TO #{quote_column_name(new_column_name)}"
|
362
357
|
end
|
363
358
|
|
364
|
-
if ActiveRecord::VERSION::MAJOR >= 4
|
365
|
-
|
366
359
|
# @override
|
367
360
|
def remove_column(table_name, column_name, type = nil, options = {})
|
368
361
|
do_remove_column(table_name, column_name)
|
369
362
|
end
|
370
363
|
|
371
|
-
else
|
372
|
-
|
373
|
-
# @override
|
374
|
-
def remove_column(table_name, *column_names)
|
375
|
-
for column_name in column_names.flatten
|
376
|
-
do_remove_column(table_name, column_name)
|
377
|
-
end
|
378
|
-
end
|
379
|
-
alias remove_columns remove_column
|
380
|
-
|
381
|
-
end
|
382
|
-
|
383
364
|
def do_remove_column(table_name, column_name)
|
384
365
|
execute "ALTER TABLE #{quote_table_name(table_name)} DROP COLUMN #{quote_column_name(column_name)}"
|
385
366
|
end
|
@@ -81,7 +81,7 @@ module ArJdbc
|
|
81
81
|
# If using Active Record's time zone support configure the connection to return
|
82
82
|
# TIMESTAMP WITH ZONE types in UTC.
|
83
83
|
# (SET TIME ZONE does not use an equals sign like other SET variables)
|
84
|
-
if ActiveRecord
|
84
|
+
if ActiveRecord.default_timezone == :utc
|
85
85
|
execute("SET time zone 'UTC'", 'SCHEMA')
|
86
86
|
elsif tz = local_tz
|
87
87
|
execute("SET time zone '#{tz}'", 'SCHEMA')
|
@@ -320,6 +320,38 @@ module ArJdbc
|
|
320
320
|
exec_query("SELECT extname FROM pg_extension", "SCHEMA").cast_values
|
321
321
|
end
|
322
322
|
|
323
|
+
# Returns a list of defined enum types, and their values.
|
324
|
+
def enum_types
|
325
|
+
query = <<~SQL
|
326
|
+
SELECT
|
327
|
+
type.typname AS name,
|
328
|
+
string_agg(enum.enumlabel, ',' ORDER BY enum.enumsortorder) AS value
|
329
|
+
FROM pg_enum AS enum
|
330
|
+
JOIN pg_type AS type
|
331
|
+
ON (type.oid = enum.enumtypid)
|
332
|
+
GROUP BY type.typname;
|
333
|
+
SQL
|
334
|
+
exec_query(query, "SCHEMA").cast_values
|
335
|
+
end
|
336
|
+
|
337
|
+
# Given a name and an array of values, creates an enum type.
|
338
|
+
def create_enum(name, values)
|
339
|
+
sql_values = values.map { |s| "'#{s}'" }.join(", ")
|
340
|
+
query = <<~SQL
|
341
|
+
DO $$
|
342
|
+
BEGIN
|
343
|
+
IF NOT EXISTS (
|
344
|
+
SELECT 1 FROM pg_type t
|
345
|
+
WHERE t.typname = '#{name}'
|
346
|
+
) THEN
|
347
|
+
CREATE TYPE \"#{name}\" AS ENUM (#{sql_values});
|
348
|
+
END IF;
|
349
|
+
END
|
350
|
+
$$;
|
351
|
+
SQL
|
352
|
+
exec_query(query)
|
353
|
+
end
|
354
|
+
|
323
355
|
# Returns the configured supported identifier length supported by PostgreSQL
|
324
356
|
def max_identifier_length
|
325
357
|
@max_identifier_length ||= query_value("SHOW max_identifier_length", "SCHEMA").to_i
|
@@ -672,6 +704,37 @@ module ActiveRecord::ConnectionAdapters
|
|
672
704
|
class PostgreSQLAdapter < AbstractAdapter
|
673
705
|
class_attribute :create_unlogged_tables, default: false
|
674
706
|
|
707
|
+
##
|
708
|
+
# :singleton-method:
|
709
|
+
# PostgreSQL allows the creation of "unlogged" tables, which do not record
|
710
|
+
# data in the PostgreSQL Write-Ahead Log. This can make the tables faster,
|
711
|
+
# but significantly increases the risk of data loss if the database
|
712
|
+
# crashes. As a result, this should not be used in production
|
713
|
+
# environments. If you would like all created tables to be unlogged in
|
714
|
+
# the test environment you can add the following line to your test.rb
|
715
|
+
# file:
|
716
|
+
#
|
717
|
+
# ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.create_unlogged_tables = true
|
718
|
+
class_attribute :create_unlogged_tables, default: false
|
719
|
+
|
720
|
+
##
|
721
|
+
# :singleton-method:
|
722
|
+
# PostgreSQL supports multiple types for DateTimes. By default, if you use +datetime+
|
723
|
+
# in migrations, Rails will translate this to a PostgreSQL "timestamp without time zone".
|
724
|
+
# Change this in an initializer to use another NATIVE_DATABASE_TYPES. For example, to
|
725
|
+
# store DateTimes as "timestamp with time zone":
|
726
|
+
#
|
727
|
+
# ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.datetime_type = :timestamptz
|
728
|
+
#
|
729
|
+
# Or if you are adding a custom type:
|
730
|
+
#
|
731
|
+
# ActiveRecord::ConnectionAdapters::PostgreSQLAdapter::NATIVE_DATABASE_TYPES[:my_custom_type] = { name: "my_custom_type_name" }
|
732
|
+
# ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.datetime_type = :my_custom_type
|
733
|
+
#
|
734
|
+
# If you're using +:ruby+ as your +config.active_record.schema_format+ and you change this
|
735
|
+
# setting, you should immediately run <tt>bin/rails db:migrate</tt> to update the types in your schema.rb.
|
736
|
+
class_attribute :datetime_type, default: :timestamp
|
737
|
+
|
675
738
|
# Try to use as much of the built in postgres logic as possible
|
676
739
|
# maybe someday we can extend the actual adapter
|
677
740
|
include ActiveRecord::ConnectionAdapters::PostgreSQL::ReferentialIntegrity
|
@@ -116,54 +116,57 @@ module ArJdbc
|
|
116
116
|
|
117
117
|
private
|
118
118
|
|
119
|
-
def
|
120
|
-
register_class_with_limit
|
121
|
-
|
122
|
-
register_class_with_limit m, 'int8', Type::Integer
|
123
|
-
m.register_type 'oid', OID::Oid.new
|
124
|
-
m.register_type 'float4', Type::Float.new
|
125
|
-
m.alias_type 'float8', 'float4'
|
126
|
-
m.register_type 'text', Type::Text.new
|
127
|
-
register_class_with_limit m, 'varchar', Type::String
|
128
|
-
m.alias_type 'char', 'varchar'
|
129
|
-
m.alias_type 'name', 'varchar'
|
130
|
-
m.alias_type 'bpchar', 'varchar'
|
131
|
-
m.register_type 'bool', Type::Boolean.new
|
132
|
-
register_class_with_limit m, 'bit', OID::Bit
|
133
|
-
register_class_with_limit m, 'varbit', OID::BitVarying
|
134
|
-
m.alias_type 'timestamptz', 'timestamp'
|
135
|
-
m.register_type 'date', OID::Date.new
|
136
|
-
|
137
|
-
m.register_type 'money', OID::Money.new
|
138
|
-
m.register_type 'bytea', OID::Bytea.new
|
139
|
-
m.register_type 'point', OID::Point.new
|
140
|
-
m.register_type 'hstore', OID::Hstore.new
|
141
|
-
m.register_type 'json', Type::Json.new
|
142
|
-
m.register_type 'jsonb', OID::Jsonb.new
|
143
|
-
m.register_type 'cidr', OID::Cidr.new
|
144
|
-
m.register_type 'inet', OID::Inet.new
|
145
|
-
m.register_type 'uuid', OID::Uuid.new
|
146
|
-
m.register_type 'xml', OID::Xml.new
|
147
|
-
m.register_type 'tsvector', OID::SpecializedString.new(:tsvector)
|
148
|
-
m.register_type 'macaddr', OID::Macaddr.new
|
149
|
-
m.register_type 'citext', OID::SpecializedString.new(:citext)
|
150
|
-
m.register_type 'ltree', OID::SpecializedString.new(:ltree)
|
151
|
-
m.register_type 'line', OID::SpecializedString.new(:line)
|
152
|
-
m.register_type 'lseg', OID::SpecializedString.new(:lseg)
|
153
|
-
m.register_type 'box', OID::SpecializedString.new(:box)
|
154
|
-
m.register_type 'path', OID::SpecializedString.new(:path)
|
155
|
-
m.register_type 'polygon', OID::SpecializedString.new(:polygon)
|
156
|
-
m.register_type 'circle', OID::SpecializedString.new(:circle)
|
157
|
-
|
158
|
-
m.register_type 'interval' do |*args, sql_type|
|
159
|
-
precision = extract_precision(sql_type)
|
160
|
-
OID::Interval.new(precision: precision)
|
161
|
-
end
|
119
|
+
def register_class_with_limit(...)
|
120
|
+
::ActiveRecord::ConnectionAdapters::AbstractAdapter.send(:register_class_with_limit, ...)
|
121
|
+
end
|
162
122
|
|
163
|
-
|
164
|
-
register_class_with_precision
|
123
|
+
def register_class_with_precision(...)
|
124
|
+
::ActiveRecord::ConnectionAdapters::AbstractAdapter.send(:register_class_with_precision, ...)
|
125
|
+
end
|
165
126
|
|
166
|
-
|
127
|
+
def initialize_type_map(m = type_map)
|
128
|
+
m.register_type "int2", Type::Integer.new(limit: 2)
|
129
|
+
m.register_type "int4", Type::Integer.new(limit: 4)
|
130
|
+
m.register_type "int8", Type::Integer.new(limit: 8)
|
131
|
+
m.register_type "oid", OID::Oid.new
|
132
|
+
m.register_type "float4", Type::Float.new
|
133
|
+
m.alias_type "float8", "float4"
|
134
|
+
m.register_type "text", Type::Text.new
|
135
|
+
register_class_with_limit m, "varchar", Type::String
|
136
|
+
m.alias_type "char", "varchar"
|
137
|
+
m.alias_type "name", "varchar"
|
138
|
+
m.alias_type "bpchar", "varchar"
|
139
|
+
m.register_type "bool", Type::Boolean.new
|
140
|
+
register_class_with_limit m, "bit", OID::Bit
|
141
|
+
register_class_with_limit m, "varbit", OID::BitVarying
|
142
|
+
m.register_type "date", OID::Date.new
|
143
|
+
|
144
|
+
m.register_type "money", OID::Money.new
|
145
|
+
m.register_type "bytea", OID::Bytea.new
|
146
|
+
m.register_type "point", OID::Point.new
|
147
|
+
m.register_type "hstore", OID::Hstore.new
|
148
|
+
m.register_type "json", Type::Json.new
|
149
|
+
m.register_type "jsonb", OID::Jsonb.new
|
150
|
+
m.register_type "cidr", OID::Cidr.new
|
151
|
+
m.register_type "inet", OID::Inet.new
|
152
|
+
m.register_type "uuid", OID::Uuid.new
|
153
|
+
m.register_type "xml", OID::Xml.new
|
154
|
+
m.register_type "tsvector", OID::SpecializedString.new(:tsvector)
|
155
|
+
m.register_type "macaddr", OID::Macaddr.new
|
156
|
+
m.register_type "citext", OID::SpecializedString.new(:citext)
|
157
|
+
m.register_type "ltree", OID::SpecializedString.new(:ltree)
|
158
|
+
m.register_type "line", OID::SpecializedString.new(:line)
|
159
|
+
m.register_type "lseg", OID::SpecializedString.new(:lseg)
|
160
|
+
m.register_type "box", OID::SpecializedString.new(:box)
|
161
|
+
m.register_type "path", OID::SpecializedString.new(:path)
|
162
|
+
m.register_type "polygon", OID::SpecializedString.new(:polygon)
|
163
|
+
m.register_type "circle", OID::SpecializedString.new(:circle)
|
164
|
+
|
165
|
+
register_class_with_precision m, "time", Type::Time
|
166
|
+
register_class_with_precision m, "timestamp", OID::Timestamp
|
167
|
+
register_class_with_precision m, "timestamptz", OID::TimestampWithTimeZone
|
168
|
+
|
169
|
+
m.register_type "numeric" do |_, fmod, sql_type|
|
167
170
|
precision = extract_precision(sql_type)
|
168
171
|
scale = extract_scale(sql_type)
|
169
172
|
|
@@ -183,7 +186,10 @@ module ArJdbc
|
|
183
186
|
end
|
184
187
|
end
|
185
188
|
|
186
|
-
|
189
|
+
m.register_type "interval" do |*args, sql_type|
|
190
|
+
precision = extract_precision(sql_type)
|
191
|
+
OID::Interval.new(precision: precision)
|
192
|
+
end
|
187
193
|
|
188
194
|
# pgjdbc returns these if the column is auto-incrmenting
|
189
195
|
m.alias_type 'serial', 'int4'
|
@@ -231,6 +237,21 @@ module ArJdbc
|
|
231
237
|
initializer.run(records)
|
232
238
|
end
|
233
239
|
|
240
|
+
def extract_scale(sql_type)
|
241
|
+
case sql_type
|
242
|
+
when /\((\d+)\)/ then 0
|
243
|
+
when /\((\d+)(,(\d+))\)/ then $3.to_i
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
def extract_precision(sql_type)
|
248
|
+
$1.to_i if sql_type =~ /\((\d+)(,\d+)?\)/
|
249
|
+
end
|
250
|
+
|
251
|
+
def extract_limit(sql_type)
|
252
|
+
$1.to_i if sql_type =~ /\((.*)\)/
|
253
|
+
end
|
254
|
+
|
234
255
|
# Support arrays/ranges for defining attributes that don't exist in the db
|
235
256
|
ActiveRecord::Type.add_modifier({ array: true }, OID::Array, adapter: :postgresql)
|
236
257
|
ActiveRecord::Type.add_modifier({ range: true }, OID::Range, adapter: :postgresql)
|