mirror of
https://github.com/dolthub/dolt.git
synced 2026-01-07 00:39:44 -06:00
Fixed DELIMITER
This commit is contained in:
@@ -21,7 +21,6 @@ import (
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
@@ -111,8 +110,6 @@ const (
|
||||
# "exit" or "quit" (or Ctrl-D) to exit.`
|
||||
)
|
||||
|
||||
var delimiterRegex = regexp.MustCompile(`(?i)^\s*DELIMITER\s+(\S+)\s*(\s+\S+\s*)?$`)
|
||||
|
||||
func init() {
|
||||
dsqle.AddDoltSystemVariables()
|
||||
}
|
||||
@@ -809,47 +806,39 @@ func runMultiStatementMode(ctx *sql.Context, se *engine.SqlEngine, input io.Read
|
||||
if len(query) == 0 || query == "\n" {
|
||||
continue
|
||||
}
|
||||
shouldProcessQuery := true
|
||||
if matches := delimiterRegex.FindStringSubmatch(query); len(matches) == 3 {
|
||||
// If we don't match from anything, then we just pass to the SQL engine and let it complain.
|
||||
scanner.Delimiter = matches[1]
|
||||
shouldProcessQuery = false
|
||||
sqlStatement, err := sqlparser.Parse(query)
|
||||
if err == sqlparser.ErrEmpty {
|
||||
continue
|
||||
} else if err != nil {
|
||||
handleError(scanner.statementStartLine, query, err)
|
||||
// If continueOnErr is set keep executing the remaining queries but print the error out anyway.
|
||||
if !continueOnErr {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if shouldProcessQuery {
|
||||
sqlStatement, err := sqlparser.Parse(query)
|
||||
if err == sqlparser.ErrEmpty {
|
||||
continue
|
||||
} else if err != nil {
|
||||
handleError(scanner.statementStartLine, query, err)
|
||||
// If continueOnErr is set keep executing the remaining queries but print the error out anyway.
|
||||
if !continueOnErr {
|
||||
return err
|
||||
|
||||
sqlSch, rowIter, err := processParsedQuery(ctx, query, se, sqlStatement)
|
||||
if err != nil {
|
||||
handleError(scanner.statementStartLine, query, err)
|
||||
// If continueOnErr is set keep executing the remaining queries but print the error out anyway.
|
||||
if !continueOnErr {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if rowIter != nil {
|
||||
switch sqlStatement.(type) {
|
||||
case *sqlparser.Select, *sqlparser.Insert, *sqlparser.Update, *sqlparser.Delete,
|
||||
*sqlparser.OtherRead, *sqlparser.Show, *sqlparser.Explain, *sqlparser.Union:
|
||||
// For any statement that prints out result, print a newline to put the regular output on its own line
|
||||
if fileReadProg != nil {
|
||||
fileReadProg.printNewLineIfNeeded()
|
||||
}
|
||||
}
|
||||
|
||||
sqlSch, rowIter, err := processParsedQuery(ctx, query, se, sqlStatement)
|
||||
err = engine.PrettyPrintResults(ctx, se.GetResultFormat(), sqlSch, rowIter)
|
||||
if err != nil {
|
||||
handleError(scanner.statementStartLine, query, err)
|
||||
// If continueOnErr is set keep executing the remaining queries but print the error out anyway.
|
||||
if !continueOnErr {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if rowIter != nil {
|
||||
switch sqlStatement.(type) {
|
||||
case *sqlparser.Select, *sqlparser.Insert, *sqlparser.Update, *sqlparser.Delete,
|
||||
*sqlparser.OtherRead, *sqlparser.Show, *sqlparser.Explain, *sqlparser.Union:
|
||||
// For any statement that prints out result, print a newline to put the regular output on its own line
|
||||
if fileReadProg != nil {
|
||||
fileReadProg.printNewLineIfNeeded()
|
||||
}
|
||||
}
|
||||
err = engine.PrettyPrintResults(ctx, se.GetResultFormat(), sqlSch, rowIter)
|
||||
if err != nil {
|
||||
handleError(scanner.statementStartLine, query, err)
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
}
|
||||
query = ""
|
||||
@@ -881,22 +870,14 @@ func runBatchMode(ctx *sql.Context, se *engine.SqlEngine, input io.Reader, conti
|
||||
if len(query) == 0 || query == "\n" {
|
||||
continue
|
||||
}
|
||||
shouldProcessQuery := true
|
||||
if matches := delimiterRegex.FindStringSubmatch(query); len(matches) == 3 {
|
||||
// If we don't match from anything, then we just pass to the SQL engine and let it complain.
|
||||
scanner.Delimiter = matches[1]
|
||||
shouldProcessQuery = false
|
||||
}
|
||||
if shouldProcessQuery {
|
||||
if err := processBatchQuery(ctx, query, se); err != nil {
|
||||
// TODO: this line number will not be accurate for errors that occur when flushing a batch of inserts (as opposed
|
||||
// to processing the query)
|
||||
verr := formatQueryError(fmt.Sprintf("error on line %d for query %s", scanner.statementStartLine, query), err)
|
||||
cli.PrintErrln(verr.Verbose())
|
||||
// If continueOnErr is set keep executing the remaining queries but print the error out anyway.
|
||||
if !continueOnErr {
|
||||
return err
|
||||
}
|
||||
if err := processBatchQuery(ctx, query, se); err != nil {
|
||||
// TODO: this line number will not be accurate for errors that occur when flushing a batch of inserts (as opposed
|
||||
// to processing the query)
|
||||
verr := formatQueryError(fmt.Sprintf("error on line %d for query %s", scanner.statementStartLine, query), err)
|
||||
cli.PrintErrln(verr.Verbose())
|
||||
// If continueOnErr is set keep executing the remaining queries but print the error out anyway.
|
||||
if !continueOnErr {
|
||||
return err
|
||||
}
|
||||
}
|
||||
query = ""
|
||||
@@ -1002,30 +983,18 @@ func runShell(ctx context.Context, se *engine.SqlEngine, mrEnv *env.MultiRepoEnv
|
||||
query = strings.TrimSuffix(query, shell.LineTerminator())
|
||||
resultFormat := se.GetResultFormat()
|
||||
|
||||
// TODO: it would be better to build this into the statement parser rahter than special case it here
|
||||
// TODO: it would be better to build this into the statement parser rather than special case it here
|
||||
for _, terminator := range verticalOutputLineTerminators {
|
||||
if strings.HasSuffix(query, "\\G") {
|
||||
if strings.HasSuffix(query, terminator) {
|
||||
resultFormat = engine.FormatVertical
|
||||
}
|
||||
query = strings.TrimSuffix(query, terminator)
|
||||
}
|
||||
|
||||
//TODO: Handle comments and enforce the current line terminator
|
||||
if matches := delimiterRegex.FindStringSubmatch(query); len(matches) == 3 {
|
||||
// If we don't match from anything, then we just pass to the SQL engine and let it complain.
|
||||
shell.SetLineTerminator(matches[1])
|
||||
return
|
||||
}
|
||||
|
||||
var nextPrompt string
|
||||
var sqlSch sql.Schema
|
||||
var rowIter sql.RowIter
|
||||
|
||||
// The SQL parser does not understand any other terminator besides semicolon, so we remove it.
|
||||
if shell.LineTerminator() != ";" && strings.HasSuffix(query, shell.LineTerminator()) {
|
||||
query = query[:len(query)-len(shell.LineTerminator())]
|
||||
}
|
||||
|
||||
cont := func() bool {
|
||||
subCtx, stop := signal.NotifyContext(ctx, os.Interrupt, syscall.SIGTERM)
|
||||
defer stop()
|
||||
|
||||
@@ -54,7 +54,7 @@ const (
|
||||
backtick = '`'
|
||||
)
|
||||
|
||||
var scannerDelimiterRegex = regexp.MustCompile(`(?i)^\s*DELIMITER\s+(\S+)[ \t]*([\n]+|\S+\s*)?`)
|
||||
var scannerDelimiterRegex = regexp.MustCompile(`(?i)^\s*DELIMITER\s+(\S+)\s*`)
|
||||
|
||||
// ScanStatements is a split function for a Scanner that returns each SQL statement in the input as a token.
|
||||
func (s *statementScanner) scanStatements(data []byte, atEOF bool) (advance int, token []byte, err error) {
|
||||
@@ -74,7 +74,9 @@ func (s *statementScanner) scanStatements(data []byte, atEOF bool) (advance int,
|
||||
s.startLineNum = s.lineNum
|
||||
|
||||
if idxs := scannerDelimiterRegex.FindIndex(data); len(idxs) == 2 {
|
||||
return idxs[1], data[0:idxs[1]], nil
|
||||
s.Delimiter = scannerDelimiterRegex.FindStringSubmatch(string(data))[1]
|
||||
// Returning a nil token is interpreted as an error condition, so we return an empty token instead
|
||||
return idxs[1], []byte{}, nil
|
||||
}
|
||||
|
||||
for i := 0; i < len(data); i++ {
|
||||
|
||||
@@ -13,7 +13,7 @@ require (
|
||||
github.com/denisbrodbeck/machineid v1.0.1
|
||||
github.com/dolthub/dolt/go/gen/proto/dolt/services/eventsapi v0.0.0-20201005193433-3ee972b1d078
|
||||
github.com/dolthub/fslock v0.0.3
|
||||
github.com/dolthub/ishell v0.0.0-20220112232610-14e753f0f371
|
||||
github.com/dolthub/ishell v0.0.0-20221214210346-d7db0b066488
|
||||
github.com/dolthub/sqllogictest/go v0.0.0-20201107003712-816f3ae12d81
|
||||
github.com/dolthub/vitess v0.0.0-20221213234424-b21f99e8027d
|
||||
github.com/dustin/go-humanize v1.0.0
|
||||
|
||||
@@ -59,7 +59,6 @@ github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWX
|
||||
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
|
||||
github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE=
|
||||
github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=
|
||||
github.com/abiosoft/ishell v2.0.0+incompatible/go.mod h1:HQR9AqF2R3P4XXpMpI0NAzgHf/aS6+zVXRj14cVk9qg=
|
||||
github.com/abiosoft/readline v0.0.0-20180607040430-155bce2042db h1:CjPUSXOiYptLbTdr1RceuZgSFDQ7U15ITERUGrUORx8=
|
||||
github.com/abiosoft/readline v0.0.0-20180607040430-155bce2042db/go.mod h1:rB3B4rKii8V21ydCbIzH5hZiCQE7f5E9SzUb/ZZx530=
|
||||
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
|
||||
@@ -164,8 +163,8 @@ github.com/dolthub/fslock v0.0.3 h1:iLMpUIvJKMKm92+N1fmHVdxJP5NdyDK5bK7z7Ba2s2U=
|
||||
github.com/dolthub/fslock v0.0.3/go.mod h1:QWql+P17oAAMLnL4HGB5tiovtDuAjdDTPbuqx7bYfa0=
|
||||
github.com/dolthub/go-mysql-server v0.14.1-0.20221214210115-e28aad108618 h1:OrRT31UIC2VmBfEOt2tSSAAwicKPQU8dXcrfgS3XmXY=
|
||||
github.com/dolthub/go-mysql-server v0.14.1-0.20221214210115-e28aad108618/go.mod h1:8zZpRD3uXPUwK8jWm+exPjANHW/DVbGX2//cpVSZoD4=
|
||||
github.com/dolthub/ishell v0.0.0-20220112232610-14e753f0f371 h1:oyPHJlzumKta1vnOQqUnfdz+pk3EmnHS3Nd0cCT0I2g=
|
||||
github.com/dolthub/ishell v0.0.0-20220112232610-14e753f0f371/go.mod h1:dhGBqcCEfK5kuFmeO5+WOx3hqc1k3M29c1oS/R7N4ms=
|
||||
github.com/dolthub/ishell v0.0.0-20221214210346-d7db0b066488 h1:0HHu0GWJH0N6a6keStrHhUAK5/o9LVfkh44pvsV4514=
|
||||
github.com/dolthub/ishell v0.0.0-20221214210346-d7db0b066488/go.mod h1:ehexgi1mPxRTk0Mok/pADALuHbvATulTh6gzr7NzZto=
|
||||
github.com/dolthub/jsonpath v0.0.0-20210609232853-d49537a30474 h1:xTrR+l5l+1Lfq0NvhiEsctylXinUMFhhsqaEcl414p8=
|
||||
github.com/dolthub/jsonpath v0.0.0-20210609232853-d49537a30474/go.mod h1:kMz7uXOXq4qRriCEyZ/LUeTqraLJCjf0WVZcUi6TxUY=
|
||||
github.com/dolthub/sqllogictest/go v0.0.0-20201107003712-816f3ae12d81 h1:7/v8q9XGFa6q5Ap4Z/OhNkAMBaK5YeuEzwJt+NZdhiE=
|
||||
|
||||
@@ -13,7 +13,7 @@ expect {
|
||||
failed { exit 1; }
|
||||
}
|
||||
expect {
|
||||
"doltsql> " { send "DELIMITER $$ ;\r"; }
|
||||
"doltsql> " { send "DELIMITER $$\r"; }
|
||||
timeout { exit 1; }
|
||||
failed { exit 1; }
|
||||
}
|
||||
@@ -23,7 +23,7 @@ expect {
|
||||
failed { exit 1; }
|
||||
}
|
||||
expect {
|
||||
"doltsql> " { send "delimiter # $$\r"; }
|
||||
"doltsql> " { send "delimiter #\r"; }
|
||||
timeout { exit 1; }
|
||||
failed { exit 1; }
|
||||
}
|
||||
@@ -53,7 +53,7 @@ expect {
|
||||
failed { exit 1; }
|
||||
}
|
||||
expect {
|
||||
"doltsql> " { send "DeLiMiTeR ; #\r"; }
|
||||
"doltsql> " { send "DeLiMiTeR ;\r"; }
|
||||
timeout { exit 1; }
|
||||
failed { exit 1; }
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ expect {
|
||||
failed { exit 1; }
|
||||
}
|
||||
expect {
|
||||
"*: one_pk*" { send "DELIMITER $$\\g\r"; }
|
||||
"*: one_pk*" { send "DELIMITER $$\r"; }
|
||||
timeout { exit 1; }
|
||||
failed { exit 1; }
|
||||
}
|
||||
@@ -18,12 +18,12 @@ expect {
|
||||
failed { exit 1; }
|
||||
}
|
||||
expect {
|
||||
"*| one_pk *" { send "show tables\\g\r"; }
|
||||
"*| one_pk*" { send "show tables\\g\r"; }
|
||||
timeout { exit 1; }
|
||||
failed { exit 1; }
|
||||
}
|
||||
expect {
|
||||
"*| one_pk *" { send "DELIMITER ;\\g\r"; }
|
||||
"*: one_pk*" { send "DELIMITER ;\r"; }
|
||||
timeout { exit 1; }
|
||||
failed { exit 1; }
|
||||
}
|
||||
@@ -38,7 +38,7 @@ expect {
|
||||
failed { exit 1; }
|
||||
}
|
||||
expect {
|
||||
"*JSON_OBJECT('id', 87, 'name', 'carrot'): {"id":87,"name":"carrot"}*" { exit 0 ; }
|
||||
"*JSON_OBJECT('id', 87, 'name', 'carrot'): {\"id\":87,\"name\":\"carrot\"}*" { exit 0 ; }
|
||||
timeout { exit 1; }
|
||||
failed { exit 1; }
|
||||
}
|
||||
|
||||
@@ -2091,14 +2091,14 @@ SQL
|
||||
|
||||
@test "sql: batch delimiter" {
|
||||
dolt sql <<SQL
|
||||
DELIMITER // ;
|
||||
DELIMITER //
|
||||
CREATE TABLE test (
|
||||
pk BIGINT PRIMARY KEY,
|
||||
v1 BIGINT,
|
||||
v2 BIGINT
|
||||
)//
|
||||
INSERT INTO test VALUES (1, 1, 1) //
|
||||
DELIMITER $ //
|
||||
DELIMITER $
|
||||
INSERT INTO test VALUES (2, 2, 2)$ $
|
||||
CREATE PROCEDURE p1(x BIGINT)
|
||||
BEGIN
|
||||
@@ -2107,9 +2107,9 @@ BEGIN
|
||||
END IF;
|
||||
SELECT pk+x, v1+x, v2+x FROM test ORDER BY 1;
|
||||
END$
|
||||
DELIMITER ; $
|
||||
DELIMITER ;
|
||||
INSERT INTO test VALUES (3, 3, 3);
|
||||
DELIMITER ********** ;
|
||||
DELIMITER **********
|
||||
INSERT INTO test VALUES (4, 4, 4)**********
|
||||
DELIMITER &
|
||||
INSERT INTO test VALUES (5, 5, 5)&
|
||||
@@ -2138,7 +2138,7 @@ SQL
|
||||
[[ "${#lines[@]}" = "7" ]] || false
|
||||
|
||||
dolt sql <<SQL
|
||||
DELIMITER // ;
|
||||
DELIMITER //
|
||||
CREATE TABLE test2(
|
||||
pk BIGINT PRIMARY KEY,
|
||||
v1 VARCHAR(20)
|
||||
@@ -2254,7 +2254,7 @@ SQL
|
||||
|
||||
@test "sql: stored procedures creation check" {
|
||||
dolt sql -q "
|
||||
DELIMITER // ;
|
||||
DELIMITER //
|
||||
CREATE PROCEDURE p1(s VARCHAR(200), N DOUBLE, m DOUBLE)
|
||||
BEGIN
|
||||
SET s = '';
|
||||
|
||||
Reference in New Issue
Block a user