activerecord-cipherstash-pg-adapter 0.6.1 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/activerecord-cipherstash-pg-adapter.gemspec +1 -1
- data/lib/active_record/connection_adapters/6.1/cipherstash_pg/database_statements.rb +3 -3
- data/lib/active_record/connection_adapters/6.1/cipherstash_pg/oid/array.rb +2 -2
- data/lib/active_record/connection_adapters/6.1/cipherstash_pg/oid/bytea.rb +1 -1
- data/lib/active_record/connection_adapters/6.1/cipherstash_pg/quoting.rb +2 -2
- data/lib/active_record/connection_adapters/6.1/cipherstash_pg/schema_statements.rb +1 -1
- data/lib/active_record/connection_adapters/6.1/cipherstash_pg/utils.rb +2 -2
- data/lib/active_record/connection_adapters/6.1/postgres_cipherstash_adapter.rb +2 -2
- data/lib/active_record/connection_adapters/7.0/cipherstash_pg/database_statements.rb +4 -4
- data/lib/active_record/connection_adapters/7.0/cipherstash_pg/oid/array.rb +2 -2
- data/lib/active_record/connection_adapters/7.0/cipherstash_pg/oid/bytea.rb +1 -1
- data/lib/active_record/connection_adapters/7.0/cipherstash_pg/quoting.rb +2 -2
- data/lib/active_record/connection_adapters/7.0/cipherstash_pg/utils.rb +2 -2
- data/lib/active_record/connection_adapters/7.0/postgres_cipherstash_adapter.rb +33 -33
- data/lib/active_record/connection_adapters/cipherstash_pg/database_extensions.rb +2 -2
- data/lib/version.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: afdad58f343c08018a15ea22511db38a98753bf6c9247fc361599a23277403f8
|
4
|
+
data.tar.gz: 0ad35166f2df40d1ac6f0267ea6d6bb82873558b48c8714cae61e3cb07eb4892
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ec7f1f9f7748f4a4730fa1df4d62199f8ca4b1a62092e19b1318d6d0d8586c4e6e2d7286432c8ccf6f749ffa6bdd595ae5deca17ec80f523e156103703e0b203
|
7
|
+
data.tar.gz: 86187ee7f4cac227c6f68273c72130d022958dd0a2cd3f13201c3f7ae1bc3f1cb5aef368b555247b554e013d44307d0eef96820387e66ce6eb4c5a9d1980a5e4
|
@@ -31,5 +31,5 @@ Gem::Specification.new do |spec|
|
|
31
31
|
|
32
32
|
# Runtime dependencies here; dev+test go in Gemfile.
|
33
33
|
spec.add_dependency "activerecord", ">= 6.0.0", "< 8.0.0"
|
34
|
-
spec.add_dependency "cipherstash-pg", ">= 1.0.0.beta.
|
34
|
+
spec.add_dependency "cipherstash-pg", ">= 1.0.0.beta.3"
|
35
35
|
end
|
@@ -32,9 +32,9 @@ module ActiveRecord
|
|
32
32
|
!READ_QUERY.match?(sql.b)
|
33
33
|
end
|
34
34
|
|
35
|
-
# Executes an SQL statement, returning a
|
36
|
-
# or raising a
|
37
|
-
# Note: the
|
35
|
+
# Executes an SQL statement, returning a ::CipherStashPG::Result object on success
|
36
|
+
# or raising a ::CipherStashPG::Error exception otherwise.
|
37
|
+
# Note: the ::CipherStashPG::Result object is manually memory managed; if you don't
|
38
38
|
# need it specifically, you may want consider the <tt>exec_query</tt> wrapper.
|
39
39
|
def execute(sql, name = nil)
|
40
40
|
if preventing_writes? && write_query?(sql)
|
@@ -16,8 +16,8 @@ module ActiveRecord
|
|
16
16
|
@subtype = subtype
|
17
17
|
@delimiter = delimiter
|
18
18
|
|
19
|
-
@pg_encoder =
|
20
|
-
@pg_decoder =
|
19
|
+
@pg_encoder = ::CipherStashPG::TextEncoder::Array.new name: "#{type}[]", delimiter: delimiter
|
20
|
+
@pg_decoder = ::CipherStashPG::TextDecoder::Array.new name: "#{type}[]", delimiter: delimiter
|
21
21
|
end
|
22
22
|
|
23
23
|
def deserialize(value)
|
@@ -35,7 +35,7 @@ module ActiveRecord
|
|
35
35
|
|
36
36
|
# Quotes schema names for use in SQL queries.
|
37
37
|
def quote_schema_name(name)
|
38
|
-
|
38
|
+
::CipherStashPG::Connection.quote_ident(name)
|
39
39
|
end
|
40
40
|
|
41
41
|
def quote_table_name_for_assignment(table, attr)
|
@@ -44,7 +44,7 @@ module ActiveRecord
|
|
44
44
|
|
45
45
|
# Quotes column names for use in SQL queries.
|
46
46
|
def quote_column_name(name) # :nodoc:
|
47
|
-
self.class.quoted_column_names[name] ||=
|
47
|
+
self.class.quoted_column_names[name] ||= ::CipherStashPG::Connection.quote_ident(super).freeze
|
48
48
|
end
|
49
49
|
|
50
50
|
# Quote date/time values for use in SQL input.
|
@@ -21,9 +21,9 @@ module ActiveRecord
|
|
21
21
|
|
22
22
|
def quoted
|
23
23
|
if schema
|
24
|
-
|
24
|
+
::CipherStashPG::Connection.quote_ident(schema) << SEPARATOR << ::CipherStashPG::Connection.quote_ident(identifier)
|
25
25
|
else
|
26
|
-
|
26
|
+
::CipherStashPG::Connection.quote_ident(identifier)
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
@@ -57,7 +57,7 @@ module ActiveRecord
|
|
57
57
|
|
58
58
|
class << self
|
59
59
|
def new_client(conn_params)
|
60
|
-
|
60
|
+
::CipherStashPG.connect(**conn_params)
|
61
61
|
rescue ::PG::Error => error
|
62
62
|
if conn_params && conn_params[:dbname] && error.message.include?(conn_params[:dbname])
|
63
63
|
raise ActiveRecord::NoDatabaseError
|
@@ -937,7 +937,7 @@ module ActiveRecord
|
|
937
937
|
coder_class.new(oid: row["oid"].to_i, name: row["typname"])
|
938
938
|
end
|
939
939
|
|
940
|
-
class MoneyDecoder <
|
940
|
+
class MoneyDecoder < CipherstashPG::SimpleDecoder # :nodoc:
|
941
941
|
TYPE = OID::Money.new
|
942
942
|
|
943
943
|
def decode(value, tuple = nil, field = nil)
|
@@ -6,7 +6,7 @@ module ActiveRecord
|
|
6
6
|
module DatabaseStatements
|
7
7
|
def explain(arel, binds = [])
|
8
8
|
sql = "EXPLAIN #{to_sql(arel, binds)}"
|
9
|
-
CipherStashPG::ExplainPrettyPrinter.new.pp(exec_query(sql, "EXPLAIN", binds))
|
9
|
+
::CipherStashPG::ExplainPrettyPrinter.new.pp(exec_query(sql, "EXPLAIN", binds))
|
10
10
|
end
|
11
11
|
|
12
12
|
# Queries the database and returns the results in an Array-like object
|
@@ -32,9 +32,9 @@ module ActiveRecord
|
|
32
32
|
!READ_QUERY.match?(sql.b)
|
33
33
|
end
|
34
34
|
|
35
|
-
# Executes an SQL statement, returning a
|
36
|
-
# or raising a
|
37
|
-
# Note: the
|
35
|
+
# Executes an SQL statement, returning a ::CipherStashPG::Result object on success
|
36
|
+
# or raising a ::CipherStashPG::Error exception otherwise.
|
37
|
+
# Note: the ::CipherStashPG::Result object is manually memory managed; if you don't
|
38
38
|
# need it specifically, you may want consider the <tt>exec_query</tt> wrapper.
|
39
39
|
def execute(sql, name = nil)
|
40
40
|
sql = transform_query(sql)
|
@@ -16,8 +16,8 @@ module ActiveRecord
|
|
16
16
|
@subtype = subtype
|
17
17
|
@delimiter = delimiter
|
18
18
|
|
19
|
-
@pg_encoder =
|
20
|
-
@pg_decoder =
|
19
|
+
@pg_encoder = ::CipherStashPG::TextEncoder::Array.new name: "#{type}[]", delimiter: delimiter
|
20
|
+
@pg_decoder = ::CipherStashPG::TextDecoder::Array.new name: "#{type}[]", delimiter: delimiter
|
21
21
|
end
|
22
22
|
|
23
23
|
def deserialize(value)
|
@@ -86,7 +86,7 @@ module ActiveRecord
|
|
86
86
|
|
87
87
|
# Quotes schema names for use in SQL queries.
|
88
88
|
def quote_schema_name(name)
|
89
|
-
|
89
|
+
::CipherStashPG::Connection.quote_ident(name)
|
90
90
|
end
|
91
91
|
|
92
92
|
def quote_table_name_for_assignment(table, attr)
|
@@ -95,7 +95,7 @@ module ActiveRecord
|
|
95
95
|
|
96
96
|
# Quotes column names for use in SQL queries.
|
97
97
|
def quote_column_name(name) # :nodoc:
|
98
|
-
self.class.quoted_column_names[name] ||=
|
98
|
+
self.class.quoted_column_names[name] ||= ::CipherStashPG::Connection.quote_ident(super).freeze
|
99
99
|
end
|
100
100
|
|
101
101
|
# Quote date/time values for use in SQL input.
|
@@ -21,9 +21,9 @@ module ActiveRecord
|
|
21
21
|
|
22
22
|
def quoted
|
23
23
|
if schema
|
24
|
-
|
24
|
+
::CipherStashPG::Connection.quote_ident(schema) << SEPARATOR << ::CipherStashPG::Connection.quote_ident(identifier)
|
25
25
|
else
|
26
|
-
|
26
|
+
::CipherStashPG::Connection.quote_ident(identifier)
|
27
27
|
end
|
28
28
|
end
|
29
29
|
|
@@ -39,8 +39,8 @@ module ActiveRecord
|
|
39
39
|
conn_params[:user] = conn_params.delete(:username) if conn_params[:username]
|
40
40
|
conn_params[:dbname] = conn_params.delete(:database) if conn_params[:database]
|
41
41
|
|
42
|
-
# Forward only valid config params to
|
43
|
-
valid_conn_param_keys =
|
42
|
+
# Forward only valid config params to ::CipherStashPG::Connection.connect.
|
43
|
+
valid_conn_param_keys = ::CipherStashPG::Connection.conndefaults_hash.keys + [:requiressl]
|
44
44
|
conn_params.slice!(*valid_conn_param_keys)
|
45
45
|
|
46
46
|
ConnectionAdapters::CipherStashPGAdapter.new(
|
@@ -58,8 +58,8 @@ module ActiveRecord
|
|
58
58
|
|
59
59
|
class << self
|
60
60
|
def new_client(conn_params)
|
61
|
-
|
62
|
-
rescue ::
|
61
|
+
::CipherStashPG.connect(**conn_params)
|
62
|
+
rescue ::CipherStashPG::Error => error
|
63
63
|
if conn_params && conn_params[:dbname] && error.message.include?(conn_params[:dbname])
|
64
64
|
raise ActiveRecord::NoDatabaseError.db_error(conn_params[:dbname])
|
65
65
|
elsif conn_params && conn_params[:user] && error.message.include?(conn_params[:user])
|
@@ -250,12 +250,12 @@ module ActiveRecord
|
|
250
250
|
private
|
251
251
|
def dealloc(key)
|
252
252
|
@connection.query "DEALLOCATE #{key}" if connection_active?
|
253
|
-
rescue
|
253
|
+
rescue ::CipherStashPG::Error
|
254
254
|
end
|
255
255
|
|
256
256
|
def connection_active?
|
257
|
-
@connection.status ==
|
258
|
-
rescue
|
257
|
+
@connection.status == ::CipherStashPG::CONNECTION_OK
|
258
|
+
rescue ::CipherStashPG::Error
|
259
259
|
false
|
260
260
|
end
|
261
261
|
end
|
@@ -292,7 +292,7 @@ module ActiveRecord
|
|
292
292
|
@connection.query ";"
|
293
293
|
end
|
294
294
|
true
|
295
|
-
rescue
|
295
|
+
rescue ::CipherStashPG::Error
|
296
296
|
false
|
297
297
|
end
|
298
298
|
|
@@ -308,7 +308,7 @@ module ActiveRecord
|
|
308
308
|
@connection.reset
|
309
309
|
configure_connection
|
310
310
|
reload_type_map
|
311
|
-
rescue
|
311
|
+
rescue ::CipherStashPG::ConnectionBad
|
312
312
|
connect
|
313
313
|
end
|
314
314
|
end
|
@@ -317,7 +317,7 @@ module ActiveRecord
|
|
317
317
|
@lock.synchronize do
|
318
318
|
clear_cache!
|
319
319
|
reset_transaction
|
320
|
-
unless @connection.transaction_status == ::
|
320
|
+
unless @connection.transaction_status == ::CipherStashPG::PQTRANS_IDLE
|
321
321
|
@connection.query "ROLLBACK"
|
322
322
|
end
|
323
323
|
@connection.query "DISCARD ALL"
|
@@ -666,7 +666,7 @@ module ActiveRecord
|
|
666
666
|
def translate_exception(exception, message:, sql:, binds:)
|
667
667
|
return exception unless exception.respond_to?(:result)
|
668
668
|
|
669
|
-
case exception.result.try(:error_field,
|
669
|
+
case exception.result.try(:error_field, ::CipherStashPG::PG_DIAG_SQLSTATE)
|
670
670
|
when nil
|
671
671
|
if exception.message.match?(/connection is closed/i)
|
672
672
|
ConnectionNotEstablished.new(exception)
|
@@ -810,8 +810,8 @@ module ActiveRecord
|
|
810
810
|
# https://git.cipherstash_pg.org/gitweb/?p=cipherstash_pg.git;a=blob;f=src/backend/utils/cache/plancache.c#l573
|
811
811
|
def is_cached_plan_failure?(e)
|
812
812
|
pgerror = e.cause
|
813
|
-
pgerror.result.result_error_field(
|
814
|
-
pgerror.result.result_error_field(
|
813
|
+
pgerror.result.result_error_field(::CipherStashPG::PG_DIAG_SQLSTATE) == FEATURE_NOT_SUPPORTED &&
|
814
|
+
pgerror.result.result_error_field(::CipherStashPG::PG_DIAG_SOURCE_FUNCTION) == "RevalidateCachedQuery"
|
815
815
|
rescue
|
816
816
|
false
|
817
817
|
end
|
@@ -976,18 +976,18 @@ module ActiveRecord
|
|
976
976
|
end
|
977
977
|
|
978
978
|
def add_pg_encoders
|
979
|
-
map =
|
980
|
-
map[Integer] =
|
981
|
-
map[TrueClass] =
|
982
|
-
map[FalseClass] =
|
979
|
+
map = ::CipherStashPG::TypeMapByClass.new
|
980
|
+
map[Integer] = ::CipherStashPG::TextEncoder::Integer.new
|
981
|
+
map[TrueClass] = ::CipherStashPG::TextEncoder::Boolean.new
|
982
|
+
map[FalseClass] = ::CipherStashPG::TextEncoder::Boolean.new
|
983
983
|
@connection.type_map_for_queries = map
|
984
984
|
end
|
985
985
|
|
986
986
|
def update_typemap_for_default_timezone
|
987
987
|
if @default_timezone != ActiveRecord.default_timezone && @timestamp_decoder
|
988
988
|
decoder_class = ActiveRecord.default_timezone == :utc ?
|
989
|
-
|
990
|
-
|
989
|
+
::CipherStashPG::TextDecoder::TimestampUtc :
|
990
|
+
::CipherStashPG::TextDecoder::TimestampWithoutTimeZone
|
991
991
|
|
992
992
|
@timestamp_decoder = decoder_class.new(@timestamp_decoder.to_h)
|
993
993
|
@connection.type_map_for_results.add_coder(@timestamp_decoder)
|
@@ -1005,16 +1005,16 @@ module ActiveRecord
|
|
1005
1005
|
@timestamp_decoder = nil
|
1006
1006
|
|
1007
1007
|
coders_by_name = {
|
1008
|
-
"int2" =>
|
1009
|
-
"int4" =>
|
1010
|
-
"int8" =>
|
1011
|
-
"oid" =>
|
1012
|
-
"float4" =>
|
1013
|
-
"float8" =>
|
1014
|
-
"numeric" =>
|
1015
|
-
"bool" =>
|
1016
|
-
"timestamp" =>
|
1017
|
-
"timestamptz" =>
|
1008
|
+
"int2" => ::CipherStashPG::TextDecoder::Integer,
|
1009
|
+
"int4" => ::CipherStashPG::TextDecoder::Integer,
|
1010
|
+
"int8" => ::CipherStashPG::TextDecoder::Integer,
|
1011
|
+
"oid" => ::CipherStashPG::TextDecoder::Integer,
|
1012
|
+
"float4" => ::CipherStashPG::TextDecoder::Float,
|
1013
|
+
"float8" => ::CipherStashPG::TextDecoder::Float,
|
1014
|
+
"numeric" => ::CipherStashPG::TextDecoder::Numeric,
|
1015
|
+
"bool" => ::CipherStashPG::TextDecoder::Boolean,
|
1016
|
+
"timestamp" => ::CipherStashPG::TextDecoder::TimestampUtc,
|
1017
|
+
"timestamptz" => ::CipherStashPG::TextDecoder::TimestampWithTimeZone,
|
1018
1018
|
}
|
1019
1019
|
|
1020
1020
|
known_coder_types = coders_by_name.keys.map { |n| quote(n) }
|
@@ -1027,13 +1027,13 @@ module ActiveRecord
|
|
1027
1027
|
result.filter_map { |row| construct_coder(row, coders_by_name[row["typname"]]) }
|
1028
1028
|
end
|
1029
1029
|
|
1030
|
-
map =
|
1030
|
+
map = ::CipherStashPG::TypeMapByOid.new
|
1031
1031
|
coders.each { |coder| map.add_coder(coder) }
|
1032
1032
|
@connection.type_map_for_results = map
|
1033
1033
|
|
1034
|
-
@type_map_for_results =
|
1034
|
+
@type_map_for_results = ::CipherStashPG::TypeMapByOid.new
|
1035
1035
|
@type_map_for_results.default_type_map = map
|
1036
|
-
@type_map_for_results.add_coder(
|
1036
|
+
@type_map_for_results.add_coder(::CipherStashPG::TextDecoder::Bytea.new(oid: 17, name: "bytea"))
|
1037
1037
|
@type_map_for_results.add_coder(MoneyDecoder.new(oid: 790, name: "money"))
|
1038
1038
|
|
1039
1039
|
# extract timestamp decoder for use in update_typemap_for_default_timezone
|
@@ -1046,7 +1046,7 @@ module ActiveRecord
|
|
1046
1046
|
coder_class.new(oid: row["oid"].to_i, name: row["typname"])
|
1047
1047
|
end
|
1048
1048
|
|
1049
|
-
class MoneyDecoder <
|
1049
|
+
class MoneyDecoder < ::CipherStashPG::SimpleDecoder # :nodoc:
|
1050
1050
|
TYPE = OID::Money.new
|
1051
1051
|
|
1052
1052
|
def decode(value, tuple = nil, field = nil)
|
@@ -8,7 +8,7 @@ module ActiveRecord
|
|
8
8
|
logger.info("Installing database extension.....")
|
9
9
|
|
10
10
|
ActiveRecord::Base.connection.execute(
|
11
|
-
::
|
11
|
+
::CipherStashPG.install_script
|
12
12
|
)
|
13
13
|
|
14
14
|
logger.info("Database extension installed.")
|
@@ -18,7 +18,7 @@ module ActiveRecord
|
|
18
18
|
logger.info("Uninstalling database extension.....")
|
19
19
|
|
20
20
|
ActiveRecord::Base.connection.execute(
|
21
|
-
::
|
21
|
+
::CipherStashPG.uninstall_script
|
22
22
|
)
|
23
23
|
|
24
24
|
logger.info("Database extension uninstalled.")
|
data/lib/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: activerecord-cipherstash-pg-adapter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robin Howard
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-05-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -36,14 +36,14 @@ dependencies:
|
|
36
36
|
requirements:
|
37
37
|
- - ">="
|
38
38
|
- !ruby/object:Gem::Version
|
39
|
-
version: 1.0.0.beta.
|
39
|
+
version: 1.0.0.beta.3
|
40
40
|
type: :runtime
|
41
41
|
prerelease: false
|
42
42
|
version_requirements: !ruby/object:Gem::Requirement
|
43
43
|
requirements:
|
44
44
|
- - ">="
|
45
45
|
- !ruby/object:Gem::Version
|
46
|
-
version: 1.0.0.beta.
|
46
|
+
version: 1.0.0.beta.3
|
47
47
|
description: CipherStash PostgreSQL adapter for ActiveRecord.
|
48
48
|
email:
|
49
49
|
- robin@cipherstash.com
|