activerecord-tidb-adapter 6.1.0 → 7.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5f82e1eb06fb93971e146fafade1c45e2e3c5909e3968f32a719c9581efb55f3
4
- data.tar.gz: 5a0bc0100489a41230115924cbff3f52e1ef2206441724116135ed01ccdd28da
3
+ metadata.gz: 77b7efd6ea4bc98b6a72a6fb761aaab270881143f79eb362369b38e6cfa8965e
4
+ data.tar.gz: 878ca587a425ae2dd5fbe5bd2da03518b0dc7501c1b99a8c2f92c03fa39b1e19
5
5
  SHA512:
6
- metadata.gz: 0b059eabd253b3e7e0ead32528ac380d874dd9ab42ff942ec86ff3ddec86257b00aa5aea3c44912f95d3c0c8ba2dc7e8ba0a33abff668f6100f929fc2ed45f61
7
- data.tar.gz: 216b0b9917670ca40cd30d3c243493e88aaf2279d946b68eaa927b0a65d78226e075279f12c8839f32a4d9be8b3edb7c348ba2038cd25bfa2845dc62aa9d4944
6
+ metadata.gz: c8a5a80313df31083a7c0d54f8e2145ca148293f1844c644bb7530f77e1e73d736e9c79ae5c1d3b89d3b94fae5024bc565ec80a1cb659508e105a2894734c660
7
+ data.tar.gz: d6004fba604462b1358166c96ed905161dfb40c38285d9050ee0c42497ec6ad32bc897640b628cdc35a7c977d36688905d78a92d84308f7ce9bb76d8cf9171eb
@@ -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"
@@ -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,96 @@
1
+ name: activerecord-tidb-adapter main
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ - 7-0-stable
8
+ paths-ignore:
9
+ - 'README*.md'
10
+ - 'docs/**'
11
+ pull_request:
12
+ branches:
13
+ - main
14
+ - 7-0-stable
15
+ paths-ignore:
16
+ - 'README*.md'
17
+ - 'docs/**'
18
+
19
+ jobs:
20
+ tidb510:
21
+ if: ${{ !contains(github.event.commits[0].message, '[skip ci]') }}
22
+ runs-on: ubuntu-latest
23
+ services:
24
+ tidb:
25
+ image: hooopo/tidb-playground:v5.1.0
26
+ env:
27
+ TIDB_VERSION: v5.1.0
28
+ ports: ["4000:4000"]
29
+ steps:
30
+ - uses: actions/checkout@v2
31
+ - uses: ruby/setup-ruby@v1
32
+ with:
33
+ ruby-version: 2.7
34
+ bundler-cache: false
35
+ - run: bundle install
36
+ - 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
37
+ - run: sleep 10 && MYSQL_USER=root MYSQL_HOST=127.0.0.1 MYSQL_PORT=4000 tidb=1 ARCONN=tidb bundle exec rake test:tidb
38
+
39
+ tidb503:
40
+ if: ${{ !contains(github.event.commits[0].message, '[skip ci]') }}
41
+ runs-on: ubuntu-latest
42
+ services:
43
+ tidb:
44
+ image: hooopo/tidb-playground:v5.0.3
45
+ env:
46
+ TIDB_VERSION: v5.0.3
47
+ ports: ["4000:4000"]
48
+ steps:
49
+ - uses: actions/checkout@v2
50
+ - uses: ruby/setup-ruby@v1
51
+ with:
52
+ ruby-version: 2.7
53
+ bundler-cache: false
54
+ - run: bundle install
55
+ - 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
56
+ - run: mysql --host 127.0.0.1 --database activerecord_unittest --port 4000 -u root -e 'set @@global.tidb_enable_change_column_type = 1'
57
+ - run: mysql --host 127.0.0.1 --database activerecord_unittest2 --port 4000 -u root -e 'set @@global.tidb_enable_change_column_type = 1'
58
+ - run: sleep 10 && MYSQL_USER=root MYSQL_HOST=127.0.0.1 MYSQL_PORT=4000 tidb=1 ARCONN=tidb bundle exec rake test:tidb
59
+
60
+ tidb511:
61
+ if: ${{ !contains(github.event.commits[0].message, '[skip ci]') }}
62
+ runs-on: ubuntu-latest
63
+ services:
64
+ tidb:
65
+ image: hooopo/tidb-playground:v5.1.1
66
+ env:
67
+ TIDB_VERSION: v5.1.1
68
+ ports: ["4000:4000"]
69
+ steps:
70
+ - uses: actions/checkout@v2
71
+ - uses: ruby/setup-ruby@v1
72
+ with:
73
+ ruby-version: 2.7
74
+ bundler-cache: false
75
+ - run: bundle install
76
+ - 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
77
+ - run: sleep 10 && MYSQL_USER=root MYSQL_HOST=127.0.0.1 MYSQL_PORT=4000 tidb=1 ARCONN=tidb bundle exec rake test:tidb
78
+
79
+ tidb520:
80
+ if: ${{ !contains(github.event.commits[0].message, '[skip ci]') }}
81
+ runs-on: ubuntu-latest
82
+ services:
83
+ tidb:
84
+ image: hooopo/tidb-playground:v5.2.0
85
+ env:
86
+ TIDB_VERSION: v5.2.0
87
+ ports: ["4000:4000"]
88
+ steps:
89
+ - uses: actions/checkout@v2
90
+ - uses: ruby/setup-ruby@v1
91
+ with:
92
+ ruby-version: 2.7
93
+ bundler-cache: false
94
+ - run: bundle install
95
+ - 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
96
+ - 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,12 @@ gem 'pry'
14
14
 
15
15
  gem 'rubocop', '~> 1.18'
16
16
 
17
- gem 'rails', git: 'https://github.com/pingcap/rails.git', branch: '6-1-stable'
17
+ gem 'rails', git: 'https://github.com/pingcap/rails.git', branch: '7-0-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 "benchmark-ips", "~> 2.9"
data/Gemfile.lock CHANGED
@@ -1,126 +1,150 @@
1
1
  GIT
2
2
  remote: https://github.com/pingcap/rails.git
3
- revision: e2a3d3fb2ee24c709b9f32221fbcb66cfda5acfc
4
- branch: 6-1-stable
3
+ revision: 8e88c0ecd838d642c542e8246a0b7c6e9df9c806
4
+ branch: 7-0-stable
5
5
  specs:
6
- actioncable (6.1.4)
7
- actionpack (= 6.1.4)
8
- activesupport (= 6.1.4)
6
+ actioncable (7.0.2.3)
7
+ actionpack (= 7.0.2.3)
8
+ activesupport (= 7.0.2.3)
9
9
  nio4r (~> 2.0)
10
10
  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)
11
+ actionmailbox (7.0.2.3)
12
+ actionpack (= 7.0.2.3)
13
+ activejob (= 7.0.2.3)
14
+ activerecord (= 7.0.2.3)
15
+ activestorage (= 7.0.2.3)
16
+ activesupport (= 7.0.2.3)
17
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)
18
+ net-imap
19
+ net-pop
20
+ net-smtp
21
+ actionmailer (7.0.2.3)
22
+ actionpack (= 7.0.2.3)
23
+ actionview (= 7.0.2.3)
24
+ activejob (= 7.0.2.3)
25
+ activesupport (= 7.0.2.3)
23
26
  mail (~> 2.5, >= 2.5.4)
27
+ net-imap
28
+ net-pop
29
+ net-smtp
24
30
  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)
31
+ actionpack (7.0.2.3)
32
+ actionview (= 7.0.2.3)
33
+ activesupport (= 7.0.2.3)
34
+ rack (~> 2.0, >= 2.2.0)
29
35
  rack-test (>= 0.6.3)
30
36
  rails-dom-testing (~> 2.0)
31
37
  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)
38
+ actiontext (7.0.2.3)
39
+ actionpack (= 7.0.2.3)
40
+ activerecord (= 7.0.2.3)
41
+ activestorage (= 7.0.2.3)
42
+ activesupport (= 7.0.2.3)
43
+ globalid (>= 0.6.0)
37
44
  nokogiri (>= 1.8.5)
38
- actionview (6.1.4)
39
- activesupport (= 6.1.4)
45
+ actionview (7.0.2.3)
46
+ activesupport (= 7.0.2.3)
40
47
  builder (~> 3.1)
41
48
  erubi (~> 1.4)
42
49
  rails-dom-testing (~> 2.0)
43
50
  rails-html-sanitizer (~> 1.1, >= 1.2.0)
44
- activejob (6.1.4)
45
- activesupport (= 6.1.4)
51
+ activejob (7.0.2.3)
52
+ activesupport (= 7.0.2.3)
46
53
  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)
57
- marcel (~> 1.0.0)
54
+ activemodel (7.0.2.3)
55
+ activesupport (= 7.0.2.3)
56
+ activerecord (7.0.2.3)
57
+ activemodel (= 7.0.2.3)
58
+ activesupport (= 7.0.2.3)
59
+ activestorage (7.0.2.3)
60
+ actionpack (= 7.0.2.3)
61
+ activejob (= 7.0.2.3)
62
+ activerecord (= 7.0.2.3)
63
+ activesupport (= 7.0.2.3)
64
+ marcel (~> 1.0)
58
65
  mini_mime (>= 1.1.0)
59
- activesupport (6.1.4)
66
+ activesupport (7.0.2.3)
60
67
  concurrent-ruby (~> 1.0, >= 1.0.2)
61
68
  i18n (>= 1.6, < 2)
62
69
  minitest (>= 5.1)
63
70
  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)
71
+ rails (7.0.2.3)
72
+ actioncable (= 7.0.2.3)
73
+ actionmailbox (= 7.0.2.3)
74
+ actionmailer (= 7.0.2.3)
75
+ actionpack (= 7.0.2.3)
76
+ actiontext (= 7.0.2.3)
77
+ actionview (= 7.0.2.3)
78
+ activejob (= 7.0.2.3)
79
+ activemodel (= 7.0.2.3)
80
+ activerecord (= 7.0.2.3)
81
+ activestorage (= 7.0.2.3)
82
+ activesupport (= 7.0.2.3)
77
83
  bundler (>= 1.15.0)
78
- railties (= 6.1.4)
79
- sprockets-rails (>= 2.0.0)
80
- railties (6.1.4)
81
- actionpack (= 6.1.4)
82
- activesupport (= 6.1.4)
84
+ railties (= 7.0.2.3)
85
+ railties (7.0.2.3)
86
+ actionpack (= 7.0.2.3)
87
+ activesupport (= 7.0.2.3)
83
88
  method_source
84
- rake (>= 0.13)
89
+ rake (>= 12.2)
85
90
  thor (~> 1.0)
91
+ zeitwerk (~> 2.5)
86
92
 
87
93
  PATH
88
94
  remote: .
89
95
  specs:
90
- activerecord-tidb-adapter (6.1.0)
91
- activerecord (~> 6.1)
96
+ activerecord-tidb-adapter (7.0.0)
97
+ activerecord (~> 7.0.1)
92
98
  mysql2
93
99
 
94
100
  GEM
95
101
  remote: https://rubygems.org/
96
102
  specs:
97
103
  ast (2.4.2)
104
+ benchmark-ips (2.9.1)
98
105
  builder (3.2.4)
99
106
  byebug (11.1.3)
100
107
  coderay (1.1.3)
101
- concurrent-ruby (1.1.9)
108
+ concurrent-ruby (1.1.10)
102
109
  crass (1.0.6)
110
+ digest (3.1.0)
103
111
  erubi (1.10.0)
104
- globalid (0.5.2)
112
+ globalid (1.0.0)
105
113
  activesupport (>= 5.0)
106
- i18n (1.8.10)
114
+ i18n (1.10.0)
107
115
  concurrent-ruby (~> 1.0)
108
- loofah (2.12.0)
116
+ io-wait (0.2.1)
117
+ loofah (2.15.0)
109
118
  crass (~> 1.0.2)
110
119
  nokogiri (>= 1.5.9)
111
120
  mail (2.7.1)
112
121
  mini_mime (>= 0.1.1)
113
- marcel (1.0.1)
122
+ marcel (1.0.2)
114
123
  method_source (1.0.0)
115
- mini_mime (1.1.0)
124
+ mini_mime (1.1.2)
116
125
  minitest (5.14.4)
117
126
  minitest-excludes (2.0.1)
118
127
  minitest (~> 5.0)
119
128
  mysql2 (0.5.3)
129
+ net-imap (0.2.3)
130
+ digest
131
+ net-protocol
132
+ strscan
133
+ net-pop (0.1.1)
134
+ digest
135
+ net-protocol
136
+ timeout
137
+ net-protocol (0.1.2)
138
+ io-wait
139
+ timeout
140
+ net-smtp (0.3.1)
141
+ digest
142
+ net-protocol
143
+ timeout
120
144
  nio4r (2.5.8)
121
- nokogiri (1.12.3-x86_64-darwin)
145
+ nokogiri (1.13.3-x86_64-darwin)
122
146
  racc (~> 1.4)
123
- nokogiri (1.12.3-x86_64-linux)
147
+ nokogiri (1.13.3-x86_64-linux)
124
148
  racc (~> 1.4)
125
149
  parallel (1.20.1)
126
150
  parser (3.0.2.0)
@@ -129,14 +153,14 @@ GEM
129
153
  pry (0.14.1)
130
154
  coderay (~> 1.1)
131
155
  method_source (~> 1.0)
132
- racc (1.5.2)
156
+ racc (1.6.0)
133
157
  rack (2.2.3)
134
158
  rack-test (1.1.0)
135
159
  rack (>= 1.0, < 3)
136
160
  rails-dom-testing (2.0.3)
137
161
  activesupport (>= 4.2.0)
138
162
  nokogiri (>= 1.6)
139
- rails-html-sanitizer (1.4.1)
163
+ rails-html-sanitizer (1.4.2)
140
164
  loofah (~> 2.3)
141
165
  rainbow (3.0.0)
142
166
  rake (13.0.6)
@@ -154,29 +178,27 @@ GEM
154
178
  rubocop-ast (1.10.0)
155
179
  parser (>= 3.0.1.1)
156
180
  ruby-progressbar (1.11.0)
157
- sprockets (4.0.2)
158
- concurrent-ruby (~> 1.0)
159
- rack (> 1, < 3)
160
- sprockets-rails (3.2.2)
161
- actionpack (>= 4.0)
162
- activesupport (>= 4.0)
163
- sprockets (>= 3.0.0)
164
181
  sqlite3 (1.4.2)
165
- thor (1.1.0)
182
+ strscan (3.0.1)
183
+ thor (1.2.1)
184
+ timeout (0.2.0)
166
185
  tzinfo (2.0.4)
167
186
  concurrent-ruby (~> 1.0)
168
187
  unicode-display_width (2.0.0)
169
188
  websocket-driver (0.7.5)
170
189
  websocket-extensions (>= 0.1.0)
171
190
  websocket-extensions (0.1.5)
172
- zeitwerk (2.4.2)
191
+ zeitwerk (2.5.4)
173
192
 
174
193
  PLATFORMS
175
194
  x86_64-darwin-18
195
+ x86_64-darwin-20
196
+ x86_64-darwin-21
176
197
  x86_64-linux
177
198
 
178
199
  DEPENDENCIES
179
200
  activerecord-tidb-adapter!
201
+ benchmark-ips (~> 2.9)
180
202
  byebug (~> 11.1)
181
203
  minitest (~> 5.0)
182
204
  minitest-excludes (~> 2.0)
@@ -188,4 +210,4 @@ DEPENDENCIES
188
210
  sqlite3 (~> 1.4)
189
211
 
190
212
  BUNDLED WITH
191
- 2.2.25
213
+ 2.3.10
data/README.md CHANGED
@@ -1,6 +1,10 @@
1
1
  # ActiveRecord TiDB Adapter
2
2
 
3
- TiDB adapter for ActiveRecord 5 and 6. This is a lightweight extension of the mysql2 adapter that establishes compatibility with [TiDB](https://github.com/pingcap/tidb).
3
+ [![Gem Version](https://badge.fury.io/rb/activerecord-tidb-adapter.svg)](https://badge.fury.io/rb/activerecord-tidb-adapter)
4
+ [![activerecord-tidb-adapter 7.0](https://github.com/pingcap/activerecord-tidb-adapter/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/pingcap/activerecord-tidb-adapter/actions/workflows/ci.yml)
5
+
6
+ TiDB adapter for ActiveRecord 5.2, 6.1 and 7.0
7
+ This is a lightweight extension of the mysql2 adapter that establishes compatibility with [TiDB](https://github.com/pingcap/tidb).
4
8
 
5
9
 
6
10
  ## Installation
@@ -8,9 +12,13 @@ TiDB adapter for ActiveRecord 5 and 6. This is a lightweight extension of the my
8
12
  Add this line to your application's Gemfile:
9
13
 
10
14
  ```ruby
11
- gem 'activerecord-tidb-adapter', "~> 6.1.0"
15
+ gem 'activerecord-tidb-adapter', '~> 6.1.0'
12
16
  ```
13
17
 
18
+ If you're using Rails 5.2, use the 5.2.x versions of this gem.
19
+
20
+ If you're using Rails 6.1, use the 6.1.x versions of this gem.
21
+
14
22
  And then execute:
15
23
 
16
24
  $ bundle install
@@ -68,24 +76,6 @@ class TestSeq < ActiveRecord::Migration[6.1]
68
76
  end
69
77
  ```
70
78
 
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
79
  This gem also adds a few helpers to interact with `SEQUENCE`
90
80
 
91
81
  ```ruby
@@ -99,6 +89,41 @@ ActiveRecord::Base.lastval("numbers")
99
89
  ActiveRecord::Base.setval("numbers", 1234)
100
90
  ```
101
91
 
92
+ **[CTE](https://docs.pingcap.com/tidb/dev/sql-statement-with#with)**
93
+
94
+ ```bash
95
+ $ bundle add activerecord-cte
96
+
97
+ ```
98
+
99
+ ```ruby
100
+ require 'activerecord/cte'
101
+
102
+ Post
103
+ .with(posts_with_tags: "SELECT * FROM posts WHERE tags_count > 0")
104
+ .from("posts_with_tags AS posts")
105
+ # WITH posts_with_tags AS (
106
+ # SELECT * FROM posts WHERE (tags_count > 0)
107
+ # )
108
+ # SELECT * FROM posts_with_tags AS posts
109
+
110
+ Post
111
+ .with(posts_with_tags: "SELECT * FROM posts WHERE tags_count > 0")
112
+ .from("posts_with_tags AS posts")
113
+ .count
114
+
115
+ # WITH posts_with_tags AS (
116
+ # SELECT * FROM posts WHERE (tags_count > 0)
117
+ # )
118
+ # SELECT COUNT(*) FROM posts_with_tags AS posts
119
+
120
+ Post
121
+ .with(posts_with_tags: Post.where("tags_count > 0"))
122
+ .from("posts_with_tags AS posts")
123
+ .count
124
+
125
+ ```
126
+
102
127
 
103
128
  ## Setting up local TiDB server
104
129
 
@@ -113,6 +138,10 @@ Starting TiDB playground
113
138
  $ tiup playground nightly
114
139
  ```
115
140
 
141
+ ## Tutorials
142
+
143
+ * [Build a Rails App with TiDB and the ActiveRecord TiDB Adapter](https://gist.github.com/hooopo/83db933ab07a054f70e23da0ff945747)
144
+
116
145
  ## Development
117
146
 
118
147
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -12,7 +12,7 @@ Gem::Specification.new do |spec|
12
12
  spec.description = 'Allows the use of TiDB as a backend for ActiveRecord and Rails apps.'
13
13
  spec.homepage = 'https://github.com/pingcap/activerecord-tidb-adapter'
14
14
  spec.license = 'Apache-2.0'
15
- spec.required_ruby_version = '>= 2.4.0'
15
+ spec.required_ruby_version = '>= 2.7.0'
16
16
 
17
17
  # spec.metadata["allowed_push_host"] = "TODO: Set to 'https://mygemserver.com'"
18
18
 
@@ -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', '~> 7.0.1'
33
33
  spec.add_dependency 'mysql2'
34
34
 
35
35
  # Uncomment to register a new dependency of your gem
data/config.toml CHANGED
@@ -1 +1,2 @@
1
1
  new_collations_enabled_on_first_bootstrap = true
2
+ allow-expression-index = true
@@ -0,0 +1,25 @@
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
+ return id_value if id_value.present?
8
+ return last_inserted_id(value) if arel.is_a?(String)
9
+ model = arel.ast.relation.instance_variable_get(:@klass)
10
+ pk_def = schema_cache.columns_hash(model.table_name)[pk]
11
+ if pk_def&.default_function && pk_def.default_function =~ /nextval/
12
+ query_value("SELECT #{pk_def.default_function.sub('nextval', 'lastval')}")
13
+ else
14
+ last_inserted_id(value)
15
+ end
16
+ end
17
+ alias create insert
18
+
19
+ def transaction_isolation_levels
20
+ {
21
+ read_committed: 'READ COMMITTED',
22
+ repeatable_read: 'REPEATABLE READ'
23
+ }
24
+ end
25
+ end
@@ -0,0 +1,71 @@
1
+ require 'active_record/connection_adapters/mysql/schema_statements'
2
+
3
+ ActiveRecord::ConnectionAdapters::MySQL::SchemaStatements.class_eval do
4
+ def indexes(table_name)
5
+ indexes = []
6
+ current_index = nil
7
+ execute_and_free("SHOW KEYS FROM #{quote_table_name(table_name)}", "SCHEMA") do |result|
8
+ each_hash(result) do |row|
9
+ if current_index != row[:Key_name]
10
+ next if row[:Key_name] == "PRIMARY" # skip the primary key
11
+ current_index = row[:Key_name]
12
+
13
+ mysql_index_type = row[:Index_type].downcase.to_sym
14
+ case mysql_index_type
15
+ when :fulltext, :spatial
16
+ index_type = mysql_index_type
17
+ when :btree, :hash
18
+ index_using = mysql_index_type
19
+ end
20
+
21
+ indexes << [
22
+ row[:Table],
23
+ row[:Key_name],
24
+ row[:Non_unique].to_i == 0,
25
+ [],
26
+ lengths: {},
27
+ orders: {},
28
+ type: index_type,
29
+ using: index_using,
30
+ comment: row[:Index_comment].presence
31
+ ]
32
+ end
33
+
34
+ # FIX https://github.com/pingcap/tidb/issues/26110 for older version of TiDB
35
+ row[:Expression] = nil if row[:Expression] == 'NULL'
36
+
37
+ if row[:Expression]
38
+ expression = row[:Expression]
39
+ expression = +"(#{expression})" unless expression.start_with?("(")
40
+ indexes.last[-2] << expression
41
+ indexes.last[-1][:expressions] ||= {}
42
+ indexes.last[-1][:expressions][expression] = expression
43
+ indexes.last[-1][:orders][expression] = :desc if row[:Collation] == "D"
44
+ else
45
+ indexes.last[-2] << row[:Column_name]
46
+ indexes.last[-1][:lengths][row[:Column_name]] = row[:Sub_part].to_i if row[:Sub_part]
47
+ indexes.last[-1][:orders][row[:Column_name]] = :desc if row[:Collation] == "D"
48
+ end
49
+ end
50
+ end
51
+
52
+ indexes.map do |index|
53
+ options = index.pop
54
+
55
+ if expressions = options.delete(:expressions)
56
+ orders = options.delete(:orders)
57
+ lengths = options.delete(:lengths)
58
+
59
+ columns = index[-1].map { |name|
60
+ [ name.to_sym, expressions[name] || +quote_column_name(name) ]
61
+ }.to_h
62
+
63
+ index[-1] = add_options_for_index_columns(
64
+ columns, order: orders, length: lengths
65
+ ).values.join(", ")
66
+ end
67
+
68
+ ActiveRecord::ConnectionAdapters::IndexDefinition.new(*index, **options)
69
+ end
70
+ end
71
+ end
@@ -5,6 +5,8 @@ require 'active_record/connection_adapters/mysql2_adapter'
5
5
  require 'active_record/connection_adapters/tidb/setup'
6
6
  require_relative '../../version'
7
7
  require_relative '../sequence'
8
+ require_relative 'tidb/schema_statements'
9
+ require_relative 'tidb/database_statements'
8
10
 
9
11
  ActiveRecord::ConnectionAdapters::Tidb.initial_setup
10
12
 
@@ -36,18 +38,22 @@ module ActiveRecord
36
38
  ADAPTER_NAME = 'Tidb'
37
39
 
38
40
  def supports_savepoints?
41
+ # https://github.com/pingcap/tidb/issues/6840 support is required
39
42
  false
40
43
  end
41
44
 
42
45
  def supports_foreign_keys?
46
+ # https://github.com/pingcap/tidb/issues/18209 support is required
43
47
  false
44
48
  end
45
49
 
46
50
  def supports_bulk_alter?
51
+ # https://github.com/pingcap/tidb/issues/14766 support is required
47
52
  false
48
53
  end
49
54
 
50
55
  def supports_advisory_locks?
56
+ # https://github.com/pingcap/tidb/issues/14994 support is required
51
57
  false
52
58
  end
53
59
 
@@ -60,25 +66,23 @@ module ActiveRecord
60
66
  end
61
67
 
62
68
  def supports_index_sort_order?
63
- # TODO: check TiDB version
64
- true
69
+ # https://github.com/pingcap/tidb/issues/2519 support is required
70
+ false
65
71
  end
66
72
 
67
73
  def supports_expression_index?
68
- true
74
+ sql = <<~SQL
75
+ SELECT VALUE
76
+ FROM INFORMATION_SCHEMA.CLUSTER_CONFIG
77
+ WHERE `KEY` = 'experimental.allow-expression-index' AND `TYPE` = 'tidb'
78
+ SQL
79
+ query_value(sql) == 'true'
69
80
  end
70
81
 
71
82
  def supports_common_table_expressions?
72
83
  tidb_version >= '5.1.0'
73
84
  end
74
85
 
75
- def transaction_isolation_levels
76
- {
77
- read_committed: 'READ COMMITTED',
78
- repeatable_read: 'REPEATABLE READ'
79
- }
80
- end
81
-
82
86
  def initialize(connection, logger, conn_params, config)
83
87
  super(connection, logger, conn_params, config)
84
88
 
@@ -100,29 +104,13 @@ module ActiveRecord
100
104
  false
101
105
  end
102
106
 
103
- def insert(arel, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = [])
104
- sql, binds = to_sql_and_binds(arel, binds)
105
- value = exec_insert(sql, name, binds, pk, sequence_name)
106
- return id_value if id_value.present?
107
-
108
- model = arel.ast.relation.instance_variable_get(:@klass)
109
- pk_def = schema_cache.columns_hash(model.table_name)[pk]
110
- if pk_def&.default_function && pk_def.default_function =~ /nextval/
111
- query_value("SELECT #{pk_def.default_function.sub('nextval', 'lastval')}")
112
- elsif model.sequence_name
113
- ActiveRecord::Base.lastval(model.sequence_name)
114
- else
115
- last_inserted_id(value)
116
- end
117
- end
118
- alias create insert
119
-
120
107
  def new_column_from_field(_table_name, field)
121
108
  type_metadata = fetch_type_metadata(field[:Type], field[:Extra])
122
109
  default = field[:Default]
123
110
  default_function = nil
124
111
 
125
112
  if type_metadata.type == :datetime && /\ACURRENT_TIMESTAMP(?:\([0-6]?\))?\z/i.match?(default)
113
+ default = "#{default} ON UPDATE #{default}" if /on update CURRENT_TIMESTAMP/i.match?(field[:Extra])
126
114
  default_function = default
127
115
  default = nil
128
116
  elsif type_metadata.extra == 'DEFAULT_GENERATED'
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 = '6.1.0'
4
+ TIDB_ADAPTER_VERSION = '7.0.0'
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: 6.1.0
4
+ version: 7.0.0
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-19 00:00:00.000000000 Z
11
+ date: 2022-03-31 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: 7.0.1
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: 7.0.1
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,7 +59,9 @@ 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
@@ -66,6 +72,7 @@ files:
66
72
  - lib/active_record/sequence/schema_dumper.rb
67
73
  - lib/activerecord-tidb-adapter.rb
68
74
  - lib/version.rb
75
+ - testing.sh
69
76
  homepage: https://github.com/pingcap/activerecord-tidb-adapter
70
77
  licenses:
71
78
  - Apache-2.0
@@ -80,7 +87,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
80
87
  requirements:
81
88
  - - ">="
82
89
  - !ruby/object:Gem::Version
83
- version: 2.4.0
90
+ version: 2.7.0
84
91
  required_rubygems_version: !ruby/object:Gem::Requirement
85
92
  requirements:
86
93
  - - ">="