diff options
| author | Robert | 2017-06-09 17:04:38 +0200 |
|---|---|---|
| committer | Robert | 2017-06-09 17:25:06 +0200 |
| commit | 63a893c22feca2c26cd8eecef2e6deb8ff97bd26 (patch) | |
| tree | a82f97b3732379167760a57012cc3197afd9b846 /lib/af83 | |
| parent | 38e5a5329541a54f98d771c3aa252b91b823b94f (diff) | |
| download | chouette-core-63a893c22feca2c26cd8eecef2e6deb8ff97bd26.tar.bz2 | |
refs 3604 @12h all tests pass
Diffstat (limited to 'lib/af83')
| -rw-r--r-- | lib/af83/schema_cloner.rb | 69 | ||||
| -rw-r--r-- | lib/af83/stored_procedures.rb | 44 |
2 files changed, 50 insertions, 63 deletions
diff --git a/lib/af83/schema_cloner.rb b/lib/af83/schema_cloner.rb index 299e63a82..40c04f400 100644 --- a/lib/af83/schema_cloner.rb +++ b/lib/af83/schema_cloner.rb @@ -1,7 +1,7 @@ module AF83 class SchemaCloner - attr_reader :source_schema, :target_schema, :include_records + attr_reader :source_schema, :target_schema def clone_schema assure_schema_preconditons @@ -10,10 +10,26 @@ module AF83 private + def adjust_default table_name, column_name, default_val + changed_default = default_val.sub(%r{\Anextval\('#{source_schema}}, "nextval('#{target_schema}") + execute "ALTER TABLE #{target_schema}.#{table_name} ALTER COLUMN #{column_name} SET DEFAULT #{changed_default}" + end + + def adjust_defaults table_name + pairs = execute <<-EOSQL + SELECT column_name, column_default + FROM information_schema.columns + WHERE table_schema = '#{target_schema}' AND table_name = '#{table_name}' AND + column_default LIKE 'nextval(''#{source_schema}%::regclass)' + EOSQL + pairs.each do | pair | + adjust_default table_name, pair['column_name'], pair['column_default'] + end + end + def alter_sequence sequence_name seq_props = execute_get_ostruct( "SELECT * FROM #{source_schema}.#{sequence_name}" ) cycle_on_off = seq_props.is_cycled == 't' ? '' : 'NO' - seq_value = include_records ? seq_props.last_value : seq_props.start_value execute <<-EOSQL ALTER SEQUENCE #{target_schema}.#{sequence_name} INCREMENT BY #{seq_props.increment_by} @@ -22,12 +38,11 @@ module AF83 START WITH #{seq_props.start_value} RESTART WITH #{seq_props.last_value} CACHE #{seq_props.cache_value} - #{cycle_on_off} CYCLE; - - - SELECT setval('#{target_schema}.#{sequence_name}', #{seq_value}, '#{seq_props.is_called}'); + #{cycle_on_off} CYCLE; - EOSQL + -- TODO: What is this good for? + SELECT setval('#{target_schema}.#{sequence_name}', #{seq_props.last_value}, '#{seq_props.is_called}'); + EOSQL end def assure_schema_preconditons @@ -37,8 +52,15 @@ module AF83 raise RuntimeError, "Source Schema #{source_schema} does not exist" unless source end + def clone_foreign_key fk_desc + relname, conname, constraint_def = fk_desc.values_at(*%w[relname conname constraint_def]) + constraint_def = constraint_def.sub(" REFERENCES #{source_schema}.", " REFERENCES #{target_schema}.") + execute <<-EOSQL + ALTER TABLE #{target_schema}.#{relname} ADD CONSTRAINT #{conname} #{constraint_def} + EOSQL + end def clone_foreign_keys - + get_foreign_keys.each(&method(:clone_foreign_key)) end def clone_sequence sequence_name @@ -51,8 +73,8 @@ module AF83 def clone_table table_name create_table table_name - end + def clone_tables table_names.each(&method(:clone_table)) end @@ -62,8 +84,8 @@ module AF83 end def create_table table_name execute "CREATE TABLE #{target_schema}.#{table_name} (LIKE #{source_schema}.#{table_name} INCLUDING ALL)" - return unless include_records - execute "INSERT INTO #{target_schema}.#{table_name} SELECT * FROM #{source_schema}.#{table_name}" + execute "INSERT INTO #{target_schema}.#{table_name} SELECT * FROM #{source_schema}.#{table_name}" + adjust_defaults table_name end def create_target_schema execute("CREATE SCHEMA #{target_schema}") @@ -84,10 +106,19 @@ module AF83 execute(str).flat_map(&:values) end - def initialize(source_schema, target_schema, include_records: true) + def get_foreign_keys + execute <<-EOS + SELECT rn.relname, ct.conname, pg_get_constraintdef(ct.oid) AS constraint_def + FROM pg_constraint ct JOIN pg_class rn ON rn.oid = ct.conrelid + WHERE connamespace = #{source['oid']} AND rn.relkind = 'r' AND ct.contype = 'f' + EOS + end + def get_columns(table_name) + end + + def initialize(source_schema, target_schema) @source_schema = source_schema @target_schema = target_schema - @include_records = include_records end # @@ -98,19 +129,19 @@ module AF83 end def source - @__source__ ||= execute("SELECT oid FROM pg_namespace WHERE nspname = '#{source_schema}' LIMIT 1").first; + @__source__ ||= execute("SELECT oid FROM pg_namespace WHERE nspname = '#{source_schema}' LIMIT 1").first; end def source_sequence_names - @__source_sequence_names__ ||= - execute_get_values \ - "SELECT sequence_name::text FROM information_schema.sequences WHERE sequence_schema = '#{source_schema}'" + @__source_sequence_names__ ||= + execute_get_values \ + "SELECT sequence_name::text FROM information_schema.sequences WHERE sequence_schema = '#{source_schema}'" end def source_oid @__source_oid__ ||= source["oid"].to_i; end def table_names - @__table_names__ ||= execute_get_values \ - "SELECT TABLE_NAME::text FROM information_schema.tables WHERE table_schema = '#{ source_schema }' AND table_type = 'BASE TABLE'" + @__table_names__ ||= execute_get_values \ + "SELECT TABLE_NAME::text FROM information_schema.tables WHERE table_schema = '#{ source_schema }' AND table_type = 'BASE TABLE'" end end end diff --git a/lib/af83/stored_procedures.rb b/lib/af83/stored_procedures.rb deleted file mode 100644 index b13941a32..000000000 --- a/lib/af83/stored_procedures.rb +++ /dev/null @@ -1,44 +0,0 @@ -module StoredProcedures extend self - - def invoke_stored_procedure(name, *params) - name = name.to_s - raise ArgumentError, "no such stored procedure #{name.inspect}" unless stored_procedures[name] - invocation = "#{name}(#{quote_params(params)})" - ActiveRecord::Base.connection.execute "SELECT #{invocation}" - end - - def create_stored_procedure(name) - name = name.to_s - sql_file = File.expand_path("../../sql/#{name}.sql", __FILE__) - raise ArgumentError, "missing sql file #{sql_file.inspect}" unless File.readable? sql_file - - # We could store the file's content for reload without application restart if desired. - stored_procedures[name] = true - - ActiveRecord::Base.connection.execute File.read(sql_file) - end - - private - def quote_params(params) - params - .map(&method(:quote_param)) - .join(", ") - end - - def quote_param(param) - case param - when String - "'#{param}'" - when TrueClass - "'t'" - when FalseClass - "'f'" - else - param - end - end - - def stored_procedures - @__stored_procedures__ ||= {} - end -end |
