Skip to content

Commit 339d62d

Browse files
committed
Merge with some older changes I made but forgot to push :(
2 parents fa0b3d3 + 78175ec commit 339d62d

File tree

2 files changed

+56
-41
lines changed

2 files changed

+56
-41
lines changed

lib/arjdbc/abstract/database_statements.rb

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,7 @@ def execute(sql, name = nil, async: false, allow_retry: false, materialize_trans
8787

8888
mark_transaction_written_if_write(sql)
8989

90-
log(sql, name, async: async) do
91-
with_raw_connection(allow_retry: allow_retry, materialize_transactions: materialize_transactions) do |conn|
92-
conn.execute(sql)
93-
end
94-
end
90+
raw_execute(sql, name, async: async, allow_retry: allow_retry, materialize_transactions: materialize_transactions)
9591
end
9692

9793
# overridden to support legacy binds
@@ -108,6 +104,16 @@ def convert_legacy_binds_to_attributes(binds)
108104
end
109105
end
110106

107+
def raw_execute(sql, name, async: false, allow_retry: false, materialize_transactions: false)
108+
log(sql, name, async: async) do
109+
with_raw_connection(allow_retry: allow_retry, materialize_transactions: materialize_transactions) do |conn|
110+
# We sometimes return an ActiveRecord::Result and sometimes a raw, so force to raw
111+
result = conn.execute(sql)
112+
result.is_a?(ActiveRecord::Result) ? result.to_a : result
113+
end
114+
end
115+
end
116+
111117
end
112118
end
113119
end

lib/arjdbc/sqlite3/adapter.rb

Lines changed: 45 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -90,38 +90,6 @@ def dealloc(stmt)
9090
end
9191
end
9292

93-
def initialize(...)
94-
super
95-
96-
@memory_database = false
97-
case @config[:database].to_s
98-
when ""
99-
raise ArgumentError, "No database file specified. Missing argument: database"
100-
when ":memory:"
101-
@memory_database = true
102-
when /\Afile:/
103-
else
104-
# Otherwise we have a path relative to Rails.root
105-
@config[:database] = File.expand_path(@config[:database], Rails.root) if defined?(Rails.root)
106-
dirname = File.dirname(@config[:database])
107-
unless File.directory?(dirname)
108-
begin
109-
Dir.mkdir(dirname)
110-
rescue Errno::ENOENT => error
111-
if error.message.include?("No such file or directory")
112-
raise ActiveRecord::NoDatabaseError.new(connection_pool: @pool)
113-
else
114-
raise
115-
end
116-
end
117-
end
118-
end
119-
120-
@config[:strict] = ConnectionAdapters::SQLite3Adapter.strict_strings_by_default unless @config.key?(:strict)
121-
@connection_parameters = @config.merge(database: @config[:database].to_s, results_as_hash: true)
122-
@use_insert_returning = @config.key?(:insert_returning) ? self.class.type_cast_config_to_boolean(@config[:insert_returning]) : true
123-
end
124-
12593
def self.database_exists?(config)
12694
@config[:database] == ":memory:" || File.exist?(@config[:database].to_s)
12795
end
@@ -321,7 +289,7 @@ def change_column_default(table_name, column_name, default_or_changes) #:nodoc:
321289

322290
def change_column_null(table_name, column_name, null, default = nil) #:nodoc:
323291
validate_change_column_null_argument!(null)
324-
292+
325293
unless null || default.nil?
326294
internal_exec_query("UPDATE #{quote_table_name(table_name)} SET #{quote_column_name(column_name)}=#{quote(default)} WHERE #{quote_column_name(column_name)} IS NULL")
327295
end
@@ -635,6 +603,11 @@ def translate_exception(exception, message:, sql:, binds:)
635603
elsif exception.message.match?(/called on a closed database/i)
636604
# DIFFERENCE: FQN
637605
::ActiveRecord::ConnectionNotEstablished.new(exception, connection_pool: @pool)
606+
elsif exception.message.match?(/sql error/i)
607+
::ActiveRecord::StatementInvalid.new(message, sql: sql, binds: binds, connection_pool: @pool)
608+
elsif exception.message.match?(/write a readonly database/i)
609+
message = message.sub('org.sqlite.SQLiteException', 'SQLite3::ReadOnlyException')
610+
::ActiveRecord::StatementInvalid.new(message, sql: sql, binds: binds, connection_pool: @pool)
638611
else
639612
super
640613
end
@@ -710,6 +683,44 @@ def reconnect
710683
end
711684
end
712685

686+
def configure_connection
687+
if @config[:timeout] && @config[:retries]
688+
raise ArgumentError, "Cannot specify both timeout and retries arguments"
689+
elsif @config[:timeout]
690+
# FIXME: missing from adapter
691+
# @raw_connection.busy_timeout(self.class.type_cast_config_to_integer(@config[:timeout]))
692+
elsif @config[:retries]
693+
retries = self.class.type_cast_config_to_integer(@config[:retries])
694+
raw_connection.busy_handler do |count|
695+
count <= retries
696+
end
697+
end
698+
699+
# Enforce foreign key constraints
700+
# https://www.sqlite.org/pragma.html#pragma_foreign_keys
701+
# https://www.sqlite.org/foreignkeys.html
702+
raw_execute("PRAGMA foreign_keys = ON", "SCHEMA")
703+
unless @memory_database
704+
# Journal mode WAL allows for greater concurrency (many readers + one writer)
705+
# https://www.sqlite.org/pragma.html#pragma_journal_mode
706+
raw_execute("PRAGMA journal_mode = WAL", "SCHEMA")
707+
# Set more relaxed level of database durability
708+
# 2 = "FULL" (sync on every write), 1 = "NORMAL" (sync every 1000 written pages) and 0 = "NONE"
709+
# https://www.sqlite.org/pragma.html#pragma_synchronous
710+
raw_execute("PRAGMA synchronous = NORMAL", "SCHEMA")
711+
# Set the global memory map so all processes can share some data
712+
# https://www.sqlite.org/pragma.html#pragma_mmap_size
713+
# https://www.sqlite.org/mmap.html
714+
raw_execute("PRAGMA mmap_size = #{128.megabytes}", "SCHEMA")
715+
end
716+
# Impose a limit on the WAL file to prevent unlimited growth
717+
# https://www.sqlite.org/pragma.html#pragma_journal_size_limit
718+
raw_execute("PRAGMA journal_size_limit = #{64.megabytes}", "SCHEMA")
719+
# Set the local connection cache to 2000 pages
720+
# https://www.sqlite.org/pragma.html#pragma_cache_size
721+
raw_execute("PRAGMA cache_size = 2000", "SCHEMA")
722+
end
723+
713724
def configure_connection
714725
if @config[:timeout] && @config[:retries]
715726
raise ArgumentError, "Cannot specify both timeout and retries arguments"
@@ -775,9 +786,7 @@ class SQLite3Adapter < AbstractAdapter
775786
# If you wish to enable this mode you can add the following line to your application.rb file:
776787
#
777788
# config.active_record.sqlite3_adapter_strict_strings_by_default = true
778-
class_attribute :strict_strings_by_default, default: false
779-
780-
789+
class_attribute :strict_strings_by_default, default: false # Does not actually do anything right now
781790

782791
def self.represent_boolean_as_integer=(value) # :nodoc:
783792
if value == false

0 commit comments

Comments
 (0)