2019-05-03 06:17:27 +08:00
# frozen_string_literal: true
2019-02-25 13:02:32 +08:00
class MiniSqlMultisiteConnection < MiniSql :: Postgres :: Connection
2018-06-19 14:13:14 +08:00
class CustomBuilder < MiniSql :: Builder
def initialize ( connection , sql )
super
end
def secure_category ( secure_category_ids , category_alias = 'c' )
if secure_category_ids . present?
2019-05-03 06:17:27 +08:00
where ( " NOT COALESCE( #{ category_alias } .read_restricted, false) OR #{ category_alias } .id in (:secure_category_ids) " , secure_category_ids : secure_category_ids )
2018-06-19 14:13:14 +08:00
else
2019-05-03 06:17:27 +08:00
where ( " NOT COALESCE( #{ category_alias } .read_restricted, false) " )
2018-06-19 14:13:14 +08:00
end
self
end
end
class ParamEncoder
def encode ( * sql_array )
# use active record to avoid any discrepencies
2019-05-07 09:27:05 +08:00
ActiveRecord :: Base . public_send ( :sanitize_sql_array , sql_array )
2018-06-19 14:13:14 +08:00
end
end
2018-07-24 16:41:55 +08:00
class AfterCommitWrapper
2019-11-11 06:36:40 +08:00
def initialize ( & blk )
raise ArgumentError , " tried to create a Proc without a block in AfterCommitWrapper " if ! blk
@callback = blk
2018-07-24 16:41:55 +08:00
end
def committed! ( * )
2020-12-08 08:03:31 +08:00
if DB . transaction_open?
# Nested transaction. Pass the callback to the parent
ActiveRecord :: Base . connection . add_transaction_record ( self )
else
@callback . call
end
2018-07-24 16:41:55 +08:00
end
def before_committed! ( * ) ; end
def rolledback! ( * ) ; end
2019-09-12 08:41:50 +08:00
def trigger_transactional_callbacks?
true
end
2018-07-24 16:41:55 +08:00
end
2020-12-08 08:03:31 +08:00
def transaction_open?
ActiveRecord :: Base . connection . transaction_open?
end
if Rails . env . test?
def test_transaction = ( transaction )
@test_transaction = transaction
end
def transaction_open?
ActiveRecord :: Base . connection . current_transaction != @test_transaction
end
end
2018-07-24 16:41:55 +08:00
# Allows running arbitrary code after the current transaction has been committed.
2020-05-01 23:37:43 +08:00
# Works with nested ActiveRecord transaction blocks. Useful for scheduling sidekiq jobs.
# If not currently in a transaction, will execute immediately
2018-07-24 16:41:55 +08:00
def after_commit ( & blk )
2020-12-08 08:03:31 +08:00
return blk . call if ! transaction_open?
2020-05-01 23:37:43 +08:00
2018-07-24 16:41:55 +08:00
ActiveRecord :: Base . connection . add_transaction_record (
AfterCommitWrapper . new ( & blk )
)
end
2018-06-19 14:13:14 +08:00
def self . instance
2018-06-19 14:43:50 +08:00
new ( nil , param_encoder : ParamEncoder . new )
2018-06-19 14:13:14 +08:00
end
2018-06-19 14:43:50 +08:00
2018-06-19 14:13:14 +08:00
# we need a tiny adapter here so we always run against the
# correct multisite connection
def raw_connection
ActiveRecord :: Base . connection . raw_connection
end
2021-03-24 05:48:04 +08:00
# make for a multisite friendly prepared statement cache
def prepared ( condition = true )
if condition
conn = raw_connection . instance_variable_get ( :@mini_sql_prepared_connection )
if ! conn
conn = MiniSql :: Postgres :: PreparedConnection . new ( self )
raw_connection . instance_variable_set ( :@mini_sql_prepared_connection , conn )
end
conn
else
self
end
end
2018-06-19 14:13:14 +08:00
def build ( sql )
CustomBuilder . new ( self , sql )
end
2018-06-20 15:48:02 +08:00
def sql_fragment ( query , * args )
if args . length > 0
param_encoder . encode ( query , * args )
else
query
end
end
2018-06-19 14:13:14 +08:00
end