aboutsummaryrefslogtreecommitdiffstats
path: root/lib/af83
diff options
context:
space:
mode:
authorRobert2017-06-09 17:04:38 +0200
committerRobert2017-06-09 17:25:06 +0200
commit63a893c22feca2c26cd8eecef2e6deb8ff97bd26 (patch)
treea82f97b3732379167760a57012cc3197afd9b846 /lib/af83
parent38e5a5329541a54f98d771c3aa252b91b823b94f (diff)
downloadchouette-core-63a893c22feca2c26cd8eecef2e6deb8ff97bd26.tar.bz2
refs 3604 @12h all tests pass
Diffstat (limited to 'lib/af83')
-rw-r--r--lib/af83/schema_cloner.rb69
-rw-r--r--lib/af83/stored_procedures.rb44
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