2019-05-03 06:17:27 +08:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
2022-02-03 18:00:28 +08:00
|
|
|
class MiniSqlMultisiteConnection < MiniSql::ActiveRecordPostgres::Connection
|
2018-06-19 14:13:14 +08:00
|
|
|
class CustomBuilder < MiniSql::Builder
|
|
|
|
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)
|
2023-12-07 06:25:00 +08:00
|
|
|
# use active record to avoid any discrepancies
|
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
|
2023-12-15 23:46:04 +08:00
|
|
|
|
2018-07-24 16:41:55 +08:00
|
|
|
def rolledback!(*)
|
|
|
|
end
|
2023-12-15 23:46:04 +08:00
|
|
|
|
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
|
2022-02-03 18:00:28 +08:00
|
|
|
def active_record_connection
|
|
|
|
ActiveRecord::Base.connection
|
2018-06-19 14:13:14 +08:00
|
|
|
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
|
|
|
|
2024-09-11 15:14:53 +08:00
|
|
|
def run(sql, params)
|
|
|
|
ActiveSupport::Notifications.instrument(
|
|
|
|
"sql.mini_sql",
|
|
|
|
sql: sql_fragment(sql, *params),
|
|
|
|
name: "MiniSql",
|
|
|
|
)
|
|
|
|
|
|
|
|
super
|
|
|
|
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
|