Skip to content

adapter fixes for db statements and sqlite3 #1194

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 12, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/arjdbc/abstract/database_statements.rb
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ def preprocess_query(sql)
sql
end

def raw_execute(sql, name, binds = [], prepare: false, async: false, allow_retry: false, materialize_transactions: true)
def raw_execute(sql, name, binds = [], prepare: false, async: false, allow_retry: false, materialize_transactions: true, batch: false)
log(sql, name, async: async) do
with_raw_connection(allow_retry: allow_retry, materialize_transactions: materialize_transactions) do |conn|
result = conn.execute(sql)
Expand Down
37 changes: 30 additions & 7 deletions lib/arjdbc/sqlite3/adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -223,17 +223,29 @@ def supports_lazy_transactions?

# REFERENTIAL INTEGRITY ====================================

def execute_batch(statements, name = nil, **kwargs)
if statements.is_a?(Array)
# SQLite JDBC doesn't support multiple statements in one execute
# Execute each statement separately
statements.each do |sql|
raw_execute(sql, name, **kwargs.merge(batch: true))
end
else
raw_execute(statements, name, batch: true, **kwargs)
end
end

def disable_referential_integrity # :nodoc:
old_foreign_keys = query_value("PRAGMA foreign_keys")
old_defer_foreign_keys = query_value("PRAGMA defer_foreign_keys")

begin
execute("PRAGMA defer_foreign_keys = ON")
execute("PRAGMA foreign_keys = OFF")
raw_execute("PRAGMA defer_foreign_keys = ON", "SCHEMA", allow_retry: false, materialize_transactions: false)
raw_execute("PRAGMA foreign_keys = OFF", "SCHEMA", allow_retry: false, materialize_transactions: false)
yield
ensure
execute("PRAGMA defer_foreign_keys = #{old_defer_foreign_keys}")
execute("PRAGMA foreign_keys = #{old_foreign_keys}")
raw_execute("PRAGMA defer_foreign_keys = #{old_defer_foreign_keys}", "SCHEMA", allow_retry: false, materialize_transactions: false)
raw_execute("PRAGMA foreign_keys = #{old_foreign_keys}", "SCHEMA", allow_retry: false, materialize_transactions: false)
end
end

Expand Down Expand Up @@ -809,7 +821,17 @@ def configure_connection
DEFAULT_PRAGMAS.merge(pragmas).each do |pragma, value|
if ::SQLite3::Pragmas.respond_to?(pragma)
stmt = ::SQLite3::Pragmas.public_send(pragma, value)
raw_execute(stmt, "SCHEMA")
# Skip pragma execution if we're inside a transaction and it's not allowed
begin
raw_execute(stmt, "SCHEMA")
rescue => e
if e.message.include?("Safety level may not be changed inside a transaction")
# Log warning and skip this pragma
warn "Cannot set pragma '#{pragma}' inside a transaction, skipping"
else
raise
end
end
else
warn "Unknown SQLite pragma: #{pragma}"
end
Expand Down Expand Up @@ -863,7 +885,7 @@ def jdbc_connection_class
include ArJdbc::Abstract::ConnectionManagement
include ArJdbc::Abstract::DatabaseStatements
include ArJdbc::Abstract::StatementCache
include ArJdbc::Abstract::TransactionSupport
# Don't include TransactionSupport - use Rails' SQLite3::DatabaseStatements instead


##
Expand Down Expand Up @@ -972,7 +994,8 @@ def initialize_type_map(m)

# because the JDBC driver doesn't like multiple SQL statements in one JDBC statement
def combine_multi_statements(total_sql)
total_sql
# For Rails 8 compatibility - join multiple statements with semicolon
total_sql.is_a?(Array) ? total_sql.join(";\n") : total_sql
end

def type_map
Expand Down
Loading