activerecord-tidb-adapter 0.3.0 → 5.2.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 442a2dcd175987185739a1fad7a8ef8788d0b13b7263018795ac144a4c10ee03
4
- data.tar.gz: e568154643ebebfc8a9dcfd506b18732d52dea1a19b6500b76e9103965fd2cff
3
+ metadata.gz: 1ec81c5f43cb98b0fe8fb61484ea7b0050a84cb8c7caac6d25e314d58f5f1be0
4
+ data.tar.gz: 4a99eafd9d2f53885e063cc89af6ecf2afce3506e0f9b118a999e52c5fe93e71
5
5
  SHA512:
6
- metadata.gz: d01699afa9a6c147317b8b6fd5763bcbf63852bccaa4fe6dd5bac076405bfc02ff98ae177cd1eef39a8aac95493a4e7eac31896260bceb8b78d2c2b3976605c6
7
- data.tar.gz: 932f70292fde728c25d21bf7180dbad488ca4b5d7630bfe669b70dbf1dee0165f24b311d284ed0ab8edd1b5ab1b688d28d29e7a1748c8a571101950568373a00
6
+ metadata.gz: 66909adaf233af63fb1f7f251cb8f11ba4a484c80e7646c9202c5636a7477575880f85927e01403ce26f8ebaa4a88c5eea6ffa1052a5a34d4e8b12d18f5cbb86
7
+ data.tar.gz: 8ad7289243de4d4f4e1b34d759be041f33c5b02d6b99428e9fc09ad918baa021751d708adc335c126495dce29eae9fca61a63cf7533711c7cd88cb6caf3511a3
@@ -0,0 +1,10 @@
1
+ #!/bin/bash
2
+
3
+ # Place this in /etc/buildkite-agent/hooks/pre-command
4
+ #
5
+ # Needs to be `chown buildkite-agent` and `chmod +x`
6
+
7
+ # RVM uses unbound variables and will fail without this
8
+ set +u
9
+
10
+ source /var/lib/buildkite-agent/.rvm/scripts/rvm
@@ -0,0 +1,7 @@
1
+ env:
2
+ MYSQL_HOST: 127.0.0.1
3
+ MYSQL_USER: root
4
+
5
+ steps:
6
+ - command: "testing.sh"
7
+ label: "Run TiDB ActiveRecord Adapter testing 5-2-stable"
@@ -0,0 +1,16 @@
1
+ #!/bin/bash
2
+ set -eu
3
+ service supervisor start
4
+
5
+ while sleep 60; do
6
+ ps aux |grep tidb |grep -q -v grep
7
+ TIDB_STATUS=$?
8
+ ps aux |grep tikv |grep -q -v grep
9
+ TIKV_STATUS=$?
10
+ # If the greps above find anything, they exit with 0 status
11
+ # If they are not both 0, then something is wrong
12
+ if [ $TIDB_STATUS -ne 0 -o $TIKV_STATUS -ne 0 ]; then
13
+ echo "One of the processes has already exited."
14
+ exit 1
15
+ fi
16
+ done
@@ -0,0 +1,35 @@
1
+ name: activerecord-tidb-adapter ci
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - 5-2-stable
7
+ paths-ignore:
8
+ - 'README*.md'
9
+ - 'docs/**'
10
+ pull_request:
11
+ branches:
12
+ - 5-2-stable
13
+ paths-ignore:
14
+ - 'README*.md'
15
+ - 'docs/**'
16
+
17
+ jobs:
18
+ build:
19
+ if: ${{ !contains(github.event.commits[0].message, '[skip ci]') }}
20
+ runs-on: ubuntu-latest
21
+ services:
22
+ tidb:
23
+ image: hawkingrei/tind:v5.1.0
24
+ options: --entrypoint /entrypoint.sh
25
+ env:
26
+ TIDB_VERSION: v5.1.0
27
+ ports: ["4000:4000"]
28
+ steps:
29
+ - uses: actions/checkout@v2
30
+ - uses: ruby/setup-ruby@v1
31
+ with:
32
+ ruby-version: 2.7
33
+ bundler-cache: true
34
+ - run: sleep 30 && MYSQL_USER=root MYSQL_HOST=127.0.0.1 MYSQL_PORT=4000 tidb=1 ARCONN=tidb bundle exec rake db:tidb:build
35
+ - run: sleep 10 && MYSQL_USER=root MYSQL_HOST=127.0.0.1 MYSQL_PORT=4000 tidb=1 ARCONN=tidb bundle exec rake test:tidb
data/Gemfile CHANGED
@@ -14,10 +14,14 @@ gem 'pry'
14
14
 
15
15
  gem 'rubocop', '~> 1.18'
16
16
 
17
- gem 'rails', git: 'https://github.com/tidb-incubator/rails.git', branch: '6-1-stable'
17
+ gem 'rails', git: 'https://github.com/pingcap/rails.git', branch: '5-2-stable'
18
18
 
19
19
  gem 'byebug', '~> 11.1'
20
20
 
21
21
  gem 'sqlite3', '~> 1.4'
22
22
 
23
23
  gem 'pg', '~> 1.2'
24
+
25
+ gem "mocha", "~> 1.13"
26
+
27
+ gem "bcrypt", "~> 3.1"
data/Gemfile.lock CHANGED
@@ -1,100 +1,82 @@
1
1
  GIT
2
- remote: https://github.com/tidb-incubator/rails.git
3
- revision: e377e0dc16e9841a048ec7eab2666c06155b6a0c
4
- branch: 6-1-stable
2
+ remote: https://github.com/pingcap/rails.git
3
+ revision: a1adbde17b229e9131d40787ee4342c1180afb36
4
+ branch: 5-2-stable
5
5
  specs:
6
- actioncable (6.1.4)
7
- actionpack (= 6.1.4)
8
- activesupport (= 6.1.4)
6
+ actioncable (5.2.6)
7
+ actionpack (= 5.2.6)
9
8
  nio4r (~> 2.0)
10
9
  websocket-driver (>= 0.6.1)
11
- actionmailbox (6.1.4)
12
- actionpack (= 6.1.4)
13
- activejob (= 6.1.4)
14
- activerecord (= 6.1.4)
15
- activestorage (= 6.1.4)
16
- activesupport (= 6.1.4)
17
- mail (>= 2.7.1)
18
- actionmailer (6.1.4)
19
- actionpack (= 6.1.4)
20
- actionview (= 6.1.4)
21
- activejob (= 6.1.4)
22
- activesupport (= 6.1.4)
10
+ actionmailer (5.2.6)
11
+ actionpack (= 5.2.6)
12
+ actionview (= 5.2.6)
13
+ activejob (= 5.2.6)
23
14
  mail (~> 2.5, >= 2.5.4)
24
15
  rails-dom-testing (~> 2.0)
25
- actionpack (6.1.4)
26
- actionview (= 6.1.4)
27
- activesupport (= 6.1.4)
28
- rack (~> 2.0, >= 2.0.9)
16
+ actionpack (5.2.6)
17
+ actionview (= 5.2.6)
18
+ activesupport (= 5.2.6)
19
+ rack (~> 2.0, >= 2.0.8)
29
20
  rack-test (>= 0.6.3)
30
21
  rails-dom-testing (~> 2.0)
31
- rails-html-sanitizer (~> 1.0, >= 1.2.0)
32
- actiontext (6.1.4)
33
- actionpack (= 6.1.4)
34
- activerecord (= 6.1.4)
35
- activestorage (= 6.1.4)
36
- activesupport (= 6.1.4)
37
- nokogiri (>= 1.8.5)
38
- actionview (6.1.4)
39
- activesupport (= 6.1.4)
22
+ rails-html-sanitizer (~> 1.0, >= 1.0.2)
23
+ actionview (5.2.6)
24
+ activesupport (= 5.2.6)
40
25
  builder (~> 3.1)
41
26
  erubi (~> 1.4)
42
27
  rails-dom-testing (~> 2.0)
43
- rails-html-sanitizer (~> 1.1, >= 1.2.0)
44
- activejob (6.1.4)
45
- activesupport (= 6.1.4)
28
+ rails-html-sanitizer (~> 1.0, >= 1.0.3)
29
+ activejob (5.2.6)
30
+ activesupport (= 5.2.6)
46
31
  globalid (>= 0.3.6)
47
- activemodel (6.1.4)
48
- activesupport (= 6.1.4)
49
- activerecord (6.1.4)
50
- activemodel (= 6.1.4)
51
- activesupport (= 6.1.4)
52
- activestorage (6.1.4)
53
- actionpack (= 6.1.4)
54
- activejob (= 6.1.4)
55
- activerecord (= 6.1.4)
56
- activesupport (= 6.1.4)
32
+ activemodel (5.2.6)
33
+ activesupport (= 5.2.6)
34
+ activerecord (5.2.6)
35
+ activemodel (= 5.2.6)
36
+ activesupport (= 5.2.6)
37
+ arel (>= 9.0)
38
+ activestorage (5.2.6)
39
+ actionpack (= 5.2.6)
40
+ activerecord (= 5.2.6)
57
41
  marcel (~> 1.0.0)
58
- mini_mime (>= 1.1.0)
59
- activesupport (6.1.4)
42
+ activesupport (5.2.6)
60
43
  concurrent-ruby (~> 1.0, >= 1.0.2)
61
- i18n (>= 1.6, < 2)
62
- minitest (>= 5.1)
63
- tzinfo (~> 2.0)
64
- zeitwerk (~> 2.3)
65
- rails (6.1.4)
66
- actioncable (= 6.1.4)
67
- actionmailbox (= 6.1.4)
68
- actionmailer (= 6.1.4)
69
- actionpack (= 6.1.4)
70
- actiontext (= 6.1.4)
71
- actionview (= 6.1.4)
72
- activejob (= 6.1.4)
73
- activemodel (= 6.1.4)
74
- activerecord (= 6.1.4)
75
- activestorage (= 6.1.4)
76
- activesupport (= 6.1.4)
77
- bundler (>= 1.15.0)
78
- railties (= 6.1.4)
44
+ i18n (>= 0.7, < 2)
45
+ minitest (~> 5.1)
46
+ tzinfo (~> 1.1)
47
+ rails (5.2.6)
48
+ actioncable (= 5.2.6)
49
+ actionmailer (= 5.2.6)
50
+ actionpack (= 5.2.6)
51
+ actionview (= 5.2.6)
52
+ activejob (= 5.2.6)
53
+ activemodel (= 5.2.6)
54
+ activerecord (= 5.2.6)
55
+ activestorage (= 5.2.6)
56
+ activesupport (= 5.2.6)
57
+ bundler (>= 1.3.0)
58
+ railties (= 5.2.6)
79
59
  sprockets-rails (>= 2.0.0)
80
- railties (6.1.4)
81
- actionpack (= 6.1.4)
82
- activesupport (= 6.1.4)
60
+ railties (5.2.6)
61
+ actionpack (= 5.2.6)
62
+ activesupport (= 5.2.6)
83
63
  method_source
84
- rake (>= 0.13)
85
- thor (~> 1.0)
64
+ rake (>= 0.8.7)
65
+ thor (>= 0.19.0, < 2.0)
86
66
 
87
67
  PATH
88
68
  remote: .
89
69
  specs:
90
- activerecord-tidb-adapter (0.3.0)
91
- activerecord (~> 6.1)
70
+ activerecord-tidb-adapter (5.2.2)
71
+ activerecord (~> 5.2)
92
72
  mysql2
93
73
 
94
74
  GEM
95
75
  remote: https://rubygems.org/
96
76
  specs:
77
+ arel (9.0.0)
97
78
  ast (2.4.2)
79
+ bcrypt (3.1.16)
98
80
  builder (3.2.4)
99
81
  byebug (11.1.3)
100
82
  coderay (1.1.3)
@@ -105,7 +87,7 @@ GEM
105
87
  activesupport (>= 5.0)
106
88
  i18n (1.8.10)
107
89
  concurrent-ruby (~> 1.0)
108
- loofah (2.11.0)
90
+ loofah (2.12.0)
109
91
  crass (~> 1.0.2)
110
92
  nokogiri (>= 1.5.9)
111
93
  mail (2.7.1)
@@ -116,8 +98,11 @@ GEM
116
98
  minitest (5.14.4)
117
99
  minitest-excludes (2.0.1)
118
100
  minitest (~> 5.0)
101
+ mocha (1.13.0)
119
102
  mysql2 (0.5.3)
120
103
  nio4r (2.5.8)
104
+ nokogiri (1.12.3-x86_64-darwin)
105
+ racc (~> 1.4)
121
106
  nokogiri (1.12.3-x86_64-linux)
122
107
  racc (~> 1.4)
123
108
  parallel (1.20.1)
@@ -134,22 +119,22 @@ GEM
134
119
  rails-dom-testing (2.0.3)
135
120
  activesupport (>= 4.2.0)
136
121
  nokogiri (>= 1.6)
137
- rails-html-sanitizer (1.3.0)
122
+ rails-html-sanitizer (1.4.1)
138
123
  loofah (~> 2.3)
139
124
  rainbow (3.0.0)
140
125
  rake (13.0.6)
141
126
  regexp_parser (2.1.1)
142
127
  rexml (3.2.5)
143
- rubocop (1.18.4)
128
+ rubocop (1.19.0)
144
129
  parallel (~> 1.10)
145
130
  parser (>= 3.0.0.0)
146
131
  rainbow (>= 2.2.2, < 4.0)
147
132
  regexp_parser (>= 1.8, < 3.0)
148
133
  rexml
149
- rubocop-ast (>= 1.8.0, < 2.0)
134
+ rubocop-ast (>= 1.9.1, < 2.0)
150
135
  ruby-progressbar (~> 1.7)
151
136
  unicode-display_width (>= 1.4.0, < 3.0)
152
- rubocop-ast (1.8.0)
137
+ rubocop-ast (1.10.0)
153
138
  parser (>= 3.0.1.1)
154
139
  ruby-progressbar (1.11.0)
155
140
  sprockets (4.0.2)
@@ -161,13 +146,13 @@ GEM
161
146
  sprockets (>= 3.0.0)
162
147
  sqlite3 (1.4.2)
163
148
  thor (1.1.0)
164
- tzinfo (2.0.4)
165
- concurrent-ruby (~> 1.0)
149
+ thread_safe (0.3.6)
150
+ tzinfo (1.2.9)
151
+ thread_safe (~> 0.1)
166
152
  unicode-display_width (2.0.0)
167
153
  websocket-driver (0.7.5)
168
154
  websocket-extensions (>= 0.1.0)
169
155
  websocket-extensions (0.1.5)
170
- zeitwerk (2.4.2)
171
156
 
172
157
  PLATFORMS
173
158
  x86_64-darwin-18
@@ -175,9 +160,11 @@ PLATFORMS
175
160
 
176
161
  DEPENDENCIES
177
162
  activerecord-tidb-adapter!
163
+ bcrypt (~> 3.1)
178
164
  byebug (~> 11.1)
179
165
  minitest (~> 5.0)
180
166
  minitest-excludes (~> 2.0)
167
+ mocha (~> 1.13)
181
168
  pg (~> 1.2)
182
169
  pry
183
170
  rails!
data/README.md CHANGED
@@ -8,7 +8,7 @@ TiDB adapter for ActiveRecord 5 and 6. This is a lightweight extension of the my
8
8
  Add this line to your application's Gemfile:
9
9
 
10
10
  ```ruby
11
- gem 'activerecord-tidb-adapter'
11
+ gem 'activerecord-tidb-adapter', "~> 5.2.2"
12
12
  ```
13
13
 
14
14
  And then execute:
@@ -44,6 +44,62 @@ development:
44
44
 
45
45
  * demo repo with rails 6.1.4: https://github.com/hooopo/activerecord-tidb-adapter-demo
46
46
 
47
+ ## TiDB features
48
+
49
+ **[Sequence](https://docs.pingcap.com/tidb/stable/sql-statement-create-sequence)**
50
+
51
+ Sequence as primary key
52
+
53
+ ```ruby
54
+ class TestSeq < ActiveRecord::Migration[6.1]
55
+ def up
56
+ # more options: increment, min_value, cycle, cache
57
+ create_sequence :orders_seq, start: 1024
58
+ create_table :orders, id: false do |t|
59
+ t.primary_key :id, default: -> { "nextval(orders_seq)" }
60
+ t.string :name
61
+ end
62
+ end
63
+
64
+ def down
65
+ drop_table :orders
66
+ drop_sequence :orders_seq
67
+ end
68
+ end
69
+ ```
70
+
71
+ Generated DDL
72
+ ```sql
73
+ mysql> show create table orders_seq\G;
74
+ *************************** 1. row ***************************
75
+ Sequence: orders_seq
76
+ Create Sequence: CREATE SEQUENCE `orders_seq` start with 1024 minvalue 1 maxvalue 9223372036854775806 increment by 1 nocache nocycle ENGINE=InnoDB
77
+
78
+ mysql> show create table orders\G;
79
+ *************************** 1. row ***************************
80
+ Table: orders
81
+ Create Table: CREATE TABLE `orders` (
82
+ `id` bigint(20) NOT NULL DEFAULT nextval(`activerecord_tidb_adapter_demo_development`.`orders_seq`),
83
+ `name` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
84
+ PRIMARY KEY (`id`) /*T![clustered_index] CLUSTERED */
85
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci
86
+
87
+ ```
88
+
89
+ This gem also adds a few helpers to interact with `SEQUENCE`
90
+
91
+ ```ruby
92
+ # Advance sequence and return new value
93
+ ActiveRecord::Base.nextval("numbers")
94
+
95
+ # Return value most recently obtained with nextval for specified sequence.
96
+ ActiveRecord::Base.lastval("numbers")
97
+
98
+ # Set sequence's current value
99
+ ActiveRecord::Base.setval("numbers", 1234)
100
+ ```
101
+
102
+
47
103
  ## Setting up local TiDB server
48
104
 
49
105
  Install [tiup](https://github.com/pingcap/tiup)
@@ -84,16 +140,22 @@ MYSQL_USER=root MYSQL_HOST=127.0.0.1 MYSQL_PORT=4000 tidb=1 ARCONN=tidb bundle e
84
140
 
85
141
  ```
86
142
 
87
- run tidb adapter tests
143
+ run tidb adapter tests and activerecord buildin tests
144
+
145
+ ```
146
+ MYSQL_USER=root MYSQL_HOST=127.0.0.1 MYSQL_PORT=4000 tidb=1 ARCONN=tidb bundle exec rake test:tidb
88
147
 
89
148
  ```
90
- MYSQL_USER=root MYSQL_HOST=127.0.0.1 MYSQL_PORT=4000 tidb=1 ARCONN=tidb bundle exec rake test:idb
91
149
 
150
+ run **ONLY** tidb adapter tests using `ONLY_TEST_TIDB` env:
151
+
152
+ ```
153
+ ONLY_TEST_TIDB=1 MYSQL_USER=root MYSQL_HOST=127.0.0.1 MYSQL_PORT=4000 tidb=1 ARCONN=tidb bundle exec rake test:tidb
92
154
  ```
93
155
 
94
156
  ## Contributing
95
157
 
96
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/activerecord-tidb-adapter.
158
+ Bug reports and pull requests are welcome on GitHub at https://github.com/pingcap/activerecord-tidb-adapter.
97
159
 
98
160
  ## License
99
161
 
data/Rakefile CHANGED
@@ -15,7 +15,7 @@ namespace :test do
15
15
  Rake::TestTask.new('tidb') do |t|
16
16
  t.libs = ARTest::TiDB.test_load_paths
17
17
  t.test_files = test_files
18
- t.warning = !!ENV['WARNING']
18
+ t.warning = !ENV['WARNING'].nil?
19
19
  t.verbose = false
20
20
  end
21
21
 
@@ -29,7 +29,7 @@ Gem::Specification.new do |spec|
29
29
  spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
30
30
  spec.require_paths = ['lib']
31
31
 
32
- spec.add_dependency 'activerecord', '~> 6.1'
32
+ spec.add_dependency 'activerecord', '~> 5.2'
33
33
  spec.add_dependency 'mysql2'
34
34
 
35
35
  # Uncomment to register a new dependency of your gem
@@ -0,0 +1,19 @@
1
+ require 'active_record/connection_adapters/abstract/database_statements'
2
+
3
+ ActiveRecord::ConnectionAdapters::DatabaseStatements.class_eval do
4
+ def insert(arel, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = [])
5
+ sql, binds = to_sql_and_binds(arel, binds)
6
+ value = exec_insert(sql, name, binds, pk, sequence_name)
7
+
8
+ return id_value if id_value.present?
9
+ return last_inserted_id(value) if arel.is_a?(String)
10
+ table_name = arel.ast.relation.table_name
11
+ pk_def = schema_cache.columns_hash(table_name)[pk]
12
+ if pk_def&.default_function && pk_def.default_function =~ /nextval/
13
+ query_value("SELECT #{pk_def.default_function.sub('nextval', 'lastval')}")
14
+ else
15
+ last_inserted_id(value)
16
+ end
17
+ end
18
+ alias create insert
19
+ end
@@ -0,0 +1,28 @@
1
+ require 'pry'
2
+ require 'active_record/connection_adapters/mysql/schema_statements'
3
+
4
+
5
+ ActiveRecord::ConnectionAdapters::MySQL::SchemaStatements.class_eval do
6
+ def new_column_from_field(table_name, field)
7
+ type_metadata = fetch_type_metadata(field[:Type], field[:Extra])
8
+ if type_metadata.type == :datetime && /\ACURRENT_TIMESTAMP(?:\([0-6]?\))?\z/i.match?(field[:Default])
9
+ default, default_function = nil, field[:Default]
10
+ elsif field[:Default].to_s =~ /nextval/i
11
+ default_function = field[:Default]
12
+ default = nil
13
+ else
14
+ default, default_function = field[:Default], nil
15
+ end
16
+
17
+ ActiveRecord::ConnectionAdapters::MySQL::Column.new(
18
+ field[:Field],
19
+ default,
20
+ type_metadata,
21
+ field[:Null] == "YES",
22
+ table_name,
23
+ default_function,
24
+ field[:Collation],
25
+ comment: field[:Comment].presence
26
+ )
27
+ end
28
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module Type
3
5
  class << self
@@ -1,16 +1,18 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'active_record/connection_adapters'
4
3
  require 'active_record/connection_adapters/mysql2_adapter'
5
4
  require 'active_record/connection_adapters/tidb/setup'
6
5
  require_relative '../../version'
6
+ require_relative '../sequence'
7
+ require_relative 'tidb/database_statements'
8
+ require_relative 'tidb/schema_statements'
7
9
 
8
10
  ActiveRecord::ConnectionAdapters::Tidb.initial_setup
9
11
 
10
12
  module ActiveRecord
11
- module ConnectionHandling #:nodoc:
13
+ module ConnectionHandling # :nodoc:
12
14
  # Establishes a connection to the database that's used by all Active Record objects.
13
- def tidb_connection(config) #:nodoc:
15
+ def tidb_connection(config) # :nodoc:
14
16
  config = config.symbolize_keys
15
17
  config[:flags] ||= 0
16
18
 
@@ -29,8 +31,30 @@ module ActiveRecord
29
31
  end
30
32
  end
31
33
 
34
+
35
+
32
36
  module ConnectionAdapters
37
+ class Mysql2Adapter < AbstractMysqlAdapter
38
+ ER_BAD_DB_ERROR = 1049
39
+ ADAPTER_NAME = "Mysql2"
40
+
41
+ include MySQL::DatabaseStatements
42
+
43
+ class << self
44
+ def new_client(config)
45
+ Mysql2::Client.new(config)
46
+ rescue Mysql2::Error => error
47
+ if error.error_number == ConnectionAdapters::Mysql2Adapter::ER_BAD_DB_ERROR
48
+ raise ActiveRecord::NoDatabaseError
49
+ else
50
+ raise ActiveRecord::ConnectionNotEstablished, error.message
51
+ end
52
+ end
53
+ end
54
+ end
55
+
33
56
  class TidbAdapter < Mysql2Adapter
57
+ include ActiveRecord::Sequence::Adapter
34
58
  ADAPTER_NAME = 'Tidb'
35
59
 
36
60
  def supports_savepoints?
@@ -93,7 +117,7 @@ module ActiveRecord
93
117
  end
94
118
 
95
119
  def self.database_exists?(config)
96
- !!ActiveRecord::Base.tidb_connection(config)
120
+ !ActiveRecord::Base.tidb_connection(config).nil?
97
121
  rescue ActiveRecord::NoDatabaseError
98
122
  false
99
123
  end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module Sequence
5
+ module Adapter
6
+ def check_sequences
7
+ select_all(
8
+ 'SELECT * FROM information_schema.sequences ORDER BY sequence_name'
9
+ ).to_a
10
+ end
11
+
12
+ def create_sequence(name, options = {})
13
+ increment = options[:increment] || options[:step]
14
+ name = quote_column_name(name)
15
+
16
+ sql = ["CREATE SEQUENCE IF NOT EXISTS #{name}"]
17
+ sql << "INCREMENT BY #{increment}" if increment
18
+ sql << "START WITH #{options[:start]}" if options[:start]
19
+ sql << if options[:cache]
20
+ "CACHE #{options[:cache]}"
21
+ else
22
+ 'NOCACHE'
23
+ end
24
+
25
+ sql << if options[:cycle]
26
+ 'CYCLE'
27
+ else
28
+ 'NOCYCLE'
29
+ end
30
+
31
+ sql << "MIN_VALUE #{options[:min_value]}" if options[:min_value]
32
+
33
+ sql << "COMMENT #{quote(options[:comment].to_s)}" if options[:comment]
34
+
35
+ execute(sql.join("\n"))
36
+ end
37
+
38
+ def drop_sequence(name)
39
+ name = quote_column_name(name)
40
+ sql = "DROP SEQUENCE IF EXISTS #{name}"
41
+ execute(sql)
42
+ end
43
+
44
+ def recreate_sequence(name, options = {})
45
+ drop_sequence(name)
46
+ create_sequence(name, options)
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module Sequence
5
+ module CommandRecorder
6
+ def create_sequence(name, options = {})
7
+ record(__method__, [name, options])
8
+ end
9
+
10
+ def drop_sequence(name)
11
+ record(__method__, [name])
12
+ end
13
+
14
+ def invert_create_sequence(args)
15
+ name, = args
16
+ [:drop_sequence, [name]]
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module Sequence
5
+ module ModelMethods
6
+ def nextval(name)
7
+ name = connection.quote_column_name(name)
8
+ connection.query_value("SELECT nextval(#{name})")
9
+ end
10
+
11
+ def lastval(name)
12
+ name = connection.quote_column_name(name)
13
+ connection.query_value("SELECT lastval(#{name})")
14
+ end
15
+
16
+ def setval(name, value)
17
+ name = connection.quote_column_name(name)
18
+ connection.query_value("SELECT setval(#{name}, #{value})")
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module Sequence
5
+ module SchemaDumper
6
+ def header(stream)
7
+ super
8
+ sequences(stream)
9
+ end
10
+
11
+ def sequences(stream)
12
+ sequences = @connection.check_sequences
13
+ return if sequences.empty?
14
+
15
+ sequences.each do |seq|
16
+ start_value = seq['START']
17
+ increment = seq['INCREMENT']
18
+ cache = seq['CACHE']
19
+ cache_value = seq['CACHE_VALUE']
20
+ min_value = seq['MIN_VALUE']
21
+ cycle = seq['CYCLE']
22
+ comment = seq['COMMENT']
23
+
24
+ options = []
25
+
26
+ options << "start: #{start_value}" if start_value && Integer(start_value) != 1
27
+
28
+ options << "increment: #{increment}" if increment && Integer(increment) != 1
29
+
30
+ options << "cache: #{cache_value}" if cache_value && Integer(cache_value) != 0
31
+
32
+ options << "min_value: #{min_value}" if min_value
33
+
34
+ options << 'cycle: true' if cycle.to_i != 0
35
+
36
+ options << "comment: #{comment.inspect}" if comment.present?
37
+
38
+ statement = [
39
+ 'create_sequence',
40
+ seq['SEQUENCE_NAME'].inspect
41
+ ].join(' ')
42
+
43
+ if options.any?
44
+ statement << (options.any? ? ", #{options.join(', ')}" : '')
45
+ end
46
+
47
+ stream.puts " #{statement}"
48
+ end
49
+
50
+ stream.puts
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support/all'
4
+ require 'active_record'
5
+ require 'active_record/connection_adapters/mysql/schema_dumper'
6
+ require 'active_record/migration/command_recorder'
7
+ require 'active_record/schema_dumper'
8
+
9
+ module ActiveRecord
10
+ module Sequence
11
+ require 'active_record/sequence/command_recorder'
12
+ require 'active_record/sequence/adapter'
13
+ require 'active_record/sequence/schema_dumper'
14
+ require 'active_record/sequence/model_methods'
15
+ end
16
+ end
17
+
18
+ ActiveRecord::Migration::CommandRecorder.include(ActiveRecord::Sequence::CommandRecorder)
19
+
20
+ ActiveRecord::SchemaDumper.prepend(ActiveRecord::Sequence::SchemaDumper)
21
+ ActiveRecord::Base.extend(ActiveRecord::Sequence::ModelMethods)
data/lib/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActiveRecord
4
- TIDB_ADAPTER_VERSION = '0.3.0'
4
+ TIDB_ADAPTER_VERSION = '5.2.2'
5
5
  end
data/testing.sh ADDED
@@ -0,0 +1,14 @@
1
+ #!/bin/bash
2
+
3
+ set -eo pipefail
4
+
5
+ bundle config set --local path '/tmp/buildkite-cache'
6
+
7
+ echo "Setup gem mirror"
8
+ bundle config mirror.https://rubygems.org https://gems.ruby-china.com
9
+
10
+ echo "Bundle install"
11
+ bundle install
12
+
13
+ echo "Setup database for testing"
14
+ tidb=1 ARCONN=tidb bundle exec rake db:tidb:rebuild && tidb=1 ARCONN=tidb bundle exec rake test:tidb
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord-tidb-adapter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 5.2.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Hooopo Wang
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-08-12 00:00:00.000000000 Z
11
+ date: 2021-08-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '6.1'
19
+ version: '5.2'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '6.1'
26
+ version: '5.2'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: mysql2
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -45,6 +45,10 @@ executables: []
45
45
  extensions: []
46
46
  extra_rdoc_files: []
47
47
  files:
48
+ - ".buildkite/hooks/pre-command"
49
+ - ".buildkite/pipeline.yml"
50
+ - ".github/entrypoint.sh"
51
+ - ".github/workflows/ci.yml"
48
52
  - ".gitignore"
49
53
  - Gemfile
50
54
  - Gemfile.lock
@@ -55,12 +59,20 @@ files:
55
59
  - bin/console
56
60
  - bin/setup
57
61
  - config.toml
62
+ - lib/active_record/connection_adapters/tidb/database_statements.rb
58
63
  - lib/active_record/connection_adapters/tidb/database_tasks.rb
64
+ - lib/active_record/connection_adapters/tidb/schema_statements.rb
59
65
  - lib/active_record/connection_adapters/tidb/setup.rb
60
66
  - lib/active_record/connection_adapters/tidb/type.rb
61
67
  - lib/active_record/connection_adapters/tidb_adapter.rb
68
+ - lib/active_record/sequence.rb
69
+ - lib/active_record/sequence/adapter.rb
70
+ - lib/active_record/sequence/command_recorder.rb
71
+ - lib/active_record/sequence/model_methods.rb
72
+ - lib/active_record/sequence/schema_dumper.rb
62
73
  - lib/activerecord-tidb-adapter.rb
63
74
  - lib/version.rb
75
+ - testing.sh
64
76
  homepage: https://github.com/pingcap/activerecord-tidb-adapter
65
77
  licenses:
66
78
  - Apache-2.0