mirror of
				https://github.com/chaisql/chai.git
				synced 2025-10-30 10:26:59 +08:00 
			
		
		
		
	Move statements into their own package
This commit is contained in:
		
							
								
								
									
										11
									
								
								db.go
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								db.go
									
									
									
									
									
								
							| @@ -9,6 +9,7 @@ import ( | |||||||
| 	errs "github.com/genjidb/genji/errors" | 	errs "github.com/genjidb/genji/errors" | ||||||
| 	"github.com/genjidb/genji/internal/database" | 	"github.com/genjidb/genji/internal/database" | ||||||
| 	"github.com/genjidb/genji/internal/query" | 	"github.com/genjidb/genji/internal/query" | ||||||
|  | 	"github.com/genjidb/genji/internal/query/statement" | ||||||
| 	"github.com/genjidb/genji/internal/sql/parser" | 	"github.com/genjidb/genji/internal/sql/parser" | ||||||
| 	"github.com/genjidb/genji/internal/stream" | 	"github.com/genjidb/genji/internal/stream" | ||||||
| 	"github.com/genjidb/genji/internal/stringutil" | 	"github.com/genjidb/genji/internal/stringutil" | ||||||
| @@ -197,7 +198,7 @@ type Statement struct { | |||||||
| // Query the database and return the result. | // Query the database and return the result. | ||||||
| // The returned result must always be closed after usage. | // The returned result must always be closed after usage. | ||||||
| func (s *Statement) Query(args ...interface{}) (*Result, error) { | func (s *Statement) Query(args ...interface{}) (*Result, error) { | ||||||
| 	var r *query.Result | 	var r *statement.Result | ||||||
| 	var err error | 	var err error | ||||||
|  |  | ||||||
| 	if s.tx != nil { | 	if s.tx != nil { | ||||||
| @@ -269,7 +270,7 @@ func (s *Statement) Exec(args ...interface{}) (err error) { | |||||||
|  |  | ||||||
| // Result of a query. | // Result of a query. | ||||||
| type Result struct { | type Result struct { | ||||||
| 	result *query.Result | 	result *statement.Result | ||||||
| } | } | ||||||
|  |  | ||||||
| func (r *Result) Iterate(fn func(d document.Document) error) error { | func (r *Result) Iterate(fn func(d document.Document) error) error { | ||||||
| @@ -281,7 +282,7 @@ func (r *Result) Fields() []string { | |||||||
| 		return nil | 		return nil | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	stmt, ok := r.result.Iterator.(*query.StreamStmtIterator) | 	stmt, ok := r.result.Iterator.(*statement.StreamStmtIterator) | ||||||
| 	if !ok || stmt.Stream.Op == nil { | 	if !ok || stmt.Stream.Op == nil { | ||||||
| 		return nil | 		return nil | ||||||
| 	} | 	} | ||||||
| @@ -369,7 +370,7 @@ func loadCatalogTables(tx *database.Transaction) ([]database.TableInfo, error) { | |||||||
| 			return err | 			return err | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		ti := stmt.(query.CreateTableStmt).Info | 		ti := stmt.(statement.CreateTableStmt).Info | ||||||
|  |  | ||||||
| 		v, err := d.GetByField("store_name") | 		v, err := d.GetByField("store_name") | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| @@ -402,7 +403,7 @@ func loadCatalogIndexes(tx *database.Transaction) ([]database.IndexInfo, error) | |||||||
| 			return err | 			return err | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		indexes = append(indexes, stmt.(query.CreateIndexStmt).Info) | 		indexes = append(indexes, stmt.(statement.CreateIndexStmt).Info) | ||||||
| 		return nil | 		return nil | ||||||
| 	}) | 	}) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -65,7 +65,7 @@ SELECT * FROM foo; | |||||||
| To populate tests that would be in an `query_test` package, create a go file named `gentests.go` in the `query` package with the following code: | To populate tests that would be in an `query_test` package, create a go file named `gentests.go` in the `query` package with the following code: | ||||||
|  |  | ||||||
| ```go | ```go | ||||||
| package query | package statement | ||||||
|  |  | ||||||
| //go:generate go run ../dev/gensqltest -package=query_test ./*_test.sql | //go:generate go run ../dev/gensqltest -package=query_test ./*_test.sql | ||||||
| ``` | ``` | ||||||
|   | |||||||
| @@ -1,3 +0,0 @@ | |||||||
| package query |  | ||||||
|  |  | ||||||
| //go:generate go run ../../dev/gensqltest -package=query_test ./*_test.sql |  | ||||||
| @@ -2,25 +2,25 @@ package query | |||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"context" | 	"context" | ||||||
| 	"errors" |  | ||||||
|  |  | ||||||
| 	"github.com/genjidb/genji/document" | 	"github.com/genjidb/genji/document" | ||||||
| 	"github.com/genjidb/genji/internal/database" | 	"github.com/genjidb/genji/internal/database" | ||||||
| 	"github.com/genjidb/genji/internal/expr" | 	"github.com/genjidb/genji/internal/expr" | ||||||
|  | 	"github.com/genjidb/genji/internal/query/statement" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| // A Query can execute statements against the database. It can read or write data | // A Query can execute statements against the database. It can read or write data | ||||||
| // from any table, or even alter the structure of the database. | // from any table, or even alter the structure of the database. | ||||||
| // Results are returned as streams. | // Results are returned as streams. | ||||||
| type Query struct { | type Query struct { | ||||||
| 	Statements []Statement | 	Statements []statement.Statement | ||||||
| 	tx         *database.Transaction | 	tx         *database.Transaction | ||||||
| 	autoCommit bool | 	autoCommit bool | ||||||
| } | } | ||||||
|  |  | ||||||
| // Run executes all the statements in their own transaction and returns the last result. | // Run executes all the statements in their own transaction and returns the last result. | ||||||
| func (q Query) Run(ctx context.Context, db *database.Database, args []expr.Param) (*Result, error) { | func (q Query) Run(ctx context.Context, db *database.Database, args []expr.Param) (*statement.Result, error) { | ||||||
| 	var res Result | 	var res statement.Result | ||||||
| 	var err error | 	var err error | ||||||
|  |  | ||||||
| 	q.tx = db.GetAttachedTx() | 	q.tx = db.GetAttachedTx() | ||||||
| @@ -40,7 +40,7 @@ func (q Query) Run(ctx context.Context, db *database.Database, args []expr.Param | |||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		// reinitialize the result | 		// reinitialize the result | ||||||
| 		res = Result{} | 		res = statement.Result{} | ||||||
|  |  | ||||||
| 		if qa, ok := stmt.(queryAlterer); ok { | 		if qa, ok := stmt.(queryAlterer); ok { | ||||||
| 			err = qa.alterQuery(ctx, db, &q) | 			err = qa.alterQuery(ctx, db, &q) | ||||||
| @@ -114,8 +114,8 @@ func (q Query) Run(ctx context.Context, db *database.Database, args []expr.Param | |||||||
| } | } | ||||||
|  |  | ||||||
| // Exec the query within the given transaction. | // Exec the query within the given transaction. | ||||||
| func (q Query) Exec(tx *database.Transaction, args []expr.Param) (*Result, error) { | func (q Query) Exec(tx *database.Transaction, args []expr.Param) (*statement.Result, error) { | ||||||
| 	var res Result | 	var res statement.Result | ||||||
| 	var err error | 	var err error | ||||||
|  |  | ||||||
| 	for i, stmt := range q.Statements { | 	for i, stmt := range q.Statements { | ||||||
| @@ -139,54 +139,6 @@ func (q Query) Exec(tx *database.Transaction, args []expr.Param) (*Result, error | |||||||
| } | } | ||||||
|  |  | ||||||
| // New creates a new query with the given statements. | // New creates a new query with the given statements. | ||||||
| func New(statements ...Statement) Query { | func New(statements ...statement.Statement) Query { | ||||||
| 	return Query{Statements: statements} | 	return Query{Statements: statements} | ||||||
| } | } | ||||||
|  |  | ||||||
| // A Statement represents a unique action that can be executed against the database. |  | ||||||
| type Statement interface { |  | ||||||
| 	Run(*database.Transaction, []expr.Param) (Result, error) |  | ||||||
| 	IsReadOnly() bool |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Result of a query. |  | ||||||
| type Result struct { |  | ||||||
| 	Iterator document.Iterator |  | ||||||
| 	Tx       *database.Transaction |  | ||||||
| 	closed   bool |  | ||||||
| 	err      error |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func (r *Result) Iterate(fn func(d document.Document) error) error { |  | ||||||
| 	if r.Iterator == nil { |  | ||||||
| 		return nil |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	r.err = r.Iterator.Iterate(fn) |  | ||||||
| 	return r.err |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // Close the result stream. |  | ||||||
| // After closing the result, Stream is not supposed to be used. |  | ||||||
| // If the result stream was already closed, it returns an error. |  | ||||||
| func (r *Result) Close() (err error) { |  | ||||||
| 	if r == nil { |  | ||||||
| 		return nil |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if r.closed { |  | ||||||
| 		return errors.New("result already closed") |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	r.closed = true |  | ||||||
|  |  | ||||||
| 	if r.Tx != nil { |  | ||||||
| 		if r.Tx.Writable && r.err == nil { |  | ||||||
| 			err = r.Tx.Commit() |  | ||||||
| 		} else { |  | ||||||
| 			err = r.Tx.Rollback() |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	return err |  | ||||||
| } |  | ||||||
|   | |||||||
| @@ -1,4 +1,4 @@ | |||||||
| package query | package statement | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"errors" | 	"errors" | ||||||
| @@ -1,4 +1,4 @@ | |||||||
| package query_test | package statement_test | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"errors" | 	"errors" | ||||||
| @@ -1,4 +1,4 @@ | |||||||
| package query | package statement | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"github.com/genjidb/genji/document" | 	"github.com/genjidb/genji/document" | ||||||
| @@ -1,4 +1,4 @@ | |||||||
| package query_test | package statement_test | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"testing" | 	"testing" | ||||||
| @@ -1,4 +1,4 @@ | |||||||
| package query | package statement | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"github.com/genjidb/genji/internal/database" | 	"github.com/genjidb/genji/internal/database" | ||||||
| @@ -1,4 +1,4 @@ | |||||||
| package query_test | package statement_test | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"bytes" | 	"bytes" | ||||||
| @@ -1,4 +1,4 @@ | |||||||
| package query | package statement | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"errors" | 	"errors" | ||||||
| @@ -1,4 +1,4 @@ | |||||||
| package query_test | package statement_test | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"testing" | 	"testing" | ||||||
| @@ -1,4 +1,4 @@ | |||||||
| package query | package statement | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"errors" | 	"errors" | ||||||
| @@ -1,4 +1,4 @@ | |||||||
| package query_test | package statement_test | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"testing" | 	"testing" | ||||||
| @@ -2,7 +2,7 @@ | |||||||
| * CODE GENERATED AUTOMATICALLY WITH github.com/genjidb/genji/dev/gensqltest | * CODE GENERATED AUTOMATICALLY WITH github.com/genjidb/genji/dev/gensqltest | ||||||
| * THIS FILE SHOULD NOT BE EDITED BY HAND | * THIS FILE SHOULD NOT BE EDITED BY HAND | ||||||
|  */ |  */ | ||||||
| package query_test | package statement_test | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"regexp" | 	"regexp" | ||||||
| @@ -2,7 +2,7 @@ | |||||||
| * CODE GENERATED AUTOMATICALLY WITH github.com/genjidb/genji/dev/gensqltest | * CODE GENERATED AUTOMATICALLY WITH github.com/genjidb/genji/dev/gensqltest | ||||||
| * THIS FILE SHOULD NOT BE EDITED BY HAND | * THIS FILE SHOULD NOT BE EDITED BY HAND | ||||||
|  */ |  */ | ||||||
| package query_test | package statement_test | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"testing" | 	"testing" | ||||||
| @@ -2,7 +2,7 @@ | |||||||
| * CODE GENERATED AUTOMATICALLY WITH github.com/genjidb/genji/dev/gensqltest | * CODE GENERATED AUTOMATICALLY WITH github.com/genjidb/genji/dev/gensqltest | ||||||
| * THIS FILE SHOULD NOT BE EDITED BY HAND | * THIS FILE SHOULD NOT BE EDITED BY HAND | ||||||
|  */ |  */ | ||||||
| package query_test | package statement_test | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"testing" | 	"testing" | ||||||
							
								
								
									
										3
									
								
								internal/query/statement/gentests.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								internal/query/statement/gentests.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | |||||||
|  | package statement | ||||||
|  |  | ||||||
|  | //go:generate go run ../../../dev/gensqltest -package=statement_test ./*_test.sql | ||||||
| @@ -1,4 +1,4 @@ | |||||||
| package query | package statement | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"errors" | 	"errors" | ||||||
| @@ -1,4 +1,4 @@ | |||||||
| package query_test | package statement_test | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"bytes" | 	"bytes" | ||||||
| @@ -1,4 +1,4 @@ | |||||||
| package query | package statement | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"errors" | 	"errors" | ||||||
| @@ -1,4 +1,4 @@ | |||||||
| package query_test | package statement_test | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"testing" | 	"testing" | ||||||
| @@ -1,4 +1,4 @@ | |||||||
| package query | package statement | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"errors" | 	"errors" | ||||||
| @@ -1,4 +1,4 @@ | |||||||
| package query_test | package statement_test | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"bytes" | 	"bytes" | ||||||
							
								
								
									
										57
									
								
								internal/query/statement/statement.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								internal/query/statement/statement.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,57 @@ | |||||||
|  | package statement | ||||||
|  |  | ||||||
|  | import ( | ||||||
|  | 	"errors" | ||||||
|  |  | ||||||
|  | 	"github.com/genjidb/genji/document" | ||||||
|  | 	"github.com/genjidb/genji/internal/database" | ||||||
|  | 	"github.com/genjidb/genji/internal/expr" | ||||||
|  | ) | ||||||
|  |  | ||||||
|  | // A Statement represents a unique action that can be executed against the database. | ||||||
|  | type Statement interface { | ||||||
|  | 	Run(*database.Transaction, []expr.Param) (Result, error) | ||||||
|  | 	IsReadOnly() bool | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Result of a query. | ||||||
|  | type Result struct { | ||||||
|  | 	Iterator document.Iterator | ||||||
|  | 	Tx       *database.Transaction | ||||||
|  | 	closed   bool | ||||||
|  | 	err      error | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (r *Result) Iterate(fn func(d document.Document) error) error { | ||||||
|  | 	if r.Iterator == nil { | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	r.err = r.Iterator.Iterate(fn) | ||||||
|  | 	return r.err | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Close the result stream. | ||||||
|  | // After closing the result, Stream is not supposed to be used. | ||||||
|  | // If the result stream was already closed, it returns an error. | ||||||
|  | func (r *Result) Close() (err error) { | ||||||
|  | 	if r == nil { | ||||||
|  | 		return nil | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	if r.closed { | ||||||
|  | 		return errors.New("result already closed") | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	r.closed = true | ||||||
|  |  | ||||||
|  | 	if r.Tx != nil { | ||||||
|  | 		if r.Tx.Writable && r.err == nil { | ||||||
|  | 			err = r.Tx.Commit() | ||||||
|  | 		} else { | ||||||
|  | 			err = r.Tx.Rollback() | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	return err | ||||||
|  | } | ||||||
| @@ -1,4 +1,4 @@ | |||||||
| package query | package statement | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"github.com/genjidb/genji/document" | 	"github.com/genjidb/genji/document" | ||||||
| @@ -1,4 +1,4 @@ | |||||||
| package query | package statement | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"github.com/genjidb/genji/document" | 	"github.com/genjidb/genji/document" | ||||||
| @@ -1,4 +1,4 @@ | |||||||
| package query_test | package statement_test | ||||||
| 
 | 
 | ||||||
| import ( | import ( | ||||||
| 	"bytes" | 	"bytes" | ||||||
| @@ -6,6 +6,7 @@ import ( | |||||||
|  |  | ||||||
| 	"github.com/genjidb/genji/internal/database" | 	"github.com/genjidb/genji/internal/database" | ||||||
| 	"github.com/genjidb/genji/internal/expr" | 	"github.com/genjidb/genji/internal/expr" | ||||||
|  | 	"github.com/genjidb/genji/internal/query/statement" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| // BeginStmt is a statement that creates a new transaction. | // BeginStmt is a statement that creates a new transaction. | ||||||
| @@ -31,8 +32,8 @@ func (stmt BeginStmt) IsReadOnly() bool { | |||||||
| 	return !stmt.Writable | 	return !stmt.Writable | ||||||
| } | } | ||||||
|  |  | ||||||
| func (stmt BeginStmt) Run(tx *database.Transaction, args []expr.Param) (Result, error) { | func (stmt BeginStmt) Run(tx *database.Transaction, args []expr.Param) (statement.Result, error) { | ||||||
| 	return Result{}, errors.New("cannot begin a transaction within a transaction") | 	return statement.Result{}, errors.New("cannot begin a transaction within a transaction") | ||||||
| } | } | ||||||
|  |  | ||||||
| // RollbackStmt is a statement that rollbacks the current active transaction. | // RollbackStmt is a statement that rollbacks the current active transaction. | ||||||
| @@ -56,8 +57,8 @@ func (stmt RollbackStmt) IsReadOnly() bool { | |||||||
| 	return false | 	return false | ||||||
| } | } | ||||||
|  |  | ||||||
| func (stmt RollbackStmt) Run(tx *database.Transaction, args []expr.Param) (Result, error) { | func (stmt RollbackStmt) Run(tx *database.Transaction, args []expr.Param) (statement.Result, error) { | ||||||
| 	return Result{}, errors.New("cannot rollback with no active transaction") | 	return statement.Result{}, errors.New("cannot rollback with no active transaction") | ||||||
| } | } | ||||||
|  |  | ||||||
| // CommitStmt is a statement that commits the current active transaction. | // CommitStmt is a statement that commits the current active transaction. | ||||||
| @@ -81,6 +82,6 @@ func (stmt CommitStmt) IsReadOnly() bool { | |||||||
| 	return false | 	return false | ||||||
| } | } | ||||||
|  |  | ||||||
| func (stmt CommitStmt) Run(tx *database.Transaction, args []expr.Param) (Result, error) { | func (stmt CommitStmt) Run(tx *database.Transaction, args []expr.Param) (statement.Result, error) { | ||||||
| 	return Result{}, errors.New("cannot commit with no active transaction") | 	return statement.Result{}, errors.New("cannot commit with no active transaction") | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,12 +1,12 @@ | |||||||
| package parser | package parser | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"github.com/genjidb/genji/internal/query" | 	"github.com/genjidb/genji/internal/query/statement" | ||||||
| 	"github.com/genjidb/genji/internal/sql/scanner" | 	"github.com/genjidb/genji/internal/sql/scanner" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| func (p *Parser) parseAlterTableRenameStatement(tableName string) (_ query.AlterStmt, err error) { | func (p *Parser) parseAlterTableRenameStatement(tableName string) (_ statement.AlterStmt, err error) { | ||||||
| 	var stmt query.AlterStmt | 	var stmt statement.AlterStmt | ||||||
| 	stmt.TableName = tableName | 	stmt.TableName = tableName | ||||||
|  |  | ||||||
| 	// Parse "TO". | 	// Parse "TO". | ||||||
| @@ -23,8 +23,8 @@ func (p *Parser) parseAlterTableRenameStatement(tableName string) (_ query.Alter | |||||||
| 	return stmt, nil | 	return stmt, nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func (p *Parser) parseAlterTableAddFieldStatement(tableName string) (_ query.AlterTableAddField, err error) { | func (p *Parser) parseAlterTableAddFieldStatement(tableName string) (_ statement.AlterTableAddField, err error) { | ||||||
| 	var stmt query.AlterTableAddField | 	var stmt statement.AlterTableAddField | ||||||
| 	stmt.TableName = tableName | 	stmt.TableName = tableName | ||||||
|  |  | ||||||
| 	// Parse "FIELD". | 	// Parse "FIELD". | ||||||
| @@ -47,7 +47,7 @@ func (p *Parser) parseAlterTableAddFieldStatement(tableName string) (_ query.Alt | |||||||
|  |  | ||||||
| // parseAlterStatement parses a Alter query string and returns a Statement AST object. | // parseAlterStatement parses a Alter query string and returns a Statement AST object. | ||||||
| // This function assumes the ALTER token has already been consumed. | // This function assumes the ALTER token has already been consumed. | ||||||
| func (p *Parser) parseAlterStatement() (query.Statement, error) { | func (p *Parser) parseAlterStatement() (statement.Statement, error) { | ||||||
| 	var err error | 	var err error | ||||||
|  |  | ||||||
| 	// Parse "TABLE". | 	// Parse "TABLE". | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ import ( | |||||||
|  |  | ||||||
| 	"github.com/genjidb/genji/document" | 	"github.com/genjidb/genji/document" | ||||||
| 	"github.com/genjidb/genji/internal/database" | 	"github.com/genjidb/genji/internal/database" | ||||||
| 	"github.com/genjidb/genji/internal/query" | 	"github.com/genjidb/genji/internal/query/statement" | ||||||
| 	"github.com/genjidb/genji/internal/sql/parser" | 	"github.com/genjidb/genji/internal/sql/parser" | ||||||
| 	"github.com/genjidb/genji/internal/testutil" | 	"github.com/genjidb/genji/internal/testutil" | ||||||
| 	"github.com/stretchr/testify/require" | 	"github.com/stretchr/testify/require" | ||||||
| @@ -15,13 +15,13 @@ func TestParserAlterTable(t *testing.T) { | |||||||
| 	tests := []struct { | 	tests := []struct { | ||||||
| 		name     string | 		name     string | ||||||
| 		s        string | 		s        string | ||||||
| 		expected query.Statement | 		expected statement.Statement | ||||||
| 		errored  bool | 		errored  bool | ||||||
| 	}{ | 	}{ | ||||||
| 		{"Basic", "ALTER TABLE foo RENAME TO bar", query.AlterStmt{TableName: "foo", NewTableName: "bar"}, false}, | 		{"Basic", "ALTER TABLE foo RENAME TO bar", statement.AlterStmt{TableName: "foo", NewTableName: "bar"}, false}, | ||||||
| 		{"With error / missing TABLE keyword", "ALTER foo RENAME TO bar", query.AlterStmt{}, true}, | 		{"With error / missing TABLE keyword", "ALTER foo RENAME TO bar", statement.AlterStmt{}, true}, | ||||||
| 		{"With error / two identifiers for table name", "ALTER TABLE foo baz RENAME TO bar", query.AlterStmt{}, true}, | 		{"With error / two identifiers for table name", "ALTER TABLE foo baz RENAME TO bar", statement.AlterStmt{}, true}, | ||||||
| 		{"With error / two identifiers for new table name", "ALTER TABLE foo RENAME TO bar baz", query.AlterStmt{}, true}, | 		{"With error / two identifiers for new table name", "ALTER TABLE foo RENAME TO bar baz", statement.AlterStmt{}, true}, | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	for _, test := range tests { | 	for _, test := range tests { | ||||||
| @@ -42,26 +42,26 @@ func TestParserAlterTableAddField(t *testing.T) { | |||||||
| 	tests := []struct { | 	tests := []struct { | ||||||
| 		name     string | 		name     string | ||||||
| 		s        string | 		s        string | ||||||
| 		expected query.Statement | 		expected statement.Statement | ||||||
| 		errored  bool | 		errored  bool | ||||||
| 	}{ | 	}{ | ||||||
| 		{"Basic", "ALTER TABLE foo ADD FIELD bar", query.AlterTableAddField{TableName: "foo", | 		{"Basic", "ALTER TABLE foo ADD FIELD bar", statement.AlterTableAddField{TableName: "foo", | ||||||
| 			Constraint: database.FieldConstraint{}, | 			Constraint: database.FieldConstraint{}, | ||||||
| 		}, true}, | 		}, true}, | ||||||
| 		{"With type", "ALTER TABLE foo ADD FIELD bar integer", query.AlterTableAddField{TableName: "foo", | 		{"With type", "ALTER TABLE foo ADD FIELD bar integer", statement.AlterTableAddField{TableName: "foo", | ||||||
| 			Constraint: database.FieldConstraint{ | 			Constraint: database.FieldConstraint{ | ||||||
| 				Path: document.Path(testutil.ParsePath(t, "bar")), | 				Path: document.Path(testutil.ParsePath(t, "bar")), | ||||||
| 				Type: document.IntegerValue, | 				Type: document.IntegerValue, | ||||||
| 			}, | 			}, | ||||||
| 		}, false}, | 		}, false}, | ||||||
| 		{"With not null", "ALTER TABLE foo ADD FIELD bar NOT NULL", query.AlterTableAddField{TableName: "foo", | 		{"With not null", "ALTER TABLE foo ADD FIELD bar NOT NULL", statement.AlterTableAddField{TableName: "foo", | ||||||
| 			Constraint: database.FieldConstraint{ | 			Constraint: database.FieldConstraint{ | ||||||
| 				Path:      document.Path(testutil.ParsePath(t, "bar")), | 				Path:      document.Path(testutil.ParsePath(t, "bar")), | ||||||
| 				IsNotNull: true, | 				IsNotNull: true, | ||||||
| 			}, | 			}, | ||||||
| 		}, false}, | 		}, false}, | ||||||
| 		{"With primary key", "ALTER TABLE foo ADD FIELD bar PRIMARY KEY", query.AlterTableAddField{}, true}, | 		{"With primary key", "ALTER TABLE foo ADD FIELD bar PRIMARY KEY", statement.AlterTableAddField{}, true}, | ||||||
| 		{"With multiple constraints", "ALTER TABLE foo ADD FIELD bar integer NOT NULL DEFAULT 0", query.AlterTableAddField{TableName: "foo", | 		{"With multiple constraints", "ALTER TABLE foo ADD FIELD bar integer NOT NULL DEFAULT 0", statement.AlterTableAddField{TableName: "foo", | ||||||
| 			Constraint: database.FieldConstraint{ | 			Constraint: database.FieldConstraint{ | ||||||
| 				Path:         document.Path(testutil.ParsePath(t, "bar")), | 				Path:         document.Path(testutil.ParsePath(t, "bar")), | ||||||
| 				Type:         document.IntegerValue, | 				Type:         document.IntegerValue, | ||||||
|   | |||||||
| @@ -3,14 +3,14 @@ package parser | |||||||
| import ( | import ( | ||||||
| 	"github.com/genjidb/genji/internal/database" | 	"github.com/genjidb/genji/internal/database" | ||||||
| 	"github.com/genjidb/genji/internal/expr" | 	"github.com/genjidb/genji/internal/expr" | ||||||
| 	"github.com/genjidb/genji/internal/query" | 	"github.com/genjidb/genji/internal/query/statement" | ||||||
| 	"github.com/genjidb/genji/internal/sql/scanner" | 	"github.com/genjidb/genji/internal/sql/scanner" | ||||||
| 	"github.com/genjidb/genji/internal/stringutil" | 	"github.com/genjidb/genji/internal/stringutil" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| // parseCreateStatement parses a create string and returns a Statement AST object. | // parseCreateStatement parses a create string and returns a Statement AST object. | ||||||
| // This function assumes the CREATE token has already been consumed. | // This function assumes the CREATE token has already been consumed. | ||||||
| func (p *Parser) parseCreateStatement() (query.Statement, error) { | func (p *Parser) parseCreateStatement() (statement.Statement, error) { | ||||||
| 	tok, pos, lit := p.ScanIgnoreWhitespace() | 	tok, pos, lit := p.ScanIgnoreWhitespace() | ||||||
| 	switch tok { | 	switch tok { | ||||||
| 	case scanner.TABLE: | 	case scanner.TABLE: | ||||||
| @@ -30,8 +30,8 @@ func (p *Parser) parseCreateStatement() (query.Statement, error) { | |||||||
|  |  | ||||||
| // parseCreateTableStatement parses a create table string and returns a Statement AST object. | // parseCreateTableStatement parses a create table string and returns a Statement AST object. | ||||||
| // This function assumes the CREATE TABLE tokens have already been consumed. | // This function assumes the CREATE TABLE tokens have already been consumed. | ||||||
| func (p *Parser) parseCreateTableStatement() (query.CreateTableStmt, error) { | func (p *Parser) parseCreateTableStatement() (statement.CreateTableStmt, error) { | ||||||
| 	var stmt query.CreateTableStmt | 	var stmt statement.CreateTableStmt | ||||||
| 	var err error | 	var err error | ||||||
|  |  | ||||||
| 	// Parse IF NOT EXISTS | 	// Parse IF NOT EXISTS | ||||||
| @@ -75,7 +75,7 @@ func (p *Parser) parseFieldDefinition(fc *database.FieldConstraint) (err error) | |||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|  |  | ||||||
| func (p *Parser) parseConstraints(stmt *query.CreateTableStmt) error { | func (p *Parser) parseConstraints(stmt *statement.CreateTableStmt) error { | ||||||
| 	// Parse ( token. | 	// Parse ( token. | ||||||
| 	if ok, err := p.parseOptional(scanner.LPAREN); !ok || err != nil { | 	if ok, err := p.parseOptional(scanner.LPAREN); !ok || err != nil { | ||||||
| 		return err | 		return err | ||||||
| @@ -203,7 +203,7 @@ func (p *Parser) parseFieldConstraint(fc *database.FieldConstraint) error { | |||||||
| 	} | 	} | ||||||
| } | } | ||||||
|  |  | ||||||
| func (p *Parser) parseTableConstraint(stmt *query.CreateTableStmt) (bool, error) { | func (p *Parser) parseTableConstraint(stmt *statement.CreateTableStmt) (bool, error) { | ||||||
| 	var err error | 	var err error | ||||||
|  |  | ||||||
| 	tok, _, _ := p.ScanIgnoreWhitespace() | 	tok, _, _ := p.ScanIgnoreWhitespace() | ||||||
| @@ -283,9 +283,9 @@ func (p *Parser) parseTableConstraint(stmt *query.CreateTableStmt) (bool, error) | |||||||
|  |  | ||||||
| // parseCreateIndexStatement parses a create index string and returns a Statement AST object. | // parseCreateIndexStatement parses a create index string and returns a Statement AST object. | ||||||
| // This function assumes the CREATE INDEX or CREATE UNIQUE INDEX tokens have already been consumed. | // This function assumes the CREATE INDEX or CREATE UNIQUE INDEX tokens have already been consumed. | ||||||
| func (p *Parser) parseCreateIndexStatement(unique bool) (query.CreateIndexStmt, error) { | func (p *Parser) parseCreateIndexStatement(unique bool) (statement.CreateIndexStmt, error) { | ||||||
| 	var err error | 	var err error | ||||||
| 	var stmt query.CreateIndexStmt | 	var stmt statement.CreateIndexStmt | ||||||
| 	stmt.Info.Unique = unique | 	stmt.Info.Unique = unique | ||||||
|  |  | ||||||
| 	// Parse IF NOT EXISTS | 	// Parse IF NOT EXISTS | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ import ( | |||||||
|  |  | ||||||
| 	"github.com/genjidb/genji/document" | 	"github.com/genjidb/genji/document" | ||||||
| 	"github.com/genjidb/genji/internal/database" | 	"github.com/genjidb/genji/internal/database" | ||||||
| 	"github.com/genjidb/genji/internal/query" | 	"github.com/genjidb/genji/internal/query/statement" | ||||||
| 	"github.com/genjidb/genji/internal/sql/parser" | 	"github.com/genjidb/genji/internal/sql/parser" | ||||||
| 	"github.com/genjidb/genji/internal/testutil" | 	"github.com/genjidb/genji/internal/testutil" | ||||||
| 	"github.com/stretchr/testify/require" | 	"github.com/stretchr/testify/require" | ||||||
| @@ -15,14 +15,14 @@ func TestParserCreateTable(t *testing.T) { | |||||||
| 	tests := []struct { | 	tests := []struct { | ||||||
| 		name     string | 		name     string | ||||||
| 		s        string | 		s        string | ||||||
| 		expected query.Statement | 		expected statement.Statement | ||||||
| 		errored  bool | 		errored  bool | ||||||
| 	}{ | 	}{ | ||||||
| 		{"Basic", "CREATE TABLE test", query.CreateTableStmt{Info: database.TableInfo{TableName: "test"}}, false}, | 		{"Basic", "CREATE TABLE test", statement.CreateTableStmt{Info: database.TableInfo{TableName: "test"}}, false}, | ||||||
| 		{"If not exists", "CREATE TABLE IF NOT EXISTS test", query.CreateTableStmt{Info: database.TableInfo{TableName: "test"}, IfNotExists: true}, false}, | 		{"If not exists", "CREATE TABLE IF NOT EXISTS test", statement.CreateTableStmt{Info: database.TableInfo{TableName: "test"}, IfNotExists: true}, false}, | ||||||
| 		{"Path only", "CREATE TABLE test(a)", query.CreateTableStmt{}, true}, | 		{"Path only", "CREATE TABLE test(a)", statement.CreateTableStmt{}, true}, | ||||||
| 		{"With primary key", "CREATE TABLE test(foo INTEGER PRIMARY KEY)", | 		{"With primary key", "CREATE TABLE test(foo INTEGER PRIMARY KEY)", | ||||||
| 			query.CreateTableStmt{ | 			statement.CreateTableStmt{ | ||||||
| 				Info: database.TableInfo{ | 				Info: database.TableInfo{ | ||||||
| 					TableName: "test", | 					TableName: "test", | ||||||
| 					FieldConstraints: []*database.FieldConstraint{ | 					FieldConstraints: []*database.FieldConstraint{ | ||||||
| @@ -31,9 +31,9 @@ func TestParserCreateTable(t *testing.T) { | |||||||
| 				}, | 				}, | ||||||
| 			}, false}, | 			}, false}, | ||||||
| 		{"With primary key twice", "CREATE TABLE test(foo PRIMARY KEY PRIMARY KEY)", | 		{"With primary key twice", "CREATE TABLE test(foo PRIMARY KEY PRIMARY KEY)", | ||||||
| 			query.CreateTableStmt{}, true}, | 			statement.CreateTableStmt{}, true}, | ||||||
| 		{"With type", "CREATE TABLE test(foo INTEGER)", | 		{"With type", "CREATE TABLE test(foo INTEGER)", | ||||||
| 			query.CreateTableStmt{ | 			statement.CreateTableStmt{ | ||||||
| 				Info: database.TableInfo{ | 				Info: database.TableInfo{ | ||||||
| 					TableName: "test", | 					TableName: "test", | ||||||
| 					FieldConstraints: []*database.FieldConstraint{ | 					FieldConstraints: []*database.FieldConstraint{ | ||||||
| @@ -42,7 +42,7 @@ func TestParserCreateTable(t *testing.T) { | |||||||
| 				}, | 				}, | ||||||
| 			}, false}, | 			}, false}, | ||||||
| 		{"With not null", "CREATE TABLE test(foo NOT NULL)", | 		{"With not null", "CREATE TABLE test(foo NOT NULL)", | ||||||
| 			query.CreateTableStmt{ | 			statement.CreateTableStmt{ | ||||||
| 				Info: database.TableInfo{ | 				Info: database.TableInfo{ | ||||||
| 					TableName: "test", | 					TableName: "test", | ||||||
| 					FieldConstraints: []*database.FieldConstraint{ | 					FieldConstraints: []*database.FieldConstraint{ | ||||||
| @@ -51,7 +51,7 @@ func TestParserCreateTable(t *testing.T) { | |||||||
| 				}, | 				}, | ||||||
| 			}, false}, | 			}, false}, | ||||||
| 		{"With default", "CREATE TABLE test(foo DEFAULT \"10\")", | 		{"With default", "CREATE TABLE test(foo DEFAULT \"10\")", | ||||||
| 			query.CreateTableStmt{ | 			statement.CreateTableStmt{ | ||||||
| 				Info: database.TableInfo{ | 				Info: database.TableInfo{ | ||||||
| 					TableName: "test", | 					TableName: "test", | ||||||
| 					FieldConstraints: []*database.FieldConstraint{ | 					FieldConstraints: []*database.FieldConstraint{ | ||||||
| @@ -60,7 +60,7 @@ func TestParserCreateTable(t *testing.T) { | |||||||
| 				}, | 				}, | ||||||
| 			}, false}, | 			}, false}, | ||||||
| 		{"With unique", "CREATE TABLE test(foo UNIQUE)", | 		{"With unique", "CREATE TABLE test(foo UNIQUE)", | ||||||
| 			query.CreateTableStmt{ | 			statement.CreateTableStmt{ | ||||||
| 				Info: database.TableInfo{ | 				Info: database.TableInfo{ | ||||||
| 					TableName: "test", | 					TableName: "test", | ||||||
| 					FieldConstraints: []*database.FieldConstraint{ | 					FieldConstraints: []*database.FieldConstraint{ | ||||||
| @@ -69,13 +69,13 @@ func TestParserCreateTable(t *testing.T) { | |||||||
| 				}, | 				}, | ||||||
| 			}, false}, | 			}, false}, | ||||||
| 		{"With default twice", "CREATE TABLE test(foo DEFAULT 10 DEFAULT 10)", | 		{"With default twice", "CREATE TABLE test(foo DEFAULT 10 DEFAULT 10)", | ||||||
| 			query.CreateTableStmt{}, true}, | 			statement.CreateTableStmt{}, true}, | ||||||
| 		{"With not null twice", "CREATE TABLE test(foo NOT NULL NOT NULL)", | 		{"With not null twice", "CREATE TABLE test(foo NOT NULL NOT NULL)", | ||||||
| 			query.CreateTableStmt{}, true}, | 			statement.CreateTableStmt{}, true}, | ||||||
| 		{"With unique twice", "CREATE TABLE test(foo UNIQUE UNIQUE)", | 		{"With unique twice", "CREATE TABLE test(foo UNIQUE UNIQUE)", | ||||||
| 			query.CreateTableStmt{}, true}, | 			statement.CreateTableStmt{}, true}, | ||||||
| 		{"With type and not null", "CREATE TABLE test(foo INTEGER NOT NULL)", | 		{"With type and not null", "CREATE TABLE test(foo INTEGER NOT NULL)", | ||||||
| 			query.CreateTableStmt{ | 			statement.CreateTableStmt{ | ||||||
| 				Info: database.TableInfo{ | 				Info: database.TableInfo{ | ||||||
| 					TableName: "test", | 					TableName: "test", | ||||||
| 					FieldConstraints: []*database.FieldConstraint{ | 					FieldConstraints: []*database.FieldConstraint{ | ||||||
| @@ -84,7 +84,7 @@ func TestParserCreateTable(t *testing.T) { | |||||||
| 				}, | 				}, | ||||||
| 			}, false}, | 			}, false}, | ||||||
| 		{"With not null and primary key", "CREATE TABLE test(foo INTEGER NOT NULL PRIMARY KEY)", | 		{"With not null and primary key", "CREATE TABLE test(foo INTEGER NOT NULL PRIMARY KEY)", | ||||||
| 			query.CreateTableStmt{ | 			statement.CreateTableStmt{ | ||||||
| 				Info: database.TableInfo{ | 				Info: database.TableInfo{ | ||||||
| 					TableName: "test", | 					TableName: "test", | ||||||
| 					FieldConstraints: []*database.FieldConstraint{ | 					FieldConstraints: []*database.FieldConstraint{ | ||||||
| @@ -93,7 +93,7 @@ func TestParserCreateTable(t *testing.T) { | |||||||
| 				}, | 				}, | ||||||
| 			}, false}, | 			}, false}, | ||||||
| 		{"With primary key and not null", "CREATE TABLE test(foo INTEGER PRIMARY KEY NOT NULL)", | 		{"With primary key and not null", "CREATE TABLE test(foo INTEGER PRIMARY KEY NOT NULL)", | ||||||
| 			query.CreateTableStmt{ | 			statement.CreateTableStmt{ | ||||||
| 				Info: database.TableInfo{ | 				Info: database.TableInfo{ | ||||||
| 					TableName: "test", | 					TableName: "test", | ||||||
| 					FieldConstraints: []*database.FieldConstraint{ | 					FieldConstraints: []*database.FieldConstraint{ | ||||||
| @@ -102,7 +102,7 @@ func TestParserCreateTable(t *testing.T) { | |||||||
| 				}, | 				}, | ||||||
| 			}, false}, | 			}, false}, | ||||||
| 		{"With multiple constraints", "CREATE TABLE test(foo INTEGER PRIMARY KEY, bar INTEGER NOT NULL, baz[4][1].bat TEXT)", | 		{"With multiple constraints", "CREATE TABLE test(foo INTEGER PRIMARY KEY, bar INTEGER NOT NULL, baz[4][1].bat TEXT)", | ||||||
| 			query.CreateTableStmt{ | 			statement.CreateTableStmt{ | ||||||
| 				Info: database.TableInfo{ | 				Info: database.TableInfo{ | ||||||
| 					TableName: "test", | 					TableName: "test", | ||||||
| 					FieldConstraints: []*database.FieldConstraint{ | 					FieldConstraints: []*database.FieldConstraint{ | ||||||
| @@ -113,7 +113,7 @@ func TestParserCreateTable(t *testing.T) { | |||||||
| 				}, | 				}, | ||||||
| 			}, false}, | 			}, false}, | ||||||
| 		{"With table constraints / PK on defined field", "CREATE TABLE test(foo INTEGER, bar NOT NULL, PRIMARY KEY (foo))", | 		{"With table constraints / PK on defined field", "CREATE TABLE test(foo INTEGER, bar NOT NULL, PRIMARY KEY (foo))", | ||||||
| 			query.CreateTableStmt{ | 			statement.CreateTableStmt{ | ||||||
| 				Info: database.TableInfo{ | 				Info: database.TableInfo{ | ||||||
| 					TableName: "test", | 					TableName: "test", | ||||||
| 					FieldConstraints: []*database.FieldConstraint{ | 					FieldConstraints: []*database.FieldConstraint{ | ||||||
| @@ -123,7 +123,7 @@ func TestParserCreateTable(t *testing.T) { | |||||||
| 				}, | 				}, | ||||||
| 			}, false}, | 			}, false}, | ||||||
| 		{"With table constraints / PK on undefined field", "CREATE TABLE test(foo INTEGER, PRIMARY KEY (bar))", | 		{"With table constraints / PK on undefined field", "CREATE TABLE test(foo INTEGER, PRIMARY KEY (bar))", | ||||||
| 			query.CreateTableStmt{ | 			statement.CreateTableStmt{ | ||||||
| 				Info: database.TableInfo{ | 				Info: database.TableInfo{ | ||||||
| 					TableName: "test", | 					TableName: "test", | ||||||
| 					FieldConstraints: []*database.FieldConstraint{ | 					FieldConstraints: []*database.FieldConstraint{ | ||||||
| @@ -136,7 +136,7 @@ func TestParserCreateTable(t *testing.T) { | |||||||
| 		{"With table constraints / duplicate pk", "CREATE TABLE test(foo INTEGER PRIMARY KEY, PRIMARY KEY (bar))", nil, true}, | 		{"With table constraints / duplicate pk", "CREATE TABLE test(foo INTEGER PRIMARY KEY, PRIMARY KEY (bar))", nil, true}, | ||||||
| 		{"With table constraints / duplicate pk on same path", "CREATE TABLE test(foo INTEGER PRIMARY KEY, PRIMARY KEY (foo))", nil, true}, | 		{"With table constraints / duplicate pk on same path", "CREATE TABLE test(foo INTEGER PRIMARY KEY, PRIMARY KEY (foo))", nil, true}, | ||||||
| 		{"With table constraints / UNIQUE on defined field", "CREATE TABLE test(foo INTEGER, bar NOT NULL, UNIQUE (foo))", | 		{"With table constraints / UNIQUE on defined field", "CREATE TABLE test(foo INTEGER, bar NOT NULL, UNIQUE (foo))", | ||||||
| 			query.CreateTableStmt{ | 			statement.CreateTableStmt{ | ||||||
| 				Info: database.TableInfo{ | 				Info: database.TableInfo{ | ||||||
| 					TableName: "test", | 					TableName: "test", | ||||||
| 					FieldConstraints: []*database.FieldConstraint{ | 					FieldConstraints: []*database.FieldConstraint{ | ||||||
| @@ -146,7 +146,7 @@ func TestParserCreateTable(t *testing.T) { | |||||||
| 				}, | 				}, | ||||||
| 			}, false}, | 			}, false}, | ||||||
| 		{"With table constraints / UNIQUE on undefined field", "CREATE TABLE test(foo INTEGER, UNIQUE (bar))", | 		{"With table constraints / UNIQUE on undefined field", "CREATE TABLE test(foo INTEGER, UNIQUE (bar))", | ||||||
| 			query.CreateTableStmt{ | 			statement.CreateTableStmt{ | ||||||
| 				Info: database.TableInfo{ | 				Info: database.TableInfo{ | ||||||
| 					TableName: "test", | 					TableName: "test", | ||||||
| 					FieldConstraints: []*database.FieldConstraint{ | 					FieldConstraints: []*database.FieldConstraint{ | ||||||
| @@ -156,7 +156,7 @@ func TestParserCreateTable(t *testing.T) { | |||||||
| 				}, | 				}, | ||||||
| 			}, false}, | 			}, false}, | ||||||
| 		{"With table constraints / UNIQUE twice", "CREATE TABLE test(foo INTEGER UNIQUE, UNIQUE (foo))", | 		{"With table constraints / UNIQUE twice", "CREATE TABLE test(foo INTEGER UNIQUE, UNIQUE (foo))", | ||||||
| 			query.CreateTableStmt{ | 			statement.CreateTableStmt{ | ||||||
| 				Info: database.TableInfo{ | 				Info: database.TableInfo{ | ||||||
| 					TableName: "test", | 					TableName: "test", | ||||||
| 					FieldConstraints: []*database.FieldConstraint{ | 					FieldConstraints: []*database.FieldConstraint{ | ||||||
| @@ -166,10 +166,10 @@ func TestParserCreateTable(t *testing.T) { | |||||||
| 			}, false}, | 			}, false}, | ||||||
| 		{"With table constraints / duplicate pk on same path", "CREATE TABLE test(foo INTEGER PRIMARY KEY, PRIMARY KEY (foo))", nil, true}, | 		{"With table constraints / duplicate pk on same path", "CREATE TABLE test(foo INTEGER PRIMARY KEY, PRIMARY KEY (foo))", nil, true}, | ||||||
| 		{"With multiple primary keys", "CREATE TABLE test(foo PRIMARY KEY, bar PRIMARY KEY)", | 		{"With multiple primary keys", "CREATE TABLE test(foo PRIMARY KEY, bar PRIMARY KEY)", | ||||||
| 			query.CreateTableStmt{}, true}, | 			statement.CreateTableStmt{}, true}, | ||||||
| 		{"With all supported fixed size data types", | 		{"With all supported fixed size data types", | ||||||
| 			"CREATE TABLE test(d double, b bool)", | 			"CREATE TABLE test(d double, b bool)", | ||||||
| 			query.CreateTableStmt{ | 			statement.CreateTableStmt{ | ||||||
| 				Info: database.TableInfo{ | 				Info: database.TableInfo{ | ||||||
| 					TableName: "test", | 					TableName: "test", | ||||||
| 					FieldConstraints: []*database.FieldConstraint{ | 					FieldConstraints: []*database.FieldConstraint{ | ||||||
| @@ -180,7 +180,7 @@ func TestParserCreateTable(t *testing.T) { | |||||||
| 			}, false}, | 			}, false}, | ||||||
| 		{"With all supported variable size data types", | 		{"With all supported variable size data types", | ||||||
| 			"CREATE TABLE test(i integer, b blob, byt bytes, t text, a array, d document)", | 			"CREATE TABLE test(i integer, b blob, byt bytes, t text, a array, d document)", | ||||||
| 			query.CreateTableStmt{ | 			statement.CreateTableStmt{ | ||||||
| 				Info: database.TableInfo{ | 				Info: database.TableInfo{ | ||||||
| 					TableName: "test", | 					TableName: "test", | ||||||
| 					FieldConstraints: []*database.FieldConstraint{ | 					FieldConstraints: []*database.FieldConstraint{ | ||||||
| @@ -195,7 +195,7 @@ func TestParserCreateTable(t *testing.T) { | |||||||
| 			}, false}, | 			}, false}, | ||||||
| 		{"With integer aliases types", | 		{"With integer aliases types", | ||||||
| 			"CREATE TABLE test(i int, ii int2, ei int8, m mediumint, s smallint, b bigint, t tinyint)", | 			"CREATE TABLE test(i int, ii int2, ei int8, m mediumint, s smallint, b bigint, t tinyint)", | ||||||
| 			query.CreateTableStmt{ | 			statement.CreateTableStmt{ | ||||||
| 				Info: database.TableInfo{ | 				Info: database.TableInfo{ | ||||||
| 					TableName: "test", | 					TableName: "test", | ||||||
| 					FieldConstraints: []*database.FieldConstraint{ | 					FieldConstraints: []*database.FieldConstraint{ | ||||||
| @@ -211,7 +211,7 @@ func TestParserCreateTable(t *testing.T) { | |||||||
| 			}, false}, | 			}, false}, | ||||||
| 		{"With double aliases types", | 		{"With double aliases types", | ||||||
| 			"CREATE TABLE test(dp DOUBLE PRECISION, r real, d double)", | 			"CREATE TABLE test(dp DOUBLE PRECISION, r real, d double)", | ||||||
| 			query.CreateTableStmt{ | 			statement.CreateTableStmt{ | ||||||
| 				Info: database.TableInfo{ | 				Info: database.TableInfo{ | ||||||
| 					TableName: "test", | 					TableName: "test", | ||||||
| 					FieldConstraints: []*database.FieldConstraint{ | 					FieldConstraints: []*database.FieldConstraint{ | ||||||
| @@ -223,7 +223,7 @@ func TestParserCreateTable(t *testing.T) { | |||||||
| 			}, false}, | 			}, false}, | ||||||
| 		{"With text aliases types", | 		{"With text aliases types", | ||||||
| 			"CREATE TABLE test(v VARCHAR(255), c CHARACTER(64), t TEXT)", | 			"CREATE TABLE test(v VARCHAR(255), c CHARACTER(64), t TEXT)", | ||||||
| 			query.CreateTableStmt{ | 			statement.CreateTableStmt{ | ||||||
| 				Info: database.TableInfo{ | 				Info: database.TableInfo{ | ||||||
| 					TableName: "test", | 					TableName: "test", | ||||||
| 					FieldConstraints: []*database.FieldConstraint{ | 					FieldConstraints: []*database.FieldConstraint{ | ||||||
| @@ -235,7 +235,7 @@ func TestParserCreateTable(t *testing.T) { | |||||||
| 			}, false}, | 			}, false}, | ||||||
| 		{"With errored text aliases types", | 		{"With errored text aliases types", | ||||||
| 			"CREATE TABLE test(v VARCHAR(1 IN [1, 2, 3] AND foo > 4) )", | 			"CREATE TABLE test(v VARCHAR(1 IN [1, 2, 3] AND foo > 4) )", | ||||||
| 			query.CreateTableStmt{ | 			statement.CreateTableStmt{ | ||||||
| 				Info: database.TableInfo{ | 				Info: database.TableInfo{ | ||||||
| 					TableName: "test", | 					TableName: "test", | ||||||
| 					FieldConstraints: []*database.FieldConstraint{ | 					FieldConstraints: []*database.FieldConstraint{ | ||||||
| @@ -263,26 +263,26 @@ func TestParserCreateIndex(t *testing.T) { | |||||||
| 	tests := []struct { | 	tests := []struct { | ||||||
| 		name     string | 		name     string | ||||||
| 		s        string | 		s        string | ||||||
| 		expected query.Statement | 		expected statement.Statement | ||||||
| 		errored  bool | 		errored  bool | ||||||
| 	}{ | 	}{ | ||||||
| 		{"Basic", "CREATE INDEX idx ON test (foo)", query.CreateIndexStmt{ | 		{"Basic", "CREATE INDEX idx ON test (foo)", statement.CreateIndexStmt{ | ||||||
| 			Info: database.IndexInfo{ | 			Info: database.IndexInfo{ | ||||||
| 				IndexName: "idx", TableName: "test", Paths: []document.Path{document.Path(testutil.ParsePath(t, "foo"))}, | 				IndexName: "idx", TableName: "test", Paths: []document.Path{document.Path(testutil.ParsePath(t, "foo"))}, | ||||||
| 			}}, false}, | 			}}, false}, | ||||||
| 		{"If not exists", "CREATE INDEX IF NOT EXISTS idx ON test (foo.bar[1])", query.CreateIndexStmt{ | 		{"If not exists", "CREATE INDEX IF NOT EXISTS idx ON test (foo.bar[1])", statement.CreateIndexStmt{ | ||||||
| 			Info: database.IndexInfo{ | 			Info: database.IndexInfo{ | ||||||
| 				IndexName: "idx", TableName: "test", Paths: []document.Path{document.Path(testutil.ParsePath(t, "foo.bar[1]"))}, | 				IndexName: "idx", TableName: "test", Paths: []document.Path{document.Path(testutil.ParsePath(t, "foo.bar[1]"))}, | ||||||
| 			}, IfNotExists: true}, false}, | 			}, IfNotExists: true}, false}, | ||||||
| 		{"Unique", "CREATE UNIQUE INDEX IF NOT EXISTS idx ON test (foo[3].baz)", query.CreateIndexStmt{ | 		{"Unique", "CREATE UNIQUE INDEX IF NOT EXISTS idx ON test (foo[3].baz)", statement.CreateIndexStmt{ | ||||||
| 			Info: database.IndexInfo{ | 			Info: database.IndexInfo{ | ||||||
| 				IndexName: "idx", TableName: "test", Paths: []document.Path{document.Path(testutil.ParsePath(t, "foo[3].baz"))}, Unique: true, | 				IndexName: "idx", TableName: "test", Paths: []document.Path{document.Path(testutil.ParsePath(t, "foo[3].baz"))}, Unique: true, | ||||||
| 			}, IfNotExists: true}, false}, | 			}, IfNotExists: true}, false}, | ||||||
| 		{"No name", "CREATE UNIQUE INDEX ON test (foo[3].baz)", query.CreateIndexStmt{ | 		{"No name", "CREATE UNIQUE INDEX ON test (foo[3].baz)", statement.CreateIndexStmt{ | ||||||
| 			Info: database.IndexInfo{TableName: "test", Paths: []document.Path{document.Path(testutil.ParsePath(t, "foo[3].baz"))}, Unique: true}}, false}, | 			Info: database.IndexInfo{TableName: "test", Paths: []document.Path{document.Path(testutil.ParsePath(t, "foo[3].baz"))}, Unique: true}}, false}, | ||||||
| 		{"No name with IF NOT EXISTS", "CREATE UNIQUE INDEX IF NOT EXISTS ON test (foo[3].baz)", nil, true}, | 		{"No name with IF NOT EXISTS", "CREATE UNIQUE INDEX IF NOT EXISTS ON test (foo[3].baz)", nil, true}, | ||||||
| 		{"More than 1 path", "CREATE INDEX idx ON test (foo, bar)", | 		{"More than 1 path", "CREATE INDEX idx ON test (foo, bar)", | ||||||
| 			query.CreateIndexStmt(query.CreateIndexStmt{ | 			statement.CreateIndexStmt(statement.CreateIndexStmt{ | ||||||
| 				Info: database.IndexInfo{ | 				Info: database.IndexInfo{ | ||||||
| 					IndexName: "idx", | 					IndexName: "idx", | ||||||
| 					TableName: "test", | 					TableName: "test", | ||||||
|   | |||||||
| @@ -1,14 +1,14 @@ | |||||||
| package parser | package parser | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"github.com/genjidb/genji/internal/query" | 	"github.com/genjidb/genji/internal/query/statement" | ||||||
| 	"github.com/genjidb/genji/internal/sql/scanner" | 	"github.com/genjidb/genji/internal/sql/scanner" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| // parseDeleteStatement parses a delete string and returns a Statement AST object. | // parseDeleteStatement parses a delete string and returns a Statement AST object. | ||||||
| // This function assumes the DELETE token has already been consumed. | // This function assumes the DELETE token has already been consumed. | ||||||
| func (p *Parser) parseDeleteStatement() (*query.DeleteStmt, error) { | func (p *Parser) parseDeleteStatement() (*statement.DeleteStmt, error) { | ||||||
| 	var stmt query.DeleteStmt | 	var stmt statement.DeleteStmt | ||||||
| 	var err error | 	var err error | ||||||
|  |  | ||||||
| 	// Parse "FROM". | 	// Parse "FROM". | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ package parser_test | |||||||
| import ( | import ( | ||||||
| 	"testing" | 	"testing" | ||||||
|  |  | ||||||
| 	"github.com/genjidb/genji/internal/query" | 	"github.com/genjidb/genji/internal/query/statement" | ||||||
| 	"github.com/genjidb/genji/internal/sql/parser" | 	"github.com/genjidb/genji/internal/sql/parser" | ||||||
| 	"github.com/genjidb/genji/internal/stream" | 	"github.com/genjidb/genji/internal/stream" | ||||||
| 	"github.com/stretchr/testify/require" | 	"github.com/stretchr/testify/require" | ||||||
| @@ -54,9 +54,9 @@ func TestParserDelete(t *testing.T) { | |||||||
| 			q, err := parser.ParseQuery(test.s) | 			q, err := parser.ParseQuery(test.s) | ||||||
| 			require.NoError(t, err) | 			require.NoError(t, err) | ||||||
| 			require.Len(t, q.Statements, 1) | 			require.Len(t, q.Statements, 1) | ||||||
| 			stmt, err := q.Statements[0].(*query.DeleteStmt).ToStream() | 			stmt, err := q.Statements[0].(*statement.DeleteStmt).ToStream() | ||||||
| 			require.NoError(t, err) | 			require.NoError(t, err) | ||||||
| 			require.EqualValues(t, &query.StreamStmt{Stream: test.expected}, stmt) | 			require.EqualValues(t, &statement.StreamStmt{Stream: test.expected}, stmt) | ||||||
| 		}) | 		}) | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
|   | |||||||
| @@ -1,13 +1,13 @@ | |||||||
| package parser | package parser | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"github.com/genjidb/genji/internal/query" | 	"github.com/genjidb/genji/internal/query/statement" | ||||||
| 	"github.com/genjidb/genji/internal/sql/scanner" | 	"github.com/genjidb/genji/internal/sql/scanner" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| // parseDropStatement parses a drop string and returns a Statement AST object. | // parseDropStatement parses a drop string and returns a Statement AST object. | ||||||
| // This function assumes the DROP token has already been consumed. | // This function assumes the DROP token has already been consumed. | ||||||
| func (p *Parser) parseDropStatement() (query.Statement, error) { | func (p *Parser) parseDropStatement() (statement.Statement, error) { | ||||||
| 	tok, pos, lit := p.ScanIgnoreWhitespace() | 	tok, pos, lit := p.ScanIgnoreWhitespace() | ||||||
| 	switch tok { | 	switch tok { | ||||||
| 	case scanner.TABLE: | 	case scanner.TABLE: | ||||||
| @@ -21,8 +21,8 @@ func (p *Parser) parseDropStatement() (query.Statement, error) { | |||||||
|  |  | ||||||
| // parseDropTableStatement parses a drop table string and returns a Statement AST object. | // parseDropTableStatement parses a drop table string and returns a Statement AST object. | ||||||
| // This function assumes the DROP TABLE tokens have already been consumed. | // This function assumes the DROP TABLE tokens have already been consumed. | ||||||
| func (p *Parser) parseDropTableStatement() (query.DropTableStmt, error) { | func (p *Parser) parseDropTableStatement() (statement.DropTableStmt, error) { | ||||||
| 	var stmt query.DropTableStmt | 	var stmt statement.DropTableStmt | ||||||
| 	var err error | 	var err error | ||||||
|  |  | ||||||
| 	stmt.IfExists, err = p.parseOptional(scanner.IF, scanner.EXISTS) | 	stmt.IfExists, err = p.parseOptional(scanner.IF, scanner.EXISTS) | ||||||
| @@ -43,8 +43,8 @@ func (p *Parser) parseDropTableStatement() (query.DropTableStmt, error) { | |||||||
|  |  | ||||||
| // parseDropIndexStatement parses a drop index string and returns a Statement AST object. | // parseDropIndexStatement parses a drop index string and returns a Statement AST object. | ||||||
| // This function assumes the DROP INDEX tokens have already been consumed. | // This function assumes the DROP INDEX tokens have already been consumed. | ||||||
| func (p *Parser) parseDropIndexStatement() (query.DropIndexStmt, error) { | func (p *Parser) parseDropIndexStatement() (statement.DropIndexStmt, error) { | ||||||
| 	var stmt query.DropIndexStmt | 	var stmt statement.DropIndexStmt | ||||||
| 	var err error | 	var err error | ||||||
|  |  | ||||||
| 	stmt.IfExists, err = p.parseOptional(scanner.IF, scanner.EXISTS) | 	stmt.IfExists, err = p.parseOptional(scanner.IF, scanner.EXISTS) | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ package parser_test | |||||||
| import ( | import ( | ||||||
| 	"testing" | 	"testing" | ||||||
|  |  | ||||||
| 	"github.com/genjidb/genji/internal/query" | 	"github.com/genjidb/genji/internal/query/statement" | ||||||
| 	"github.com/genjidb/genji/internal/sql/parser" | 	"github.com/genjidb/genji/internal/sql/parser" | ||||||
| 	"github.com/stretchr/testify/require" | 	"github.com/stretchr/testify/require" | ||||||
| ) | ) | ||||||
| @@ -12,13 +12,13 @@ func TestParserDrop(t *testing.T) { | |||||||
| 	tests := []struct { | 	tests := []struct { | ||||||
| 		name     string | 		name     string | ||||||
| 		s        string | 		s        string | ||||||
| 		expected query.Statement | 		expected statement.Statement | ||||||
| 		errored  bool | 		errored  bool | ||||||
| 	}{ | 	}{ | ||||||
| 		{"Drop table", "DROP TABLE test", query.DropTableStmt{TableName: "test"}, false}, | 		{"Drop table", "DROP TABLE test", statement.DropTableStmt{TableName: "test"}, false}, | ||||||
| 		{"Drop table If not exists", "DROP TABLE IF EXISTS test", query.DropTableStmt{TableName: "test", IfExists: true}, false}, | 		{"Drop table If not exists", "DROP TABLE IF EXISTS test", statement.DropTableStmt{TableName: "test", IfExists: true}, false}, | ||||||
| 		{"Drop index", "DROP INDEX test", query.DropIndexStmt{IndexName: "test"}, false}, | 		{"Drop index", "DROP INDEX test", statement.DropIndexStmt{IndexName: "test"}, false}, | ||||||
| 		{"Drop index if exists", "DROP INDEX IF EXISTS test", query.DropIndexStmt{IndexName: "test", IfExists: true}, false}, | 		{"Drop index if exists", "DROP INDEX IF EXISTS test", statement.DropIndexStmt{IndexName: "test", IfExists: true}, false}, | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	for _, test := range tests { | 	for _, test := range tests { | ||||||
|   | |||||||
| @@ -1,13 +1,13 @@ | |||||||
| package parser | package parser | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"github.com/genjidb/genji/internal/query" | 	"github.com/genjidb/genji/internal/query/statement" | ||||||
| 	"github.com/genjidb/genji/internal/sql/scanner" | 	"github.com/genjidb/genji/internal/sql/scanner" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| // parseExplainStatement parses any statement and returns an ExplainStmt object. | // parseExplainStatement parses any statement and returns an ExplainStmt object. | ||||||
| // This function assumes the EXPLAIN token has already been consumed. | // This function assumes the EXPLAIN token has already been consumed. | ||||||
| func (p *Parser) parseExplainStatement() (query.Statement, error) { | func (p *Parser) parseExplainStatement() (statement.Statement, error) { | ||||||
| 	// ensure we don't have multiple EXPLAIN keywords | 	// ensure we don't have multiple EXPLAIN keywords | ||||||
| 	tok, pos, lit := p.ScanIgnoreWhitespace() | 	tok, pos, lit := p.ScanIgnoreWhitespace() | ||||||
| 	if tok != scanner.SELECT && tok != scanner.UPDATE && tok != scanner.DELETE && tok != scanner.INSERT { | 	if tok != scanner.SELECT && tok != scanner.UPDATE && tok != scanner.DELETE && tok != scanner.INSERT { | ||||||
| @@ -20,5 +20,5 @@ func (p *Parser) parseExplainStatement() (query.Statement, error) { | |||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	return &query.ExplainStmt{Statement: innerStmt}, nil | 	return &statement.ExplainStmt{Statement: innerStmt}, nil | ||||||
| } | } | ||||||
|   | |||||||
| @@ -4,7 +4,7 @@ import ( | |||||||
| 	"testing" | 	"testing" | ||||||
|  |  | ||||||
| 	"github.com/genjidb/genji/internal/expr" | 	"github.com/genjidb/genji/internal/expr" | ||||||
| 	"github.com/genjidb/genji/internal/query" | 	"github.com/genjidb/genji/internal/query/statement" | ||||||
| 	"github.com/genjidb/genji/internal/sql/parser" | 	"github.com/genjidb/genji/internal/sql/parser" | ||||||
| 	"github.com/stretchr/testify/require" | 	"github.com/stretchr/testify/require" | ||||||
| ) | ) | ||||||
| @@ -13,10 +13,10 @@ func TestParserExplain(t *testing.T) { | |||||||
| 	tests := []struct { | 	tests := []struct { | ||||||
| 		name     string | 		name     string | ||||||
| 		s        string | 		s        string | ||||||
| 		expected query.Statement | 		expected statement.Statement | ||||||
| 		errored  bool | 		errored  bool | ||||||
| 	}{ | 	}{ | ||||||
| 		{"Explain create table", "EXPLAIN SELECT * FROM test", &query.ExplainStmt{Statement: &query.SelectStmt{ | 		{"Explain create table", "EXPLAIN SELECT * FROM test", &statement.ExplainStmt{Statement: &statement.SelectStmt{ | ||||||
| 			TableName:       "test", | 			TableName:       "test", | ||||||
| 			ProjectionExprs: []expr.Expr{expr.Wildcard{}}, | 			ProjectionExprs: []expr.Expr{expr.Wildcard{}}, | ||||||
| 		}}, false}, | 		}}, false}, | ||||||
|   | |||||||
| @@ -3,15 +3,15 @@ package parser | |||||||
| import ( | import ( | ||||||
| 	"github.com/genjidb/genji/internal/database" | 	"github.com/genjidb/genji/internal/database" | ||||||
| 	"github.com/genjidb/genji/internal/expr" | 	"github.com/genjidb/genji/internal/expr" | ||||||
| 	"github.com/genjidb/genji/internal/query" | 	"github.com/genjidb/genji/internal/query/statement" | ||||||
| 	"github.com/genjidb/genji/internal/sql/scanner" | 	"github.com/genjidb/genji/internal/sql/scanner" | ||||||
| 	"github.com/genjidb/genji/internal/stringutil" | 	"github.com/genjidb/genji/internal/stringutil" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| // parseInsertStatement parses an insert string and returns a Statement AST object. | // parseInsertStatement parses an insert string and returns a Statement AST object. | ||||||
| // This function assumes the INSERT token has already been consumed. | // This function assumes the INSERT token has already been consumed. | ||||||
| func (p *Parser) parseInsertStatement() (*query.InsertStmt, error) { | func (p *Parser) parseInsertStatement() (*statement.InsertStmt, error) { | ||||||
| 	var stmt query.InsertStmt | 	var stmt statement.InsertStmt | ||||||
| 	var err error | 	var err error | ||||||
|  |  | ||||||
| 	// Parse "INTO". | 	// Parse "INTO". | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ import ( | |||||||
|  |  | ||||||
| 	"github.com/genjidb/genji/internal/database" | 	"github.com/genjidb/genji/internal/database" | ||||||
| 	"github.com/genjidb/genji/internal/expr" | 	"github.com/genjidb/genji/internal/expr" | ||||||
| 	"github.com/genjidb/genji/internal/query" | 	"github.com/genjidb/genji/internal/query/statement" | ||||||
| 	"github.com/genjidb/genji/internal/sql/parser" | 	"github.com/genjidb/genji/internal/sql/parser" | ||||||
| 	"github.com/genjidb/genji/internal/stream" | 	"github.com/genjidb/genji/internal/stream" | ||||||
| 	"github.com/genjidb/genji/internal/testutil" | 	"github.com/genjidb/genji/internal/testutil" | ||||||
| @@ -181,7 +181,7 @@ func TestParserInsert(t *testing.T) { | |||||||
| 			} | 			} | ||||||
| 			require.NoError(t, err) | 			require.NoError(t, err) | ||||||
| 			require.Len(t, q.Statements, 1) | 			require.Len(t, q.Statements, 1) | ||||||
| 			stmt := q.Statements[0].(*query.InsertStmt) | 			stmt := q.Statements[0].(*statement.InsertStmt) | ||||||
| 			require.False(t, stmt.IsReadOnly()) | 			require.False(t, stmt.IsReadOnly()) | ||||||
| 			ss, err := stmt.ToStream() | 			ss, err := stmt.ToStream() | ||||||
| 			require.NoError(t, err) | 			require.NoError(t, err) | ||||||
|   | |||||||
| @@ -7,6 +7,7 @@ import ( | |||||||
| 	"github.com/genjidb/genji/document" | 	"github.com/genjidb/genji/document" | ||||||
| 	"github.com/genjidb/genji/internal/expr" | 	"github.com/genjidb/genji/internal/expr" | ||||||
| 	"github.com/genjidb/genji/internal/query" | 	"github.com/genjidb/genji/internal/query" | ||||||
|  | 	"github.com/genjidb/genji/internal/query/statement" | ||||||
| 	"github.com/genjidb/genji/internal/sql/scanner" | 	"github.com/genjidb/genji/internal/sql/scanner" | ||||||
| 	"github.com/genjidb/genji/internal/stringutil" | 	"github.com/genjidb/genji/internal/stringutil" | ||||||
| ) | ) | ||||||
| @@ -61,7 +62,7 @@ func MustParseExpr(s string) expr.Expr { | |||||||
|  |  | ||||||
| // ParseQuery parses a Genji SQL string and returns a Query. | // ParseQuery parses a Genji SQL string and returns a Query. | ||||||
| func (p *Parser) ParseQuery() (query.Query, error) { | func (p *Parser) ParseQuery() (query.Query, error) { | ||||||
| 	var statements []query.Statement | 	var statements []statement.Statement | ||||||
| 	semi := true | 	semi := true | ||||||
|  |  | ||||||
| 	for { | 	for { | ||||||
| @@ -85,7 +86,7 @@ func (p *Parser) ParseQuery() (query.Query, error) { | |||||||
| } | } | ||||||
|  |  | ||||||
| // ParseStatement parses a Genji SQL string and returns a Statement AST object. | // ParseStatement parses a Genji SQL string and returns a Statement AST object. | ||||||
| func (p *Parser) ParseStatement() (query.Statement, error) { | func (p *Parser) ParseStatement() (statement.Statement, error) { | ||||||
| 	tok, pos, lit := p.ScanIgnoreWhitespace() | 	tok, pos, lit := p.ScanIgnoreWhitespace() | ||||||
| 	switch tok { | 	switch tok { | ||||||
| 	case scanner.ALTER: | 	case scanner.ALTER: | ||||||
|   | |||||||
| @@ -6,7 +6,7 @@ import ( | |||||||
| 	"github.com/stretchr/testify/require" | 	"github.com/stretchr/testify/require" | ||||||
|  |  | ||||||
| 	"github.com/genjidb/genji/internal/expr" | 	"github.com/genjidb/genji/internal/expr" | ||||||
| 	"github.com/genjidb/genji/internal/query" | 	"github.com/genjidb/genji/internal/query/statement" | ||||||
| 	"github.com/genjidb/genji/internal/sql/parser" | 	"github.com/genjidb/genji/internal/sql/parser" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| @@ -14,15 +14,15 @@ func TestParserMultiStatement(t *testing.T) { | |||||||
| 	tests := []struct { | 	tests := []struct { | ||||||
| 		name     string | 		name     string | ||||||
| 		s        string | 		s        string | ||||||
| 		expected []query.Statement | 		expected []statement.Statement | ||||||
| 	}{ | 	}{ | ||||||
| 		{"OnlyCommas", ";;;", nil}, | 		{"OnlyCommas", ";;;", nil}, | ||||||
| 		{"TrailingComma", "SELECT * FROM foo;;;DELETE FROM foo;", []query.Statement{ | 		{"TrailingComma", "SELECT * FROM foo;;;DELETE FROM foo;", []statement.Statement{ | ||||||
| 			&query.SelectStmt{ | 			&statement.SelectStmt{ | ||||||
| 				TableName:       "foo", | 				TableName:       "foo", | ||||||
| 				ProjectionExprs: []expr.Expr{expr.Wildcard{}}, | 				ProjectionExprs: []expr.Expr{expr.Wildcard{}}, | ||||||
| 			}, | 			}, | ||||||
| 			&query.DeleteStmt{ | 			&statement.DeleteStmt{ | ||||||
| 				TableName: "foo", | 				TableName: "foo", | ||||||
| 			}, | 			}, | ||||||
| 		}}, | 		}}, | ||||||
|   | |||||||
| @@ -1,14 +1,14 @@ | |||||||
| package parser | package parser | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"github.com/genjidb/genji/internal/query" | 	"github.com/genjidb/genji/internal/query/statement" | ||||||
| 	"github.com/genjidb/genji/internal/sql/scanner" | 	"github.com/genjidb/genji/internal/sql/scanner" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| // parseReindexStatement parses a reindex statement. | // parseReindexStatement parses a reindex statement. | ||||||
| // This function assumes the REINDEX token has already been consumed. | // This function assumes the REINDEX token has already been consumed. | ||||||
| func (p *Parser) parseReIndexStatement() (query.Statement, error) { | func (p *Parser) parseReIndexStatement() (statement.Statement, error) { | ||||||
| 	var stmt query.ReIndexStmt | 	var stmt statement.ReIndexStmt | ||||||
| 	var err error | 	var err error | ||||||
|  |  | ||||||
| 	tok, _, lit := p.ScanIgnoreWhitespace() | 	tok, _, lit := p.ScanIgnoreWhitespace() | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ package parser_test | |||||||
| import ( | import ( | ||||||
| 	"testing" | 	"testing" | ||||||
|  |  | ||||||
| 	"github.com/genjidb/genji/internal/query" | 	"github.com/genjidb/genji/internal/query/statement" | ||||||
| 	"github.com/genjidb/genji/internal/sql/parser" | 	"github.com/genjidb/genji/internal/sql/parser" | ||||||
| 	"github.com/stretchr/testify/require" | 	"github.com/stretchr/testify/require" | ||||||
| ) | ) | ||||||
| @@ -12,11 +12,11 @@ func TestParserReIndex(t *testing.T) { | |||||||
| 	tests := []struct { | 	tests := []struct { | ||||||
| 		name     string | 		name     string | ||||||
| 		s        string | 		s        string | ||||||
| 		expected query.Statement | 		expected statement.Statement | ||||||
| 		errored  bool | 		errored  bool | ||||||
| 	}{ | 	}{ | ||||||
| 		{"All", "REINDEX", query.ReIndexStmt{}, false}, | 		{"All", "REINDEX", statement.ReIndexStmt{}, false}, | ||||||
| 		{"With ident", "REINDEX tableOrIndex", query.ReIndexStmt{TableOrIndexName: "tableOrIndex"}, false}, | 		{"With ident", "REINDEX tableOrIndex", statement.ReIndexStmt{TableOrIndexName: "tableOrIndex"}, false}, | ||||||
| 		{"With extra", "REINDEX tableOrIndex tableOrIndex", nil, true}, | 		{"With extra", "REINDEX tableOrIndex tableOrIndex", nil, true}, | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|   | |||||||
| @@ -2,14 +2,14 @@ package parser | |||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"github.com/genjidb/genji/internal/expr" | 	"github.com/genjidb/genji/internal/expr" | ||||||
| 	"github.com/genjidb/genji/internal/query" | 	"github.com/genjidb/genji/internal/query/statement" | ||||||
| 	"github.com/genjidb/genji/internal/sql/scanner" | 	"github.com/genjidb/genji/internal/sql/scanner" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| // parseSelectStatement parses a select string and returns a Statement AST object. | // parseSelectStatement parses a select string and returns a Statement AST object. | ||||||
| // This function assumes the SELECT token has already been consumed. | // This function assumes the SELECT token has already been consumed. | ||||||
| func (p *Parser) parseSelectStatement() (*query.SelectStmt, error) { | func (p *Parser) parseSelectStatement() (*statement.SelectStmt, error) { | ||||||
| 	var stmt query.SelectStmt | 	var stmt statement.SelectStmt | ||||||
| 	var err error | 	var err error | ||||||
|  |  | ||||||
| 	stmt.Distinct, err = p.parseDistinct() | 	stmt.Distinct, err = p.parseDistinct() | ||||||
|   | |||||||
| @@ -4,7 +4,7 @@ import ( | |||||||
| 	"testing" | 	"testing" | ||||||
|  |  | ||||||
| 	"github.com/genjidb/genji/internal/expr" | 	"github.com/genjidb/genji/internal/expr" | ||||||
| 	"github.com/genjidb/genji/internal/query" | 	"github.com/genjidb/genji/internal/query/statement" | ||||||
| 	"github.com/genjidb/genji/internal/sql/parser" | 	"github.com/genjidb/genji/internal/sql/parser" | ||||||
| 	"github.com/genjidb/genji/internal/stream" | 	"github.com/genjidb/genji/internal/stream" | ||||||
| 	"github.com/genjidb/genji/internal/testutil" | 	"github.com/genjidb/genji/internal/testutil" | ||||||
| @@ -132,9 +132,9 @@ func TestParserSelect(t *testing.T) { | |||||||
| 			if !test.mustFail { | 			if !test.mustFail { | ||||||
| 				require.NoError(t, err) | 				require.NoError(t, err) | ||||||
| 				require.Len(t, q.Statements, 1) | 				require.Len(t, q.Statements, 1) | ||||||
| 				st, err := q.Statements[0].(*query.SelectStmt).ToStream() | 				st, err := q.Statements[0].(*statement.SelectStmt).ToStream() | ||||||
| 				require.NoError(t, err) | 				require.NoError(t, err) | ||||||
| 				require.EqualValues(t, &query.StreamStmt{Stream: test.expected, ReadOnly: true}, st) | 				require.EqualValues(t, &statement.StreamStmt{Stream: test.expected, ReadOnly: true}, st) | ||||||
| 			} else { | 			} else { | ||||||
| 				require.Error(t, err) | 				require.Error(t, err) | ||||||
| 			} | 			} | ||||||
|   | |||||||
| @@ -2,12 +2,13 @@ package parser | |||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"github.com/genjidb/genji/internal/query" | 	"github.com/genjidb/genji/internal/query" | ||||||
|  | 	"github.com/genjidb/genji/internal/query/statement" | ||||||
| 	"github.com/genjidb/genji/internal/sql/scanner" | 	"github.com/genjidb/genji/internal/sql/scanner" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| // parseBeginStatement parses a BEGIN statement. | // parseBeginStatement parses a BEGIN statement. | ||||||
| // This function assumes the BEGIN token has already been consumed. | // This function assumes the BEGIN token has already been consumed. | ||||||
| func (p *Parser) parseBeginStatement() (query.Statement, error) { | func (p *Parser) parseBeginStatement() (statement.Statement, error) { | ||||||
| 	// parse optional TRANSACTION token | 	// parse optional TRANSACTION token | ||||||
| 	_, _ = p.parseOptional(scanner.TRANSACTION) | 	_, _ = p.parseOptional(scanner.TRANSACTION) | ||||||
|  |  | ||||||
| @@ -34,7 +35,7 @@ func (p *Parser) parseBeginStatement() (query.Statement, error) { | |||||||
|  |  | ||||||
| // parseRollbackStatement parses a ROLLBACK statement. | // parseRollbackStatement parses a ROLLBACK statement. | ||||||
| // This function assumes the ROLLBACK token has already been consumed. | // This function assumes the ROLLBACK token has already been consumed. | ||||||
| func (p *Parser) parseRollbackStatement() (query.Statement, error) { | func (p *Parser) parseRollbackStatement() (statement.Statement, error) { | ||||||
| 	// parse optional TRANSACTION token | 	// parse optional TRANSACTION token | ||||||
| 	_, _ = p.parseOptional(scanner.TRANSACTION) | 	_, _ = p.parseOptional(scanner.TRANSACTION) | ||||||
|  |  | ||||||
| @@ -43,7 +44,7 @@ func (p *Parser) parseRollbackStatement() (query.Statement, error) { | |||||||
|  |  | ||||||
| // parseCommitStatement parses a COMMIT statement. | // parseCommitStatement parses a COMMIT statement. | ||||||
| // This function assumes the COMMIT token has already been consumed. | // This function assumes the COMMIT token has already been consumed. | ||||||
| func (p *Parser) parseCommitStatement() (query.Statement, error) { | func (p *Parser) parseCommitStatement() (statement.Statement, error) { | ||||||
| 	// parse optional TRANSACTION token | 	// parse optional TRANSACTION token | ||||||
| 	_, _ = p.parseOptional(scanner.TRANSACTION) | 	_, _ = p.parseOptional(scanner.TRANSACTION) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -4,6 +4,7 @@ import ( | |||||||
| 	"testing" | 	"testing" | ||||||
|  |  | ||||||
| 	"github.com/genjidb/genji/internal/query" | 	"github.com/genjidb/genji/internal/query" | ||||||
|  | 	"github.com/genjidb/genji/internal/query/statement" | ||||||
| 	"github.com/genjidb/genji/internal/sql/parser" | 	"github.com/genjidb/genji/internal/sql/parser" | ||||||
| 	"github.com/stretchr/testify/require" | 	"github.com/stretchr/testify/require" | ||||||
| ) | ) | ||||||
| @@ -11,7 +12,7 @@ import ( | |||||||
| func TestParserTransactions(t *testing.T) { | func TestParserTransactions(t *testing.T) { | ||||||
| 	tests := []struct { | 	tests := []struct { | ||||||
| 		s        string | 		s        string | ||||||
| 		expected query.Statement | 		expected statement.Statement | ||||||
| 		errored  bool | 		errored  bool | ||||||
| 	}{ | 	}{ | ||||||
| 		{"BEGIN", query.BeginStmt{Writable: true}, false}, | 		{"BEGIN", query.BeginStmt{Writable: true}, false}, | ||||||
|   | |||||||
| @@ -1,14 +1,14 @@ | |||||||
| package parser | package parser | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
| 	"github.com/genjidb/genji/internal/query" | 	"github.com/genjidb/genji/internal/query/statement" | ||||||
| 	"github.com/genjidb/genji/internal/sql/scanner" | 	"github.com/genjidb/genji/internal/sql/scanner" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| // parseUpdateStatement parses a update string and returns a Statement AST object. | // parseUpdateStatement parses a update string and returns a Statement AST object. | ||||||
| // This function assumes the UPDATE token has already been consumed. | // This function assumes the UPDATE token has already been consumed. | ||||||
| func (p *Parser) parseUpdateStatement() (*query.UpdateStmt, error) { | func (p *Parser) parseUpdateStatement() (*statement.UpdateStmt, error) { | ||||||
| 	var stmt query.UpdateStmt | 	var stmt statement.UpdateStmt | ||||||
| 	var err error | 	var err error | ||||||
|  |  | ||||||
| 	// Parse table name | 	// Parse table name | ||||||
| @@ -43,8 +43,8 @@ func (p *Parser) parseUpdateStatement() (*query.UpdateStmt, error) { | |||||||
| } | } | ||||||
|  |  | ||||||
| // parseSetClause parses the "SET" clause of the query. | // parseSetClause parses the "SET" clause of the query. | ||||||
| func (p *Parser) parseSetClause() ([]query.UpdateSetPair, error) { | func (p *Parser) parseSetClause() ([]statement.UpdateSetPair, error) { | ||||||
| 	var pairs []query.UpdateSetPair | 	var pairs []statement.UpdateSetPair | ||||||
|  |  | ||||||
| 	firstPair := true | 	firstPair := true | ||||||
| 	for { | 	for { | ||||||
| @@ -75,7 +75,7 @@ func (p *Parser) parseSetClause() ([]query.UpdateSetPair, error) { | |||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return nil, err | 			return nil, err | ||||||
| 		} | 		} | ||||||
| 		pairs = append(pairs, query.UpdateSetPair{Path: path, E: expr}) | 		pairs = append(pairs, statement.UpdateSetPair{Path: path, E: expr}) | ||||||
|  |  | ||||||
| 		firstPair = false | 		firstPair = false | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -4,7 +4,7 @@ import ( | |||||||
| 	"testing" | 	"testing" | ||||||
|  |  | ||||||
| 	"github.com/genjidb/genji/document" | 	"github.com/genjidb/genji/document" | ||||||
| 	"github.com/genjidb/genji/internal/query" | 	"github.com/genjidb/genji/internal/query/statement" | ||||||
| 	"github.com/genjidb/genji/internal/sql/parser" | 	"github.com/genjidb/genji/internal/sql/parser" | ||||||
| 	"github.com/genjidb/genji/internal/stream" | 	"github.com/genjidb/genji/internal/stream" | ||||||
| 	"github.com/genjidb/genji/internal/testutil" | 	"github.com/genjidb/genji/internal/testutil" | ||||||
| @@ -75,7 +75,7 @@ func TestParserUpdate(t *testing.T) { | |||||||
|  |  | ||||||
| 			require.NoError(t, err) | 			require.NoError(t, err) | ||||||
| 			require.Len(t, q.Statements, 1) | 			require.Len(t, q.Statements, 1) | ||||||
| 			stmt := q.Statements[0].(*query.UpdateStmt) | 			stmt := q.Statements[0].(*statement.UpdateStmt) | ||||||
| 			require.False(t, stmt.IsReadOnly()) | 			require.False(t, stmt.IsReadOnly()) | ||||||
| 			require.EqualValues(t, test.expected, stmt.ToStream().Stream) | 			require.EqualValues(t, test.expected, stmt.ToStream().Stream) | ||||||
| 		}) | 		}) | ||||||
|   | |||||||
| @@ -9,7 +9,7 @@ import ( | |||||||
| 	"github.com/genjidb/genji/engine/memoryengine" | 	"github.com/genjidb/genji/engine/memoryengine" | ||||||
| 	"github.com/genjidb/genji/internal/database" | 	"github.com/genjidb/genji/internal/database" | ||||||
| 	"github.com/genjidb/genji/internal/expr" | 	"github.com/genjidb/genji/internal/expr" | ||||||
| 	"github.com/genjidb/genji/internal/query" | 	"github.com/genjidb/genji/internal/query/statement" | ||||||
| 	"github.com/genjidb/genji/internal/sql/parser" | 	"github.com/genjidb/genji/internal/sql/parser" | ||||||
| 	"github.com/stretchr/testify/require" | 	"github.com/stretchr/testify/require" | ||||||
| ) | ) | ||||||
| @@ -54,7 +54,7 @@ func Exec(tx *database.Transaction, q string, params ...expr.Param) error { | |||||||
| 	}) | 	}) | ||||||
| } | } | ||||||
|  |  | ||||||
| func Query(tx *database.Transaction, q string, params ...expr.Param) (*query.Result, error) { | func Query(tx *database.Transaction, q string, params ...expr.Param) (*statement.Result, error) { | ||||||
| 	pq, err := parser.ParseQuery(q) | 	pq, err := parser.ParseQuery(q) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| @@ -68,7 +68,7 @@ func MustExec(t *testing.T, tx *database.Transaction, q string, params ...expr.P | |||||||
| 	require.NoError(t, err) | 	require.NoError(t, err) | ||||||
| } | } | ||||||
|  |  | ||||||
| func MustQuery(t *testing.T, tx *database.Transaction, q string, params ...expr.Param) *query.Result { | func MustQuery(t *testing.T, tx *database.Transaction, q string, params ...expr.Param) *statement.Result { | ||||||
| 	res, err := Query(tx, q, params...) | 	res, err := Query(tx, q, params...) | ||||||
| 	require.NoError(t, err) | 	require.NoError(t, err) | ||||||
| 	return res | 	return res | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Asdine El Hrychy
					Asdine El Hrychy