sequel-sequence 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/CHANGELOG.md +16 -0
- data/CODE_OF_CONDUCT.md +132 -0
- data/CONTRIBUTING.md +120 -0
- data/Gemfile +5 -0
- data/LICENSE.md +20 -0
- data/README.md +108 -0
- data/Rakefile +15 -0
- data/lib/sequel/error.rb +12 -0
- data/lib/sequel/sequence/database/mysql.rb +10 -0
- data/lib/sequel/sequence/database/mysql2.rb +80 -0
- data/lib/sequel/sequence/database/postgresql.rb +96 -0
- data/lib/sequel/sequence/database.rb +47 -0
- data/lib/sequel/sequence/version.rb +7 -0
- data/lib/sequel/sequence.rb +32 -0
- data/lib/sequel-sequence.rb +3 -0
- data/sequel-sequence.gemspec +45 -0
- data/test/mysql_test_helper.rb +28 -0
- data/test/postgresql_test_helper.rb +28 -0
- data/test/sequel/mysql_sequence_test.rb +172 -0
- data/test/sequel/postgresql_sequence_test.rb +183 -0
- data/test/test_helper.rb +11 -0
- metadata +197 -0
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'sequel/database'
|
4
|
+
require 'sequel/adapters/postgres'
|
5
|
+
# require 'sequel/adapters/mysql'
|
6
|
+
require 'sequel/adapters/mysql2'
|
7
|
+
require 'sequel/error'
|
8
|
+
|
9
|
+
module Sequel
|
10
|
+
module Sequence
|
11
|
+
require 'sequel/sequence/database'
|
12
|
+
|
13
|
+
module Database
|
14
|
+
require 'sequel/sequence/database/postgresql'
|
15
|
+
# require "sequel/sequence/database/mysql"
|
16
|
+
require 'sequel/sequence/database/mysql2'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
Sequel::Database.include(
|
22
|
+
Sequel::Sequence::Database
|
23
|
+
)
|
24
|
+
Sequel::Postgres::Database.include(
|
25
|
+
Sequel::Sequence::Database::PostgreSQL
|
26
|
+
)
|
27
|
+
Sequel::Mysql2::Database.include(
|
28
|
+
Sequel::Sequence::Database::Mysql2
|
29
|
+
)
|
30
|
+
# Sequel::Mysql::Database.include(
|
31
|
+
# Sequel::Sequence::Database::Mysql
|
32
|
+
# )
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require './lib/sequel/sequence/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = 'sequel-sequence'
|
7
|
+
spec.version = Sequel::Sequence::VERSION
|
8
|
+
spec.licenses = ['MIT']
|
9
|
+
spec.summary = \
|
10
|
+
"Add support for PostgreSQL's and MySQL's SEQUENCE on Sequel migrations."
|
11
|
+
spec.description = <<-DES
|
12
|
+
This gem provides a single interface for SEQUENCE functionality
|
13
|
+
in Postgresql and Mysql databases within the Sequel ORM.
|
14
|
+
DES
|
15
|
+
spec.authors = ['Nikolai Bocharov']
|
16
|
+
spec.email = ['it.architect@yahoo.com']
|
17
|
+
spec.files = `git ls-files -z`.split("\x0")
|
18
|
+
spec.require_paths = ['lib']
|
19
|
+
spec.extra_rdoc_files = ['README.md']
|
20
|
+
spec.homepage = 'https://rubygems.org/gems/sequel-sequence'
|
21
|
+
spec.metadata = {
|
22
|
+
'source_code_uri' => 'https://github.com/oreol-group/sequel-sequence',
|
23
|
+
'changelog_uri' => 'https://github.com/oreol-group/sequel-sequence/blob/master/CHANGELOG.md',
|
24
|
+
'bug_tracker_uri' => 'https://github.com/oreol-group/sequel-sequence/issues'
|
25
|
+
}
|
26
|
+
spec.platform = Gem::Platform::RUBY
|
27
|
+
spec.required_ruby_version = '>= 2.7.0'
|
28
|
+
|
29
|
+
spec.add_dependency 'sequel'
|
30
|
+
spec.add_development_dependency 'bundler'
|
31
|
+
spec.add_development_dependency 'minitest-utils'
|
32
|
+
spec.add_development_dependency 'pry-byebug'
|
33
|
+
spec.add_development_dependency 'rake'
|
34
|
+
spec.add_development_dependency 'rubocop'
|
35
|
+
spec.add_development_dependency 'simplecov'
|
36
|
+
if RUBY_ENGINE == 'jruby'
|
37
|
+
# JRuby Adapter Dependencies
|
38
|
+
spec.add_development_dependency 'jdbc-mysql'
|
39
|
+
spec.add_development_dependency 'jdbc-postgres'
|
40
|
+
else
|
41
|
+
# MRI/Rubinius Adapter Dependencies
|
42
|
+
spec.add_development_dependency 'mysql2'
|
43
|
+
spec.add_development_dependency 'pg'
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
|
5
|
+
MysqlDB = Sequel.connect('mysql2://root:root@localhost/test')
|
6
|
+
|
7
|
+
Sequel::Model.db = MysqlDB
|
8
|
+
|
9
|
+
class Ware < Sequel::Model
|
10
|
+
end
|
11
|
+
|
12
|
+
class InheritedWare < Ware
|
13
|
+
end
|
14
|
+
|
15
|
+
class Builder < Sequel::Model
|
16
|
+
end
|
17
|
+
|
18
|
+
module MysqlTestHelper
|
19
|
+
def recreate_table
|
20
|
+
MysqlDB.run 'DROP SEQUENCE IF EXISTS position'
|
21
|
+
MysqlDB.run 'DROP TABLE IF EXISTS wares'
|
22
|
+
MysqlDB.run 'DROP SEQUENCE IF EXISTS a'
|
23
|
+
MysqlDB.run 'DROP SEQUENCE IF EXISTS b'
|
24
|
+
MysqlDB.run 'DROP SEQUENCE IF EXISTS c'
|
25
|
+
sql = 'CREATE TABLE wares (id INT AUTO_INCREMENT, slug VARCHAR(255), quantity INT DEFAULT(0), PRIMARY KEY(id));'
|
26
|
+
MysqlDB.run sql
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
|
5
|
+
PostgresqlDB = Sequel.connect('postgres:///test')
|
6
|
+
|
7
|
+
Sequel::Model.db = PostgresqlDB
|
8
|
+
|
9
|
+
class Thing < Sequel::Model
|
10
|
+
end
|
11
|
+
|
12
|
+
class InheritedThing < Thing
|
13
|
+
end
|
14
|
+
|
15
|
+
class Master < Sequel::Model
|
16
|
+
end
|
17
|
+
|
18
|
+
module PostgresqlTestHelper
|
19
|
+
def recreate_table
|
20
|
+
PostgresqlDB.run 'DROP TABLE IF EXISTS things'
|
21
|
+
PostgresqlDB.run 'DROP SEQUENCE IF EXISTS position'
|
22
|
+
PostgresqlDB.run 'DROP SEQUENCE IF EXISTS a'
|
23
|
+
PostgresqlDB.run 'DROP SEQUENCE IF EXISTS b'
|
24
|
+
PostgresqlDB.run 'DROP SEQUENCE IF EXISTS c'
|
25
|
+
sql = 'CREATE TABLE things (id SERIAL PRIMARY KEY, slug VARCHAR(255), quantity INTEGER DEFAULT 0);'
|
26
|
+
PostgresqlDB.run sql
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,172 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'mysql_test_helper'
|
4
|
+
|
5
|
+
class MysqlSequenceTest < Minitest::Test
|
6
|
+
include MysqlTestHelper
|
7
|
+
|
8
|
+
setup do
|
9
|
+
recreate_table
|
10
|
+
end
|
11
|
+
|
12
|
+
test 'adds sequence with default values' do
|
13
|
+
Sequel.migration do
|
14
|
+
up do
|
15
|
+
create_sequence :position
|
16
|
+
end
|
17
|
+
end.apply(MysqlDB, :up)
|
18
|
+
|
19
|
+
assert_equal 1, Ware.db.nextval(:position)
|
20
|
+
assert_equal 2, Ware.db.nextval(:position)
|
21
|
+
end
|
22
|
+
|
23
|
+
test 'adds sequence reader within inherited class' do
|
24
|
+
Sequel.migration do
|
25
|
+
up do
|
26
|
+
create_sequence :position
|
27
|
+
end
|
28
|
+
end.apply(MysqlDB, :up)
|
29
|
+
|
30
|
+
assert_equal 1, InheritedWare.db.nextval(:position)
|
31
|
+
assert_equal 2, InheritedWare.db.nextval(:position)
|
32
|
+
end
|
33
|
+
|
34
|
+
test 'adds sequence starting at 100' do
|
35
|
+
Sequel.migration do
|
36
|
+
up do
|
37
|
+
create_sequence :position, start: 100
|
38
|
+
end
|
39
|
+
end.apply(MysqlDB, :up)
|
40
|
+
|
41
|
+
assert_equal 100, Ware.db.nextval(:position)
|
42
|
+
assert_equal 101, Ware.db.nextval(:position)
|
43
|
+
end
|
44
|
+
|
45
|
+
test 'adds sequence incremented by 2' do
|
46
|
+
Sequel.migration do
|
47
|
+
up do
|
48
|
+
create_sequence :position, increment: 2
|
49
|
+
end
|
50
|
+
end.apply(MysqlDB, :up)
|
51
|
+
|
52
|
+
assert_equal 1, Ware.db.nextval(:position)
|
53
|
+
assert_equal 3, Ware.db.nextval(:position)
|
54
|
+
end
|
55
|
+
|
56
|
+
test 'adds sequence incremented by 2 (using :step alias)' do
|
57
|
+
Sequel.migration do
|
58
|
+
up do
|
59
|
+
create_sequence :position, step: 2
|
60
|
+
end
|
61
|
+
end.apply(MysqlDB, :up)
|
62
|
+
|
63
|
+
assert_equal 1, Ware.db.nextval(:position)
|
64
|
+
assert_equal 3, Ware.db.nextval(:position)
|
65
|
+
end
|
66
|
+
|
67
|
+
test 'returns current/last sequence value without incrementing it' do
|
68
|
+
Sequel.migration do
|
69
|
+
up do
|
70
|
+
create_sequence :position
|
71
|
+
end
|
72
|
+
end.apply(MysqlDB, :up)
|
73
|
+
|
74
|
+
Ware.db.nextval(:position)
|
75
|
+
|
76
|
+
assert_equal 1, Ware.db.currval(:position)
|
77
|
+
assert_equal 1, Ware.db.lastval(:position)
|
78
|
+
assert_equal 1, Ware.db.currval(:position)
|
79
|
+
assert_equal 1, Ware.db.lastval(:position)
|
80
|
+
end
|
81
|
+
|
82
|
+
test 'sets sequence value' do
|
83
|
+
Sequel.migration do
|
84
|
+
up do
|
85
|
+
create_sequence :position
|
86
|
+
end
|
87
|
+
end.apply(MysqlDB, :up)
|
88
|
+
|
89
|
+
Ware.db.nextval(:position)
|
90
|
+
assert_equal Ware.db.currval(:position), 1
|
91
|
+
|
92
|
+
# in mariaDB, 'lastval' only works after 'nextval' rather than 'setval'
|
93
|
+
Ware.db.setval(:position, 101)
|
94
|
+
Ware.db.nextval(:position)
|
95
|
+
assert_equal Ware.db.lastval(:position), 102
|
96
|
+
end
|
97
|
+
|
98
|
+
test 'drops sequence and check_sequences' do
|
99
|
+
Sequel.migration do
|
100
|
+
up do
|
101
|
+
create_sequence :position
|
102
|
+
end
|
103
|
+
end.apply(MysqlDB, :up)
|
104
|
+
|
105
|
+
sequence = MysqlDB.check_sequences.find_all do |seq|
|
106
|
+
seq[:Tables_in_test] == 'position'
|
107
|
+
end
|
108
|
+
|
109
|
+
assert_equal 1, sequence.size
|
110
|
+
|
111
|
+
Sequel.migration do
|
112
|
+
down do
|
113
|
+
drop_sequence :position
|
114
|
+
end
|
115
|
+
end.apply(MysqlDB, :down)
|
116
|
+
|
117
|
+
sequence = MysqlDB.check_sequences.find do |seq|
|
118
|
+
seq[:sequence_name] == 'position'
|
119
|
+
end
|
120
|
+
|
121
|
+
assert_nil sequence
|
122
|
+
end
|
123
|
+
|
124
|
+
test 'orders sequences' do
|
125
|
+
list = MysqlDB.check_sequences.map { |s| s[:Tables_in_test] }
|
126
|
+
assert !list.include?('a')
|
127
|
+
assert !list.include?('b')
|
128
|
+
assert !list.include?('c')
|
129
|
+
|
130
|
+
Sequel.migration do
|
131
|
+
up do
|
132
|
+
drop_table :things, if_exists: true
|
133
|
+
# drop_table :masters, if_exists: true
|
134
|
+
create_sequence :c
|
135
|
+
create_sequence :a
|
136
|
+
create_sequence :b
|
137
|
+
end
|
138
|
+
end.apply(MysqlDB, :up)
|
139
|
+
|
140
|
+
list = MysqlDB.check_sequences.map { |s| s[:Tables_in_test] }
|
141
|
+
assert list.include?('a')
|
142
|
+
assert list.include?('b')
|
143
|
+
assert list.include?('c')
|
144
|
+
end
|
145
|
+
|
146
|
+
test 'creates table that references sequence' do
|
147
|
+
Sequel.migration do
|
148
|
+
up do
|
149
|
+
drop_table :builders, if_exists: true
|
150
|
+
create_sequence :position_id, if_exists: false
|
151
|
+
create_table :builders do
|
152
|
+
primary_key :id
|
153
|
+
String :name, text: true
|
154
|
+
|
155
|
+
# PostgreSQL uses bigint as the sequence's default type.
|
156
|
+
Bignum :position, null: false
|
157
|
+
end
|
158
|
+
set_column_default_nextval :builders, :position, :position_id
|
159
|
+
end
|
160
|
+
end.apply(MysqlDB, :up)
|
161
|
+
|
162
|
+
builder1 = Builder.create(name: 'Builder 1')
|
163
|
+
pos1 = MysqlDB.currval(:position_id)
|
164
|
+
assert_equal pos1, builder1.reload.position
|
165
|
+
|
166
|
+
builder2 = Builder.create(name: 'Builder 2')
|
167
|
+
pos2 = MysqlDB.currval(:position_id)
|
168
|
+
assert_equal pos2, builder2.reload.position
|
169
|
+
|
170
|
+
assert_equal pos2 - pos1, 1
|
171
|
+
end
|
172
|
+
end
|
@@ -0,0 +1,183 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'postgresql_test_helper'
|
4
|
+
|
5
|
+
class PostgresqlSequenceTest < Minitest::Test
|
6
|
+
include PostgresqlTestHelper
|
7
|
+
|
8
|
+
setup do
|
9
|
+
recreate_table
|
10
|
+
end
|
11
|
+
|
12
|
+
test 'adds sequence with default values' do
|
13
|
+
Sequel.migration do
|
14
|
+
up do
|
15
|
+
# create_sequence :position, {start: 1, increment: 1} - default values
|
16
|
+
create_sequence :position
|
17
|
+
end
|
18
|
+
end.apply(PostgresqlDB, :up)
|
19
|
+
|
20
|
+
assert_equal 1, PostgresqlDB.nextval('position')
|
21
|
+
assert_equal 2, PostgresqlDB.nextval('position')
|
22
|
+
end
|
23
|
+
|
24
|
+
test 'adds sequence reader within inherited class' do
|
25
|
+
Sequel.migration do
|
26
|
+
up do
|
27
|
+
create_sequence :position
|
28
|
+
end
|
29
|
+
end.apply(PostgresqlDB, :up)
|
30
|
+
|
31
|
+
assert_equal 1, InheritedThing.db.nextval(:position)
|
32
|
+
assert_equal 2, InheritedThing.db.nextval(:position)
|
33
|
+
end
|
34
|
+
|
35
|
+
test 'adds sequence starting at 100' do
|
36
|
+
Sequel.migration do
|
37
|
+
up do
|
38
|
+
create_sequence :position, start: 100
|
39
|
+
end
|
40
|
+
end.apply(PostgresqlDB, :up)
|
41
|
+
|
42
|
+
assert_equal 100, Thing.db.nextval(:position)
|
43
|
+
assert_equal 101, Thing.db.nextval(:position)
|
44
|
+
end
|
45
|
+
|
46
|
+
test 'adds sequence incremented by 2' do
|
47
|
+
Sequel.migration do
|
48
|
+
up do
|
49
|
+
create_sequence :position, increment: 2
|
50
|
+
end
|
51
|
+
end.apply(PostgresqlDB, :up)
|
52
|
+
|
53
|
+
assert_equal 1, Thing.db.nextval(:position)
|
54
|
+
assert_equal 3, Thing.db.nextval(:position)
|
55
|
+
end
|
56
|
+
|
57
|
+
test 'adds sequence incremented by 2 (using :step alias)' do
|
58
|
+
Sequel.migration do
|
59
|
+
up do
|
60
|
+
create_sequence :position, step: 2
|
61
|
+
end
|
62
|
+
end.apply(PostgresqlDB, :up)
|
63
|
+
|
64
|
+
assert_equal 1, Thing.db.nextval(:position)
|
65
|
+
assert_equal 3, Thing.db.nextval(:position)
|
66
|
+
end
|
67
|
+
|
68
|
+
test 'returns current (or last as alias) sequence value without incrementing it' do
|
69
|
+
Sequel.migration do
|
70
|
+
up do
|
71
|
+
create_sequence :position, start: 2, increment: 2
|
72
|
+
end
|
73
|
+
end.apply(PostgresqlDB, :up)
|
74
|
+
|
75
|
+
Thing.db.nextval(:position)
|
76
|
+
|
77
|
+
assert_equal 2, Thing.db.currval(:position)
|
78
|
+
assert_equal 2, Thing.db.lastval(:position)
|
79
|
+
assert_equal 2, Thing.db.currval(:position)
|
80
|
+
assert_equal 2, Thing.db.lastval(:position)
|
81
|
+
end
|
82
|
+
|
83
|
+
test 'sets sequence value' do
|
84
|
+
Sequel.migration do
|
85
|
+
up do
|
86
|
+
create_sequence :position
|
87
|
+
end
|
88
|
+
end.apply(PostgresqlDB, :up)
|
89
|
+
|
90
|
+
Thing.db.nextval(:position)
|
91
|
+
assert_equal Thing.db.currval(:position), 1
|
92
|
+
|
93
|
+
Thing.db.setval(:position, 101)
|
94
|
+
assert_equal 101, Thing.db.currval(:position)
|
95
|
+
end
|
96
|
+
|
97
|
+
test 'drops sequence and check_sequences' do
|
98
|
+
Sequel.migration do
|
99
|
+
up do
|
100
|
+
create_sequence :position
|
101
|
+
end
|
102
|
+
end.apply(PostgresqlDB, :up)
|
103
|
+
|
104
|
+
sequence = PostgresqlDB.check_sequences.find_all do |seq|
|
105
|
+
seq[:sequence_name] == 'position'
|
106
|
+
end
|
107
|
+
|
108
|
+
assert_equal 1, sequence.size
|
109
|
+
|
110
|
+
Sequel.migration do
|
111
|
+
down do
|
112
|
+
drop_sequence :position
|
113
|
+
end
|
114
|
+
end.apply(PostgresqlDB, :down)
|
115
|
+
|
116
|
+
sequence = PostgresqlDB.check_sequences.find do |seq|
|
117
|
+
seq[:sequence_name] == 'position'
|
118
|
+
end
|
119
|
+
|
120
|
+
assert_nil sequence
|
121
|
+
end
|
122
|
+
|
123
|
+
test 'orders sequences' do
|
124
|
+
list = PostgresqlDB.check_sequences.map { |s| s[:sequence_name] }
|
125
|
+
assert !list.include?('a')
|
126
|
+
assert !list.include?('b')
|
127
|
+
assert !list.include?('c')
|
128
|
+
|
129
|
+
Sequel.migration do
|
130
|
+
up do
|
131
|
+
drop_table :things, if_exists: true
|
132
|
+
# drop_table :masters, if_exists: true
|
133
|
+
create_sequence :c
|
134
|
+
create_sequence :a
|
135
|
+
create_sequence :b
|
136
|
+
end
|
137
|
+
end.apply(PostgresqlDB, :up)
|
138
|
+
|
139
|
+
list = PostgresqlDB.check_sequences.map { |s| s[:sequence_name] }
|
140
|
+
assert list.include?('a')
|
141
|
+
assert list.include?('b')
|
142
|
+
assert list.include?('c')
|
143
|
+
end
|
144
|
+
|
145
|
+
test 'checks custom sequence generated from code' do
|
146
|
+
assert_equal PostgresqlDB.custom_sequence?(:c), false
|
147
|
+
|
148
|
+
Sequel.migration do
|
149
|
+
up do
|
150
|
+
create_sequence :c
|
151
|
+
end
|
152
|
+
end.apply(PostgresqlDB, :up)
|
153
|
+
|
154
|
+
assert_equal PostgresqlDB.custom_sequence?(:c), true
|
155
|
+
end
|
156
|
+
|
157
|
+
test 'creates table that references sequence' do
|
158
|
+
Sequel.migration do
|
159
|
+
up do
|
160
|
+
drop_table :masters, if_exists: true
|
161
|
+
create_sequence :position_id, if_exists: false
|
162
|
+
create_table :masters do
|
163
|
+
primary_key :id
|
164
|
+
String :name, text: true
|
165
|
+
|
166
|
+
# PostgreSQL uses bigint as the sequence's default type.
|
167
|
+
Bignum :position, null: false
|
168
|
+
end
|
169
|
+
set_column_default_nextval :masters, :position, :position_id
|
170
|
+
end
|
171
|
+
end.apply(PostgresqlDB, :up)
|
172
|
+
|
173
|
+
master1 = Master.create(name: 'MASTER 1')
|
174
|
+
pos1 = PostgresqlDB.currval(:position_id)
|
175
|
+
assert_equal pos1, master1.reload.position
|
176
|
+
|
177
|
+
master2 = Master.create(name: 'MASTER 2')
|
178
|
+
pos2 = PostgresqlDB.currval(:position_id)
|
179
|
+
assert_equal pos2, master2.reload.position
|
180
|
+
|
181
|
+
assert_equal pos2 - pos1, 1
|
182
|
+
end
|
183
|
+
end
|
data/test/test_helper.rb
ADDED