pg_sequencer 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +96 -0
- data/Rakefile +18 -0
- data/lib/pg_sequencer.rb +11 -0
- data/lib/pg_sequencer/connection_adapters/postgresql_adapter.rb +146 -0
- data/lib/pg_sequencer/railtie.rb +28 -0
- data/lib/pg_sequencer/schema_dumper.rb +32 -0
- data/lib/pg_sequencer/version.rb +3 -0
- data/test/helper.rb +5 -0
- data/test/unit/postgresql_adapter_test.rb +138 -0
- data/test/unit/schema_dumper_test.rb +111 -0
- metadata +125 -0
data/README.rdoc
ADDED
@@ -0,0 +1,96 @@
|
|
1
|
+
= pg_sequencer
|
2
|
+
|
3
|
+
pg_sequencer adds methods to your migrations to allow you to create, drop and change sequence objects in PostgreSQL. It also dumps sequences to schema.rb.
|
4
|
+
|
5
|
+
This is especially useful if you are connecting to a legacy database where the primary key field is declared as an INTEGER and a sequence is queried for the value of the next record.
|
6
|
+
|
7
|
+
The design of pg_sequencer is heavily influenced on Matthew Higgins' Foreigner gem:
|
8
|
+
* https://github.com/matthuhiggins/foreigner
|
9
|
+
|
10
|
+
== Installation
|
11
|
+
|
12
|
+
Add this to your Gemfile:
|
13
|
+
|
14
|
+
gem 'pg_sequencer'
|
15
|
+
|
16
|
+
== API
|
17
|
+
|
18
|
+
pg_sequencer adds the following methods to migrations:
|
19
|
+
|
20
|
+
* create_sequence(sequence_name, options)
|
21
|
+
* change_sequence(sequence_name, options)
|
22
|
+
* drop_sequence(sequence_name)
|
23
|
+
|
24
|
+
The methods closely mimic the syntax of the PostgreSQL SQL for CREATE SEQUENCE, DROP SEQUENCE and ALTER SEQUENCE. See the REFERENCES section below for more information.
|
25
|
+
|
26
|
+
== Options
|
27
|
+
|
28
|
+
For create_sequence and change_sequence, all options are the same, except create_sequence will look for :start or :start_with, and
|
29
|
+
change_sequence will look for :restart or :restart_with.
|
30
|
+
|
31
|
+
* :increment/:increment_by (integer) - The value to increment the sequence by.
|
32
|
+
* :min (integer/false) - The minimum value of the sequence. If specified as false (e.g. :min => false), "NO MINVALUE" is sent to Postgres.
|
33
|
+
* :max (integer/false) - The maximum value of the sequence. May be specified as ":max => false" to generate "NO MAXVALUE"
|
34
|
+
* :start/:start_with (integer) - The starting value of the sequence (create_sequence only)
|
35
|
+
* :restart/:restart_with (integer) The value to restart the sequence with (change_sequence only)
|
36
|
+
* :cache (integer) - The number of values the sequence should cache.
|
37
|
+
* :cycle (boolean) - Whether the sequence should cycle. Generated at "CYCLE" or "NO CYCLE"
|
38
|
+
|
39
|
+
== Examples
|
40
|
+
|
41
|
+
=== Creating a sequence
|
42
|
+
|
43
|
+
Create a sequence called "seq_user", incrementing by 1, min of 1, max of 2000000, starts at 1, caches 10 values, and disallows cycles:
|
44
|
+
|
45
|
+
create_sequence("seq_user", {
|
46
|
+
:increment => 1,
|
47
|
+
:min => 1,
|
48
|
+
:max => 2000000,
|
49
|
+
:start => 1,
|
50
|
+
:cache => 10,
|
51
|
+
:cycle => false
|
52
|
+
})
|
53
|
+
|
54
|
+
This is equivalent of the following query:
|
55
|
+
|
56
|
+
CREATE SEQUENCE seq_user INCREMENT BY 1 MIN 1 MAX 2000000 START 1 CACHE 10 NO CYCLE
|
57
|
+
|
58
|
+
=== Reset a sequence's value:
|
59
|
+
|
60
|
+
change_sequence "seq_accounts", :restart_with => 50
|
61
|
+
|
62
|
+
This is equivalent to:
|
63
|
+
|
64
|
+
ALTER SEQUENCE seq_accounts RESTART WITH 50
|
65
|
+
|
66
|
+
=== Removing a sequence:
|
67
|
+
|
68
|
+
drop_sequence "seq_products"
|
69
|
+
|
70
|
+
== Caveats / Bugs
|
71
|
+
* Tested with postgres 9.0.4, should work down to 8.1.
|
72
|
+
* Listing all the sequences in a database creates n+1 queries (1 to get the names and n to describe each sequence). Is there a way to fully describe all sequences in a database in one query?
|
73
|
+
* The "SET SCHEMA" fragment of the ALTER command is not implemented.
|
74
|
+
* Oracle/other databases not supported
|
75
|
+
* Other unknown bugs :)
|
76
|
+
|
77
|
+
== References
|
78
|
+
* http://www.postgresql.org/docs/8.1/static/sql-createsequence.html
|
79
|
+
* http://www.postgresql.org/docs/8.1/static/sql-altersequence.html
|
80
|
+
* http://www.alberton.info/postgresql_meta_info.html
|
81
|
+
|
82
|
+
== License
|
83
|
+
|
84
|
+
Copyright (c) 2011 Code 42 Software.
|
85
|
+
|
86
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
87
|
+
you may not use this file except in compliance with the License.
|
88
|
+
You may obtain a copy of the License at
|
89
|
+
|
90
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
91
|
+
|
92
|
+
Unless required by applicable law or agreed to in writing, software
|
93
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
94
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
95
|
+
See the License for the specific language governing permissions and
|
96
|
+
limitations under the License.
|
data/Rakefile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'rake'
|
2
|
+
# begin
|
3
|
+
# require 'bundler/setup'
|
4
|
+
# rescue LoadError
|
5
|
+
# puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
6
|
+
# end
|
7
|
+
|
8
|
+
desc 'Default: run unit tests.'
|
9
|
+
task :default => :test
|
10
|
+
|
11
|
+
require 'rake/testtask'
|
12
|
+
desc 'Test the foreigner plugin.'
|
13
|
+
Rake::TestTask.new(:test) do |t|
|
14
|
+
t.libs << 'lib'
|
15
|
+
t.libs << 'test'
|
16
|
+
t.pattern = 'test/**/*_test.rb'
|
17
|
+
t.verbose = true
|
18
|
+
end
|
data/lib/pg_sequencer.rb
ADDED
@@ -0,0 +1,146 @@
|
|
1
|
+
module PgSequencer
|
2
|
+
module ConnectionAdapters
|
3
|
+
|
4
|
+
class SequenceDefinition < Struct.new(:name, :options)
|
5
|
+
end
|
6
|
+
|
7
|
+
module PostgreSQLAdapter
|
8
|
+
def create_sequence(name, options = {})
|
9
|
+
execute create_sequence_sql(name, options)
|
10
|
+
end
|
11
|
+
|
12
|
+
def drop_sequence(name)
|
13
|
+
execute drop_sequence_sql(name)
|
14
|
+
end
|
15
|
+
|
16
|
+
def change_sequence(name, options = {})
|
17
|
+
execute change_sequence_sql(name, options)
|
18
|
+
end
|
19
|
+
|
20
|
+
# CREATE [ TEMPORARY | TEMP ] SEQUENCE name [ INCREMENT [ BY ] increment ]
|
21
|
+
# [ MINVALUE minvalue | NO MINVALUE ] [ MAXVALUE maxvalue | NO MAXVALUE ]
|
22
|
+
# [ START [ WITH ] start ] [ CACHE cache ] [ [ NO ] CYCLE ]
|
23
|
+
#
|
24
|
+
# create_sequence "seq_user",
|
25
|
+
# :increment => 1,
|
26
|
+
# :min => (1|false),
|
27
|
+
# :max => (20000|false),
|
28
|
+
# :start => 1,
|
29
|
+
# :cache => 5,
|
30
|
+
# :cycle => true
|
31
|
+
def create_sequence_sql(name, options = {})
|
32
|
+
options.delete(:restart)
|
33
|
+
"CREATE SEQUENCE #{name}#{sequence_options_sql(options)}"
|
34
|
+
end
|
35
|
+
|
36
|
+
def drop_sequence_sql(name)
|
37
|
+
"DROP SEQUENCE #{name}"
|
38
|
+
end
|
39
|
+
|
40
|
+
def change_sequence_sql(name, options = {})
|
41
|
+
return "" if options.blank?
|
42
|
+
options.delete(:start)
|
43
|
+
"ALTER SEQUENCE #{name}#{sequence_options_sql(options)}"
|
44
|
+
end
|
45
|
+
|
46
|
+
def sequence_options_sql(options = {})
|
47
|
+
sql = ""
|
48
|
+
sql << increment_option_sql(options) if options[:increment] or options[:increment_by]
|
49
|
+
sql << min_option_sql(options)
|
50
|
+
sql << max_option_sql(options)
|
51
|
+
sql << start_option_sql(options) if options[:start] or options[:start_with]
|
52
|
+
sql << restart_option_sql(options) if options[:restart] or options[:restart_with]
|
53
|
+
sql << cache_option_sql(options) if options[:cache]
|
54
|
+
sql << cycle_option_sql(options)
|
55
|
+
sql
|
56
|
+
end
|
57
|
+
|
58
|
+
def sequences
|
59
|
+
# sequence_temp=# select * from temp;
|
60
|
+
# -[ RECORD 1 ]-+--------------------
|
61
|
+
# sequence_name | temp
|
62
|
+
# last_value | 7
|
63
|
+
# start_value | 1
|
64
|
+
# increment_by | 1
|
65
|
+
# max_value | 9223372036854775807
|
66
|
+
# min_value | 1
|
67
|
+
# cache_value | 1
|
68
|
+
# log_cnt | 26
|
69
|
+
# is_cycled | f
|
70
|
+
# is_called | t
|
71
|
+
sequence_names = select_all("SELECT c.relname FROM pg_class c WHERE c.relkind = 'S' order by c.relname asc").map { |row| row['relname'] }
|
72
|
+
|
73
|
+
all_sequences = []
|
74
|
+
|
75
|
+
sequence_names.each do |sequence_name|
|
76
|
+
row = select_one("SELECT * FROM #{sequence_name}")
|
77
|
+
|
78
|
+
options = {
|
79
|
+
:increment => row['increment_by'].to_i,
|
80
|
+
:min => row['min_value'].to_i,
|
81
|
+
:max => row['max_value'].to_i,
|
82
|
+
:start => row['start_value'].to_i,
|
83
|
+
:cache => row['cache_value'].to_i,
|
84
|
+
:cycle => row['is_cycled'] == 't'
|
85
|
+
}
|
86
|
+
|
87
|
+
all_sequences << SequenceDefinition.new(sequence_name, options)
|
88
|
+
end
|
89
|
+
|
90
|
+
all_sequences
|
91
|
+
end
|
92
|
+
|
93
|
+
protected
|
94
|
+
def increment_option_sql(options = {})
|
95
|
+
" INCREMENT BY #{options[:increment] || options[:increment_by]}"
|
96
|
+
end
|
97
|
+
|
98
|
+
def min_option_sql(options = {})
|
99
|
+
case options[:min]
|
100
|
+
when nil then ""
|
101
|
+
when false then " NO MINVALUE"
|
102
|
+
else " MINVALUE #{options[:min]}"
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def max_option_sql(options = {})
|
107
|
+
case options[:max]
|
108
|
+
when nil then ""
|
109
|
+
when false then " NO MAXVALUE"
|
110
|
+
else " MAXVALUE #{options[:max]}"
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def restart_option_sql(options = {})
|
115
|
+
" RESTART WITH #{options[:restart] || options[:restart_with]}"
|
116
|
+
end
|
117
|
+
|
118
|
+
def start_option_sql(options = {})
|
119
|
+
" START WITH #{options[:start] || options[:start_with]}"
|
120
|
+
end
|
121
|
+
|
122
|
+
def cache_option_sql(options = {})
|
123
|
+
" CACHE #{options[:cache]}"
|
124
|
+
end
|
125
|
+
|
126
|
+
def cycle_option_sql(options = {})
|
127
|
+
case options[:cycle]
|
128
|
+
when nil then ""
|
129
|
+
when false then " NO CYCLE"
|
130
|
+
else " CYCLE"
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
# todo: add JDBCAdapter?
|
139
|
+
[:PostgreSQLAdapter].each do |adapter|
|
140
|
+
begin
|
141
|
+
ActiveRecord::ConnectionAdapters.const_get(adapter).class_eval do
|
142
|
+
include PgSequencer::ConnectionAdapters::PostgreSQLAdapter
|
143
|
+
end
|
144
|
+
rescue
|
145
|
+
end
|
146
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module PgSequencer
|
2
|
+
class Railtie < Rails::Railtie
|
3
|
+
initializer "pg_sequencer.load_adapter" do
|
4
|
+
ActiveSupport.on_load :active_record do
|
5
|
+
require 'pg_sequencer/connection_adapters/postgresql_adapter'
|
6
|
+
|
7
|
+
ActiveRecord::ConnectionAdapters.module_eval do
|
8
|
+
include PgSequencer::ConnectionAdapters::PostgreSQLAdapter
|
9
|
+
end
|
10
|
+
|
11
|
+
ActiveRecord::SchemaDumper.class_eval do
|
12
|
+
include PgSequencer::SchemaDumper
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
# if defined?(ActiveRecord::Migration::CommandRecorder)
|
18
|
+
# ActiveRecord::Migration::CommandRecorder.class_eval do
|
19
|
+
# include PgSequencer::Migration::CommandRecorder
|
20
|
+
# end
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
# # PgSequencer::Adapter.load!
|
24
|
+
# end
|
25
|
+
|
26
|
+
end # initializer
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module PgSequencer
|
2
|
+
module SchemaDumper
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
alias_method_chain :tables, :sequences
|
7
|
+
end
|
8
|
+
|
9
|
+
def tables_with_sequences(stream)
|
10
|
+
tables_without_sequences(stream)
|
11
|
+
sequences(stream)
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
def sequences(stream)
|
16
|
+
sequence_statements = @connection.sequences.map do |sequence|
|
17
|
+
statement_parts = [ ('create_sequence ') + sequence.name.inspect ]
|
18
|
+
statement_parts << (':increment => ' + sequence.options[:increment].inspect)
|
19
|
+
statement_parts << (':min => ' + sequence.options[:min].inspect)
|
20
|
+
statement_parts << (':max => ' + sequence.options[:max].inspect)
|
21
|
+
statement_parts << (':start => ' + sequence.options[:start].inspect)
|
22
|
+
statement_parts << (':cache => ' + sequence.options[:cache].inspect)
|
23
|
+
statement_parts << (':cycle => ' + sequence.options[:cycle].inspect)
|
24
|
+
|
25
|
+
' ' + statement_parts.join(', ')
|
26
|
+
end
|
27
|
+
|
28
|
+
stream.puts sequence_statements.sort.join("\n")
|
29
|
+
stream.puts
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,138 @@
|
|
1
|
+
require 'helper'
|
2
|
+
require 'pg_sequencer/connection_adapters/postgresql_adapter'
|
3
|
+
|
4
|
+
class PostgreSQLAdapterTest < ActiveSupport::TestCase
|
5
|
+
include PgSequencer::ConnectionAdapters::PostgreSQLAdapter
|
6
|
+
|
7
|
+
setup do
|
8
|
+
@options = {
|
9
|
+
:increment => 1,
|
10
|
+
:min => 1,
|
11
|
+
:max => 2_000_000,
|
12
|
+
:cache => 5,
|
13
|
+
:cycle => true
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
context "generating sequence option SQL" do
|
18
|
+
context "for :increment" do
|
19
|
+
should "include 'INCREMENT BY' in the SQL" do
|
20
|
+
assert_equal(" INCREMENT BY 1", sequence_options_sql(:increment => 1))
|
21
|
+
assert_equal(" INCREMENT BY 2", sequence_options_sql(:increment => 2))
|
22
|
+
end
|
23
|
+
|
24
|
+
should "not include the option if nil value specified" do
|
25
|
+
assert_equal("", sequence_options_sql(:increment => nil))
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context "for :min" do
|
30
|
+
should "include 'MINVALUE' in the SQL if specified" do
|
31
|
+
assert_equal(" MINVALUE 1", sequence_options_sql(:min => 1))
|
32
|
+
assert_equal(" MINVALUE 2", sequence_options_sql(:min => 2))
|
33
|
+
end
|
34
|
+
|
35
|
+
should "not include 'MINVALUE' in SQL if set to nil" do
|
36
|
+
assert_equal("", sequence_options_sql(:min => nil))
|
37
|
+
end
|
38
|
+
|
39
|
+
should "set 'NO MINVALUE' if :min specified as false" do
|
40
|
+
assert_equal(" NO MINVALUE", sequence_options_sql(:min => false))
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context "for :max" do
|
45
|
+
should "include 'MAXVALUE' in the SQL if specified" do
|
46
|
+
assert_equal(" MAXVALUE 1", sequence_options_sql(:max => 1))
|
47
|
+
assert_equal(" MAXVALUE 2", sequence_options_sql(:max => 2))
|
48
|
+
end
|
49
|
+
|
50
|
+
should "not include 'MAXVALUE' in SQL if set to nil" do
|
51
|
+
assert_equal("", sequence_options_sql(:max => nil))
|
52
|
+
end
|
53
|
+
|
54
|
+
should "set 'NO MAXVALUE' if :min specified as false" do
|
55
|
+
assert_equal(" NO MAXVALUE", sequence_options_sql(:max => false))
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context "for :start" do
|
60
|
+
should "include 'START WITH' in SQL if specified" do
|
61
|
+
assert_equal(" START WITH 1", sequence_options_sql(:start => 1))
|
62
|
+
assert_equal(" START WITH 2", sequence_options_sql(:start => 2))
|
63
|
+
assert_equal(" START WITH 500", sequence_options_sql(:start => 500))
|
64
|
+
end
|
65
|
+
|
66
|
+
should "not include 'START WITH' in SQL if specified as nil" do
|
67
|
+
assert_equal("", sequence_options_sql(:start => nil))
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context "for :cache" do
|
72
|
+
should "include 'CACHE' in SQL if specified" do
|
73
|
+
assert_equal(" CACHE 1", sequence_options_sql(:cache => 1))
|
74
|
+
assert_equal(" CACHE 2", sequence_options_sql(:cache => 2))
|
75
|
+
assert_equal(" CACHE 500", sequence_options_sql(:cache => 500))
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context "for :cycle" do
|
80
|
+
should "include 'CYCLE' option if specified" do
|
81
|
+
assert_equal(" CYCLE", sequence_options_sql(:cycle => true))
|
82
|
+
end
|
83
|
+
|
84
|
+
should "include 'NO CYCLE' option if set as false" do
|
85
|
+
assert_equal(" NO CYCLE", sequence_options_sql(:cycle => false))
|
86
|
+
end
|
87
|
+
|
88
|
+
should "not include 'CYCLE' statement if specified as nil" do
|
89
|
+
assert_equal("", sequence_options_sql(:cycle => nil))
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
should "include all options" do
|
94
|
+
assert_equal " INCREMENT BY 1 MINVALUE 1 MAXVALUE 2000000 START WITH 1 CACHE 5 CYCLE", sequence_options_sql(@options.merge(:start => 1))
|
95
|
+
end
|
96
|
+
end # generating sequence option SQL
|
97
|
+
|
98
|
+
context "creating sequences" do
|
99
|
+
context "without options" do
|
100
|
+
should "generate the proper SQL" do
|
101
|
+
assert_equal("CREATE SEQUENCE things", create_sequence_sql('things'))
|
102
|
+
assert_equal("CREATE SEQUENCE blahs", create_sequence_sql('blahs'))
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
context "with options" do
|
107
|
+
should "include options at the end" do
|
108
|
+
assert_equal("CREATE SEQUENCE things INCREMENT BY 1 MINVALUE 1 MAXVALUE 2000000 START WITH 1 CACHE 5 CYCLE", create_sequence_sql('things', @options.merge(:start => 1)))
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end # creating sequences
|
112
|
+
|
113
|
+
context "altering sequences" do
|
114
|
+
context "without options" do
|
115
|
+
should "return a blank SQL statement" do
|
116
|
+
assert_equal("", change_sequence_sql('things'))
|
117
|
+
assert_equal("", change_sequence_sql('things', {}))
|
118
|
+
assert_equal("", change_sequence_sql('things', nil))
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
context "with options" do
|
123
|
+
|
124
|
+
should "include options at the end" do
|
125
|
+
assert_equal("ALTER SEQUENCE things INCREMENT BY 1 MINVALUE 1 MAXVALUE 2000000 RESTART WITH 1 CACHE 5 CYCLE", change_sequence_sql('things', @options.merge(:restart => 1)))
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
end # altering sequences
|
130
|
+
|
131
|
+
context "dropping sequences" do
|
132
|
+
should "generate the proper SQL" do
|
133
|
+
assert_equal("DROP SEQUENCE seq_users", drop_sequence_sql('seq_users'))
|
134
|
+
assert_equal("DROP SEQUENCE seq_items", drop_sequence_sql('seq_items'))
|
135
|
+
end
|
136
|
+
end # dropping sequences
|
137
|
+
|
138
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class SchemaDumperTest < ActiveSupport::TestCase
|
4
|
+
|
5
|
+
class SequenceDefinition < Struct.new(:name, :options); end
|
6
|
+
|
7
|
+
class MockConnection
|
8
|
+
attr_accessor :sequences
|
9
|
+
|
10
|
+
def initialize(sequences = [])
|
11
|
+
@sequences = sequences
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
|
16
|
+
class MockStream
|
17
|
+
attr_accessor :output
|
18
|
+
def initialize; @output = []; end
|
19
|
+
def puts(str = ""); @output << str; end
|
20
|
+
def to_s; @output.join("\n"); end
|
21
|
+
end
|
22
|
+
|
23
|
+
class MockSchemaDumper
|
24
|
+
def initialize(connection)
|
25
|
+
@connection = connection
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.dump(conn, stream)
|
29
|
+
new(conn).dump(stream)
|
30
|
+
end
|
31
|
+
|
32
|
+
def header(stream)
|
33
|
+
stream.puts '# Fake Schema Header'
|
34
|
+
end
|
35
|
+
|
36
|
+
def tables(stream)
|
37
|
+
stream.puts '# (No Tables)'
|
38
|
+
end
|
39
|
+
|
40
|
+
def dump(stream)
|
41
|
+
header(stream)
|
42
|
+
tables(stream)
|
43
|
+
trailer(stream)
|
44
|
+
stream
|
45
|
+
end
|
46
|
+
|
47
|
+
def trailer(stream)
|
48
|
+
stream.puts '# Fake Schema Trailer'
|
49
|
+
end
|
50
|
+
|
51
|
+
include PgSequencer::SchemaDumper
|
52
|
+
end
|
53
|
+
|
54
|
+
context "dumping the schema" do
|
55
|
+
setup do
|
56
|
+
@options = {
|
57
|
+
:increment => 1,
|
58
|
+
:min => 1,
|
59
|
+
:max => 2_000_000,
|
60
|
+
:start => 1,
|
61
|
+
:cache => 5,
|
62
|
+
:cycle => true
|
63
|
+
}
|
64
|
+
|
65
|
+
@stream = MockStream.new
|
66
|
+
end
|
67
|
+
|
68
|
+
should "output all sequences correctly" do
|
69
|
+
sequences = ['seq_t_user', 'seq_t_item'].map do |name|
|
70
|
+
SequenceDefinition.new(name, @options)
|
71
|
+
end
|
72
|
+
|
73
|
+
@conn = MockConnection.new(sequences)
|
74
|
+
|
75
|
+
expected_output = <<-SCHEMAEND
|
76
|
+
# Fake Schema Header
|
77
|
+
# (No Tables)
|
78
|
+
create_sequence "seq_t_item", :increment => 1, :min => 1, :max => 2000000, :start => 1, :cache => 5, :cycle => true
|
79
|
+
create_sequence "seq_t_user", :increment => 1, :min => 1, :max => 2000000, :start => 1, :cache => 5, :cycle => true
|
80
|
+
|
81
|
+
# Fake Schema Trailer
|
82
|
+
SCHEMAEND
|
83
|
+
|
84
|
+
MockSchemaDumper.dump(@conn, @stream)
|
85
|
+
assert_equal(expected_output.strip, @stream.to_s)
|
86
|
+
end
|
87
|
+
|
88
|
+
context "when min specified as false" do
|
89
|
+
setup do
|
90
|
+
sequences = ['seq_t_user', 'seq_t_item'].map do |name|
|
91
|
+
SequenceDefinition.new(name, @options.merge(:min => false))
|
92
|
+
end
|
93
|
+
@conn = MockConnection.new(sequences)
|
94
|
+
end
|
95
|
+
|
96
|
+
should "properly quote false values in schema output" do
|
97
|
+
expected_output = <<-SCHEMAEND
|
98
|
+
# Fake Schema Header
|
99
|
+
# (No Tables)
|
100
|
+
create_sequence "seq_t_item", :increment => 1, :min => false, :max => 2000000, :start => 1, :cache => 5, :cycle => true
|
101
|
+
create_sequence "seq_t_user", :increment => 1, :min => false, :max => 2000000, :start => 1, :cache => 5, :cycle => true
|
102
|
+
|
103
|
+
# Fake Schema Trailer
|
104
|
+
SCHEMAEND
|
105
|
+
|
106
|
+
MockSchemaDumper.dump(@conn, @stream)
|
107
|
+
assert_equal(expected_output.strip, @stream.to_s)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
metadata
ADDED
@@ -0,0 +1,125 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: pg_sequencer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Tony Collen
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-09-30 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: activerecord
|
16
|
+
requirement: &70303200278560 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 3.0.0
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70303200278560
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: activerecord
|
27
|
+
requirement: &70303200278060 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 3.1.0
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70303200278060
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: pg
|
38
|
+
requirement: &70303200310860 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - =
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 0.11.0
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *70303200310860
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: guard
|
49
|
+
requirement: &70303200310480 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *70303200310480
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: guard-test
|
60
|
+
requirement: &70303200310020 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
type: :development
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *70303200310020
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: shoulda-context
|
71
|
+
requirement: &70303200309600 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ! '>='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: '0'
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: *70303200309600
|
80
|
+
description: Sequences need some love. pg_sequencer teaches Rails what sequences are,
|
81
|
+
and will dump them to schema.rb, and also lets you create/drop sequences in migrations.
|
82
|
+
email:
|
83
|
+
- tonyc@code42.com
|
84
|
+
executables: []
|
85
|
+
extensions: []
|
86
|
+
extra_rdoc_files: []
|
87
|
+
files:
|
88
|
+
- lib/pg_sequencer/connection_adapters/postgresql_adapter.rb
|
89
|
+
- lib/pg_sequencer/railtie.rb
|
90
|
+
- lib/pg_sequencer/schema_dumper.rb
|
91
|
+
- lib/pg_sequencer/version.rb
|
92
|
+
- lib/pg_sequencer.rb
|
93
|
+
- Rakefile
|
94
|
+
- README.rdoc
|
95
|
+
- test/helper.rb
|
96
|
+
- test/unit/postgresql_adapter_test.rb
|
97
|
+
- test/unit/schema_dumper_test.rb
|
98
|
+
homepage: https://github.com/code42/pg_sequencer/
|
99
|
+
licenses: []
|
100
|
+
post_install_message:
|
101
|
+
rdoc_options: []
|
102
|
+
require_paths:
|
103
|
+
- lib
|
104
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
111
|
+
none: false
|
112
|
+
requirements:
|
113
|
+
- - ! '>='
|
114
|
+
- !ruby/object:Gem::Version
|
115
|
+
version: '0'
|
116
|
+
requirements: []
|
117
|
+
rubyforge_project:
|
118
|
+
rubygems_version: 1.8.6
|
119
|
+
signing_key:
|
120
|
+
specification_version: 3
|
121
|
+
summary: Manage postgres sequences in Rails migrations
|
122
|
+
test_files:
|
123
|
+
- test/helper.rb
|
124
|
+
- test/unit/postgresql_adapter_test.rb
|
125
|
+
- test/unit/schema_dumper_test.rb
|