sequel-sequence 0.1.0 → 0.3.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 +4 -4
- data/.github/ISSUE_TEMPLATE/bug_report.md +41 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +23 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +38 -0
- data/.github/dependabot.yml +14 -0
- data/.github/workflows/ci.yml +97 -0
- data/.gitignore +8 -2
- data/.rubocop.yml +37 -0
- data/CHANGELOG.md +14 -0
- data/CONTRIBUTING.md +29 -8
- data/README.md +31 -12
- data/lib/sequel/sequence/database/mysql2.rb +3 -2
- data/lib/sequel/sequence/database/postgresql.rb +3 -2
- data/lib/sequel/sequence/database/sqlite.rb +132 -0
- data/lib/sequel/sequence/database.rb +37 -6
- data/lib/sequel/sequence/version.rb +1 -1
- data/lib/sequel/sequence.rb +5 -0
- data/sequel-sequence.gemspec +14 -12
- data/test/mysql_test_helper.rb +16 -12
- data/test/postgresql_test_helper.rb +16 -12
- data/test/sequel/mysql_sequence_test.rb +70 -60
- data/test/sequel/postgresql_sequence_test.rb +66 -60
- data/test/sequel/sqlite_sequence_test.rb +257 -0
- data/test/sqlite_test_helper.rb +29 -0
- metadata +64 -34
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c7012e03aa326861bef294edcf042850f662f9122664da409aa0dd764d9375d9
|
4
|
+
data.tar.gz: b309b36a931be17ee7cb628c21083ef8543bb60139a249aa9fd1d42378321297
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7c13a9a6e000990aaee2bdcca4d3d7519a7164c3217d4164f35e40e43deb76f652215169396647568cb03cf111d2a103f2f0f5d5f45e174b8107588e4be1808f
|
7
|
+
data.tar.gz: e9483ab69ea26d780164a4e4683d75c2bd86d8c5d92983b506645c5544a3ebc277f25f12a463b1f959f675f0e780eaf3b22a82b9560e247f16f2a895518d0e53
|
@@ -0,0 +1,41 @@
|
|
1
|
+
---
|
2
|
+
name: "🐛 Bug Report"
|
3
|
+
about: Report a reproducible bug or regression.
|
4
|
+
title: 'Bug: '
|
5
|
+
labels: 'Status: Unconfirmed'
|
6
|
+
|
7
|
+
---
|
8
|
+
|
9
|
+
<!--
|
10
|
+
- Please provide a clear and concise description of what the bug is.
|
11
|
+
- If possible, add an example reproducing your issue.
|
12
|
+
- Please test using the latest version of ar-sequence
|
13
|
+
to make sure your issue has not already been fixed.
|
14
|
+
-->
|
15
|
+
|
16
|
+
## Description
|
17
|
+
|
18
|
+
[Add bug description here]
|
19
|
+
|
20
|
+
## How to reproduce
|
21
|
+
|
22
|
+
[Add steps on how to reproduce this issue]
|
23
|
+
|
24
|
+
## What do you expect
|
25
|
+
|
26
|
+
[Describe what do you expect to happen]
|
27
|
+
|
28
|
+
## What happened instead
|
29
|
+
|
30
|
+
[Describe the actual results]
|
31
|
+
|
32
|
+
## Software:
|
33
|
+
|
34
|
+
- Gem version: [Add gem version here]
|
35
|
+
- Ruby version: [Add version here]
|
36
|
+
|
37
|
+
## Full backtrace
|
38
|
+
|
39
|
+
```text
|
40
|
+
[Paste full backtrace here]
|
41
|
+
```
|
@@ -0,0 +1,23 @@
|
|
1
|
+
---
|
2
|
+
name: "💡 Feature request"
|
3
|
+
about: Have an idea that may be useful? Make a suggestion!
|
4
|
+
title: 'Feature Request: '
|
5
|
+
labels: 'Feature request'
|
6
|
+
|
7
|
+
---
|
8
|
+
|
9
|
+
## Description
|
10
|
+
|
11
|
+
_A clear and concise description of what the problem is._
|
12
|
+
|
13
|
+
## Describe the solution
|
14
|
+
|
15
|
+
_A clear and concise description of what you want to happen._
|
16
|
+
|
17
|
+
## Alternatives you considered
|
18
|
+
|
19
|
+
_A clear and concise description of any alternative solutions or features you've considered._
|
20
|
+
|
21
|
+
## Additional context
|
22
|
+
|
23
|
+
_Add any other context, screenshots, links, etc about the feature request here._
|
@@ -0,0 +1,38 @@
|
|
1
|
+
<!--
|
2
|
+
If you're making a doc PR or something tiny where the below is irrelevant,
|
3
|
+
delete this template and use a short description, but in your description aim to
|
4
|
+
include both what the change is, and why it is being made, with enough context
|
5
|
+
for anyone to understand.
|
6
|
+
-->
|
7
|
+
|
8
|
+
<details>
|
9
|
+
<summary>PR Checklist</summary>
|
10
|
+
|
11
|
+
### PR Structure
|
12
|
+
|
13
|
+
- [ ] This PR has reasonably narrow scope (if not, break it down into smaller
|
14
|
+
PRs).
|
15
|
+
- [ ] This PR avoids mixing refactoring changes with feature changes (split into
|
16
|
+
two PRs otherwise).
|
17
|
+
- [ ] This PR's title starts is concise and descriptive.
|
18
|
+
|
19
|
+
### Thoroughness
|
20
|
+
|
21
|
+
- [ ] This PR adds tests for the most critical parts of the new functionality or
|
22
|
+
fixes.
|
23
|
+
- [ ] I've updated any docs, `.md` files, etc… affected by this change.
|
24
|
+
|
25
|
+
</details>
|
26
|
+
|
27
|
+
### What
|
28
|
+
|
29
|
+
[TODO: Short statement about what is changing.]
|
30
|
+
|
31
|
+
### Why
|
32
|
+
|
33
|
+
[TODO: Why this change is being made. Include any context required to understand
|
34
|
+
the why.]
|
35
|
+
|
36
|
+
### Known limitations
|
37
|
+
|
38
|
+
[TODO or N/A]
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# Documentation:
|
2
|
+
# https://docs.github.com/en/free-pro-team@latest/github/administering-a-repository/configuration-options-for-dependency-updates
|
3
|
+
|
4
|
+
version: 2
|
5
|
+
updates:
|
6
|
+
- package-ecosystem: "github-actions"
|
7
|
+
directory: "/"
|
8
|
+
schedule:
|
9
|
+
interval: "monthly"
|
10
|
+
|
11
|
+
- package-ecosystem: "bundler"
|
12
|
+
directory: "/"
|
13
|
+
schedule:
|
14
|
+
interval: "monthly"
|
@@ -0,0 +1,97 @@
|
|
1
|
+
name: CI
|
2
|
+
|
3
|
+
on:
|
4
|
+
workflow_dispatch:
|
5
|
+
inputs: {}
|
6
|
+
push:
|
7
|
+
branches: [ master ]
|
8
|
+
pull_request:
|
9
|
+
branches: ['**']
|
10
|
+
|
11
|
+
jobs:
|
12
|
+
tests:
|
13
|
+
strategy:
|
14
|
+
fail-fast: false
|
15
|
+
matrix:
|
16
|
+
os: ['ubuntu-latest']
|
17
|
+
sequel: ['~>5.28']
|
18
|
+
ruby: ['3.2', '3.1', '3.0', '2.7']
|
19
|
+
gemfile: ['Gemfile']
|
20
|
+
runs-on: ${{ matrix.os }}
|
21
|
+
name: Tests with Ruby ${{ matrix.ruby }}
|
22
|
+
|
23
|
+
services:
|
24
|
+
postgres:
|
25
|
+
image: postgres:13
|
26
|
+
env:
|
27
|
+
POSTGRES_USER: postgres
|
28
|
+
POSTGRES_PASSWORD: postgres
|
29
|
+
ports:
|
30
|
+
- 5432:5432
|
31
|
+
options: >-
|
32
|
+
--health-cmd pg_isready
|
33
|
+
--health-interval 10s
|
34
|
+
--health-timeout 5s
|
35
|
+
--health-retries 5
|
36
|
+
mysql:
|
37
|
+
image: mariadb:11.1
|
38
|
+
env:
|
39
|
+
MARIADB_ROOT_PASSWORD: root
|
40
|
+
ports:
|
41
|
+
- 3306:3306
|
42
|
+
options: >-
|
43
|
+
--health-cmd="healthcheck.sh --connect --innodb_initialized"
|
44
|
+
--health-interval 10s
|
45
|
+
--health-timeout 5s
|
46
|
+
--health-retries 3
|
47
|
+
|
48
|
+
env:
|
49
|
+
SEQUEL: ${{ matrix.sequel }}
|
50
|
+
BUNDLE_GEMFILE: ${{ matrix.gemfile }}
|
51
|
+
steps:
|
52
|
+
- uses: actions/checkout@v4
|
53
|
+
|
54
|
+
- name: Install db dependencies and check connections
|
55
|
+
run: |
|
56
|
+
DEBIAN_FRONTEND="noninteractive" sudo apt-get install -yqq mysql-client libmysqlclient-dev postgresql-client libpq-dev
|
57
|
+
mysql --host 127.0.0.1 --port ${{ job.services.mysql.ports[3306] }} -uroot -proot -e "SHOW GRANTS FOR 'root'@'localhost'"
|
58
|
+
env PGPASSWORD=postgres psql -h localhost -p ${{ job.services.postgres.ports[5432] }} -U postgres -l
|
59
|
+
sqlite3 --version
|
60
|
+
|
61
|
+
- name: Set up Ruby
|
62
|
+
uses: ruby/setup-ruby@v1
|
63
|
+
with:
|
64
|
+
ruby-version: ${{ matrix.ruby }}
|
65
|
+
bundler-cache: true
|
66
|
+
|
67
|
+
- name: Create MySQL database
|
68
|
+
run: |
|
69
|
+
mysql -e 'create database test; use test; create table if not exists wares(id int auto_increment, primary key(id)); create table if not exists builders(id int auto_increment, primary key(id));' --host 127.0.0.1 --port ${{ job.services.mysql.ports[3306] }} -uroot -proot
|
70
|
+
|
71
|
+
- name: Create PostgreSQL database
|
72
|
+
env:
|
73
|
+
PGPASSWORD: postgres
|
74
|
+
run: |
|
75
|
+
psql -c 'create database "test";' -U postgres -h localhost -p ${{ job.services.postgres.ports[5432] }}
|
76
|
+
|
77
|
+
- name: Create SQLite database
|
78
|
+
run: |
|
79
|
+
mkdir ./db && touch ./db/test.sqlite3 && sqlite3 ./db/test.sqlite3
|
80
|
+
|
81
|
+
- name: Run Tests
|
82
|
+
run: bundle exec rake test
|
83
|
+
env:
|
84
|
+
TEST_POSTGRES_DATABASE: test
|
85
|
+
TEST_POSTGRES_HOST: localhost
|
86
|
+
TEST_POSTGRES_PORT: ${{ job.services.postgres.ports[5432] }}
|
87
|
+
TEST_POSTGRES_USERNAME: postgres
|
88
|
+
TEST_POSTGRES_PASSWORD: postgres
|
89
|
+
TEST_MYSQL_DATABASE: test
|
90
|
+
TEST_MYSQL_HOST: 127.0.0.1
|
91
|
+
TEST_MYSQL_PORT: ${{ job.services.mysql.ports[3306] }}
|
92
|
+
TEST_MYSQL_USERNAME: root
|
93
|
+
TEST_MYSQL_PASSWORD: root
|
94
|
+
TEST_SQLITE_DATABASE: "db/test.sqlite3"
|
95
|
+
|
96
|
+
- name: Run Rubocop
|
97
|
+
run: bundle exec rake rubocop
|
data/.gitignore
CHANGED
data/.rubocop.yml
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
AllCops:
|
2
|
+
TargetRubyVersion: 2.7
|
3
|
+
NewCops: enable
|
4
|
+
SuggestExtensions:
|
5
|
+
rubocop-rake: false
|
6
|
+
|
7
|
+
Naming/FileName:
|
8
|
+
Enabled: false
|
9
|
+
|
10
|
+
Metrics/MethodLength:
|
11
|
+
Enabled: false
|
12
|
+
|
13
|
+
Metrics/ClassLength:
|
14
|
+
Exclude:
|
15
|
+
- test/**/*
|
16
|
+
|
17
|
+
Metrics/AbcSize:
|
18
|
+
Enabled: false
|
19
|
+
|
20
|
+
Metrics/CyclomaticComplexity:
|
21
|
+
Enabled: false
|
22
|
+
|
23
|
+
Metrics/PerceivedComplexity:
|
24
|
+
Enabled: false
|
25
|
+
|
26
|
+
Gemspec/RequireMFA:
|
27
|
+
Enabled: false
|
28
|
+
|
29
|
+
Gemspec/DevelopmentDependencies:
|
30
|
+
EnforcedStyle: gemspec
|
31
|
+
|
32
|
+
Style/Documentation:
|
33
|
+
Enabled: false
|
34
|
+
|
35
|
+
Lint/ConstantDefinitionInBlock:
|
36
|
+
Exclude:
|
37
|
+
- test/**/*
|
data/CHANGELOG.md
CHANGED
@@ -11,6 +11,20 @@ Prefix your message with one of the following:
|
|
11
11
|
- [Security] in case of vulnerabilities.
|
12
12
|
-->
|
13
13
|
|
14
|
+
## v0.3.0 - 2023-09-21
|
15
|
+
|
16
|
+
- [Added] A parametrized 'IF EXISTS' condition into the drop_sequence.
|
17
|
+
- [Added] A parametrized 'IF NOT EXISTS' condition into the create_sequence.
|
18
|
+
- [Added] Gem API support for SQLite databases.
|
19
|
+
- [Fixed] Tests for the Mysql database.
|
20
|
+
|
21
|
+
## v0.2.0 - 2023-09-14
|
22
|
+
|
23
|
+
- [Added] CI features based on GitHub Actions.
|
24
|
+
- [Fixed] README.md
|
25
|
+
- [Changed] Unit tests.
|
26
|
+
- [Fixed] Sequel::Sequence::Database exceptions.
|
27
|
+
|
14
28
|
## v0.1.0 - 2023-09-10
|
15
29
|
|
16
30
|
- Initial release.
|
data/CONTRIBUTING.md
CHANGED
@@ -9,7 +9,7 @@ changes to this document in a pull request.
|
|
9
9
|
## Code of Conduct
|
10
10
|
|
11
11
|
Everyone interacting in this project's codebases, issue trackers, chat rooms and
|
12
|
-
mailing lists is expected to follow the [code of conduct](https://github.com/
|
12
|
+
mailing lists is expected to follow the [code of conduct](https://github.com/oreol-group/sequel-sequence/blob/master/CODE_OF_CONDUCT.md).
|
13
13
|
|
14
14
|
## Reporting bugs
|
15
15
|
|
@@ -26,7 +26,7 @@ the behavior, and find related reports.
|
|
26
26
|
## Contributing with code
|
27
27
|
|
28
28
|
Before making any radicals changes, please make sure you discuss your intention
|
29
|
-
by [opening an issue on Github](https://github.com/
|
29
|
+
by [opening an issue on Github](https://github.com/oreol-group/sequel-sequence/issues).
|
30
30
|
|
31
31
|
When you're ready to make your pull request, follow checklist below to make sure
|
32
32
|
your contribution is according to how this project works.
|
@@ -81,11 +81,22 @@ test=# \dt
|
|
81
81
|
--------+---------+-------+-----------
|
82
82
|
public | masters | table | USER_NAME
|
83
83
|
public | things | table | USER_NAME
|
84
|
-
(2 rows)
|
85
84
|
```
|
86
|
-
|
85
|
+
and role `postgres`
|
86
|
+
```bash
|
87
|
+
psql -d test -c 'SELECT rolname FROM pg_roles;'
|
88
|
+
rolname
|
89
|
+
---------------------------
|
90
|
+
postgres
|
91
|
+
```
|
92
|
+
- If none of them exist, create role
|
93
|
+
```bash
|
94
|
+
psql -d postgres -c "create role postgres superuser createdb login password 'postgres';"
|
95
|
+
```
|
96
|
+
and database with a couple of tables:
|
97
|
+
|
87
98
|
```bash
|
88
|
-
sudo psql -U
|
99
|
+
sudo psql -U postgres -d postgres
|
89
100
|
postgres=# CREATE DATABASE test;
|
90
101
|
postgres=# \c test
|
91
102
|
test=# CREATE TABLE IF NOT EXISTS things ();
|
@@ -104,7 +115,6 @@ MariaDB [test]> SHOW TABLES;
|
|
104
115
|
| builders |
|
105
116
|
| wares |
|
106
117
|
+----------------------+
|
107
|
-
4 rows in set (0.001 sec)
|
108
118
|
```
|
109
119
|
- If it doesn't exists, create one with a couple of tables:
|
110
120
|
```bash
|
@@ -113,8 +123,19 @@ MariaDB [(none)]> USE test;
|
|
113
123
|
MariaDB [test]> CREATE TABLE IF NOT EXISTS wares(id int auto_increment, primary key(id));
|
114
124
|
MariaDB [test]> CREATE TABLE IF NOT EXISTS builders(id int auto_increment, primary key(id));
|
115
125
|
```
|
126
|
+
- Add a test SQLite database:
|
127
|
+
```bash
|
128
|
+
mkdir db && touch db/test.sqlite3
|
129
|
+
```
|
130
|
+
- Add a couple of tables in the SQLite database:
|
131
|
+
```bash
|
132
|
+
sqlite3 db/test.sqlite3
|
133
|
+
sqlite> create table objects(id integer primary key autoincrement);
|
134
|
+
sqlite> create table apprentices(id integer primary key autoincrement);
|
135
|
+
```
|
116
136
|
- Run the tests separately:
|
117
137
|
```bash
|
118
|
-
bundle exec rake TEST=test/
|
119
|
-
bundle exec rake TEST=test/
|
138
|
+
bundle exec rake TEST=test/sequel/postgresql_sequence_test.rb
|
139
|
+
bundle exec rake TEST=test/sequel/mysql_sequence_test.rb
|
140
|
+
bundle exec rake TEST=test/sequel/sqlite_sequence_test.rb
|
120
141
|
```
|
data/README.md
CHANGED
@@ -1,10 +1,11 @@
|
|
1
1
|
# sequel-sequence
|
2
2
|
|
3
|
-
[](https://github.com/oreol-group/sequel-sequence)
|
4
4
|
[](https://rubygems.org/gems/sequel-sequence)
|
5
|
-
[](https://rubygems.org/
|
5
|
+
[](https://rubygems.org/profiles/it_architect)
|
6
|
+
[](https://codeclimate.com/github/Oreol-Group/sequel-sequence)
|
6
7
|
|
7
|
-
Adds a useful interface and support for PostgreSQL and MySQL `SEQUENCE` on Sequel migrations
|
8
|
+
Adds a useful interface and support for PostgreSQL and MySQL `SEQUENCE` on Sequel migrations. Gem includes functionality to cover the needs of SQLite users as well.
|
8
9
|
|
9
10
|
## Installation
|
10
11
|
|
@@ -18,14 +19,14 @@ Or add the following line to your project's Gemfile:
|
|
18
19
|
gem "sequel-sequence"
|
19
20
|
```
|
20
21
|
|
21
|
-
## Usage
|
22
|
+
## Usage with PostgreSQL and MariaDB
|
22
23
|
|
23
24
|
To create a `SEQUENCE`, just use the method `create_sequence`.
|
24
25
|
|
25
26
|
```ruby
|
26
27
|
Sequel.migration do
|
27
28
|
up do
|
28
|
-
create_sequence :position
|
29
|
+
create_sequence :position, if_exists: false
|
29
30
|
end
|
30
31
|
|
31
32
|
down do
|
@@ -39,22 +40,22 @@ You can also specify the initial value and increment:
|
|
39
40
|
```ruby
|
40
41
|
create_sequence :position, increment: 2
|
41
42
|
create_sequence :position, start: 100
|
43
|
+
create_sequence :position, if_exists: false
|
42
44
|
```
|
43
45
|
|
44
|
-
To define a column that has a sequence as its default value, use something like
|
45
|
-
the following:
|
46
|
+
To define a column that has a sequence as its default value, use something like the following:
|
46
47
|
|
47
48
|
```ruby
|
48
49
|
Sequel.migration do
|
49
50
|
change do
|
50
|
-
create_sequence :position_id
|
51
|
+
create_sequence :position_id, if_exists: false, start: 1
|
51
52
|
|
52
53
|
create_table(:things) do
|
53
54
|
primary_key :id
|
54
55
|
String :name, text: true
|
55
56
|
|
56
57
|
# PostgreSQL uses bigint as the sequence's default type.
|
57
|
-
Bignum :position
|
58
|
+
Bignum :position
|
58
59
|
|
59
60
|
Time :created_at, null: false
|
60
61
|
Time :updated_at, null: false
|
@@ -82,6 +83,24 @@ DB.lastval("position")
|
|
82
83
|
DB.setval("position", 1234)
|
83
84
|
```
|
84
85
|
|
86
|
+
## Usage with SQLite
|
87
|
+
|
88
|
+
In SQLite, the sequence functionality is implemented by registering tables in the database with a primary key of `id` and an additional integer field `fiction`.
|
89
|
+
```sql
|
90
|
+
CREATE TABLE `name_of_your_sequence_table`
|
91
|
+
(id integer primary key autoincrement, fiction integer);
|
92
|
+
```
|
93
|
+
|
94
|
+
You might utilize the last one as a numeric label to collect statistics on the operation of the end-to-end counter `"name_of_your_sequence_table".id` within the application.
|
95
|
+
|
96
|
+
```ruby
|
97
|
+
DB.nextval_with_label("position", 1)
|
98
|
+
```
|
99
|
+
|
100
|
+
By default, `fiction` has a zero value.
|
101
|
+
|
102
|
+
Otherwise, the operation of this gem for SQLite is identical to the ways of using Sequence in more advanced databases.
|
103
|
+
|
85
104
|
## Maintainer
|
86
105
|
|
87
106
|
- [Nikolai Bocharov](https://github.com/oreol-group)
|
@@ -93,16 +112,16 @@ DB.setval("position", 1234)
|
|
93
112
|
## Contributing
|
94
113
|
|
95
114
|
For more details about how to contribute, please read
|
96
|
-
https://github.com/oreol-group/sequel-sequence/blob/
|
115
|
+
https://github.com/oreol-group/sequel-sequence/blob/master/CONTRIBUTING.md.
|
97
116
|
|
98
117
|
## License
|
99
118
|
|
100
119
|
The gem is available as open source under the terms of the
|
101
120
|
[MIT License](https://opensource.org/licenses/MIT). A copy of the license can be
|
102
|
-
found at https://github.com/oreol-group/sequel-sequence/blob/
|
121
|
+
found at https://github.com/oreol-group/sequel-sequence/blob/master/LICENSE.md.
|
103
122
|
|
104
123
|
## Code of Conduct
|
105
124
|
|
106
125
|
Everyone interacting in the sequel-sequence project's codebases, issue trackers,
|
107
126
|
chat rooms and mailing lists is expected to follow the
|
108
|
-
[code of conduct](https://github.com/oreol-group/sequel-sequence/blob/
|
127
|
+
[code of conduct](https://github.com/oreol-group/sequel-sequence/blob/master/CODE_OF_CONDUCT.md).
|
@@ -20,9 +20,10 @@ module Sequel
|
|
20
20
|
|
21
21
|
def create_sequence(name, options = {})
|
22
22
|
increment = options[:increment] || options[:step]
|
23
|
+
if_exists = build_exists_condition(options[:if_exists])
|
23
24
|
name = quote_name(name.to_s)
|
24
25
|
|
25
|
-
sql = ["CREATE SEQUENCE
|
26
|
+
sql = ["CREATE SEQUENCE #{if_exists} #{name}"]
|
26
27
|
sql << "INCREMENT BY #{increment}" if increment
|
27
28
|
sql << "START WITH #{options[:start]}" if options[:start]
|
28
29
|
sql << ';'
|
@@ -32,7 +33,7 @@ module Sequel
|
|
32
33
|
|
33
34
|
def drop_sequence(name)
|
34
35
|
name = quote_name(name.to_s)
|
35
|
-
sql = "DROP SEQUENCE #{name}"
|
36
|
+
sql = "DROP SEQUENCE IF EXISTS #{name}"
|
36
37
|
run(sql)
|
37
38
|
end
|
38
39
|
|
@@ -35,9 +35,10 @@ module Sequel
|
|
35
35
|
|
36
36
|
def create_sequence(name, options = {})
|
37
37
|
increment = options[:increment] || options[:step]
|
38
|
+
if_exists = build_exists_condition(options[:if_exists])
|
38
39
|
name = quote_name(name.to_s)
|
39
40
|
|
40
|
-
sql = ["CREATE SEQUENCE
|
41
|
+
sql = ["CREATE SEQUENCE #{if_exists} #{name}"]
|
41
42
|
sql << "INCREMENT BY #{increment}" if increment
|
42
43
|
sql << "START WITH #{options[:start]}" if options[:start]
|
43
44
|
sql << ';'
|
@@ -48,7 +49,7 @@ module Sequel
|
|
48
49
|
|
49
50
|
def drop_sequence(name)
|
50
51
|
name = quote_name(name.to_s)
|
51
|
-
sql = "DROP SEQUENCE #{name}"
|
52
|
+
sql = "DROP SEQUENCE IF EXISTS #{name}"
|
52
53
|
run(sql)
|
53
54
|
end
|
54
55
|
|
@@ -0,0 +1,132 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# https://sequel.jeremyevans.net/rdoc/files/doc/sql_rdoc.html
|
4
|
+
# https://github.com/jeremyevans/sequel/blob/master/lib/sequel/database/connecting.rb
|
5
|
+
module Sequel
|
6
|
+
module Sequence
|
7
|
+
module Database
|
8
|
+
module SQLite
|
9
|
+
def check_sequences
|
10
|
+
fetch('SELECT * FROM `sqlite_sequence`;').all.to_a
|
11
|
+
end
|
12
|
+
|
13
|
+
def create_sequence(name, options = {})
|
14
|
+
check_options(options)
|
15
|
+
if_exists = build_exists_condition(options[:if_exists])
|
16
|
+
start_option = options[:start] || 1
|
17
|
+
sql = [create_sequence_table(stringify(name), if_exists)]
|
18
|
+
sql << insert_into_sqlite_sequence(stringify(name), start_option)
|
19
|
+
run(sql.join("\n"))
|
20
|
+
end
|
21
|
+
|
22
|
+
def drop_sequence(name, options = {})
|
23
|
+
if_exists = build_exists_condition(options[:if_exists])
|
24
|
+
run(drop_sequence_table(stringify(name), if_exists))
|
25
|
+
end
|
26
|
+
|
27
|
+
def nextval(name)
|
28
|
+
run(insert_into_sequence_table(stringify(name), 0))
|
29
|
+
take_seq(name)
|
30
|
+
end
|
31
|
+
|
32
|
+
def nextval_with_label(name, num_label = 0)
|
33
|
+
run(insert_into_sequence_table(stringify(name), num_label))
|
34
|
+
take_seq(name)
|
35
|
+
end
|
36
|
+
|
37
|
+
def lastval(name)
|
38
|
+
take_seq(stringify(name))
|
39
|
+
end
|
40
|
+
|
41
|
+
alias currval lastval
|
42
|
+
|
43
|
+
def setval(name, value)
|
44
|
+
current = lastval(stringify(name))
|
45
|
+
if current.nil?
|
46
|
+
create_sequence(stringify(name), { start: value })
|
47
|
+
elsif value < current
|
48
|
+
# sql = [delete_from_sqlite_sequence(name)]
|
49
|
+
# sql << drop_sequence_table(name)
|
50
|
+
# sql << insert_into_sqlite_sequence(name, value)
|
51
|
+
# run(sql.join("\n"))
|
52
|
+
log_info DANGER_OPT_ID
|
53
|
+
value = current
|
54
|
+
else
|
55
|
+
run(insert_into_sqlite_sequence(stringify(name), value))
|
56
|
+
end
|
57
|
+
value
|
58
|
+
end
|
59
|
+
|
60
|
+
def set_column_default_nextval(table, column, sequence)
|
61
|
+
run(create_sequenced_column(stringify(table),
|
62
|
+
stringify(column),
|
63
|
+
stringify(sequence)))
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
def stringify(name)
|
69
|
+
@name ||= {}
|
70
|
+
@name.fetch(name, nil) || (@name[name] = name.to_s)
|
71
|
+
end
|
72
|
+
|
73
|
+
def take_seq(name)
|
74
|
+
out = nil
|
75
|
+
fetch(select_max_seq(name)) do |row|
|
76
|
+
out = row[:id]
|
77
|
+
end
|
78
|
+
out
|
79
|
+
end
|
80
|
+
|
81
|
+
def create_sequence_table(name, if_exists = nil)
|
82
|
+
%(
|
83
|
+
CREATE TABLE #{if_exists || IF_NOT_EXISTS} #{name}
|
84
|
+
(id integer primary key autoincrement, fiction integer);
|
85
|
+
)
|
86
|
+
end
|
87
|
+
|
88
|
+
def insert_into_sequence_table(name, num_label)
|
89
|
+
"INSERT INTO #{name} (fiction) VALUES (#{num_label});"
|
90
|
+
end
|
91
|
+
|
92
|
+
def insert_into_sqlite_sequence(name, value)
|
93
|
+
current = take_seq(name)
|
94
|
+
if current.nil?
|
95
|
+
"INSERT INTO sqlite_sequence (name, seq) VALUES ('#{name}', #{value});"
|
96
|
+
else
|
97
|
+
%(
|
98
|
+
UPDATE sqlite_sequence
|
99
|
+
SET seq = #{[current, value].max}
|
100
|
+
WHERE name = '#{name}';
|
101
|
+
)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def delete_from_sqlite_sequence(name)
|
106
|
+
"DELETE FROM sqlite_sequence WHERE name = '#{name}';"
|
107
|
+
end
|
108
|
+
|
109
|
+
def drop_sequence_table(name, if_exists = nil)
|
110
|
+
"DROP TABLE #{if_exists || IF_EXISTS} #{name};"
|
111
|
+
end
|
112
|
+
|
113
|
+
def select_max_seq(name)
|
114
|
+
"SELECT MAX(seq) AS id FROM sqlite_sequence WHERE name = '#{name}';"
|
115
|
+
end
|
116
|
+
|
117
|
+
def create_sequenced_column(table, column, sequence)
|
118
|
+
%(
|
119
|
+
CREATE TRIGGER IF NOT EXISTS #{table}_#{sequence} AFTER INSERT
|
120
|
+
ON #{table}
|
121
|
+
BEGIN
|
122
|
+
INSERT INTO #{sequence}(fiction) VALUES (0);
|
123
|
+
UPDATE #{table}
|
124
|
+
SET #{column} = (SELECT MAX(seq) FROM sqlite_sequence WHERE name = '#{sequence}')
|
125
|
+
WHERE rowid = NEW.rowid;
|
126
|
+
END;
|
127
|
+
)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|