From b207139f99a65ef522802e3e7ec7ec02f5ddec40 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 27 Sep 2023 09:35:10 -0500 Subject: [PATCH 1/4] add test cases for booleans --- driver/driver_test.go | 60 ++++++++++++++++++++++++++++++++++++++++++ engine/parser/lexer.go | 45 +++++++++++++++++++++++++++++-- 2 files changed, 103 insertions(+), 2 deletions(-) diff --git a/driver/driver_test.go b/driver/driver_test.go index d1e1484..6c7e999 100644 --- a/driver/driver_test.go +++ b/driver/driver_test.go @@ -1170,6 +1170,66 @@ func TestInsertByteArrayODBC(t *testing.T) { } } +func TestInsertBoolTrueODBC(t *testing.T) { + log.UseTestLogger(t) + + db, err := sql.Open("ramsql", "TestInsertBoolODBC") + if err != nil { + t.Fatalf("sql.Open : Error : %s\n", err) + } + + _, err = db.Exec(`CREATE TABLE test_bool (sequence_number BIGSERIAL PRIMARY KEY, is_ready boolean, created_at TIMESTAMP)`) + if err != nil { + t.Fatalf("sql.Exec: Error: %s\n", err) + } + + want := true + _, err = db.Exec("INSERT INTO test_bool (is_ready) values (?)", want) + if err != nil { + t.Fatalf("sql.Exec: Error: %s\n", err) + } + + var got bool + err = db.QueryRow("SELECT is_ready FROM test_bool limit 1").Scan(&got) + if err != nil { + t.Fatalf("sql.Select: Error: %s\n", err) + } + + if !reflect.DeepEqual(want, got) { + t.Fatalf("Expected JSON to be '%v', got '%v'", want, got) + } +} + +func TestInsertBoolFalseODBC(t *testing.T) { + log.UseTestLogger(t) + + db, err := sql.Open("ramsql", "TestInsertBoolODBC") + if err != nil { + t.Fatalf("sql.Open : Error : %s\n", err) + } + + _, err = db.Exec(`CREATE TABLE test_bool (sequence_number BIGSERIAL PRIMARY KEY, is_ready boolean, created_at TIMESTAMP)`) + if err != nil { + t.Fatalf("sql.Exec: Error: %s\n", err) + } + + want := false + _, err = db.Exec("INSERT INTO test_bool (is_ready) values (?)", want) + if err != nil { + t.Fatalf("sql.Exec: Error: %s\n", err) + } + + var got bool + err = db.QueryRow("SELECT is_ready FROM test_bool limit 1").Scan(&got) + if err != nil { + t.Fatalf("sql.Select: Error: %s\n", err) + } + + if !reflect.DeepEqual(want, got) { + t.Fatalf("Expected JSON to be '%v', got '%v'", want, got) + } +} + func TestSchema(t *testing.T) { db, err := sql.Open("ramsql", "TestSchema") diff --git a/engine/parser/lexer.go b/engine/parser/lexer.go index 4665923..bce4dc4 100644 --- a/engine/parser/lexer.go +++ b/engine/parser/lexer.go @@ -196,7 +196,8 @@ func (l *lexer) lex(instruction []byte) ([]Token, error) { matchers = append(matchers, l.genericStringMatcher("for", ForToken)) matchers = append(matchers, l.genericStringMatcher("default", DefaultToken)) matchers = append(matchers, l.genericStringMatcher("localtimestamp", LocalTimestampToken)) - matchers = append(matchers, l.genericStringMatcher("false", LocalTimestampToken)) + matchers = append(matchers, l.MatchBooleanToken) + matchers = append(matchers, l.genericStringMatcher("false", FalseToken)) matchers = append(matchers, l.genericStringMatcher("unique", UniqueToken)) matchers = append(matchers, l.genericStringMatcher("now()", NowToken)) matchers = append(matchers, l.genericStringMatcher("offset", OffsetToken)) @@ -217,12 +218,13 @@ func (l *lexer) lex(instruction []byte) ([]Token, error) { for l.pos < l.instructionLen { r = false for _, m := range matchers { + // fmt.Println("here!", string(l.instruction[l.pos:])) if r = m(); r { securityPos = l.pos break } } - + fmt.Println("l.tokens", l.tokens) if r { continue } @@ -430,6 +432,45 @@ func (l *lexer) MatchNumberToken() bool { return false } +func (l *lexer) MatchBooleanToken() bool { + + // check if it is an update or insert statment; make sure it is not a create statement + canContinue := false + for _, token := range l.tokens { + if token.Token == CreateToken { + return false + } + if token.Token == UpdateToken || token.Token == InsertToken { + canContinue = true + } + } + + if !canContinue { + return false + } + + i := l.pos + for i < l.instructionLen && + (unicode.IsLetter(rune(l.instruction[i])) || + unicode.IsDigit(rune(l.instruction[i])) || + l.instruction[i] == '_' || + l.instruction[i] == '@' /* || l.instruction[i] == '.'*/) { + i++ + } + + if i != l.pos { + t := Token{ + Token: StringToken, + Lexeme: string(l.instruction[l.pos:i]), + } + l.tokens = append(l.tokens, t) + l.pos = i + return true + } + + return false +} + // 2015-09-10 14:03:09.444695269 +0200 CEST); func (l *lexer) MatchDateToken() bool { From c41174ffc98a1a6a09318c9ebef2db8952168635 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 27 Sep 2023 09:44:23 -0500 Subject: [PATCH 2/4] make sure tests are passing --- engine/parser/lexer.go | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/engine/parser/lexer.go b/engine/parser/lexer.go index bce4dc4..18e5651 100644 --- a/engine/parser/lexer.go +++ b/engine/parser/lexer.go @@ -218,13 +218,12 @@ func (l *lexer) lex(instruction []byte) ([]Token, error) { for l.pos < l.instructionLen { r = false for _, m := range matchers { - // fmt.Println("here!", string(l.instruction[l.pos:])) if r = m(); r { securityPos = l.pos break } } - fmt.Println("l.tokens", l.tokens) + if r { continue } @@ -452,9 +451,8 @@ func (l *lexer) MatchBooleanToken() bool { i := l.pos for i < l.instructionLen && (unicode.IsLetter(rune(l.instruction[i])) || - unicode.IsDigit(rune(l.instruction[i])) || l.instruction[i] == '_' || - l.instruction[i] == '@' /* || l.instruction[i] == '.'*/) { + l.instruction[i] == '@') { i++ } From 01acd6972b03cf2b4aaf16deda1a77f11a7ff47e Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 27 Sep 2023 09:49:08 -0500 Subject: [PATCH 3/4] pull in upstream --- driver/driver_test.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/driver/driver_test.go b/driver/driver_test.go index 6c7e999..a5d0567 100644 --- a/driver/driver_test.go +++ b/driver/driver_test.go @@ -1171,7 +1171,6 @@ func TestInsertByteArrayODBC(t *testing.T) { } func TestInsertBoolTrueODBC(t *testing.T) { - log.UseTestLogger(t) db, err := sql.Open("ramsql", "TestInsertBoolODBC") if err != nil { @@ -1201,7 +1200,6 @@ func TestInsertBoolTrueODBC(t *testing.T) { } func TestInsertBoolFalseODBC(t *testing.T) { - log.UseTestLogger(t) db, err := sql.Open("ramsql", "TestInsertBoolODBC") if err != nil { From f6ed1d5e27ec077a5934d50335cbf233923292fb Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 27 Sep 2023 11:34:00 -0500 Subject: [PATCH 4/4] try to fix timestamp bug --- engine/parser/lexer.go | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/engine/parser/lexer.go b/engine/parser/lexer.go index 18e5651..ca4fc55 100644 --- a/engine/parser/lexer.go +++ b/engine/parser/lexer.go @@ -196,8 +196,7 @@ func (l *lexer) lex(instruction []byte) ([]Token, error) { matchers = append(matchers, l.genericStringMatcher("for", ForToken)) matchers = append(matchers, l.genericStringMatcher("default", DefaultToken)) matchers = append(matchers, l.genericStringMatcher("localtimestamp", LocalTimestampToken)) - matchers = append(matchers, l.MatchBooleanToken) - matchers = append(matchers, l.genericStringMatcher("false", FalseToken)) + matchers = append(matchers, l.isCreateStatement(l.genericStringMatcher("false", FalseToken))) matchers = append(matchers, l.genericStringMatcher("unique", UniqueToken)) matchers = append(matchers, l.genericStringMatcher("now()", NowToken)) matchers = append(matchers, l.genericStringMatcher("offset", OffsetToken)) @@ -213,6 +212,7 @@ func (l *lexer) lex(instruction []byte) ([]Token, error) { matchers = append(matchers, l.MatchDateToken) matchers = append(matchers, l.MatchNumberToken) matchers = append(matchers, l.MatchStringToken) + matchers = append(matchers, l.MatchBooleanToken) var r bool for l.pos < l.instructionLen { @@ -238,6 +238,23 @@ func (l *lexer) lex(instruction []byte) ([]Token, error) { return l.tokens, nil } +func (l *lexer) isCreateStatement(matcher Matcher) Matcher { + return func() bool { + isCreateStmt := false + for _, token := range l.tokens { + if token.Token == CreateToken { + isCreateStmt = true + } + } + + if !isCreateStmt { + return false + } + + return matcher() + } +} + func (l *lexer) MatchArgTokenODBC() bool { i := l.pos