diff options
| author | Robert | 2017-06-06 15:50:54 +0200 |
|---|---|---|
| committer | Robert | 2017-06-06 15:50:54 +0200 |
| commit | 15b7cf8213d730fa36740a74bc75baa5fc56dd62 (patch) | |
| tree | ad1901d30d814257e738a0348d190171c212d6e5 | |
| parent | 12290bbdabb8f53c4dddb1a647296a426b88709e (diff) | |
| download | chouette-core-15b7cf8213d730fa36740a74bc75baa5fc56dd62.tar.bz2 | |
Refs: #3604; rewriting schema cloner in Ruby
| -rw-r--r-- | Gemfile | 2 | ||||
| -rw-r--r-- | Gemfile.lock | 2 | ||||
| -rw-r--r-- | app/workers/referential_cloning_worker.rb | 2 | ||||
| -rw-r--r-- | lib/af83/schema_cloner.rb | 38 | ||||
| -rw-r--r-- | spec/lib/af83/cloning/clone_schema_spec.rb | 150 | ||||
| -rw-r--r-- | spec/lib/af83/stored_procedures/clone_schema_spec.rb | 4 |
6 files changed, 193 insertions, 5 deletions
@@ -110,6 +110,8 @@ gem 'ransack' gem "squeel", github: 'activerecord-hackery/squeel' gem 'active_attr' +gem 'sequel' + gem 'draper' gem 'enumerize', '~> 0.10.0' diff --git a/Gemfile.lock b/Gemfile.lock index 992e44af0..cc3458802 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -462,6 +462,7 @@ GEM rdoc (~> 4.0) select2-rails (4.0.3) thor (~> 0.14) + sequel (4.47.0) shoulda-matchers (3.1.1) activesupport (>= 4.0.0) sidekiq (4.2.10) @@ -647,6 +648,7 @@ DEPENDENCIES sawyer (~> 0.6.0) sdoc (~> 0.4.0) select2-rails (~> 4.0, >= 4.0.3) + sequel shoulda-matchers (~> 3.1) sidekiq simple_form (~> 3.1.0) diff --git a/app/workers/referential_cloning_worker.rb b/app/workers/referential_cloning_worker.rb index 2a524dbcd..c74566966 100644 --- a/app/workers/referential_cloning_worker.rb +++ b/app/workers/referential_cloning_worker.rb @@ -16,7 +16,7 @@ class ReferentialCloningWorker def clone_schema ref_cloning, source_schema, target_schema ref_cloning.run! - StoredProcedures.invoke_stored_procedure(:clone_schema, source_schema, target_schema) + StoredProcedures.invoke_stored_procedure(:clone_schema, source_schema, target_schema, true) ref_cloning.successful! rescue Exception => e diff --git a/lib/af83/schema_cloner.rb b/lib/af83/schema_cloner.rb new file mode 100644 index 000000000..933fffc3d --- /dev/null +++ b/lib/af83/schema_cloner.rb @@ -0,0 +1,38 @@ +module AF83 + class SchemaCloner + + attr_reader :source_schema, :target_schema, :include_records + def clone_schema(source_schema, target_schema, include_records: true) + @source_schema = source_schema + @target_schema = target_schema + @include_records = include_records + + clone_schema_ + end + + private + def assure_schema_preconditons + raise RuntimeError, "Target Schema #{target_schema} does already exist" unless + execute("SELECT oid FROM pg_namespace WHERE nspname = '#{target_schema}' LIMIT 1").empty? + + raise RuntimeError, "Source Schema #{source_schema} does not exist" unless source + end + + def clone_schema_ + assure_schema_preconditons + end + def connection + @__connection__ ||= ActiveRecord::Base.connection + end + def execute(str) + connection.execute(str).to_a + end + + def source + @__source__ ||= execute("SELECT oid FROM pg_namespace WHERE nspname = '#{source_schema}' LIMIT 1").first; + end + def source_oid + @__source_oid__ ||= source["oid"].to_i; + end + end +end diff --git a/spec/lib/af83/cloning/clone_schema_spec.rb b/spec/lib/af83/cloning/clone_schema_spec.rb new file mode 100644 index 000000000..aa74bb372 --- /dev/null +++ b/spec/lib/af83/cloning/clone_schema_spec.rb @@ -0,0 +1,150 @@ +include Support::PGCatalog + +RSpec.describe AF83::SchemaCloner do + let( :source_schema ){ "source_schema" } + let( :target_schema ){ "target_schema" } + let( :child_table ){ "children" } + let( :parent_table ){ "parents" } + + subject { described_class.new } + + before do + create_schema_with_tables + end + + context "before cloning" do + it "target schema does not exist" do + expect( get_schema_oid(target_schema) ).to be_nil + end + end + + shared_examples_for "after cloning schema" do + + let( :expected_target_parent_count ){ include_recs ? 1 : 0 } + let( :expected_target_child_count ){ include_recs ? 1 : 0 } + + it "table information is correctly read" do + expect(get_table_information(source_schema, child_table)) + .to eq([{"table_schema"=>"source_schema", + "table_name"=>"children", + "table_type"=>"BASE TABLE", + "self_referencing_column_name"=>nil, + "reference_generation"=>nil, + "user_defined_type_catalog"=>nil, + "user_defined_type_schema"=>nil, + "user_defined_type_name"=>nil, + "is_insertable_into"=>"YES", + "is_typed"=>"NO", + "commit_action"=>nil}]) + + expect( get_table_information(target_schema, child_table)) + .to eq([{"table_schema"=>"target_schema", + "table_name"=>"children", + "table_type"=>"BASE TABLE", + "self_referencing_column_name"=>nil, + "reference_generation"=>nil, + "user_defined_type_catalog"=>nil, + "user_defined_type_schema"=>nil, + "user_defined_type_name"=>nil, + "is_insertable_into"=>"YES", + "is_typed"=>"NO", + "commit_action"=>nil}]) + end + + it "has the correct sequences" do + expect(get_sequences(target_schema, child_table)) + .to eq([{"sequence_name"=>"#{child_table}_id_seq", + "last_value"=>"1", + "start_value"=>"1", + "increment_by"=>"1", + "max_value"=>"9223372036854775807", + "min_value"=>"1", + "cache_value"=>"1", + "log_cnt"=>"0", + "is_cycled"=>"f", + "is_called"=>"f"}]) + + expect(get_sequences(target_schema, parent_table)) + .to eq([{"sequence_name"=>"#{parent_table}_id_seq", + "last_value"=>"1", + "start_value"=>"1", + "increment_by"=>"1", + "max_value"=>"9223372036854775807", + "min_value"=>"1", + "cache_value"=>"1", + "log_cnt"=>"0", + "is_cycled"=>"f", + "is_called"=>"f"}]) + end + + it "has the correct foreign keys" do + expect( get_foreign_keys(target_schema, child_table) ) + .to eq([{ + "constraint_name" => "children_parents", + "constraint_def" => "FOREIGN KEY (parents_id) REFERENCES target_schema.parents(id)"}]) + end + + it "the data has been copied or not" do + source_pt_count = count_records(source_schema, parent_table) + source_ch_count = count_records(source_schema, child_table) + target_pt_count = count_records(target_schema, parent_table) + target_ch_count = count_records(target_schema, child_table) + + expect( source_pt_count ).to eq( 1 ) + expect( source_ch_count ).to eq( 1 ) + expect( target_pt_count ).to eq( expected_target_parent_count ) + expect( target_ch_count ).to eq( expected_target_child_count ) + end + end + + context "step by step", :wip do + # before do + # subject.clone_schema(source_schema, target_schema) + # end + it "assure target schema nonexistance" do + expect{ subject.clone_schema(source_schema, source_schema) }.to raise_error(RuntimeError) + end + it "assure source schema's existance" do + expect{ subject.clone_schema(target_schema, target_schema) }.to raise_error(RuntimeError) + end + + end + + context "after cloning" do + before do + subject.clone_schema(source_schema, target_schema, include_recs: include_recs) + end + + context "without including records" do + let( :include_recs ){ false } + it_behaves_like 'after cloning schema' + end + + context "with including records" do + let( :include_recs ){ true } + it_behaves_like 'after cloning schema' + end + end + +end + +def create_schema_with_tables + execute <<-EOSQL + DROP SCHEMA IF EXISTS #{source_schema} CASCADE; + CREATE SCHEMA #{source_schema}; + + CREATE TABLE #{source_schema}.#{parent_table} ( + id bigserial PRIMARY KEY + ); + CREATE TABLE #{source_schema}.#{child_table} ( + id bigserial PRIMARY KEY, + #{parent_table}_id bigint + ); + ALTER TABLE #{source_schema}.#{child_table} + ADD CONSTRAINT #{child_table}_#{parent_table} + FOREIGN KEY( #{parent_table}_id ) REFERENCES #{source_schema}.#{parent_table}(id); + INSERT INTO #{source_schema}.#{parent_table} VALUES (100); + INSERT INTO #{source_schema}.#{child_table} VALUES (1, 100); + EOSQL +end + diff --git a/spec/lib/af83/stored_procedures/clone_schema_spec.rb b/spec/lib/af83/stored_procedures/clone_schema_spec.rb index c0502f1ad..bdc3bd6cc 100644 --- a/spec/lib/af83/stored_procedures/clone_schema_spec.rb +++ b/spec/lib/af83/stored_procedures/clone_schema_spec.rb @@ -78,10 +78,6 @@ RSpec.describe StoredProcedures do let( :expected_target_parent_count ){ include_recs ? 1 : 0 } let( :expected_target_child_count ){ include_recs ? 1 : 0 } - it "target schema does exist" do - expect( get_schema_oid(target_schema) ).not_to be_nil - end - it "table information is correctly read" do expect(get_table_information(source_schema, child_table)) .to eq([{"table_schema"=>"source_schema", |
