activerecord-jdbc-adapter-ficoh 1.3.21-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 +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
|