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.
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Sequel
4
+ module Sequence
5
+ VERSION = '0.1.0'
6
+ end
7
+ end
@@ -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,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'sequel/sequence'
@@ -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
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'simplecov'
4
+ SimpleCov.start
5
+
6
+ require 'bundler/setup'
7
+ require 'sequel'
8
+ require 'sequel/extensions/migration'
9
+ require 'sequel/sequence'
10
+ require 'minitest/utils'
11
+ require 'minitest/autorun'