activerecord-jdbc-alt-adapter 61.0.0-java → 70.0.0.rc1-java
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 +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)
|