sequel-sequence 0.4.1 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.ci.gemfile +25 -0
- data/.github/workflows/ci.yml +1 -2
- data/CHANGELOG.md +21 -0
- data/CONTRIBUTING.md +15 -5
- data/README.md +41 -4
- data/lib/sequel/sequence/database/postgresql.rb +43 -15
- data/lib/sequel/sequence/database/server/mariadb.rb +57 -17
- data/lib/sequel/sequence/database/server/mysql.rb +20 -12
- data/lib/sequel/sequence/database/sqlite.rb +21 -8
- data/lib/sequel/sequence/database.rb +17 -0
- data/lib/sequel/sequence/version.rb +1 -1
- data/lib/sequel/sequence.rb +46 -14
- data/sequel-sequence.gemspec +13 -13
- data/test/mariadb_test_helper.rb +4 -0
- data/test/mysql_test_helper.rb +2 -0
- data/test/postgresql_test_helper.rb +5 -1
- data/test/sequel/mariadb_sequence_test.rb +163 -16
- data/test/sequel/mock_sequence_test.rb +19 -1
- data/test/sequel/mysql_sequence_test.rb +133 -16
- data/test/sequel/postgresql_sequence_test.rb +156 -6
- data/test/sequel/sqlite_sequence_test.rb +131 -4
- data/test/sqlite_test_helper.rb +3 -3
- metadata +6 -47
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e6e1a94456ed2dca944d9f5dc7775acdde3db19912cf65c556fc315902dd6514
|
4
|
+
data.tar.gz: 0c6c8ec72019f94c819922dc3c8cc63e63e0d0138a3f95ed442384838d02beb5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 97954c433db834abdd23e91fd97abfee863f7f55bcf08d83048a6f3afd7d8fa9e780bfab010758af8b0ec01936ff1f40461ff5ec942e39bf59da894b23670798
|
7
|
+
data.tar.gz: 208dc0051f42068cae2009bb2ee04b0cfc1f0381aa872504621541d3ea36d8aef7aa8800559425a5c107eac8620d82f52722444d8bda0de58caf20e9ced1145f
|
data/.ci.gemfile
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
source 'https://rubygems.org'
|
4
|
+
|
5
|
+
gem 'bundler', '>= 2.2.4'
|
6
|
+
gem 'minitest-utils', '~> 0.4.6'
|
7
|
+
gem 'pry-byebug', '~> 3.10.1'
|
8
|
+
gem 'rake', '~> 13.0.2'
|
9
|
+
gem 'rubocop', '~> 1.56.3'
|
10
|
+
gem 'sequel', '>= 5.28', '<6.0'
|
11
|
+
gem 'simplecov', '~> 0.22.0'
|
12
|
+
|
13
|
+
# MRI/Rubinius Adapter Dependencies
|
14
|
+
platform :ruby do
|
15
|
+
gem 'mysql2', '~> 0.5.3'
|
16
|
+
gem 'pg', '~> 1.5.4'
|
17
|
+
gem 'sqlite3', '~> 1.6.0'
|
18
|
+
end
|
19
|
+
|
20
|
+
# JRuby Adapter Dependencies
|
21
|
+
platform :jruby do
|
22
|
+
gem 'jdbc-mysql', '~> 8.0.17'
|
23
|
+
gem 'jdbc-postgres', '~> 42.2.14'
|
24
|
+
gem 'jdbc-sqlite3', '~> 3.42'
|
25
|
+
end
|
data/.github/workflows/ci.yml
CHANGED
@@ -16,7 +16,6 @@ jobs:
|
|
16
16
|
os: ['ubuntu-latest']
|
17
17
|
sequel: ['~>5.28']
|
18
18
|
ruby: ['3.2', '3.1', '3.0', '2.7']
|
19
|
-
gemfile: ['Gemfile']
|
20
19
|
runs-on: ${{ matrix.os }}
|
21
20
|
name: Tests with Ruby ${{ matrix.ruby }}
|
22
21
|
|
@@ -58,7 +57,7 @@ jobs:
|
|
58
57
|
|
59
58
|
env:
|
60
59
|
SEQUEL: ${{ matrix.sequel }}
|
61
|
-
BUNDLE_GEMFILE:
|
60
|
+
BUNDLE_GEMFILE: .ci.gemfile
|
62
61
|
steps:
|
63
62
|
- uses: actions/checkout@v4
|
64
63
|
|
data/CHANGELOG.md
CHANGED
@@ -11,6 +11,27 @@ Prefix your message with one of the following:
|
|
11
11
|
- [Security] in case of vulnerabilities.
|
12
12
|
-->
|
13
13
|
|
14
|
+
## v0.5.0 - 2023-10-08
|
15
|
+
|
16
|
+
- [Fixed] The conditions of migrations were clarified and fixed in README.md.
|
17
|
+
- [Added] The `delete_to_currval(name)` method for MySQL and SQLite `SEQUENCE`-table and Exceptions for any other cases.
|
18
|
+
- [Added] The `drop_sequence?` can accept multiple arguments with condition 'IF EXISTS'.
|
19
|
+
- [Added] The `create_sequence!` drops the `SEQUENCE` if it exists before attempting to create it.
|
20
|
+
- [Changed] INT type to BIGINT type for the primery key of a MySQL `SEQUENCE`-table.
|
21
|
+
- [Added] The ext. params for the PostgreSql `SEQUENCE` ( https://www.postgresql.org/docs/current/sql-createsequence.html )
|
22
|
+
- [Added] The ext. params for the Mariadb `SEQUENCE` ( https://mariadb.com/kb/en/create-sequence )
|
23
|
+
|
24
|
+
## v0.4.2 - 2023-10-03
|
25
|
+
|
26
|
+
- [Added] Additions into README.md.
|
27
|
+
- [Added] Exclusion of dependence on the Postgresql constraint for "PG::The object is not in the required state P: ERROR: currval of sequence "name_of_sequence" is not yet defined in this session".
|
28
|
+
- [Added] `custom_sequence?` method for MariaDB and SQLite.
|
29
|
+
- [Fixed] Dependencies on gems by moving them from .gemspec to Gemfile
|
30
|
+
- [Fixed] `currval` for initial state of sequence in Postgresql
|
31
|
+
- [Fixed] `lastval` for initial state of sequence in MariaDB
|
32
|
+
- [Changed] The default action `setval` for MariaDB to invoke `setval` if necessary
|
33
|
+
- [Changed] The class initialization algorithm in `sequence.rb` depending on the gems included in the user project.
|
34
|
+
|
14
35
|
## v0.4.1 - 2023-09-28
|
15
36
|
|
16
37
|
- [Added] Important notice to README.md.
|
data/CONTRIBUTING.md
CHANGED
@@ -33,13 +33,14 @@ your contribution is according to how this project works.
|
|
33
33
|
|
34
34
|
1. [Fork](https://help.github.com/forking/) sequel-sequence
|
35
35
|
2. Create a topic branch - `git checkout -b my_branch`
|
36
|
-
3.
|
37
|
-
4.
|
36
|
+
3. Unlock gem dependencies in `sequel-sequence.gemspec`
|
37
|
+
4. Make your changes using [descriptive commit messages](#commit-messages)
|
38
|
+
5. Update CHANGELOG.md describing your changes by adding an entry to the
|
38
39
|
"Unreleased" section. If this section is not available, create one right
|
39
40
|
before the last version.
|
40
|
-
|
41
|
-
|
42
|
-
|
41
|
+
6. Push to your branch - `git push origin my_branch`
|
42
|
+
7. [Create a pull request](https://docs.github.com/articles/creating-a-pull-request)
|
43
|
+
8. That's it!
|
43
44
|
|
44
45
|
## Styleguides
|
45
46
|
|
@@ -237,3 +238,12 @@ $ bundle exec rake TEST=test/sequel/mysql_sequence_test.rb
|
|
237
238
|
$ bundle exec rake TEST=test/sequel/sqlite_sequence_test.rb
|
238
239
|
$ bundle exec rake TEST=test/sequel/mock_sequence_test.rb
|
239
240
|
```
|
241
|
+
|
242
|
+
Short command:
|
243
|
+
```bash
|
244
|
+
$ bundle exec rake postgresql
|
245
|
+
$ bundle exec rake mariadb
|
246
|
+
$ bundle exec rake mysql
|
247
|
+
$ bundle exec rake sqlite
|
248
|
+
$ bundle exec rake mock
|
249
|
+
```
|
data/README.md
CHANGED
@@ -16,7 +16,7 @@ gem install sequel-sequence
|
|
16
16
|
Or add the following line to your project's Gemfile:
|
17
17
|
|
18
18
|
```ruby
|
19
|
-
gem
|
19
|
+
gem 'sequel-sequence'
|
20
20
|
```
|
21
21
|
|
22
22
|
## Usage with PostgreSQL and MariaDB
|
@@ -82,6 +82,17 @@ Sequel.migration do
|
|
82
82
|
end
|
83
83
|
```
|
84
84
|
|
85
|
+
Before running the migration for your application, don't forget to invoke `require`s, for example like this:
|
86
|
+
```ruby
|
87
|
+
require 'sequel'
|
88
|
+
require 'sequel-sequence'
|
89
|
+
|
90
|
+
migrate = -> (env, version) do
|
91
|
+
...
|
92
|
+
Sequel::Migrator.apply(DB, 'db/migrations', version)
|
93
|
+
end
|
94
|
+
```
|
95
|
+
|
85
96
|
This gem also adds a few helpers to interact with `SEQUENCE`s.
|
86
97
|
|
87
98
|
```ruby
|
@@ -95,7 +106,7 @@ DB.currval("position")
|
|
95
106
|
DB.lastval("position")
|
96
107
|
# Both options are acceptable in PostgreSQL and MySQL.
|
97
108
|
|
98
|
-
# Set sequence
|
109
|
+
# Set a new sequence value. It must be greater than lastval or currval. Only PostgreSQL allows setting a lower value.
|
99
110
|
DB.setval("position", 1234)
|
100
111
|
```
|
101
112
|
|
@@ -116,13 +127,39 @@ and
|
|
116
127
|
DB.nextval_with_label(:position, 1)
|
117
128
|
```
|
118
129
|
|
119
|
-
By default, `fiction` has a zero value.
|
130
|
+
By default, `fiction` has a zero value. Moreover, it is assumed that you can use the history of sequence changes, for example, to collect statistics on the fiction field. However, in most cases, such statistics will not be necessary and you can program periodic cleaning of the SEQUENCE table using the method:
|
131
|
+
```ruby
|
132
|
+
DB.delete_to_currval(:position)
|
133
|
+
```
|
120
134
|
|
121
135
|
Otherwise, the operation of this gem for SQLite and MySQL is similar to the ways of using Sequence in more advanced RDBMS. There is only one difference here, you won't be able to change the increment value from 1 to another using the `increment` or `step` parameter.
|
122
136
|
|
123
137
|
## Known issues you may encounter
|
124
138
|
|
125
|
-
This solution does not allow you to simultaneously work with MySQL and MariaDB databases from one application. If such a need arises, move the data processing functionality to different microservices.
|
139
|
+
- This solution does not allow you to simultaneously work with MySQL and MariaDB databases from one application. If such a need arises, move the data processing functionality to different microservices.
|
140
|
+
- When you start with a new database in SQLite, you'll receive an error message - "`SQLite3::SQLException: no such table: sqlite_sequence`". `sqlite_sequence` table is not created, until you define at least one autoincrement and primary key column in your schema.
|
141
|
+
|
142
|
+
All methods defined in this gem can use either a String or a Symbol parameter to denote a `SEQUENCE`.
|
143
|
+
```ruby
|
144
|
+
DB.nextval('position')
|
145
|
+
```
|
146
|
+
is equivalent to
|
147
|
+
```ruby
|
148
|
+
DB.nextval(:position)
|
149
|
+
```
|
150
|
+
- This solution allows you to specify advanced options for a `SEQUENCE` when creating it in PostgreSQL and MariaDB. For more information, check out the description at https://www.postgresql.org/docs/current/sql-createsequence.html and https://mariadb.com/kb/en/create-sequence.
|
151
|
+
|
152
|
+
## Additional handy methods:
|
153
|
+
|
154
|
+
To discover a database information about `SEQUENCE`s you could take advantage of `check_sequences` and `custom_sequence?` methods.
|
155
|
+
- `custom_sequence?(:sequence_name)` allows you to instantly find out the availability of the called `SEQUENCE`.
|
156
|
+
- `check_sequences` provides complete information about known `SEQUENCE`s in the datebase. The output data depends on RDBMS.
|
157
|
+
|
158
|
+
To remove several sequences at once, you can use the method:
|
159
|
+
- `drop_sequence?` can accept multiple arguments of `SEQUENCE`s and checks the `IF EXISTS` condition for each one.
|
160
|
+
|
161
|
+
To drop previous `SEQUENCE` and recreate the new one utilize the method:
|
162
|
+
- `create_sequence!`.
|
126
163
|
|
127
164
|
## Maintainer
|
128
165
|
|
@@ -7,8 +7,6 @@ module Sequel
|
|
7
7
|
module Sequence
|
8
8
|
module Database
|
9
9
|
module PostgreSQL
|
10
|
-
SEQUENCE_COMMENT = 'created by sequel-sequence'
|
11
|
-
|
12
10
|
def quote_column_name(name)
|
13
11
|
PG::Connection.quote_ident(name).freeze
|
14
12
|
end
|
@@ -27,7 +25,7 @@ module Sequel
|
|
27
25
|
return false
|
28
26
|
end
|
29
27
|
|
30
|
-
out == SEQUENCE_COMMENT
|
28
|
+
out == Sequel::Database::SEQUENCE_COMMENT
|
31
29
|
end
|
32
30
|
|
33
31
|
def check_sequences
|
@@ -35,23 +33,37 @@ module Sequel
|
|
35
33
|
end
|
36
34
|
|
37
35
|
def create_sequence(name, options = {})
|
36
|
+
data_type = options[:data_type]
|
37
|
+
minvalue = options[:minvalue]
|
38
|
+
maxvalue = options[:maxvalue]
|
39
|
+
start = options[:start]
|
40
|
+
cache = options[:cache]
|
41
|
+
cycle = options[:cycle]
|
42
|
+
owned_by = options[:owned_by]
|
43
|
+
|
38
44
|
increment = options[:increment] || options[:step]
|
39
45
|
if_exists = build_exists_condition(options[:if_exists])
|
40
46
|
name = quote_name(name.to_s)
|
41
47
|
|
42
48
|
sql = ["CREATE SEQUENCE #{if_exists} #{name}"]
|
49
|
+
sql << "AS #{data_type}" if data_type
|
43
50
|
sql << "INCREMENT BY #{increment}" if increment
|
44
|
-
sql << "
|
51
|
+
sql << "MINVALUE #{minvalue}" if minvalue
|
52
|
+
sql << "MAXVALUE #{maxvalue}" if maxvalue
|
53
|
+
sql << "START WITH #{start}" if start
|
54
|
+
sql << "CACHE #{cache}" if cache
|
55
|
+
sql << cycle.to_s if cycle
|
56
|
+
sql << "OWNED BY #{owned_by}" if owned_by
|
45
57
|
sql << ';'
|
46
|
-
sql << "COMMENT ON SEQUENCE #{name} IS '#{SEQUENCE_COMMENT}';"
|
58
|
+
sql << "COMMENT ON SEQUENCE #{name} IS '#{Sequel::Database::SEQUENCE_COMMENT}';"
|
47
59
|
|
48
60
|
run(sql.join("\n"))
|
49
61
|
end
|
50
62
|
|
51
|
-
def drop_sequence(name)
|
63
|
+
def drop_sequence(name, options = {})
|
64
|
+
if_exists = build_exists_condition(options[:if_exists])
|
52
65
|
name = quote_name(name.to_s)
|
53
|
-
|
54
|
-
run(sql)
|
66
|
+
run drop_sequence_table(name, if_exists)
|
55
67
|
end
|
56
68
|
|
57
69
|
def nextval(name)
|
@@ -65,12 +77,21 @@ module Sequel
|
|
65
77
|
|
66
78
|
# for Postgres
|
67
79
|
def currval(name)
|
68
|
-
|
80
|
+
quoted_name = quote(name.to_s)
|
69
81
|
out = nil
|
70
|
-
fetch("SELECT currval(#{
|
82
|
+
fetch("SELECT currval(#{quoted_name})") do |row|
|
71
83
|
out = row[:currval]
|
72
84
|
end
|
73
85
|
out
|
86
|
+
rescue Sequel::DatabaseError => e
|
87
|
+
# We exclude dependence on the postgresql constraint.
|
88
|
+
if e.message =~ /\APG::ObjectNotInPrerequisiteState:(.)*is not yet defined in this session\n\z/
|
89
|
+
return nextval(name)
|
90
|
+
end
|
91
|
+
|
92
|
+
# :nocov:
|
93
|
+
raise e
|
94
|
+
# :nocov:
|
74
95
|
end
|
75
96
|
|
76
97
|
# for MariaDB
|
@@ -86,11 +107,18 @@ module Sequel
|
|
86
107
|
end
|
87
108
|
|
88
109
|
def set_column_default_nextval(table, column, sequence)
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
110
|
+
sql = %(
|
111
|
+
ALTER TABLE IF EXISTS #{table}
|
112
|
+
ALTER COLUMN #{quote_name(column.to_s)}
|
113
|
+
SET DEFAULT nextval(#{quote(sequence.to_s)}::regclass)
|
114
|
+
).strip
|
115
|
+
run sql
|
116
|
+
end
|
117
|
+
|
118
|
+
private
|
119
|
+
|
120
|
+
def drop_sequence_table(name, if_exists = nil)
|
121
|
+
"DROP SEQUENCE #{if_exists || Sequel::Database::IF_EXISTS} #{name};"
|
94
122
|
end
|
95
123
|
end
|
96
124
|
end
|
@@ -13,27 +13,46 @@ module Sequel
|
|
13
13
|
"`#{name.gsub(/[`"']/, '')}`"
|
14
14
|
end
|
15
15
|
|
16
|
+
def custom_sequence?(sequence_name)
|
17
|
+
db = name_of_current_database
|
18
|
+
return false if db.empty?
|
19
|
+
|
20
|
+
sql = "SHOW FULL TABLES WHERE Table_type = 'SEQUENCE' and Tables_in_#{db} = '#{sequence_name}';"
|
21
|
+
fetch(sql).all.size.positive?
|
22
|
+
end
|
23
|
+
|
16
24
|
def check_sequences
|
17
25
|
fetch("SHOW FULL TABLES WHERE Table_type = 'SEQUENCE';").all.to_a
|
18
26
|
end
|
19
27
|
|
20
28
|
def create_sequence(name, options = {})
|
29
|
+
minvalue = options[:minvalue]
|
30
|
+
maxvalue = options[:maxvalue]
|
31
|
+
start = options[:start]
|
32
|
+
cache = options[:cache]
|
33
|
+
cycle = options[:cycle]
|
34
|
+
|
21
35
|
increment = options[:increment] || options[:step]
|
22
36
|
if_exists = build_exists_condition(options[:if_exists])
|
23
37
|
name = quote_name(name.to_s)
|
24
38
|
|
25
39
|
sql = ["CREATE SEQUENCE #{if_exists || Sequel::Database::IF_NOT_EXISTS} #{name}"]
|
26
40
|
sql << "INCREMENT BY #{increment}" if increment
|
27
|
-
sql << "
|
41
|
+
sql << "MINVALUE #{minvalue}" if minvalue
|
42
|
+
sql << "MAXVALUE #{maxvalue}" if maxvalue
|
43
|
+
sql << "START WITH #{start}" if start
|
44
|
+
sql << "CACHE #{cache}" if cache
|
45
|
+
sql << cycle.to_s if cycle
|
46
|
+
sql << "COMMENT '#{Sequel::Database::SEQUENCE_COMMENT}'"
|
28
47
|
sql << ';'
|
29
48
|
|
30
49
|
run(sql.join("\n"))
|
31
50
|
end
|
32
51
|
|
33
|
-
def drop_sequence(name)
|
52
|
+
def drop_sequence(name, options = {})
|
53
|
+
if_exists = build_exists_condition(options[:if_exists])
|
34
54
|
name = quote_name(name.to_s)
|
35
|
-
|
36
|
-
run(sql)
|
55
|
+
run drop_sequence_table(name, if_exists)
|
37
56
|
end
|
38
57
|
|
39
58
|
def nextval(name)
|
@@ -46,31 +65,52 @@ module Sequel
|
|
46
65
|
end
|
47
66
|
|
48
67
|
def lastval(name)
|
49
|
-
|
68
|
+
quoted_name = quote(name.to_s)
|
50
69
|
out = nil
|
51
|
-
fetch("SELECT lastval(#{
|
52
|
-
out = row["lastval(#{
|
70
|
+
fetch("SELECT lastval(#{quoted_name});") do |row|
|
71
|
+
out = row["lastval(#{quoted_name})".to_sym]
|
53
72
|
end
|
73
|
+
return nextval(name) if out.nil?
|
74
|
+
|
54
75
|
out
|
55
76
|
end
|
56
77
|
|
57
78
|
alias currval lastval
|
58
79
|
|
59
80
|
def setval(name, value)
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
81
|
+
current = lastval(name)
|
82
|
+
if value <= current
|
83
|
+
log_info Sequel::Database::DANGER_OPT_ID if value < current
|
84
|
+
value = current
|
85
|
+
else
|
86
|
+
quoted_name = quote(name.to_s)
|
87
|
+
value -= 1
|
88
|
+
out = nil
|
89
|
+
fetch("SELECT setval(#{quoted_name}, #{value});") do |row|
|
90
|
+
out = row["setval(#{quoted_name}, #{value})".to_sym]
|
91
|
+
end
|
92
|
+
value = nextval(name)
|
64
93
|
end
|
65
|
-
|
94
|
+
value
|
66
95
|
end
|
67
96
|
|
68
97
|
def set_column_default_nextval(table, column, sequence)
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
98
|
+
sql = %(
|
99
|
+
ALTER TABLE IF EXISTS #{quote(table.to_s)}
|
100
|
+
ALTER COLUMN #{quote_name(column.to_s)}
|
101
|
+
SET DEFAULT nextval(#{quote(sequence.to_s)})
|
102
|
+
).strip
|
103
|
+
run sql
|
104
|
+
end
|
105
|
+
|
106
|
+
private
|
107
|
+
|
108
|
+
def name_of_current_database
|
109
|
+
fetch('SELECT DATABASE() AS db;').first[:db]
|
110
|
+
end
|
111
|
+
|
112
|
+
def drop_sequence_table(name, if_exists = nil)
|
113
|
+
"DROP SEQUENCE #{if_exists || Sequel::Database::IF_EXISTS} #{name};"
|
74
114
|
end
|
75
115
|
end
|
76
116
|
end
|
@@ -60,7 +60,7 @@ module Sequel
|
|
60
60
|
alias currval lastval
|
61
61
|
|
62
62
|
def setval(name, value)
|
63
|
-
current = lastval(
|
63
|
+
current = lastval(name)
|
64
64
|
if current.nil?
|
65
65
|
create_sequence(stringify(name), { start: value })
|
66
66
|
elsif value < current
|
@@ -75,12 +75,16 @@ module Sequel
|
|
75
75
|
end
|
76
76
|
|
77
77
|
def set_column_default_nextval(table, column, sequence)
|
78
|
-
run
|
79
|
-
|
80
|
-
|
81
|
-
run
|
82
|
-
|
83
|
-
|
78
|
+
run trigger_create_sequenced_column(stringify(table),
|
79
|
+
stringify(column),
|
80
|
+
stringify(sequence))
|
81
|
+
run trigger_update_sequenced_column(stringify(table),
|
82
|
+
stringify(column),
|
83
|
+
stringify(sequence))
|
84
|
+
end
|
85
|
+
|
86
|
+
def delete_to_currval(name)
|
87
|
+
run delete_to_current_seq(stringify(name))
|
84
88
|
end
|
85
89
|
|
86
90
|
private
|
@@ -97,8 +101,8 @@ module Sequel
|
|
97
101
|
def create_sequence_table(name, if_exists = nil)
|
98
102
|
%(
|
99
103
|
CREATE TABLE #{if_exists || Sequel::Database::IF_NOT_EXISTS} #{name}
|
100
|
-
(id
|
101
|
-
fiction
|
104
|
+
(id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
105
|
+
fiction BIGINT);
|
102
106
|
).strip
|
103
107
|
end
|
104
108
|
|
@@ -109,7 +113,7 @@ module Sequel
|
|
109
113
|
def create_mysql_sequence
|
110
114
|
%(
|
111
115
|
CREATE TABLE #{Sequel::Database::IF_NOT_EXISTS} mysql_sequence
|
112
|
-
(name VARCHAR(40), seq
|
116
|
+
(name VARCHAR(40), seq BIGINT);
|
113
117
|
).strip
|
114
118
|
end
|
115
119
|
|
@@ -147,7 +151,7 @@ module Sequel
|
|
147
151
|
"INSERT INTO mysql_sequence (name, seq) VALUES ('#{name}', LAST_INSERT_ID());"
|
148
152
|
end
|
149
153
|
|
150
|
-
def
|
154
|
+
def trigger_create_sequenced_column(table, _column, sequence)
|
151
155
|
%(
|
152
156
|
CREATE TRIGGER IF NOT EXISTS #{table}_#{sequence} BEFORE INSERT
|
153
157
|
ON #{table}
|
@@ -160,7 +164,7 @@ module Sequel
|
|
160
164
|
).strip
|
161
165
|
end
|
162
166
|
|
163
|
-
def
|
167
|
+
def trigger_update_sequenced_column(table, column, sequence)
|
164
168
|
%(
|
165
169
|
CREATE TRIGGER IF NOT EXISTS #{table}_#{column} BEFORE INSERT
|
166
170
|
ON #{table}
|
@@ -178,6 +182,10 @@ module Sequel
|
|
178
182
|
raise e
|
179
183
|
# :nocov:
|
180
184
|
end
|
185
|
+
|
186
|
+
def delete_to_current_seq(name)
|
187
|
+
"DELETE QUICK IGNORE FROM #{name} WHERE id < (SELECT * FROM (SELECT MAX(id) FROM #{name} ) AS a);"
|
188
|
+
end
|
181
189
|
end
|
182
190
|
end
|
183
191
|
end
|
@@ -6,6 +6,11 @@ module Sequel
|
|
6
6
|
module Sequence
|
7
7
|
module Database
|
8
8
|
module SQLite
|
9
|
+
def custom_sequence?(sequence_name)
|
10
|
+
sql = "SELECT * FROM `sqlite_sequence` WHERE name = '#{stringify(sequence_name)}';"
|
11
|
+
fetch(sql).all.size.positive?
|
12
|
+
end
|
13
|
+
|
9
14
|
def check_sequences
|
10
15
|
fetch('SELECT * FROM `sqlite_sequence`;').all.to_a
|
11
16
|
end
|
@@ -44,11 +49,11 @@ module Sequel
|
|
44
49
|
alias currval lastval
|
45
50
|
|
46
51
|
def setval(name, value)
|
47
|
-
current = lastval(
|
52
|
+
current = lastval(name)
|
48
53
|
if current.nil?
|
49
54
|
create_sequence(stringify(name), { start: value })
|
50
55
|
elsif value < current
|
51
|
-
log_info DANGER_OPT_ID
|
56
|
+
log_info Sequel::Database::DANGER_OPT_ID
|
52
57
|
value = current
|
53
58
|
else
|
54
59
|
run(update_sqlite_sequence(stringify(name), value))
|
@@ -57,9 +62,13 @@ module Sequel
|
|
57
62
|
end
|
58
63
|
|
59
64
|
def set_column_default_nextval(table, column, sequence)
|
60
|
-
run(
|
61
|
-
|
62
|
-
|
65
|
+
run(trigger_create_sequenced_column(stringify(table),
|
66
|
+
stringify(column),
|
67
|
+
stringify(sequence)))
|
68
|
+
end
|
69
|
+
|
70
|
+
def delete_to_currval(name)
|
71
|
+
run delete_to_current_seq(stringify(name))
|
63
72
|
end
|
64
73
|
|
65
74
|
private
|
@@ -79,7 +88,7 @@ module Sequel
|
|
79
88
|
|
80
89
|
def create_sequence_table(name, if_exists = nil)
|
81
90
|
%(
|
82
|
-
CREATE TABLE #{if_exists || IF_NOT_EXISTS} #{name}
|
91
|
+
CREATE TABLE #{if_exists || Sequel::Database::IF_NOT_EXISTS} #{name}
|
83
92
|
(id integer primary key autoincrement, fiction integer);
|
84
93
|
)
|
85
94
|
end
|
@@ -101,14 +110,14 @@ module Sequel
|
|
101
110
|
end
|
102
111
|
|
103
112
|
def drop_sequence_table(name, if_exists = nil)
|
104
|
-
"DROP TABLE #{if_exists || IF_EXISTS} #{name};"
|
113
|
+
"DROP TABLE #{if_exists || Sequel::Database::IF_EXISTS} #{name};"
|
105
114
|
end
|
106
115
|
|
107
116
|
def select_max_seq(name)
|
108
117
|
"SELECT MAX(seq) AS id FROM sqlite_sequence WHERE name = '#{name}';"
|
109
118
|
end
|
110
119
|
|
111
|
-
def
|
120
|
+
def trigger_create_sequenced_column(table, column, sequence)
|
112
121
|
%(
|
113
122
|
CREATE TRIGGER IF NOT EXISTS #{table}_#{sequence} AFTER INSERT
|
114
123
|
ON #{table}
|
@@ -120,6 +129,10 @@ module Sequel
|
|
120
129
|
END;
|
121
130
|
)
|
122
131
|
end
|
132
|
+
|
133
|
+
def delete_to_current_seq(name)
|
134
|
+
"DELETE FROM #{name} WHERE id < (SELECT MAX(id) FROM #{name});"
|
135
|
+
end
|
123
136
|
end
|
124
137
|
end
|
125
138
|
end
|
@@ -7,6 +7,7 @@ module Sequel
|
|
7
7
|
DANGER_OPT_INCREMENT = 'Warning! Increments greater than 1 are not supported.'
|
8
8
|
IF_EXISTS = 'IF EXISTS'
|
9
9
|
IF_NOT_EXISTS = 'IF NOT EXISTS'
|
10
|
+
SEQUENCE_COMMENT = 'created by sequel-sequence'
|
10
11
|
|
11
12
|
def check_options(params)
|
12
13
|
log_info DANGER_OPT_INCREMENT if params[:increment] && params[:increment] != 1
|
@@ -73,6 +74,22 @@ module Sequel
|
|
73
74
|
IF_NOT_EXISTS
|
74
75
|
end
|
75
76
|
end
|
77
|
+
|
78
|
+
def delete_to_currval(_name)
|
79
|
+
raise Sequel::MethodNotAllowed, Sequel::Database::METHOD_NOT_ALLOWED
|
80
|
+
end
|
81
|
+
|
82
|
+
def drop_sequence?(*names)
|
83
|
+
names.each do |n|
|
84
|
+
drop_sequence(n, if_exists: true)
|
85
|
+
end
|
86
|
+
false
|
87
|
+
end
|
88
|
+
|
89
|
+
def create_sequence!(name, options = nil)
|
90
|
+
drop_sequence(name, if_exists: true)
|
91
|
+
create_sequence(name, options)
|
92
|
+
end
|
76
93
|
end
|
77
94
|
end
|
78
95
|
end
|