activerecord-jdbc-adapter-ficoh 1.3.21-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +35 -0
- data/.travis.yml +462 -0
- data/.yardopts +4 -0
- data/Appraisals +36 -0
- data/CONTRIBUTING.md +49 -0
- data/Gemfile +68 -0
- data/History.md +1191 -0
- data/LICENSE.txt +25 -0
- data/README.md +277 -0
- data/RUNNING_TESTS.md +88 -0
- data/Rakefile +298 -0
- data/Rakefile.jdbc +20 -0
- data/activerecord-jdbc-adapter.gemspec +63 -0
- data/lib/active_record/connection_adapters/as400_adapter.rb +2 -0
- data/lib/active_record/connection_adapters/db2_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/derby_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/firebird_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/h2_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/hsqldb_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/informix_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/jdbc_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/jndi_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/mariadb_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/mssql_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/mysql_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/oracle_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/sqlserver_adapter.rb +1 -0
- data/lib/activerecord-jdbc-adapter.rb +1 -0
- data/lib/arel/visitors/compat.rb +64 -0
- data/lib/arel/visitors/db2.rb +137 -0
- data/lib/arel/visitors/derby.rb +112 -0
- data/lib/arel/visitors/firebird.rb +79 -0
- data/lib/arel/visitors/h2.rb +25 -0
- data/lib/arel/visitors/hsqldb.rb +32 -0
- data/lib/arel/visitors/postgresql_jdbc.rb +6 -0
- data/lib/arel/visitors/sql_server.rb +225 -0
- data/lib/arel/visitors/sql_server/ng42.rb +293 -0
- data/lib/arjdbc.rb +22 -0
- data/lib/arjdbc/db2.rb +4 -0
- data/lib/arjdbc/db2/adapter.rb +802 -0
- data/lib/arjdbc/db2/as400.rb +137 -0
- data/lib/arjdbc/db2/column.rb +177 -0
- data/lib/arjdbc/db2/connection_methods.rb +45 -0
- data/lib/arjdbc/derby.rb +3 -0
- data/lib/arjdbc/derby/active_record_patch.rb +13 -0
- data/lib/arjdbc/derby/adapter.rb +567 -0
- data/lib/arjdbc/derby/connection_methods.rb +16 -0
- data/lib/arjdbc/derby/schema_creation.rb +15 -0
- data/lib/arjdbc/discover.rb +104 -0
- data/lib/arjdbc/firebird.rb +4 -0
- data/lib/arjdbc/firebird/adapter.rb +468 -0
- data/lib/arjdbc/firebird/connection_methods.rb +20 -0
- data/lib/arjdbc/h2.rb +3 -0
- data/lib/arjdbc/h2/adapter.rb +335 -0
- data/lib/arjdbc/h2/connection_methods.rb +22 -0
- data/lib/arjdbc/hsqldb.rb +3 -0
- data/lib/arjdbc/hsqldb/adapter.rb +304 -0
- data/lib/arjdbc/hsqldb/connection_methods.rb +23 -0
- data/lib/arjdbc/hsqldb/explain_support.rb +35 -0
- data/lib/arjdbc/hsqldb/schema_creation.rb +11 -0
- data/lib/arjdbc/informix.rb +5 -0
- data/lib/arjdbc/informix/adapter.rb +160 -0
- data/lib/arjdbc/informix/connection_methods.rb +9 -0
- data/lib/arjdbc/jdbc.rb +62 -0
- data/lib/arjdbc/jdbc/adapter.rb +997 -0
- data/lib/arjdbc/jdbc/adapter_require.rb +46 -0
- data/lib/arjdbc/jdbc/arel_support.rb +149 -0
- data/lib/arjdbc/jdbc/base_ext.rb +34 -0
- data/lib/arjdbc/jdbc/callbacks.rb +52 -0
- data/lib/arjdbc/jdbc/column.rb +83 -0
- data/lib/arjdbc/jdbc/connection.rb +26 -0
- data/lib/arjdbc/jdbc/connection_methods.rb +59 -0
- data/lib/arjdbc/jdbc/driver.rb +44 -0
- data/lib/arjdbc/jdbc/error.rb +75 -0
- data/lib/arjdbc/jdbc/extension.rb +69 -0
- data/lib/arjdbc/jdbc/java.rb +13 -0
- data/lib/arjdbc/jdbc/type_cast.rb +154 -0
- data/lib/arjdbc/jdbc/type_converter.rb +142 -0
- data/lib/arjdbc/mssql.rb +7 -0
- data/lib/arjdbc/mssql/adapter.rb +822 -0
- data/lib/arjdbc/mssql/column.rb +207 -0
- data/lib/arjdbc/mssql/connection_methods.rb +72 -0
- data/lib/arjdbc/mssql/explain_support.rb +99 -0
- data/lib/arjdbc/mssql/limit_helpers.rb +231 -0
- data/lib/arjdbc/mssql/lock_methods.rb +77 -0
- data/lib/arjdbc/mssql/types.rb +343 -0
- data/lib/arjdbc/mssql/utils.rb +82 -0
- data/lib/arjdbc/mysql.rb +3 -0
- data/lib/arjdbc/mysql/adapter.rb +998 -0
- data/lib/arjdbc/mysql/bulk_change_table.rb +150 -0
- data/lib/arjdbc/mysql/column.rb +167 -0
- data/lib/arjdbc/mysql/connection_methods.rb +137 -0
- data/lib/arjdbc/mysql/explain_support.rb +82 -0
- data/lib/arjdbc/mysql/schema_creation.rb +58 -0
- data/lib/arjdbc/oracle.rb +4 -0
- data/lib/arjdbc/oracle/adapter.rb +968 -0
- data/lib/arjdbc/oracle/column.rb +136 -0
- data/lib/arjdbc/oracle/connection_methods.rb +21 -0
- data/lib/arjdbc/postgresql.rb +3 -0
- data/lib/arjdbc/postgresql/_bc_time_cast_patch.rb +21 -0
- data/lib/arjdbc/postgresql/adapter.rb +1498 -0
- data/lib/arjdbc/postgresql/base/array_parser.rb +95 -0
- data/lib/arjdbc/postgresql/base/oid.rb +412 -0
- data/lib/arjdbc/postgresql/base/pgconn.rb +8 -0
- data/lib/arjdbc/postgresql/base/schema_definitions.rb +132 -0
- data/lib/arjdbc/postgresql/column.rb +640 -0
- data/lib/arjdbc/postgresql/connection_methods.rb +44 -0
- data/lib/arjdbc/postgresql/explain_support.rb +53 -0
- data/lib/arjdbc/postgresql/oid/bytea.rb +3 -0
- data/lib/arjdbc/postgresql/oid_types.rb +265 -0
- data/lib/arjdbc/postgresql/schema_creation.rb +60 -0
- data/lib/arjdbc/railtie.rb +11 -0
- data/lib/arjdbc/sqlite3.rb +3 -0
- data/lib/arjdbc/sqlite3/adapter.rb +654 -0
- data/lib/arjdbc/sqlite3/connection_methods.rb +36 -0
- data/lib/arjdbc/sqlite3/explain_support.rb +29 -0
- data/lib/arjdbc/sybase.rb +2 -0
- data/lib/arjdbc/sybase/adapter.rb +47 -0
- data/lib/arjdbc/tasks.rb +13 -0
- data/lib/arjdbc/tasks/database_tasks.rb +66 -0
- data/lib/arjdbc/tasks/databases.rake +91 -0
- data/lib/arjdbc/tasks/databases3.rake +239 -0
- data/lib/arjdbc/tasks/databases4.rake +39 -0
- data/lib/arjdbc/tasks/db2_database_tasks.rb +104 -0
- data/lib/arjdbc/tasks/derby_database_tasks.rb +95 -0
- data/lib/arjdbc/tasks/h2_database_tasks.rb +31 -0
- data/lib/arjdbc/tasks/hsqldb_database_tasks.rb +70 -0
- data/lib/arjdbc/tasks/jdbc_database_tasks.rb +169 -0
- data/lib/arjdbc/tasks/mssql_database_tasks.rb +46 -0
- data/lib/arjdbc/tasks/oracle/enhanced_structure_dump.rb +297 -0
- data/lib/arjdbc/tasks/oracle_database_tasks.rb +65 -0
- data/lib/arjdbc/util/quoted_cache.rb +60 -0
- data/lib/arjdbc/util/serialized_attributes.rb +98 -0
- data/lib/arjdbc/util/table_copier.rb +108 -0
- data/lib/arjdbc/version.rb +8 -0
- data/lib/generators/jdbc/USAGE +9 -0
- data/lib/generators/jdbc/jdbc_generator.rb +17 -0
- data/pom.xml +285 -0
- data/rails_generators/jdbc_generator.rb +15 -0
- data/rails_generators/templates/config/initializers/jdbc.rb +10 -0
- data/rails_generators/templates/lib/tasks/jdbc.rake +11 -0
- data/rakelib/01-tomcat.rake +51 -0
- data/rakelib/02-test.rake +151 -0
- data/rakelib/bundler_ext.rb +11 -0
- data/rakelib/db.rake +58 -0
- data/rakelib/rails.rake +77 -0
- data/src/java/arjdbc/ArJdbcModule.java +288 -0
- data/src/java/arjdbc/db2/DB2Module.java +77 -0
- data/src/java/arjdbc/db2/DB2RubyJdbcConnection.java +128 -0
- data/src/java/arjdbc/derby/DerbyModule.java +180 -0
- data/src/java/arjdbc/derby/DerbyRubyJdbcConnection.java +153 -0
- data/src/java/arjdbc/firebird/FirebirdRubyJdbcConnection.java +190 -0
- data/src/java/arjdbc/h2/H2Module.java +50 -0
- data/src/java/arjdbc/h2/H2RubyJdbcConnection.java +86 -0
- data/src/java/arjdbc/hsqldb/HSQLDBModule.java +74 -0
- data/src/java/arjdbc/informix/InformixRubyJdbcConnection.java +76 -0
- data/src/java/arjdbc/jdbc/AdapterJavaService.java +43 -0
- data/src/java/arjdbc/jdbc/Callable.java +44 -0
- data/src/java/arjdbc/jdbc/ConnectionFactory.java +77 -0
- data/src/java/arjdbc/jdbc/DataSourceConnectionFactory.java +156 -0
- data/src/java/arjdbc/jdbc/DriverConnectionFactory.java +63 -0
- data/src/java/arjdbc/jdbc/DriverWrapper.java +128 -0
- data/src/java/arjdbc/jdbc/JdbcConnectionFactory.java +32 -0
- data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +4541 -0
- data/src/java/arjdbc/jdbc/SQLBlock.java +54 -0
- data/src/java/arjdbc/jdbc/WithResultSet.java +37 -0
- data/src/java/arjdbc/mssql/MSSQLModule.java +91 -0
- data/src/java/arjdbc/mssql/MSSQLRubyJdbcConnection.java +193 -0
- data/src/java/arjdbc/mysql/MySQLModule.java +140 -0
- data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +456 -0
- data/src/java/arjdbc/oracle/OracleModule.java +81 -0
- data/src/java/arjdbc/oracle/OracleRubyJdbcConnection.java +477 -0
- data/src/java/arjdbc/postgresql/ByteaUtils.java +171 -0
- data/src/java/arjdbc/postgresql/DriverImplementation.java +78 -0
- data/src/java/arjdbc/postgresql/PGDriverImplementation.java +535 -0
- data/src/java/arjdbc/postgresql/PostgreSQLModule.java +189 -0
- data/src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java +489 -0
- data/src/java/arjdbc/sqlite3/SQLite3Module.java +93 -0
- data/src/java/arjdbc/sqlite3/SQLite3RubyJdbcConnection.java +405 -0
- data/src/java/arjdbc/util/CallResultSet.java +826 -0
- data/src/java/arjdbc/util/DateTimeUtils.java +517 -0
- data/src/java/arjdbc/util/NumberUtils.java +50 -0
- data/src/java/arjdbc/util/ObjectSupport.java +65 -0
- data/src/java/arjdbc/util/QuotingUtils.java +139 -0
- data/src/java/arjdbc/util/StringCache.java +60 -0
- data/src/java/arjdbc/util/StringHelper.java +155 -0
- metadata +288 -0
@@ -0,0 +1,8 @@
|
|
1
|
+
module ActiveRecord::ConnectionAdapters::PostgreSQL::OID
|
2
|
+
class PGconn # emulate PGconn#unescape_bytea due #652
|
3
|
+
# NOTE: on pg gem ... PGconn = (class) PG::Connection
|
4
|
+
def self.unescape_bytea(escaped)
|
5
|
+
ArJdbc::PostgreSQL.unescape_bytea(escaped)
|
6
|
+
end
|
7
|
+
end
|
8
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module ConnectionAdapters
|
3
|
+
module PostgreSQL
|
4
|
+
class ColumnDefinition < ActiveRecord::ConnectionAdapters::ColumnDefinition
|
5
|
+
attr_accessor :array
|
6
|
+
def array?; !!@array; end
|
7
|
+
end
|
8
|
+
|
9
|
+
# @private
|
10
|
+
module ColumnHelpers
|
11
|
+
def xml(*args)
|
12
|
+
options = args.extract_options!
|
13
|
+
column(args[0], 'xml', options)
|
14
|
+
end
|
15
|
+
|
16
|
+
def tsvector(*args)
|
17
|
+
options = args.extract_options!
|
18
|
+
column(args[0], 'tsvector', options)
|
19
|
+
end
|
20
|
+
|
21
|
+
def int4range(name, options = {})
|
22
|
+
column(name, 'int4range', options)
|
23
|
+
end
|
24
|
+
|
25
|
+
def int8range(name, options = {})
|
26
|
+
column(name, 'int8range', options)
|
27
|
+
end
|
28
|
+
|
29
|
+
def tsrange(name, options = {})
|
30
|
+
column(name, 'tsrange', options)
|
31
|
+
end
|
32
|
+
|
33
|
+
def tstzrange(name, options = {})
|
34
|
+
column(name, 'tstzrange', options)
|
35
|
+
end
|
36
|
+
|
37
|
+
def numrange(name, options = {})
|
38
|
+
column(name, 'numrange', options)
|
39
|
+
end
|
40
|
+
|
41
|
+
def daterange(name, options = {})
|
42
|
+
column(name, 'daterange', options)
|
43
|
+
end
|
44
|
+
|
45
|
+
def hstore(name, options = {})
|
46
|
+
column(name, 'hstore', options)
|
47
|
+
end
|
48
|
+
|
49
|
+
def ltree(name, options = {})
|
50
|
+
column(name, 'ltree', options)
|
51
|
+
end
|
52
|
+
|
53
|
+
def inet(name, options = {})
|
54
|
+
column(name, 'inet', options)
|
55
|
+
end
|
56
|
+
|
57
|
+
def cidr(name, options = {})
|
58
|
+
column(name, 'cidr', options)
|
59
|
+
end
|
60
|
+
|
61
|
+
def macaddr(name, options = {})
|
62
|
+
column(name, 'macaddr', options)
|
63
|
+
end
|
64
|
+
|
65
|
+
def uuid(name, options = {})
|
66
|
+
column(name, 'uuid', options)
|
67
|
+
end
|
68
|
+
|
69
|
+
def json(name, options = {})
|
70
|
+
column(name, 'json', options)
|
71
|
+
end
|
72
|
+
|
73
|
+
def jsonb(name, options = {})
|
74
|
+
column(name, :jsonb, options)
|
75
|
+
end
|
76
|
+
|
77
|
+
def bit(name, options)
|
78
|
+
column(name, 'bit', options)
|
79
|
+
end
|
80
|
+
|
81
|
+
def bit_varying(name, options)
|
82
|
+
column(name, 'bit varying', options)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition
|
87
|
+
include ColumnHelpers
|
88
|
+
|
89
|
+
def primary_key(name, type = :primary_key, options = {})
|
90
|
+
return super unless type == :uuid
|
91
|
+
options[:default] = options.fetch(:default, 'uuid_generate_v4()')
|
92
|
+
options[:primary_key] = true
|
93
|
+
column name, type, options
|
94
|
+
end if ::ActiveRecord::VERSION::MAJOR > 3 # 3.2 super expects (name)
|
95
|
+
|
96
|
+
def column(name, type = nil, options = {})
|
97
|
+
super
|
98
|
+
column = self[name]
|
99
|
+
# NOTE: <= 3.1 no #new_column_definition hard-coded ColumnDef.new :
|
100
|
+
# column = self[name] || ColumnDefinition.new(@base, name, type)
|
101
|
+
# thus we simply do not support array column definitions on <= 3.1
|
102
|
+
column.array = options[:array] if column.is_a?(ColumnDefinition)
|
103
|
+
self
|
104
|
+
end
|
105
|
+
|
106
|
+
private
|
107
|
+
|
108
|
+
if ::ActiveRecord::VERSION::MAJOR > 3
|
109
|
+
|
110
|
+
def create_column_definition(name, type)
|
111
|
+
ColumnDefinition.new name, type
|
112
|
+
end
|
113
|
+
|
114
|
+
else # no #create_column_definition on 3.2
|
115
|
+
|
116
|
+
def new_column_definition(base, name, type)
|
117
|
+
definition = ColumnDefinition.new base, name, type
|
118
|
+
@columns << definition
|
119
|
+
@columns_hash[name] = definition
|
120
|
+
definition
|
121
|
+
end
|
122
|
+
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
126
|
+
|
127
|
+
class Table < ActiveRecord::ConnectionAdapters::Table
|
128
|
+
include ColumnHelpers
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
@@ -0,0 +1,640 @@
|
|
1
|
+
module ArJdbc
|
2
|
+
module PostgreSQL
|
3
|
+
|
4
|
+
# @see ActiveRecord::ConnectionAdapters::JdbcColumn#column_types
|
5
|
+
def self.column_selector
|
6
|
+
[ /postgre/i, lambda { |cfg, column| column.extend(ColumnMethods) } ]
|
7
|
+
end
|
8
|
+
|
9
|
+
# @private these are defined on the Adapter class since 4.2
|
10
|
+
module ColumnHelpers
|
11
|
+
|
12
|
+
def extract_limit(sql_type) # :nodoc:
|
13
|
+
case sql_type
|
14
|
+
when /^bigint/i, /^int8/i then 8
|
15
|
+
when /^smallint/i then 2
|
16
|
+
when /^timestamp/i then nil
|
17
|
+
else
|
18
|
+
super
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Extracts the value from a PostgreSQL column default definition.
|
23
|
+
def extract_value_from_default(oid, default) # :nodoc:
|
24
|
+
case default
|
25
|
+
# Quoted types
|
26
|
+
when /\A[\(B]?'(.*)'::/m
|
27
|
+
$1.gsub(/''/, "'")
|
28
|
+
# Boolean types
|
29
|
+
when 'true', 'false'
|
30
|
+
default
|
31
|
+
# Numeric types
|
32
|
+
when /\A\(?(-?\d+(\.\d*)?)\)?(::bigint)?\z/
|
33
|
+
$1
|
34
|
+
# Object identifier types
|
35
|
+
when /\A-?\d+\z/
|
36
|
+
$1
|
37
|
+
else
|
38
|
+
# Anything else is blank, some user type, or some function
|
39
|
+
# and we can't know the value of that, so return nil.
|
40
|
+
nil
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def extract_default_function(default_value, default) # :nodoc:
|
45
|
+
default if ! default_value && ( %r{\w+\(.*\)} === default )
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
|
50
|
+
# Column behavior based on PostgreSQL adapter in Rails.
|
51
|
+
# @see ActiveRecord::ConnectionAdapters::JdbcColumn
|
52
|
+
module ColumnMethods
|
53
|
+
|
54
|
+
attr_accessor :array
|
55
|
+
alias array? array
|
56
|
+
|
57
|
+
def initialize(name, default, cast_type, sql_type = nil, null = true, default_function = nil,
|
58
|
+
oid = nil, adapter = nil) # added arguments
|
59
|
+
if sql_type.to_s[-2, 2] == '[]'
|
60
|
+
@array = true
|
61
|
+
super(name, default, cast_type, sql_type[0..-3], null)
|
62
|
+
else
|
63
|
+
@array = false
|
64
|
+
super(name, default, cast_type, sql_type, null)
|
65
|
+
end
|
66
|
+
|
67
|
+
@oid = oid # used on Java side - expects @oid on Column instances
|
68
|
+
#@adapter = adapter
|
69
|
+
|
70
|
+
@default_function = default_function
|
71
|
+
end
|
72
|
+
|
73
|
+
end if AR42
|
74
|
+
|
75
|
+
# @private (AR < 4.2 version) documented above
|
76
|
+
module ColumnMethods
|
77
|
+
|
78
|
+
def initialize(name, default, oid_type = nil, sql_type = nil, null = true,
|
79
|
+
fmod = nil, adapter = nil) # added due resolving #oid_type
|
80
|
+
if oid_type.is_a?(Integer) # the "main" if branch (on AR 4.x)
|
81
|
+
@oid = oid_type; @fmod = fmod; @adapter = adapter # see Column#oid_type
|
82
|
+
elsif oid_type.respond_to?(:type_cast) # MRI compatibility
|
83
|
+
@oid_type = oid_type; # @fmod = fmod; @adapter = adapter
|
84
|
+
else # NOTE: AR <= 3.2 : (name, default, sql_type = nil, null = true)
|
85
|
+
null, sql_type, oid_type = !! sql_type, oid_type, nil
|
86
|
+
end
|
87
|
+
if sql_type.to_s[-2, 2] == '[]' && AR40
|
88
|
+
@array = true if respond_to?(:array)
|
89
|
+
super(name, default, sql_type[0..-3], null)
|
90
|
+
else
|
91
|
+
@array = false if respond_to?(:array)
|
92
|
+
super(name, default, sql_type, null)
|
93
|
+
end
|
94
|
+
|
95
|
+
@default_function = extract_default_function(@default, default)
|
96
|
+
end
|
97
|
+
|
98
|
+
def self.included(base)
|
99
|
+
# NOTE: assumes a standalone PostgreSQLColumn class
|
100
|
+
base_meta = class << base; self end
|
101
|
+
base_meta.send :attr_accessor, :money_precision
|
102
|
+
|
103
|
+
# Loads pg_array_parser if available. String parsing can be
|
104
|
+
# performed quicker by a native extension, which will not create
|
105
|
+
# a large amount of Ruby objects that will need to be garbage
|
106
|
+
# collected. pg_array_parser has a C and Java extension
|
107
|
+
begin
|
108
|
+
require 'pg_array_parser'
|
109
|
+
base_meta.send :include, PgArrayParser
|
110
|
+
rescue LoadError
|
111
|
+
if AR42
|
112
|
+
require 'active_record/connection_adapters/postgresql/array_parser'
|
113
|
+
else
|
114
|
+
require 'arjdbc/postgresql/base/array_parser'
|
115
|
+
end
|
116
|
+
base_meta.send :include, ActiveRecord::ConnectionAdapters::PostgreSQL::ArrayParser
|
117
|
+
end if AR40
|
118
|
+
|
119
|
+
base_meta.send :include, Cast
|
120
|
+
|
121
|
+
base.send :include, ColumnHelpers
|
122
|
+
end
|
123
|
+
|
124
|
+
if AR40 && ! AR42
|
125
|
+
|
126
|
+
# @private
|
127
|
+
def oid_type
|
128
|
+
@oid_type ||= begin
|
129
|
+
raise "oid not defined" unless oid = (@oid ||= nil)
|
130
|
+
@adapter.get_oid_type(oid.to_i, @fmod.to_i, name)
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
# @private
|
135
|
+
def accessor; oid_type.accessor end
|
136
|
+
|
137
|
+
end
|
138
|
+
|
139
|
+
( attr_accessor :array; def array?; array; end ) if AR40
|
140
|
+
|
141
|
+
def number?; !array && super end if AR40
|
142
|
+
def text?; !array && super end if AR40
|
143
|
+
|
144
|
+
# Extracts the value from a PostgreSQL column default definition.
|
145
|
+
#
|
146
|
+
# @override JdbcColumn#default_value
|
147
|
+
# NOTE: based on `self.extract_value_from_default(default)` code
|
148
|
+
def default_value(default)
|
149
|
+
# This is a performance optimization for Ruby 1.9.2 in development.
|
150
|
+
# If the value is nil, we return nil straight away without checking
|
151
|
+
# the regular expressions. If we check each regular expression,
|
152
|
+
# Regexp#=== will call NilClass#to_str, which will trigger
|
153
|
+
# method_missing (defined by whiny nil in ActiveSupport) which
|
154
|
+
# makes this method very very slow.
|
155
|
+
return default unless default
|
156
|
+
|
157
|
+
case default
|
158
|
+
when /\A'(.*)'::(num|date|tstz|ts|int4|int8)range\z/m
|
159
|
+
$1
|
160
|
+
# Numeric types
|
161
|
+
when /\A\(?(-?\d+(\.\d*)?\)?(::bigint)?)\z/
|
162
|
+
$1
|
163
|
+
# Character types
|
164
|
+
when /\A\(?'(.*)'::.*\b(?:character varying|bpchar|text)\z/m
|
165
|
+
$1
|
166
|
+
# Binary data types
|
167
|
+
when /\A'(.*)'::bytea\z/m
|
168
|
+
$1
|
169
|
+
# Date/time types
|
170
|
+
when /\A'(.+)'::(?:time(?:stamp)? with(?:out)? time zone|date)\z/
|
171
|
+
$1
|
172
|
+
when /\A'(.*)'::interval\z/
|
173
|
+
$1
|
174
|
+
# Boolean type
|
175
|
+
when 'true'
|
176
|
+
true
|
177
|
+
when 'false'
|
178
|
+
false
|
179
|
+
# Geometric types
|
180
|
+
when /\A'(.*)'::(?:point|line|lseg|box|"?path"?|polygon|circle)\z/
|
181
|
+
$1
|
182
|
+
# Network address types
|
183
|
+
when /\A'(.*)'::(?:cidr|inet|macaddr)\z/
|
184
|
+
$1
|
185
|
+
# Bit string types
|
186
|
+
when /\AB'(.*)'::"?bit(?: varying)?"?\z/
|
187
|
+
$1
|
188
|
+
# XML type
|
189
|
+
when /\A'(.*)'::xml\z/m
|
190
|
+
$1
|
191
|
+
# Arrays
|
192
|
+
when /\A'(.*)'::"?\D+"?\[\]\z/
|
193
|
+
$1
|
194
|
+
when /\AARRAY\[(.*)\](::\D+)?\z/
|
195
|
+
"{#{$1.gsub(/'(.*?)'::[a-z]+(,)?\s?/, '\1\2')}}"
|
196
|
+
# Hstore
|
197
|
+
when /\A'(.*)'::hstore\z/
|
198
|
+
$1
|
199
|
+
# JSON
|
200
|
+
when /\A'(.*)'::json\z/
|
201
|
+
$1
|
202
|
+
# JSONB
|
203
|
+
when /\A'(.*)'::jsonb\z/
|
204
|
+
$1
|
205
|
+
# Object identifier types
|
206
|
+
when /\A-?\d+\z/
|
207
|
+
$1
|
208
|
+
else
|
209
|
+
# Anything else is blank, some user type, or some function
|
210
|
+
# and we can't know the value of that, so return nil.
|
211
|
+
nil
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
# Casts value (which is a String) to an appropriate instance.
|
216
|
+
# @private
|
217
|
+
def type_cast(value) # AR < 4.0 version
|
218
|
+
return if value.nil?
|
219
|
+
return super if respond_to?(:encoded?) && encoded? # since AR-3.2
|
220
|
+
|
221
|
+
case sql_type
|
222
|
+
when 'money'
|
223
|
+
self.class.string_to_money(value)
|
224
|
+
else super
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
# Casts value (which is a String) to an appropriate instance.
|
229
|
+
def type_cast(value, type = false) # AR >= 4.0 version
|
230
|
+
return if value.nil?
|
231
|
+
return super(value) if encoded?
|
232
|
+
|
233
|
+
# NOTE: we do not use OID::Type
|
234
|
+
# @oid_type.type_cast value
|
235
|
+
|
236
|
+
return self.class.string_to_array(value, self) if array? && type == false
|
237
|
+
|
238
|
+
case type ||= self.type
|
239
|
+
when :hstore then self.class.string_to_hstore value
|
240
|
+
when :json then self.class.string_to_json value
|
241
|
+
when :jsonb then self.class.string_to_json value
|
242
|
+
when :cidr, :inet then self.class.string_to_cidr value
|
243
|
+
when :macaddr then value
|
244
|
+
when :tsvector then value
|
245
|
+
when :datetime, :timestamp then self.class.string_to_time value
|
246
|
+
else
|
247
|
+
if ( sql_type = self.sql_type.to_s ) == 'money'
|
248
|
+
self.class.string_to_money(value)
|
249
|
+
elsif sql_type.start_with?('point')
|
250
|
+
value.is_a?(String) ? self.class.string_to_point(value) : value
|
251
|
+
elsif sql_type.start_with?('bit') || sql_type.start_with?('varbit')
|
252
|
+
value.is_a?(String) ? self.class.string_to_bit(value) : value
|
253
|
+
elsif sql_type.end_with?('range')
|
254
|
+
return if value.nil? || value == 'empty'
|
255
|
+
return value if value.is_a?(::Range)
|
256
|
+
|
257
|
+
extracted = extract_bounds(value)
|
258
|
+
|
259
|
+
case sql_type[0...-5] # range sub-type
|
260
|
+
when 'date' # :date
|
261
|
+
from = self.class.value_to_date(extracted[:from])
|
262
|
+
from += 1.day if extracted[:exclude_start]
|
263
|
+
to = self.class.value_to_date(extracted[:to])
|
264
|
+
when 'num' # :decimal
|
265
|
+
from = ::BigDecimal.new(extracted[:from].to_s)
|
266
|
+
# FIXME: add exclude start for ::Range, same for timestamp ranges
|
267
|
+
to = ::BigDecimal.new(extracted[:to].to_s)
|
268
|
+
when 'ts', 'tstz' # :time
|
269
|
+
from = self.class.string_to_time(extracted[:from])
|
270
|
+
to = self.class.string_to_time(extracted[:to])
|
271
|
+
when 'int4', 'int8' # :integer
|
272
|
+
from = extracted[:from]
|
273
|
+
unless (from.respond_to?(:infinite?) && from.infinite?)
|
274
|
+
from = from.respond_to?(:to_i) ? from.to_i : ( value ? 1 : 0 )
|
275
|
+
end
|
276
|
+
from += 1 if extracted[:exclude_start]
|
277
|
+
to = extracted[:to]
|
278
|
+
unless (to.respond_to?(:infinite?) && to.infinite?)
|
279
|
+
to = to.respond_to?(:to_i) ? to.to_i : ( value ? 1 : 0 )
|
280
|
+
end
|
281
|
+
else
|
282
|
+
return value
|
283
|
+
end
|
284
|
+
|
285
|
+
::Range.new(from, to, extracted[:exclude_end])
|
286
|
+
else
|
287
|
+
super(value)
|
288
|
+
end
|
289
|
+
end
|
290
|
+
end if AR40
|
291
|
+
|
292
|
+
private
|
293
|
+
|
294
|
+
# Extracts the scale from PostgreSQL-specific data types.
|
295
|
+
def extract_scale(sql_type)
|
296
|
+
# Money type has a fixed scale of 2.
|
297
|
+
sql_type =~ /^money/ ? 2 : super
|
298
|
+
end
|
299
|
+
|
300
|
+
# Extracts the precision from PostgreSQL-specific data types.
|
301
|
+
def extract_precision(sql_type)
|
302
|
+
if sql_type == 'money'
|
303
|
+
self.class.money_precision
|
304
|
+
elsif sql_type =~ /timestamp/i
|
305
|
+
$1.to_i if sql_type =~ /\((\d+)\)/
|
306
|
+
else
|
307
|
+
super
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
# Maps PostgreSQL-specific data types to logical Rails types.
|
312
|
+
def simplified_type(field_type)
|
313
|
+
case field_type
|
314
|
+
# Numeric and monetary types
|
315
|
+
when /^(?:real|double precision)$/ then :float
|
316
|
+
# Monetary types
|
317
|
+
when 'money' then :decimal
|
318
|
+
# Character types
|
319
|
+
when /^(?:character varying|bpchar)(?:\(\d+\))?$/ then :string
|
320
|
+
# Binary data types
|
321
|
+
when 'bytea' then :binary
|
322
|
+
# Date/time types
|
323
|
+
when /^timestamp with(?:out)? time zone$/ then :datetime
|
324
|
+
when 'interval' then :string
|
325
|
+
# Geometric types
|
326
|
+
when /^(?:point|line|lseg|box|"?path"?|polygon|circle)$/ then :string
|
327
|
+
# Network address types
|
328
|
+
when /^(?:cidr|inet|macaddr)$/ then :string
|
329
|
+
# Bit strings
|
330
|
+
when /^bit(?: varying)?(?:\(\d+\))?$/ then :string
|
331
|
+
# XML type
|
332
|
+
when 'xml' then :xml
|
333
|
+
# tsvector type
|
334
|
+
when 'tsvector' then :tsvector
|
335
|
+
# Arrays
|
336
|
+
when /^\D+\[\]$/ then :string
|
337
|
+
# Object identifier types
|
338
|
+
when 'oid' then :integer
|
339
|
+
# UUID type
|
340
|
+
when 'uuid' then :string
|
341
|
+
# Small and big integer types
|
342
|
+
when /^(?:small|big)int$/ then :integer
|
343
|
+
# AR-JDBC added :
|
344
|
+
when 'bool' then :boolean
|
345
|
+
when 'char' then :string
|
346
|
+
when 'serial' then :integer
|
347
|
+
# Pass through all types that are not specific to PostgreSQL.
|
348
|
+
else
|
349
|
+
super
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
353
|
+
# @private
|
354
|
+
def simplified_type(field_type)
|
355
|
+
case field_type
|
356
|
+
# Numeric and monetary types
|
357
|
+
when /^(?:real|double precision)$/ then :float
|
358
|
+
# Monetary types
|
359
|
+
when 'money' then :decimal
|
360
|
+
when 'hstore' then :hstore
|
361
|
+
when 'ltree' then :ltree
|
362
|
+
# Network address types
|
363
|
+
when 'inet' then :inet
|
364
|
+
when 'cidr' then :cidr
|
365
|
+
when 'macaddr' then :macaddr
|
366
|
+
# Character types
|
367
|
+
when /^(?:character varying|bpchar)(?:\(\d+\))?$/ then :string
|
368
|
+
# Binary data types
|
369
|
+
when 'bytea' then :binary
|
370
|
+
# Date/time types
|
371
|
+
when /^timestamp with(?:out)? time zone$/ then :datetime
|
372
|
+
when /^interval(?:|\(\d+\))$/ then :string
|
373
|
+
# Geometric types
|
374
|
+
when /^(?:point|line|lseg|box|"?path"?|polygon|circle)$/ then :string
|
375
|
+
# Bit strings
|
376
|
+
when /^bit(?: varying)?(?:\(\d+\))?$/ then :string
|
377
|
+
# XML type
|
378
|
+
when 'xml' then :xml
|
379
|
+
# tsvector type
|
380
|
+
when 'tsvector' then :tsvector
|
381
|
+
# Arrays
|
382
|
+
when /^\D+\[\]$/ then :string
|
383
|
+
# Object identifier types
|
384
|
+
when 'oid' then :integer
|
385
|
+
# UUID type
|
386
|
+
when 'uuid' then :uuid
|
387
|
+
# JSON type
|
388
|
+
when 'json' then :json
|
389
|
+
when 'jsonb' then :jsonb
|
390
|
+
# Small and big integer types
|
391
|
+
when /^(?:small|big)int$/ then :integer
|
392
|
+
when /(num|date|tstz|ts|int4|int8)range$/
|
393
|
+
field_type.to_sym
|
394
|
+
# AR-JDBC added :
|
395
|
+
when 'bool' then :boolean
|
396
|
+
when 'char' then :string
|
397
|
+
when 'serial' then :integer
|
398
|
+
# Pass through all types that are not specific to PostgreSQL.
|
399
|
+
else
|
400
|
+
super
|
401
|
+
end
|
402
|
+
end if AR40
|
403
|
+
|
404
|
+
# OID Type::Range helpers :
|
405
|
+
|
406
|
+
def extract_bounds(value)
|
407
|
+
f, t = value[1..-2].split(',')
|
408
|
+
{
|
409
|
+
:from => (value[1] == ',' || f == '-infinity') ? infinity(:negative => true) : f,
|
410
|
+
:to => (value[-2] == ',' || t == 'infinity') ? infinity : t,
|
411
|
+
:exclude_start => (value[0] == '('), :exclude_end => (value[-1] == ')')
|
412
|
+
}
|
413
|
+
end if AR40
|
414
|
+
|
415
|
+
def infinity(options = {})
|
416
|
+
::Float::INFINITY * (options[:negative] ? -1 : 1)
|
417
|
+
end if AR40
|
418
|
+
|
419
|
+
private
|
420
|
+
|
421
|
+
# TODO marshaling worked in 1.3.7 ,,, got broken in 1.3.8 (due @adapter)
|
422
|
+
# but the fix introduced in 1.3.10 causes backwards (1.3) incompatibility
|
423
|
+
# ... for now should be fine - there's likely more refactoring to happen!
|
424
|
+
|
425
|
+
def marshal_dump
|
426
|
+
# NOTE: disabled oid_type ... due range warnings (maybe they're fine) :
|
427
|
+
# unknown OID 3904: failed to recognize type of 'int4_range'. It will be treated as String.
|
428
|
+
#oid_type if respond_to?(:oid_type)
|
429
|
+
@adapter = nil
|
430
|
+
instance_variables.map { |var| [ var, instance_variable_get(var) ] }
|
431
|
+
end
|
432
|
+
|
433
|
+
def marshal_load(data)
|
434
|
+
data.each { |pair| instance_variable_set( pair[0], pair[1] ) }
|
435
|
+
end
|
436
|
+
|
437
|
+
# @note Based on *active_record/connection_adapters/postgresql/cast.rb* (4.0).
|
438
|
+
module Cast
|
439
|
+
|
440
|
+
def string_to_money(string)
|
441
|
+
return string unless String === string
|
442
|
+
|
443
|
+
# Because money output is formatted according to the locale, there
|
444
|
+
# are two cases to consider (note the decimal separators) :
|
445
|
+
# (1) $12,345,678.12
|
446
|
+
# (2) $12.345.678,12
|
447
|
+
# Negative values are represented as follows:
|
448
|
+
# (3) -$2.55
|
449
|
+
# (4) ($2.55)
|
450
|
+
string = string.sub(/^\((.+)\)$/, '-\1') # (4)
|
451
|
+
case string
|
452
|
+
when /^-?\D+[\d,]+\.\d{2}$/ # (1)
|
453
|
+
string.gsub!(/[^-\d.]/, '')
|
454
|
+
when /^-?\D+[\d.]+,\d{2}$/ # (2)
|
455
|
+
string.gsub!(/[^-\d,]/, '')
|
456
|
+
string.sub!(/,/, '.')
|
457
|
+
end
|
458
|
+
value_to_decimal string
|
459
|
+
end
|
460
|
+
|
461
|
+
def point_to_string(point)
|
462
|
+
"(#{point[0]},#{point[1]})"
|
463
|
+
end
|
464
|
+
|
465
|
+
def string_to_point(string)
|
466
|
+
if string[0] == '(' && string[-1] == ')'
|
467
|
+
string = string[1...-1]
|
468
|
+
end
|
469
|
+
string.split(',').map { |v| Float(v) }
|
470
|
+
end
|
471
|
+
|
472
|
+
def string_to_time(string)
|
473
|
+
return string unless String === string
|
474
|
+
|
475
|
+
case string
|
476
|
+
when 'infinity' then 1.0 / 0.0
|
477
|
+
when '-infinity' then -1.0 / 0.0
|
478
|
+
when / BC$/
|
479
|
+
super("-#{string.sub(/ BC$/, "")}")
|
480
|
+
else
|
481
|
+
super
|
482
|
+
end
|
483
|
+
end
|
484
|
+
|
485
|
+
def string_to_bit(value)
|
486
|
+
case value
|
487
|
+
when /^[01]*$/ then value # Bit-string notation
|
488
|
+
when /^[0-9A-F]*$/i then value.hex.to_s(2) # Hexadecimal notation
|
489
|
+
end
|
490
|
+
end
|
491
|
+
|
492
|
+
def string_to_bit(value)
|
493
|
+
case value
|
494
|
+
when /^0x/i
|
495
|
+
value[2..-1].hex.to_s(2) # Hexadecimal notation
|
496
|
+
else
|
497
|
+
value # Bit-string notation
|
498
|
+
end
|
499
|
+
end if AR40
|
500
|
+
|
501
|
+
def hstore_to_string(object, array_member = false)
|
502
|
+
if Hash === object
|
503
|
+
string = object.map { |k, v| "#{escape_hstore(k)}=>#{escape_hstore(v)}" }.join(',')
|
504
|
+
string = escape_hstore(string) if array_member
|
505
|
+
string
|
506
|
+
else
|
507
|
+
object
|
508
|
+
end
|
509
|
+
end
|
510
|
+
|
511
|
+
def string_to_hstore(string)
|
512
|
+
if string.nil?
|
513
|
+
nil
|
514
|
+
elsif String === string
|
515
|
+
Hash[string.scan(HstorePair).map { |k, v|
|
516
|
+
v = v.upcase == 'NULL' ? nil : v.gsub(/\A"(.*)"\Z/m,'\1').gsub(/\\(.)/, '\1')
|
517
|
+
k = k.gsub(/\A"(.*)"\Z/m,'\1').gsub(/\\(.)/, '\1')
|
518
|
+
[k, v]
|
519
|
+
}]
|
520
|
+
else
|
521
|
+
string
|
522
|
+
end
|
523
|
+
end
|
524
|
+
|
525
|
+
def json_to_string(object)
|
526
|
+
if Hash === object || Array === object
|
527
|
+
ActiveSupport::JSON.encode(object)
|
528
|
+
else
|
529
|
+
object
|
530
|
+
end
|
531
|
+
end
|
532
|
+
|
533
|
+
def array_to_string(value, column, adapter)
|
534
|
+
casted_values = value.map do |val|
|
535
|
+
if String === val
|
536
|
+
if val == "NULL"
|
537
|
+
"\"#{val}\""
|
538
|
+
else
|
539
|
+
quote_and_escape(adapter.type_cast(val, column, true))
|
540
|
+
end
|
541
|
+
else
|
542
|
+
adapter.type_cast(val, column, true)
|
543
|
+
end
|
544
|
+
end
|
545
|
+
"{#{casted_values.join(',')}}"
|
546
|
+
end
|
547
|
+
|
548
|
+
def range_to_string(object)
|
549
|
+
from = object.begin.respond_to?(:infinite?) && object.begin.infinite? ? '' : object.begin
|
550
|
+
to = object.end.respond_to?(:infinite?) && object.end.infinite? ? '' : object.end
|
551
|
+
"[#{from},#{to}#{object.exclude_end? ? ')' : ']'}"
|
552
|
+
end
|
553
|
+
|
554
|
+
def string_to_json(string)
|
555
|
+
if String === string
|
556
|
+
ActiveSupport::JSON.decode(string)
|
557
|
+
else
|
558
|
+
string
|
559
|
+
end
|
560
|
+
end
|
561
|
+
|
562
|
+
def string_to_cidr(string)
|
563
|
+
if string.nil?
|
564
|
+
nil
|
565
|
+
elsif String === string
|
566
|
+
begin
|
567
|
+
IPAddr.new(string)
|
568
|
+
rescue ArgumentError
|
569
|
+
nil
|
570
|
+
end
|
571
|
+
else
|
572
|
+
string
|
573
|
+
end
|
574
|
+
end
|
575
|
+
|
576
|
+
def cidr_to_string(object)
|
577
|
+
if IPAddr === object
|
578
|
+
"#{object.to_s}/#{object.instance_variable_get(:@mask_addr).to_s(2).count('1')}"
|
579
|
+
else
|
580
|
+
object
|
581
|
+
end
|
582
|
+
end
|
583
|
+
|
584
|
+
# @note Only used for default values - we get a "parsed" array from JDBC.
|
585
|
+
def string_to_array(string, column_or_oid)
|
586
|
+
return string unless String === string
|
587
|
+
parse_pg_array(string).map { |val| type_cast_array(column_or_oid, val) }
|
588
|
+
end
|
589
|
+
|
590
|
+
private
|
591
|
+
|
592
|
+
# @private
|
593
|
+
HstorePair = begin
|
594
|
+
quoted_string = /"[^"\\]*(?:\\.[^"\\]*)*"/
|
595
|
+
unquoted_string = /(?:\\.|[^\s,])[^\s=,\\]*(?:\\.[^\s=,\\]*|=[^,>])*/
|
596
|
+
/(#{quoted_string}|#{unquoted_string})\s*=>\s*(#{quoted_string}|#{unquoted_string})/
|
597
|
+
end
|
598
|
+
|
599
|
+
def escape_hstore(value)
|
600
|
+
if value.nil?
|
601
|
+
'NULL'
|
602
|
+
else
|
603
|
+
if value == ""
|
604
|
+
'""'
|
605
|
+
else
|
606
|
+
'"%s"' % value.to_s.gsub(/(["\\])/, '\\\\\1')
|
607
|
+
end
|
608
|
+
end
|
609
|
+
end
|
610
|
+
|
611
|
+
ARRAY_ESCAPE = "\\" * 2 * 2 # escape the backslash twice for PG arrays
|
612
|
+
|
613
|
+
def quote_and_escape(value)
|
614
|
+
case value
|
615
|
+
when "NULL", Numeric
|
616
|
+
value
|
617
|
+
else
|
618
|
+
value = value.gsub(/\\/, ARRAY_ESCAPE)
|
619
|
+
value.gsub!(/"/,"\\\"")
|
620
|
+
"\"#{value}\""
|
621
|
+
end
|
622
|
+
end
|
623
|
+
|
624
|
+
def type_cast_array(oid, value)
|
625
|
+
if ::Array === value
|
626
|
+
value.map { |item| type_cast_array(oid, item) }
|
627
|
+
else
|
628
|
+
if oid.is_a?(ColumnMethods)
|
629
|
+
oid.type_cast value, oid.type # column.type
|
630
|
+
else
|
631
|
+
oid.type_cast value
|
632
|
+
end
|
633
|
+
end
|
634
|
+
end
|
635
|
+
|
636
|
+
end
|
637
|
+
|
638
|
+
end unless AR42
|
639
|
+
end
|
640
|
+
end
|