Skip to content

Commit 002b097

Browse files
BuonOmorafiss
authored andcommitted
feat: support sql dump
Add `ActiveRecord::CockroachDB::DatabaseTasks#structure_dump` method. Which itself allows for the related rake tasks (ex: `rake db:schema:dump`). We are doing that using the `SHOW CREATE ...` family of queries in cockroach and some local logic to sort out what is needed. See https://www.cockroachlabs.com/docs/v23.1/show-create.html. Most tests are grouped in one to avoid dumping many time. This clutters a bit lisibility in case of failure, but this part of the code should not change often, so we'd rather have velocity rather than lisibility. Fixes #2
1 parent 0c60b9c commit 002b097

File tree

3 files changed

+95
-1
lines changed

3 files changed

+95
-1
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
## Ongoing
44

5+
- Add support for sql dump in rake tasks (#273).
56
- Add support for table optimize hints (#266).
67

78
## 7.0.2 - 2023-05-23

lib/active_record/connection_adapters/cockroachdb/database_tasks.rb

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,43 @@ module ConnectionAdapters
55
module CockroachDB
66
class DatabaseTasks < ActiveRecord::Tasks::PostgreSQLDatabaseTasks
77
def structure_dump(filename, extra_flags=nil)
8-
raise "db:structure:dump is unimplemented. See https://github.com/cockroachdb/activerecord-cockroachdb-adapter/issues/2"
8+
if extra_flags
9+
raise "No flag supported yet, please raise an issue if needed. " \
10+
"https://github.com/cockroachdb/activerecord-cockroachdb-adapter/issues/new"
11+
end
12+
13+
case ActiveRecord.dump_schemas
14+
when :all, String
15+
raise "Custom schemas are not supported in CockroachDB. " \
16+
"See https://github.com/cockroachdb/cockroach/issues/26443."
17+
when :schema_search_path
18+
if configuration_hash[:schema_search_path]
19+
raise "Custom schemas are not supported in CockroachDB. " \
20+
"See https://github.com/cockroachdb/cockroach/issues/26443."
21+
end
22+
end
23+
24+
conn = ActiveRecord::Base.connection
25+
File.open(filename, "w") do |file|
26+
%w(SCHEMAS TYPES).each do |object_kind|
27+
ActiveRecord::Base.connection.execute("SHOW CREATE ALL #{object_kind}").each_row { file.puts _1 }
28+
end
29+
30+
ignore_tables = ActiveRecord::SchemaDumper.ignore_tables.to_set
31+
32+
conn.execute("SHOW CREATE ALL TABLES").each_row do |(sql)|
33+
if sql.start_with?("CREATE")
34+
table_name = sql[/CREATE TABLE (?:.*?\.)?\"?(.*?)[\" ]/, 1]
35+
next if ignore_tables.member?(table_name)
36+
elsif sql.start_with?("ALTER")
37+
table_name = sql[/ALTER TABLE (?:.*?\.)?\"?(.*?)[\" ]/, 1]
38+
ref_table_name = sql[/REFERENCES (?:.*?\.)?\"?(.*?)[\" ]/, 1]
39+
next if ignore_tables.member?(table_name) || ignore_tables.member?(ref_table_name)
40+
end
41+
42+
file.puts sql
43+
end
44+
end
945
end
1046

1147
def structure_load(filename, extra_flags=nil)
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# frozen_string_literal: true
2+
3+
require "cases/helper"
4+
require "active_record/tasks/database_tasks"
5+
require "active_record/connection_adapters/cockroachdb/database_tasks"
6+
7+
module ActiveRecord
8+
class CockroachDBStructureDumpTest < ActiveRecord::TestCase
9+
def setup
10+
@configuration = {
11+
"adapter" => "cockroachdb",
12+
"database" => "my-app-db"
13+
}
14+
@filename = "/tmp/awesome-file.sql"
15+
FileUtils.touch(@filename)
16+
end
17+
18+
def teardown
19+
FileUtils.rm_f(@filename)
20+
end
21+
22+
def test_structure_dump
23+
assert_equal "", File.read(@filename)
24+
File.write(@filename, "NOT TODAY\n")
25+
26+
config = @configuration.dup
27+
config["database"] = ARTest.config["connections"]["cockroachdb"]["arunit"]["database"]
28+
29+
begin
30+
ActiveRecord::Base.connection.execute(<<~SQL)
31+
CREATE TYPE IF NOT EXISTS status AS ENUM ('open', 'closed', 'inactive');
32+
SQL
33+
assert_called(
34+
ActiveRecord::SchemaDumper,
35+
:ignore_tables,
36+
returns: ["accounts", "articles"]
37+
) do
38+
ActiveRecord::Tasks::DatabaseTasks.structure_dump(config, @filename)
39+
40+
read = File.read(@filename)
41+
end
42+
ensure
43+
ActiveRecord::Base.connection.execute(<<~SQL)
44+
DROP TYPE IF EXISTS status;
45+
SQL
46+
end
47+
48+
read = File.read(@filename)
49+
refute read.include?("NOT TODAY"), "The dump file previous content was not overwritten"
50+
assert read.include?("CREATE SCHEMA public;"), "Schemas are not dumped"
51+
assert read.include?("CREATE TYPE public.status AS ENUM ('open', 'closed', 'inactive');"), "Types are not dumped"
52+
assert read.include?("CREATE TABLE public.schema_migrations"), "No dump done"
53+
refute read.include?("CREATE TABLE public.articles ("), "\"articles\" table should be ignored"
54+
refute read.include?("CREATE TABLE public.accounts ("), "\"accounts\" table should be ignored"
55+
end
56+
end
57+
end

0 commit comments

Comments
 (0)