diff options
Diffstat (limited to 'activerecord/test/cases/adapters/sqlite3')
8 files changed, 840 insertions, 0 deletions
diff --git a/activerecord/test/cases/adapters/sqlite3/collation_test.rb b/activerecord/test/cases/adapters/sqlite3/collation_test.rb new file mode 100644 index 0000000000..76c8f7d8dd --- /dev/null +++ b/activerecord/test/cases/adapters/sqlite3/collation_test.rb @@ -0,0 +1,55 @@ +# frozen_string_literal: true + +require "cases/helper" +require "support/schema_dumping_helper" + +class SQLite3CollationTest < ActiveRecord::SQLite3TestCase + include SchemaDumpingHelper + + def setup + @connection = ActiveRecord::Base.connection + @connection.create_table :collation_table_sqlite3, force: true do |t| + t.string :string_nocase, collation: "NOCASE" + t.text :text_rtrim, collation: "RTRIM" + end + end + + def teardown + @connection.drop_table :collation_table_sqlite3, if_exists: true + end + + test "string column with collation" do + column = @connection.columns(:collation_table_sqlite3).find { |c| c.name == "string_nocase" } + assert_equal :string, column.type + assert_equal "NOCASE", column.collation + end + + test "text column with collation" do + column = @connection.columns(:collation_table_sqlite3).find { |c| c.name == "text_rtrim" } + assert_equal :text, column.type + assert_equal "RTRIM", column.collation + end + + test "add column with collation" do + @connection.add_column :collation_table_sqlite3, :title, :string, collation: "RTRIM" + + column = @connection.columns(:collation_table_sqlite3).find { |c| c.name == "title" } + assert_equal :string, column.type + assert_equal "RTRIM", column.collation + end + + test "change column with collation" do + @connection.add_column :collation_table_sqlite3, :description, :string + @connection.change_column :collation_table_sqlite3, :description, :text, collation: "RTRIM" + + column = @connection.columns(:collation_table_sqlite3).find { |c| c.name == "description" } + assert_equal :text, column.type + assert_equal "RTRIM", column.collation + end + + test "schema dump includes collation" do + output = dump_table_schema("collation_table_sqlite3") + assert_match %r{t\.string\s+"string_nocase",\s+collation: "NOCASE"$}, output + assert_match %r{t\.text\s+"text_rtrim",\s+collation: "RTRIM"$}, output + end +end diff --git a/activerecord/test/cases/adapters/sqlite3/copy_table_test.rb b/activerecord/test/cases/adapters/sqlite3/copy_table_test.rb new file mode 100644 index 0000000000..ffb1d6afce --- /dev/null +++ b/activerecord/test/cases/adapters/sqlite3/copy_table_test.rb @@ -0,0 +1,101 @@ +# frozen_string_literal: true + +require "cases/helper" + +class CopyTableTest < ActiveRecord::SQLite3TestCase + fixtures :customers + + def setup + @connection = ActiveRecord::Base.connection + class << @connection + public :copy_table, :table_structure, :indexes + end + end + + def test_copy_table(from = "customers", to = "customers2", options = {}) + assert_nothing_raised { copy_table(from, to, options) } + assert_equal row_count(from), row_count(to) + + if block_given? + yield from, to, options + else + assert_equal column_names(from), column_names(to) + end + + @connection.drop_table(to) rescue nil + end + + def test_copy_table_renaming_column + test_copy_table("customers", "customers2", + rename: { "name" => "person_name" }) do |from, to, options| + expected = column_values(from, "name") + assert_equal expected, column_values(to, "person_name") + assert expected.any?, "No values in table: #{expected.inspect}" + end + end + + def test_copy_table_allows_to_pass_options_to_create_table + @connection.create_table("blocker_table") + test_copy_table("customers", "blocker_table", force: true) + end + + def test_copy_table_with_index + test_copy_table("comments", "comments_with_index") do + @connection.add_index("comments_with_index", ["post_id", "type"]) + test_copy_table("comments_with_index", "comments_with_index2") do + assert_nil table_indexes_without_name("comments_with_index") + assert_nil table_indexes_without_name("comments_with_index2") + end + end + end + + def test_copy_table_without_primary_key + test_copy_table("developers_projects", "programmers_projects") do + assert_nil @connection.primary_key("programmers_projects") + end + end + + def test_copy_table_with_id_col_that_is_not_primary_key + test_copy_table("goofy_string_id", "goofy_string_id2") do + original_id = @connection.columns("goofy_string_id").detect { |col| col.name == "id" } + copied_id = @connection.columns("goofy_string_id2").detect { |col| col.name == "id" } + assert_equal original_id.type, copied_id.type + assert_equal original_id.sql_type, copied_id.sql_type + assert_nil original_id.limit + assert_nil copied_id.limit + end + end + + def test_copy_table_with_unconventional_primary_key + test_copy_table("owners", "owners_unconventional") do + original_pk = @connection.primary_key("owners") + copied_pk = @connection.primary_key("owners_unconventional") + assert_equal original_pk, copied_pk + end + end + + def test_copy_table_with_binary_column + test_copy_table "binaries", "binaries2" + end + +private + def copy_table(from, to, options = {}) + @connection.copy_table(from, to, { temporary: true }.merge(options)) + end + + def column_names(table) + @connection.table_structure(table).map { |column| column["name"] } + end + + def column_values(table, column) + @connection.select_all("SELECT #{column} FROM #{table} ORDER BY id").map { |row| row[column] } + end + + def table_indexes_without_name(table) + @connection.indexes(table).delete(:name) + end + + def row_count(table) + @connection.select_one("SELECT COUNT(*) AS count FROM #{table}")["count"] + end +end diff --git a/activerecord/test/cases/adapters/sqlite3/explain_test.rb b/activerecord/test/cases/adapters/sqlite3/explain_test.rb new file mode 100644 index 0000000000..b6d2ccdb53 --- /dev/null +++ b/activerecord/test/cases/adapters/sqlite3/explain_test.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +require "cases/helper" +require "models/author" +require "models/post" + +class SQLite3ExplainTest < ActiveRecord::SQLite3TestCase + fixtures :authors + + def test_explain_for_one_query + explain = Author.where(id: 1).explain + assert_match %r(EXPLAIN for: SELECT "authors"\.\* FROM "authors" WHERE "authors"\."id" = (?:\? \[\["id", 1\]\]|1)), explain + assert_match(/(SEARCH )?TABLE authors USING (INTEGER )?PRIMARY KEY/, explain) + end + + def test_explain_with_eager_loading + explain = Author.where(id: 1).includes(:posts).explain + assert_match %r(EXPLAIN for: SELECT "authors"\.\* FROM "authors" WHERE "authors"\."id" = (?:\? \[\["id", 1\]\]|1)), explain + assert_match(/(SEARCH )?TABLE authors USING (INTEGER )?PRIMARY KEY/, explain) + assert_match %r(EXPLAIN for: SELECT "posts"\.\* FROM "posts" WHERE "posts"\."author_id" = (?:\? \[\["author_id", 1\]\]|1)), explain + assert_match(/(SCAN )?TABLE posts/, explain) + end +end diff --git a/activerecord/test/cases/adapters/sqlite3/json_test.rb b/activerecord/test/cases/adapters/sqlite3/json_test.rb new file mode 100644 index 0000000000..6f247fcd22 --- /dev/null +++ b/activerecord/test/cases/adapters/sqlite3/json_test.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +require "cases/helper" +require "cases/json_shared_test_cases" + +class SQLite3JSONTest < ActiveRecord::SQLite3TestCase + include JSONSharedTestCases + + def setup + super + @connection.create_table("json_data_type") do |t| + t.json "payload", default: {} + t.json "settings" + end + end + + def test_default + @connection.add_column "json_data_type", "permissions", column_type, default: { "users": "read", "posts": ["read", "write"] } + klass.reset_column_information + + assert_equal({ "users" => "read", "posts" => ["read", "write"] }, klass.column_defaults["permissions"]) + assert_equal({ "users" => "read", "posts" => ["read", "write"] }, klass.new.permissions) + end + + private + def column_type + :json + end +end diff --git a/activerecord/test/cases/adapters/sqlite3/quoting_test.rb b/activerecord/test/cases/adapters/sqlite3/quoting_test.rb new file mode 100644 index 0000000000..6fdb353368 --- /dev/null +++ b/activerecord/test/cases/adapters/sqlite3/quoting_test.rb @@ -0,0 +1,58 @@ +# frozen_string_literal: true + +require "cases/helper" +require "bigdecimal" +require "securerandom" + +class SQLite3QuotingTest < ActiveRecord::SQLite3TestCase + def setup + @conn = ActiveRecord::Base.connection + @initial_represent_boolean_as_integer = ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer + end + + def teardown + ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer = @initial_represent_boolean_as_integer + end + + def test_type_cast_binary_encoding_without_logger + @conn.extend(Module.new { def logger; end }) + binary = SecureRandom.hex + expected = binary.dup.encode!(Encoding::UTF_8) + assert_equal expected, @conn.type_cast(binary) + end + + def test_type_cast_true + ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer = false + assert_equal "t", @conn.type_cast(true) + + ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer = true + assert_equal 1, @conn.type_cast(true) + end + + def test_type_cast_false + ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer = false + assert_equal "f", @conn.type_cast(false) + + ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer = true + assert_equal 0, @conn.type_cast(false) + end + + def test_type_cast_bigdecimal + bd = BigDecimal "10.0" + assert_equal bd.to_f, @conn.type_cast(bd) + end + + def test_quoting_binary_strings + value = "hello".encode("ascii-8bit") + type = ActiveRecord::Type::String.new + + assert_equal "'hello'", @conn.quote(type.serialize(value)) + end + + def test_quoted_time_returns_date_qualified_time + value = ::Time.utc(2000, 1, 1, 12, 30, 0, 999999) + type = ActiveRecord::Type::Time.new + + assert_equal "'2000-01-01 12:30:00.999999'", @conn.quote(type.serialize(value)) + end +end diff --git a/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb b/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb new file mode 100644 index 0000000000..7e0ce3a28e --- /dev/null +++ b/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb @@ -0,0 +1,527 @@ +# frozen_string_literal: true + +require "cases/helper" +require "models/owner" +require "tempfile" +require "support/ddl_helper" + +module ActiveRecord + module ConnectionAdapters + class SQLite3AdapterTest < ActiveRecord::SQLite3TestCase + include DdlHelper + + self.use_transactional_tests = false + + class DualEncoding < ActiveRecord::Base + end + + def setup + @conn = Base.sqlite3_connection database: ":memory:", + adapter: "sqlite3", + timeout: 100 + end + + def test_bad_connection + assert_raise ActiveRecord::NoDatabaseError do + connection = ActiveRecord::Base.sqlite3_connection(adapter: "sqlite3", database: "/tmp/should/_not/_exist/-cinco-dog.db") + connection.drop_table "ex", if_exists: true + end + end + + unless in_memory_db? + def test_connect_with_url + original_connection = ActiveRecord::Base.remove_connection + tf = Tempfile.open "whatever" + url = "sqlite3:#{tf.path}" + ActiveRecord::Base.establish_connection(url) + assert ActiveRecord::Base.connection + ensure + tf.close + tf.unlink + ActiveRecord::Base.establish_connection(original_connection) + end + + def test_connect_memory_with_url + original_connection = ActiveRecord::Base.remove_connection + url = "sqlite3::memory:" + ActiveRecord::Base.establish_connection(url) + assert ActiveRecord::Base.connection + ensure + ActiveRecord::Base.establish_connection(original_connection) + end + end + + def test_column_types + owner = Owner.create!(name: "hello".encode("ascii-8bit")) + owner.reload + select = Owner.columns.map { |c| "typeof(#{c.name})" }.join ", " + result = Owner.connection.exec_query <<-esql + SELECT #{select} + FROM #{Owner.table_name} + WHERE #{Owner.primary_key} = #{owner.id} + esql + + assert(!result.rows.first.include?("blob"), "should not store blobs") + ensure + owner.delete + end + + def test_exec_insert + with_example_table do + vals = [Relation::QueryAttribute.new("number", 10, Type::Value.new)] + @conn.exec_insert("insert into ex (number) VALUES (?)", "SQL", vals) + + result = @conn.exec_query( + "select number from ex where number = ?", "SQL", vals) + + assert_equal 1, result.rows.length + assert_equal 10, result.rows.first.first + end + end + + def test_primary_key_returns_nil_for_no_pk + with_example_table "id int, data string" do + assert_nil @conn.primary_key("ex") + end + end + + def test_connection_no_db + assert_raises(ArgumentError) do + Base.sqlite3_connection {} + end + end + + def test_bad_timeout + assert_raises(TypeError) do + Base.sqlite3_connection database: ":memory:", + adapter: "sqlite3", + timeout: "usa" + end + end + + # connection is OK with a nil timeout + def test_nil_timeout + conn = Base.sqlite3_connection database: ":memory:", + adapter: "sqlite3", + timeout: nil + assert conn, "made a connection" + end + + def test_connect + assert @conn, "should have connection" + end + + # sqlite3 defaults to UTF-8 encoding + def test_encoding + assert_equal "UTF-8", @conn.encoding + end + + def test_exec_no_binds + with_example_table "id int, data string" do + result = @conn.exec_query("SELECT id, data FROM ex") + assert_equal 0, result.rows.length + assert_equal 2, result.columns.length + assert_equal %w{ id data }, result.columns + + @conn.exec_query('INSERT INTO ex (id, data) VALUES (1, "foo")') + result = @conn.exec_query("SELECT id, data FROM ex") + assert_equal 1, result.rows.length + assert_equal 2, result.columns.length + + assert_equal [[1, "foo"]], result.rows + end + end + + def test_exec_query_with_binds + with_example_table "id int, data string" do + @conn.exec_query('INSERT INTO ex (id, data) VALUES (1, "foo")') + result = @conn.exec_query( + "SELECT id, data FROM ex WHERE id = ?", nil, [Relation::QueryAttribute.new(nil, 1, Type::Value.new)]) + + assert_equal 1, result.rows.length + assert_equal 2, result.columns.length + + assert_equal [[1, "foo"]], result.rows + end + end + + def test_exec_query_typecasts_bind_vals + with_example_table "id int, data string" do + @conn.exec_query('INSERT INTO ex (id, data) VALUES (1, "foo")') + + result = @conn.exec_query( + "SELECT id, data FROM ex WHERE id = ?", nil, [Relation::QueryAttribute.new("id", "1-fuu", Type::Integer.new)]) + + assert_equal 1, result.rows.length + assert_equal 2, result.columns.length + + assert_equal [[1, "foo"]], result.rows + end + end + + def test_quote_binary_column_escapes_it + DualEncoding.connection.execute(<<-eosql) + CREATE TABLE IF NOT EXISTS dual_encodings ( + id integer PRIMARY KEY AUTOINCREMENT, + name varchar(255), + data binary + ) + eosql + str = "\x80".dup.force_encoding("ASCII-8BIT") + binary = DualEncoding.new name: "いただきます!", data: str + binary.save! + assert_equal str, binary.data + ensure + DualEncoding.connection.drop_table "dual_encodings", if_exists: true + end + + def test_type_cast_should_not_mutate_encoding + name = "hello".dup.force_encoding(Encoding::ASCII_8BIT) + Owner.create(name: name) + assert_equal Encoding::ASCII_8BIT, name.encoding + ensure + Owner.delete_all + end + + def test_execute + with_example_table do + @conn.execute "INSERT INTO ex (number) VALUES (10)" + records = @conn.execute "SELECT * FROM ex" + assert_equal 1, records.length + + record = records.first + assert_equal 10, record["number"] + assert_equal 1, record["id"] + end + end + + def test_quote_string + assert_equal "''", @conn.quote_string("'") + end + + def test_insert_logged + with_example_table do + sql = "INSERT INTO ex (number) VALUES (10)" + name = "foo" + assert_logged [[sql, name, []]] do + @conn.insert(sql, name) + end + end + end + + def test_insert_id_value_returned + with_example_table do + sql = "INSERT INTO ex (number) VALUES (10)" + idval = "vuvuzela" + id = @conn.insert(sql, nil, nil, idval) + assert_equal idval, id + end + end + + def test_select_rows + with_example_table do + 2.times do |i| + @conn.create "INSERT INTO ex (number) VALUES (#{i})" + end + rows = @conn.select_rows "select number, id from ex" + assert_equal [[0, 1], [1, 2]], rows + end + end + + def test_select_rows_logged + with_example_table do + sql = "select * from ex" + name = "foo" + assert_logged [[sql, name, []]] do + @conn.select_rows sql, name + end + end + end + + def test_transaction + with_example_table do + count_sql = "select count(*) from ex" + + @conn.begin_db_transaction + @conn.create "INSERT INTO ex (number) VALUES (10)" + + assert_equal 1, @conn.select_rows(count_sql).first.first + @conn.rollback_db_transaction + assert_equal 0, @conn.select_rows(count_sql).first.first + end + end + + def test_tables + with_example_table do + assert_equal %w{ ex }, @conn.tables + with_example_table "id integer PRIMARY KEY AUTOINCREMENT, number integer", "people" do + assert_equal %w{ ex people }.sort, @conn.tables.sort + end + end + end + + def test_tables_logs_name + sql = <<-SQL + SELECT name FROM sqlite_master WHERE name <> 'sqlite_sequence' AND type IN ('table') + SQL + assert_logged [[sql.squish, "SCHEMA", []]] do + @conn.tables + end + end + + def test_table_exists_logs_name + with_example_table do + sql = <<-SQL + SELECT name FROM sqlite_master WHERE name <> 'sqlite_sequence' AND name = 'ex' AND type IN ('table') + SQL + assert_logged [[sql.squish, "SCHEMA", []]] do + assert @conn.table_exists?("ex") + end + end + end + + def test_columns + with_example_table do + columns = @conn.columns("ex").sort_by(&:name) + assert_equal 2, columns.length + assert_equal %w{ id number }.sort, columns.map(&:name) + assert_equal [nil, nil], columns.map(&:default) + assert_equal [true, true], columns.map(&:null) + end + end + + def test_columns_with_default + with_example_table "id integer PRIMARY KEY AUTOINCREMENT, number integer default 10" do + column = @conn.columns("ex").find { |x| + x.name == "number" + } + assert_equal "10", column.default + end + end + + def test_columns_with_not_null + with_example_table "id integer PRIMARY KEY AUTOINCREMENT, number integer not null" do + column = @conn.columns("ex").find { |x| x.name == "number" } + assert_not column.null, "column should not be null" + end + end + + def test_indexes_logs + with_example_table do + assert_logged [["PRAGMA index_list(\"ex\")", "SCHEMA", []]] do + @conn.indexes("ex") + end + end + end + + def test_no_indexes + assert_equal [], @conn.indexes("items") + end + + def test_index + with_example_table do + @conn.add_index "ex", "id", unique: true, name: "fun" + index = @conn.indexes("ex").find { |idx| idx.name == "fun" } + + assert_equal "ex", index.table + assert index.unique, "index is unique" + assert_equal ["id"], index.columns + end + end + + def test_non_unique_index + with_example_table do + @conn.add_index "ex", "id", name: "fun" + index = @conn.indexes("ex").find { |idx| idx.name == "fun" } + assert_not index.unique, "index is not unique" + end + end + + def test_compound_index + with_example_table do + @conn.add_index "ex", %w{ id number }, name: "fun" + index = @conn.indexes("ex").find { |idx| idx.name == "fun" } + assert_equal %w{ id number }.sort, index.columns.sort + end + end + + def test_primary_key + with_example_table do + assert_equal "id", @conn.primary_key("ex") + with_example_table "internet integer PRIMARY KEY AUTOINCREMENT, number integer not null", "foos" do + assert_equal "internet", @conn.primary_key("foos") + end + end + end + + def test_no_primary_key + with_example_table "number integer not null" do + assert_nil @conn.primary_key("ex") + end + end + + class Barcode < ActiveRecord::Base + self.primary_key = "code" + end + + def test_copy_table_with_existing_records_have_custom_primary_key + connection = Barcode.connection + connection.create_table(:barcodes, primary_key: "code", id: :string, limit: 42, force: true) do |t| + t.text :other_attr + end + code = "214fe0c2-dd47-46df-b53b-66090b3c1d40" + Barcode.create!(code: code, other_attr: "xxx") + + connection.remove_column("barcodes", "other_attr") + + assert_equal code, Barcode.first.id + ensure + Barcode.reset_column_information + end + + def test_copy_table_with_composite_primary_keys + connection = Barcode.connection + connection.create_table(:barcodes, primary_key: ["region", "code"], force: true) do |t| + t.string :region + t.string :code + t.text :other_attr + end + region = "US" + code = "214fe0c2-dd47-46df-b53b-66090b3c1d40" + Barcode.create!(region: region, code: code, other_attr: "xxx") + + connection.remove_column("barcodes", "other_attr") + + assert_equal ["region", "code"], connection.primary_keys("barcodes") + + barcode = Barcode.first + assert_equal region, barcode.region + assert_equal code, barcode.code + ensure + Barcode.reset_column_information + end + + def test_custom_primary_key_in_create_table + connection = Barcode.connection + connection.create_table :barcodes, id: false, force: true do |t| + t.primary_key :id, :string + end + + assert_equal "id", connection.primary_key("barcodes") + + custom_pk = Barcode.columns_hash["id"] + + assert_equal :string, custom_pk.type + assert_not custom_pk.null + ensure + Barcode.reset_column_information + end + + def test_custom_primary_key_in_change_table + connection = Barcode.connection + connection.create_table :barcodes, id: false, force: true do |t| + t.integer :dummy + end + connection.change_table :barcodes do |t| + t.primary_key :id, :string + end + + assert_equal "id", connection.primary_key("barcodes") + + custom_pk = Barcode.columns_hash["id"] + + assert_equal :string, custom_pk.type + assert_not custom_pk.null + ensure + Barcode.reset_column_information + end + + def test_add_column_with_custom_primary_key + connection = Barcode.connection + connection.create_table :barcodes, id: false, force: true do |t| + t.integer :dummy + end + connection.add_column :barcodes, :id, :string, primary_key: true + + assert_equal "id", connection.primary_key("barcodes") + + custom_pk = Barcode.columns_hash["id"] + + assert_equal :string, custom_pk.type + assert_not custom_pk.null + ensure + Barcode.reset_column_information + end + + def test_remove_column_preserves_partial_indexes + connection = Barcode.connection + connection.create_table :barcodes, force: true do |t| + t.string :code + t.string :region + t.boolean :bool_attr + + t.index :code, unique: true, where: :bool_attr, name: "partial" + end + connection.remove_column :barcodes, :region + + index = connection.indexes("barcodes").find { |idx| idx.name == "partial" } + assert_equal "bool_attr", index.where + ensure + Barcode.reset_column_information + end + + def test_supports_extensions + assert_not @conn.supports_extensions?, "does not support extensions" + end + + def test_respond_to_enable_extension + assert_respond_to @conn, :enable_extension + end + + def test_respond_to_disable_extension + assert_respond_to @conn, :disable_extension + end + + def test_statement_closed + db = ::SQLite3::Database.new(ActiveRecord::Base. + configurations["arunit"]["database"]) + statement = ::SQLite3::Statement.new(db, + "CREATE TABLE statement_test (number integer not null)") + statement.stub(:step, -> { raise ::SQLite3::BusyException.new("busy") }) do + assert_called(statement, :columns, returns: []) do + assert_called(statement, :close) do + ::SQLite3::Statement.stub(:new, statement) do + assert_raises ActiveRecord::StatementInvalid do + @conn.exec_query "select * from statement_test" + end + end + end + end + end + end + + def test_deprecate_valid_alter_table_type + assert_deprecated { @conn.valid_alter_table_type?(:string) } + end + + private + + def assert_logged(logs) + subscriber = SQLSubscriber.new + subscription = ActiveSupport::Notifications.subscribe("sql.active_record", subscriber) + yield + assert_equal logs, subscriber.logged + ensure + ActiveSupport::Notifications.unsubscribe(subscription) + end + + def with_example_table(definition = nil, table_name = "ex", &block) + definition ||= <<-SQL + id integer PRIMARY KEY AUTOINCREMENT, + number integer + SQL + super(@conn, table_name, definition, &block) + end + end + end +end diff --git a/activerecord/test/cases/adapters/sqlite3/sqlite3_create_folder_test.rb b/activerecord/test/cases/adapters/sqlite3/sqlite3_create_folder_test.rb new file mode 100644 index 0000000000..d70486605f --- /dev/null +++ b/activerecord/test/cases/adapters/sqlite3/sqlite3_create_folder_test.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +require "cases/helper" +require "models/owner" + +module ActiveRecord + module ConnectionAdapters + class SQLite3CreateFolder < ActiveRecord::SQLite3TestCase + def test_sqlite_creates_directory + Dir.mktmpdir do |dir| + begin + dir = Pathname.new(dir) + @conn = Base.sqlite3_connection database: dir.join("db/foo.sqlite3"), + adapter: "sqlite3", + timeout: 100 + + assert Dir.exist? dir.join("db") + assert File.exist? dir.join("db/foo.sqlite3") + ensure + @conn.disconnect! if @conn + end + end + end + end + end +end diff --git a/activerecord/test/cases/adapters/sqlite3/statement_pool_test.rb b/activerecord/test/cases/adapters/sqlite3/statement_pool_test.rb new file mode 100644 index 0000000000..61002435a4 --- /dev/null +++ b/activerecord/test/cases/adapters/sqlite3/statement_pool_test.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +require "cases/helper" + +class SQLite3StatementPoolTest < ActiveRecord::SQLite3TestCase + if Process.respond_to?(:fork) + def test_cache_is_per_pid + cache = ActiveRecord::ConnectionAdapters::SQLite3Adapter::StatementPool.new(10) + cache["foo"] = "bar" + assert_equal "bar", cache["foo"] + + pid = fork { + lookup = cache["foo"] + exit!(!lookup) + } + + Process.waitpid pid + assert $?.success?, "process should exit successfully" + end + end +end |