Skip to content

Commit d8ed972

Browse files
authored
feat: support automatic redirection to __sys__ (#296)
* feat: support automatic redirection to __sys__ Signed-off-by: Noy <[email protected]> * ci: let clients compatibility tests recover Signed-off-by: Noy <[email protected]> --------- Signed-off-by: Noy <[email protected]>
1 parent 708d026 commit d8ed972

File tree

5 files changed

+57
-11
lines changed

5 files changed

+57
-11
lines changed

.github/workflows/clients-compatibility.yml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ jobs:
3333
- name: Install system packages
3434
uses: awalsh128/cache-apt-pkgs-action@latest
3535
with:
36-
packages: bats cpanminus libmysqlclient-dev dotnet-sdk-8.0 dotnet-runtime-8.0 php-mysql r-base-core libblas-dev
37-
version: 1.0
36+
packages: bats cpanminus libmysqlclient-dev dotnet-sdk-8.0 dotnet-runtime-8.0 php-mysql r-base-core
37+
version: 1.1
3838

3939
- name: Install dependencies
4040
run: |
@@ -52,6 +52,7 @@ jobs:
5252
npm install mysql
5353
sudo cpanm --notest DBD::mysql
5454
pip3 install mysql-connector-python
55+
sudo apt-get install -y libblas-dev
5556
sudo R -e "install.packages('RMySQL', repos='http://cran.r-project.org')"
5657
sudo gem install mysql2
5758
@@ -90,8 +91,8 @@ jobs:
9091
- name: Install system packages
9192
uses: awalsh128/cache-apt-pkgs-action@latest
9293
with:
93-
packages: bats cpanminus libpq-dev postgresql-client dotnet-sdk-8.0 dotnet-runtime-8.0 r-base-core libblas-dev
94-
version: 1.0
94+
packages: bats cpanminus libpq-dev postgresql-client dotnet-sdk-8.0 dotnet-runtime-8.0 r-base-core
95+
version: 1.1
9596

9697
- name: Install dependencies
9798
run: |
@@ -109,6 +110,7 @@ jobs:
109110
npm install pg
110111
sudo cpanm --notest DBD::Pg
111112
pip3 install "psycopg[binary]" pandas pyarrow polars
113+
sudo apt-get install -y libblas-dev
112114
# TODO: Speed up the installation of RPostgres
113115
sudo R -e "install.packages('RPostgres', repos='http://cran.r-project.org')"
114116
sudo gem install pg

catalog/internal_tables.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,7 @@ var InternalTables = struct {
177177
// Once we add 'pg_catalog' and support views for PG, replace this by a view.
178178
// https://www.postgresql.org/docs/current/monitoring-stats.html#MONITORING-PG-STAT-REPLICATION-VIEW
179179
PGStatReplication InternalTable
180+
PGRange InternalTable
180181
}{
181182
PersistentVariable: InternalTable{
182183
Schema: "__sys__",
@@ -287,6 +288,21 @@ var InternalTables = struct {
287288
},
288289
DDL: "pid INTEGER PRIMARY KEY, usesysid TEXT, usename TEXT, application_name TEXT, client_addr TEXT, client_hostname TEXT, client_port INTEGER, backend_start TIMESTAMP, backend_xmin INTEGER, state TEXT, sent_lsn TEXT, write_lsn TEXT, flush_lsn TEXT, replay_lsn TEXT, write_lag INTERVAL, flush_lag INTERVAL, replay_lag INTERVAL, sync_priority INTEGER, sync_state TEXT, reply_time TIMESTAMP",
289290
},
291+
PGRange: InternalTable{
292+
Schema: "__sys__",
293+
Name: "pg_range",
294+
KeyColumns: []string{"rngtypid"},
295+
ValueColumns: []string{"rngsubtype", "rngmultitypid", "rngcollation", "rngsubopc", "rngcanonical", "rngsubdiff"},
296+
DDL: "rngtypid TEXT PRIMARY KEY, rngsubtype TEXT, rngmultitypid TEXT, rngcollation TEXT, rngsubopc TEXT, rngcanonical TEXT, rngsubdiff TEXT",
297+
InitialData: [][]any{
298+
{"3904", "23", "4451", "0", "1978", "int4range_canonical", "int4range_subdiff"},
299+
{"3906", "1700", "4532", "0", "3125", "-", "numrange_subdiff"},
300+
{"3908", "1114", "4533", "0", "3128", "-", "tsrange_subdiff"},
301+
{"3910", "1184", "4534", "0", "3127", "-", "tstzrange_subdiff"},
302+
{"3912", "1082", "4535", "0", "3122", "daterange_canonical", "daterange_subdiff"},
303+
{"3926", "20", "4536", "0", "3124", "int8range_canonical", "int8range_subdiff"},
304+
},
305+
},
290306
}
291307

292308
var internalTables = []InternalTable{
@@ -295,4 +311,9 @@ var internalTables = []InternalTable{
295311
InternalTables.PgSubscription,
296312
InternalTables.GlobalStatus,
297313
InternalTables.PGStatReplication,
314+
InternalTables.PGRange,
315+
}
316+
317+
func GetInternalTables() []InternalTable {
318+
return internalTables
298319
}

pgserver/duck_handler.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -424,7 +424,7 @@ func (h *DuckHandler) executeQuery(ctx *sql.Context, query string, parsed tree.S
424424
}))
425425

426426
default:
427-
rows, err = adapter.QueryCatalog(ctx, query)
427+
rows, err = adapter.QueryCatalog(ctx, ConvertToSys(query))
428428
if err != nil {
429429
break
430430
}

pgserver/pg_catalog_handler.go

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,6 @@ var pgWALLSNRegex = regexp.MustCompile(`(?i)^\s*select\s+pg_catalog\.(pg_current
2525
// precompile a regex to match "select pg_catalog.current_setting('xxx');".
2626
var currentSettingRegex = regexp.MustCompile(`(?i)^\s*select\s+(pg_catalog.)?current_setting\(\s*'([^']+)'\s*\)\s*;?\s*$`)
2727

28-
// precompile a regex to match any "from pg_catalog.pg_stat_replication" in the query.
29-
var pgCatalogRegex = regexp.MustCompile(`(?i)\s+from\s+pg_catalog\.(pg_stat_replication)`)
30-
3128
// isInRecovery will get the count of
3229
func (h *ConnectionHandler) isInRecovery() (string, error) {
3330
// Grab a sql.Context.
@@ -167,9 +164,8 @@ func (h *ConnectionHandler) handleCurrentSetting(query ConvertedStatement) (bool
167164

168165
// handler for pgCatalog
169166
func (h *ConnectionHandler) handlePgCatalog(query ConvertedStatement) (bool, error) {
170-
sql := RemoveComments(query.String)
171167
return true, h.run(ConvertedStatement{
172-
String: pgCatalogRegex.ReplaceAllString(sql, " FROM __sys__.$1"),
168+
String: ConvertToSys(query.String),
173169
Tag: "SELECT",
174170
})
175171
}
@@ -208,7 +204,7 @@ func isPgCurrentSetting(query ConvertedStatement) bool {
208204

209205
func isSpecialPgCatalog(query ConvertedStatement) bool {
210206
sql := RemoveComments(query.String)
211-
return pgCatalogRegex.MatchString(sql)
207+
return getPgCatalogRegex().MatchString(sql)
212208
}
213209

214210
// The key is the statement tag of the query.

pgserver/stmt.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ package pgserver
22

33
import (
44
"bytes"
5+
"github.com/apecloud/myduckserver/catalog"
6+
"regexp"
57
"strings"
8+
"sync"
69
"unicode"
710

811
"github.com/dolthub/go-mysql-server/sql"
@@ -259,3 +262,27 @@ func RemoveComments(query string) string {
259262

260263
return buf.String()
261264
}
265+
266+
var (
267+
pgCatalogRegex *regexp.Regexp
268+
initPgCatalogRegex sync.Once
269+
)
270+
271+
// get the regex to match any table in pg_catalog in the query.
272+
func getPgCatalogRegex() *regexp.Regexp {
273+
initPgCatalogRegex.Do(func() {
274+
var tableNames []string
275+
for _, table := range catalog.GetInternalTables() {
276+
if table.Schema != "__sys__" {
277+
continue
278+
}
279+
tableNames = append(tableNames, table.Name)
280+
}
281+
pgCatalogRegex = regexp.MustCompile(`(?i)\b(?:FROM|JOIN)\s+(?:pg_catalog\.)?(` + strings.Join(tableNames, "|") + `)`)
282+
})
283+
return pgCatalogRegex
284+
}
285+
286+
func ConvertToSys(sql string) string {
287+
return getPgCatalogRegex().ReplaceAllString(RemoveComments(sql), " __sys__.$1")
288+
}

0 commit comments

Comments
 (0)