forked from crashtech/torque-postgresql
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Dump types to generate a correct schema.rb
- Loading branch information
Carlos Silva
committed
Dec 8, 2016
1 parent
75cfb15
commit 1543821
Showing
7 changed files
with
166 additions
and
69 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,7 @@ | |
.bundle | ||
.config | ||
.yardoc | ||
.byebug_history | ||
Gemfile.lock | ||
coverage | ||
doc/ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
module Torque | ||
module Postgresql | ||
module Migration | ||
|
||
module TypesStatements | ||
# Gets a list of user defined types. | ||
# You can even choose the +typcategory+ filter | ||
def user_defined_types(category = nil) | ||
category_condition = "AND typcategory = '#{category}'" unless category.nil? | ||
select_all(<<-SQL).rows.to_h | ||
SELECT t.typname AS name, | ||
CASE t.typcategory | ||
WHEN 'E' THEN 'enum' | ||
END AS type | ||
FROM pg_type t | ||
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace | ||
WHERE n.nspname NOT IN ('pg_catalog', 'information_schema') | ||
#{category_condition} | ||
AND NOT EXISTS( | ||
SELECT 1 FROM pg_catalog.pg_type el | ||
WHERE el.oid = t.typelem AND el.typarray = t.oid | ||
) | ||
AND (t.typrelid = 0 OR ( | ||
SELECT c.relkind = 'c' FROM pg_catalog.pg_class c | ||
WHERE c.oid = t.typrelid | ||
)) | ||
SQL | ||
end | ||
|
||
# Check if a given type is valid. | ||
def valid_type?(type) | ||
super || user_defined_types.key?(type.to_s) | ||
end | ||
|
||
# Returns true if type exists. | ||
def type_exists?(name) | ||
select_value("SELECT 1 FROM pg_type WHERE typname = '#{name}'").to_i > 0 | ||
end | ||
|
||
# Drops a type. | ||
def drop_type(name) | ||
execute "DROP TYPE IF EXISTS #{quote_type_name(name)}" | ||
end | ||
|
||
# Renames a type. | ||
def rename_type(type_name, new_name) | ||
execute <<-SQL | ||
ALTER TYPE #{quote_type_name(type_name)} | ||
RENAME TO #{quote_type_name(new_name)} | ||
SQL | ||
end | ||
end | ||
|
||
module TypesDumper | ||
|
||
def self.included(base) | ||
base.class_eval do | ||
def dump(stream) | ||
header(stream) | ||
extensions(stream) | ||
user_defined_types(stream) | ||
tables(stream) | ||
trailer(stream) | ||
stream | ||
end | ||
end | ||
end | ||
|
||
private | ||
|
||
def user_defined_types(stream) | ||
types = @connection.user_defined_types | ||
return unless types.any? | ||
|
||
stream.puts " # These are user defined custom column types used on this database" | ||
@connection.user_defined_types.each do |name, type| | ||
send(type.to_sym, name, stream) | ||
end | ||
stream.puts | ||
end | ||
|
||
def enum(name, stream) | ||
values = @connection.enum_values(name).map { |v| "\"#{v}\"" } | ||
stream.puts " create_enum :#{name}, [#{values.join(', ')}]" | ||
end | ||
|
||
end | ||
|
||
Adapter.send :include, TypesStatements | ||
|
||
ActiveRecord::SchemaDumper.send :include, TypesDumper | ||
|
||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
module Torque | ||
module Postgresql | ||
VERSION = '0.0.1' | ||
VERSION = '0.0.2' | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,67 +1,86 @@ | ||
require 'spec_helper' | ||
|
||
RSpec.describe 'Enum', 'on migration' do | ||
RSpec.describe 'Enum' do | ||
before(:each) { ActiveRecord::Base.connection.drop_type(:status) } | ||
after(:all) { ActiveRecord::Base.connection.drop_type(:status) } | ||
|
||
let(:migration) { ActiveRecord::Base.connection } | ||
let(:connection) { ActiveRecord::Base.connection } | ||
|
||
it 'can be created' do | ||
migration.create_enum(:status, %i(foo bar)) | ||
expect(migration.type_exists?(:status)).to be_truthy | ||
expect(migration.enum_values(:status)).to eql(['foo', 'bar']) | ||
end | ||
context 'on migration' do | ||
it 'can be created' do | ||
connection.create_enum(:status, %i(foo bar)) | ||
expect(connection.type_exists?(:status)).to be_truthy | ||
expect(connection.enum_values(:status)).to eql(['foo', 'bar']) | ||
end | ||
|
||
it 'can be deleted' do | ||
migration.create_enum(:status, %i(foo bar)) | ||
expect(migration.type_exists?(:status)).to be_truthy | ||
it 'can be deleted' do | ||
connection.create_enum(:status, %i(foo bar)) | ||
expect(connection.type_exists?(:status)).to be_truthy | ||
|
||
migration.drop_type(:status) | ||
expect(migration.type_exists?(:status)).to be_falsey | ||
end | ||
connection.drop_type(:status) | ||
expect(connection.type_exists?(:status)).to be_falsey | ||
end | ||
|
||
it 'can be renamed' do | ||
migration.create_enum(:status, %i(foo bar)) | ||
migration.rename_type(:status, :new_status) | ||
expect(migration.type_exists?(:new_status)).to be_truthy | ||
expect(migration.type_exists?(:status)).to be_falsey | ||
end | ||
it 'can be renamed' do | ||
connection.create_enum(:status, %i(foo bar)) | ||
connection.rename_type(:status, :new_status) | ||
expect(connection.type_exists?(:new_status)).to be_truthy | ||
expect(connection.type_exists?(:status)).to be_falsey | ||
end | ||
|
||
it 'can have prefix' do | ||
migration.create_enum(:status, %i(foo bar), prefix: true) | ||
expect(migration.enum_values(:status)).to eql(['status_foo', 'status_bar']) | ||
end | ||
it 'can have prefix' do | ||
connection.create_enum(:status, %i(foo bar), prefix: true) | ||
expect(connection.enum_values(:status)).to eql(['status_foo', 'status_bar']) | ||
end | ||
|
||
it 'can have suffix' do | ||
migration.create_enum(:status, %i(foo bar), suffix: 'tst') | ||
expect(migration.enum_values(:status)).to eql(['foo_tst', 'bar_tst']) | ||
end | ||
it 'can have suffix' do | ||
connection.create_enum(:status, %i(foo bar), suffix: 'tst') | ||
expect(connection.enum_values(:status)).to eql(['foo_tst', 'bar_tst']) | ||
end | ||
|
||
it 'inserts values at the end' do | ||
migration.create_enum(:status, %i(foo bar)) | ||
migration.add_enum_values(:status, %i(baz qux)) | ||
expect(migration.enum_values(:status)).to eql(['foo', 'bar', 'baz', 'qux']) | ||
end | ||
it 'inserts values at the end' do | ||
connection.create_enum(:status, %i(foo bar)) | ||
connection.add_enum_values(:status, %i(baz qux)) | ||
expect(connection.enum_values(:status)).to eql(['foo', 'bar', 'baz', 'qux']) | ||
end | ||
|
||
it 'inserts values in the beginning' do | ||
migration.create_enum(:status, %i(foo bar)) | ||
migration.add_enum_values(:status, %i(baz qux), prepend: true) | ||
expect(migration.enum_values(:status)).to eql(['baz', 'qux', 'foo', 'bar']) | ||
end | ||
it 'inserts values in the beginning' do | ||
connection.create_enum(:status, %i(foo bar)) | ||
connection.add_enum_values(:status, %i(baz qux), prepend: true) | ||
expect(connection.enum_values(:status)).to eql(['baz', 'qux', 'foo', 'bar']) | ||
end | ||
|
||
it 'inserts values in the middle' do | ||
migration.create_enum(:status, %i(foo bar)) | ||
migration.add_enum_values(:status, %i(baz), after: 'foo') | ||
expect(migration.enum_values(:status)).to eql(['foo', 'baz', 'bar']) | ||
it 'inserts values in the middle' do | ||
connection.create_enum(:status, %i(foo bar)) | ||
connection.add_enum_values(:status, %i(baz), after: 'foo') | ||
expect(connection.enum_values(:status)).to eql(['foo', 'baz', 'bar']) | ||
|
||
migration.add_enum_values(:status, %i(qux), before: 'bar') | ||
expect(migration.enum_values(:status)).to eql(['foo', 'baz', 'qux', 'bar']) | ||
connection.add_enum_values(:status, %i(qux), before: 'bar') | ||
expect(connection.enum_values(:status)).to eql(['foo', 'baz', 'qux', 'bar']) | ||
end | ||
|
||
it 'inserts values with prefix or suffix' do | ||
connection.create_enum(:status, %i(foo bar)) | ||
connection.add_enum_values(:status, %i(baz), prefix: true) | ||
connection.add_enum_values(:status, %i(qux), suffix: 'tst') | ||
expect(connection.enum_values(:status)).to eql(['foo', 'bar', 'status_baz', 'qux_tst']) | ||
end | ||
end | ||
|
||
it 'inserts values with prefix or suffix' do | ||
migration.create_enum(:status, %i(foo bar)) | ||
migration.add_enum_values(:status, %i(baz), prefix: true) | ||
migration.add_enum_values(:status, %i(qux), suffix: 'tst') | ||
expect(migration.enum_values(:status)).to eql(['foo', 'bar', 'status_baz', 'qux_tst']) | ||
context 'on schema' do | ||
it 'dumps when has it' do | ||
connection.create_enum(:status, %i(foo bar)) | ||
|
||
dumo_io = StringIO.new | ||
ActiveRecord::SchemaDumper.dump(connection, dumo_io) | ||
expect(dumo_io.string).to match /create_enum :status, \["foo", "bar"\]/ | ||
end | ||
it 'doesn\'t dump when has none' do | ||
connection.user_defined_types.map(&connection.method(:drop_type)) | ||
|
||
dumo_io = StringIO.new | ||
ActiveRecord::SchemaDumper.dump(connection, dumo_io) | ||
expect(dumo_io.string).not_to match /create_enum :\w+, \[[^\]]+\]/ | ||
end | ||
end | ||
end |