Repository: src-d/go-mysql-server
Pull request #841 (2019-10-14 09:34:07)

sql/index/pilosa: better error messages
Related to https://github.com/src-d/gitbase/issues/971


Patch:
diff --git a/SUPPORTED.md b/SUPPORTED.md
index 6b89188..a316dff 100644
--- a/SUPPORTED.md
+++ b/SUPPORTED.md
@@ -80,6 +80,9 @@
 - div
 - %
 
+## Subqueries
+- supported only as tables, not as expressions.
+
 ## Functions
 - ARRAY_LENGTH
 - CEIL
@@ -130,6 +133,3 @@
 - WEEKDAY
 - YEAR
 - YEARWEEK
-
-## Subqueries
-Supported both as a table and as expressions but they can't access the parent query scope.
diff --git a/engine.go b/engine.go
index 4cb90c3..ae11ef7 100644
--- a/engine.go
+++ b/engine.go
@@ -1,4 +1,4 @@
-package sqle
+package sqle // import "github.com/src-d/go-mysql-server"
 
 import (
 	"time"
diff --git a/log.go b/log.go
index 346b545..4880ace 100644
--- a/log.go
+++ b/log.go
@@ -1,4 +1,4 @@
-package sqle
+package sqle // import "github.com/src-d/go-mysql-server"
 
 import (
 	"github.com/golang/glog"
diff --git a/server/server.go b/server/server.go
index 15fdb45..b2bc892 100644
--- a/server/server.go
+++ b/server/server.go
@@ -1,4 +1,4 @@
-package server
+package server // import "github.com/src-d/go-mysql-server/server"
 
 import (
 	"time"
diff --git a/sql/analyzer/analyzer.go b/sql/analyzer/analyzer.go
index f7bc456..1066d61 100644
--- a/sql/analyzer/analyzer.go
+++ b/sql/analyzer/analyzer.go
@@ -1,4 +1,4 @@
-package analyzer
+package analyzer // import "github.com/src-d/go-mysql-server/sql/analyzer"
 
 import (
 	"os"
diff --git a/sql/analyzer/assign_indexes.go b/sql/analyzer/assign_indexes.go
index b6bcb13..4462cb9 100644
--- a/sql/analyzer/assign_indexes.go
+++ b/sql/analyzer/assign_indexes.go
@@ -759,20 +759,8 @@ func containsColumns(e sql.Expression) bool {
 	return result
 }
 
-func containsSubquery(e sql.Expression) bool {
-	var result bool
-	expression.Inspect(e, func(e sql.Expression) bool {
-		if _, ok := e.(*expression.Subquery); ok {
-			result = true
-			return false
-		}
-		return true
-	})
-	return result
-}
-
 func isEvaluable(e sql.Expression) bool {
-	return !containsColumns(e) && !containsSubquery(e)
+	return !containsColumns(e)
 }
 
 func canMergeIndexes(a, b sql.IndexLookup) bool {
diff --git a/sql/analyzer/resolve_subqueries.go b/sql/analyzer/resolve_subqueries.go
index 20b97df..5015253 100644
--- a/sql/analyzer/resolve_subqueries.go
+++ b/sql/analyzer/resolve_subqueries.go
@@ -2,7 +2,6 @@ package analyzer
 
 import (
 	"github.com/src-d/go-mysql-server/sql"
-	"github.com/src-d/go-mysql-server/sql/expression"
 	"github.com/src-d/go-mysql-server/sql/plan"
 )
 
@@ -11,7 +10,7 @@ func resolveSubqueries(ctx *sql.Context, a *Analyzer, n sql.Node) (sql.Node, err
 	defer span.Finish()
 
 	a.Log("resolving subqueries")
-	n, err := plan.TransformUp(n, func(n sql.Node) (sql.Node, error) {
+	return plan.TransformUp(n, func(n sql.Node) (sql.Node, error) {
 		switch n := n.(type) {
 		case *plan.SubqueryAlias:
 			a.Log("found subquery %q with child of type %T", n.Name(), n.Child)
@@ -25,25 +24,4 @@ func resolveSubqueries(ctx *sql.Context, a *Analyzer, n sql.Node) (sql.Node, err
 			return n, nil
 		}
 	})
-	if err != nil {
-		return nil, err
-	}
-
-	return plan.TransformExpressionsUp(n, func(e sql.Expression) (sql.Expression, error) {
-		s, ok := e.(*expression.Subquery)
-		if !ok || s.Resolved() {
-			return e, nil
-		}
-
-		q, err := a.Analyze(ctx, s.Query)
-		if err != nil {
-			return nil, err
-		}
-
-		if qp, ok := q.(*plan.QueryProcess); ok {
-			q = qp.Child
-		}
-
-		return s.WithQuery(q), nil
-	})
 }
diff --git a/sql/analyzer/validation_rules.go b/sql/analyzer/validation_rules.go
index 7d35ee6..e7448d9 100644
--- a/sql/analyzer/validation_rules.go
+++ b/sql/analyzer/validation_rules.go
@@ -20,7 +20,6 @@ const (
 	validateCaseResultTypesRule = "validate_case_result_types"
 	validateIntervalUsageRule   = "validate_interval_usage"
 	validateExplodeUsageRule    = "validate_explode_usage"
-	validateSubqueryColumnsRule = "validate_subquery_columns"
 )
 
 var (
@@ -58,12 +57,6 @@ var (
 	ErrExplodeInvalidUse = errors.NewKind(
 		"using EXPLODE is not supported outside a Project node",
 	)
-
-	// ErrSubqueryColumns is returned when an expression subquery returns
-	// more than a single column.
-	ErrSubqueryColumns = errors.NewKind(
-		"subquery expressions can only return a single column",
-	)
 )
 
 // DefaultValidationRules to apply while analyzing nodes.
@@ -77,7 +70,6 @@ var DefaultValidationRules = []Rule{
 	{validateCaseResultTypesRule, validateCaseResultTypes},
 	{validateIntervalUsageRule, validateIntervalUsage},
 	{validateExplodeUsageRule, validateExplodeUsage},
-	{validateSubqueryColumnsRule, validateSubqueryColumns},
 }
 
 func validateIsResolved(ctx *sql.Context, a *Analyzer, n sql.Node) (sql.Node, error) {
@@ -330,25 +322,6 @@ func validateExplodeUsage(ctx *sql.Context, a *Analyzer, n sql.Node) (sql.Node,
 	return n, nil
 }
 
-func validateSubqueryColumns(ctx *sql.Context, a *Analyzer, n sql.Node) (sql.Node, error) {
-	valid := true
-	plan.InspectExpressions(n, func(e sql.Expression) bool {
-		s, ok := e.(*expression.Subquery)
-		if ok && len(s.Query.Schema()) != 1 {
-			valid = false
-			return false
-		}
-
-		return true
-	})
-
-	if !valid {
-		return nil, ErrSubqueryColumns.New()
-	}
-
-	return n, nil
-}
-
 func stringContains(strs []string, target string) bool {
 	for _, s := range strs {
 		if s == target {
diff --git a/sql/core.go b/sql/core.go
index e91ce0b..a45a1d6 100644
--- a/sql/core.go
+++ b/sql/core.go
@@ -1,4 +1,4 @@
-package sql
+package sql // import "github.com/src-d/go-mysql-server/sql"
 
 import (
 	"fmt"
diff --git a/sql/expression/comparison.go b/sql/expression/comparison.go
index 8760157..8491f9c 100644
--- a/sql/expression/comparison.go
+++ b/sql/expression/comparison.go
@@ -466,6 +466,7 @@ func (in *In) Eval(ctx *sql.Context, row sql.Row) (interface{}, error) {
 		return nil, err
 	}
 
+	// TODO: support subqueries
 	switch right := in.Right().(type) {
 	case Tuple:
 		for _, el := range right {
@@ -495,34 +496,6 @@ func (in *In) Eval(ctx *sql.Context, row sql.Row) (interface{}, error) {
 			}
 		}
 
-		return false, nil
-	case *Subquery:
-		if leftElems > 1 {
-			return nil, ErrInvalidOperandColumns.New(leftElems, 1)
-		}
-
-		typ := right.Type()
-		values, err := right.EvalMultiple(ctx)
-		if err != nil {
-			return nil, err
-		}
-
-		for _, val := range values {
-			val, err = typ.Convert(val)
-			if err != nil {
-				return nil, err
-			}
-
-			cmp, err := typ.Compare(left, val)
-			if err != nil {
-				return nil, err
-			}
-
-			if cmp == 0 {
-				return true, nil
-			}
-		}
-
 		return false, nil
 	default:
 		return nil, ErrUnsupportedInOperand.New(right)
@@ -574,6 +547,7 @@ func (in *NotIn) Eval(ctx *sql.Context, row sql.Row) (interface{}, error) {
 		return nil, err
 	}
 
+	// TODO: support subqueries
 	switch right := in.Right().(type) {
 	case Tuple:
 		for _, el := range right {
@@ -603,34 +577,6 @@ func (in *NotIn) Eval(ctx *sql.Context, row sql.Row) (interface{}, error) {
 			}
 		}
 
-		return true, nil
-	case *Subquery:
-		if leftElems > 1 {
-			return nil, ErrInvalidOperandColumns.New(leftElems, 1)
-		}
-
-		typ := right.Type()
-		values, err := right.EvalMultiple(ctx)
-		if err != nil {
-			return nil, err
-		}
-
-		for _, val := range values {
-			val, err = typ.Convert(val)
-			if err != nil {
-				return nil, err
-			}
-
-			cmp, err := typ.Compare(left, val)
-			if err != nil {
-				return nil, err
-			}
-
-			if cmp == 0 {
-				return false, nil
-			}
-		}
-
 		return true, nil
 	default:
 		return nil, ErrUnsupportedInOperand.New(right)
diff --git a/sql/expression/doc.go b/sql/expression/doc.go
new file mode 100644
index 0000000..820316f
--- /dev/null
+++ b/sql/expression/doc.go
@@ -0,0 +1,1 @@
+package expression // import "github.com/src-d/go-mysql-server/sql/expression"
diff --git a/sql/expression/function/aggregation/avg.go b/sql/expression/function/aggregation/avg.go
index eae1c8c..5e6b2ff 100644
--- a/sql/expression/function/aggregation/avg.go
+++ b/sql/expression/function/aggregation/avg.go
@@ -1,4 +1,4 @@
-package aggregation
+package aggregation // import "github.com/src-d/go-mysql-server/sql/expression/function/aggregation"
 
 import (
 	"fmt"
diff --git a/sql/expression/function/arraylength.go b/sql/expression/function/arraylength.go
index 61a902c..00d10cf 100644
--- a/sql/expression/function/arraylength.go
+++ b/sql/expression/function/arraylength.go
@@ -1,4 +1,4 @@
-package function
+package function // import "github.com/src-d/go-mysql-server/sql/expression/function"
 
 import (
 	"fmt"
diff --git a/sql/expression/subquery.go b/sql/expression/subquery.go
deleted file mode 100644
index faae15a..0000000
--- a/sql/expression/subquery.go
+++ /dev/null
@@ -1,125 +0,0 @@
-package expression
-
-import (
-	"fmt"
-
-	"github.com/src-d/go-mysql-server/sql"
-	errors "gopkg.in/src-d/go-errors.v1"
-)
-
-var errExpectedSingleRow = errors.NewKind("the subquery returned more than 1 row")
-
-// Subquery that is executed as an expression.
-type Subquery struct {
-	Query sql.Node
-	value interface{}
-}
-
-// NewSubquery returns a new subquery node.
-func NewSubquery(node sql.Node) *Subquery {
-	return &Subquery{node, nil}
-}
-
-// Eval implements the Expression interface.
-func (s *Subquery) Eval(ctx *sql.Context, _ sql.Row) (interface{}, error) {
-	if s.value != nil {
-		if elems, ok := s.value.([]interface{}); ok {
-			if len(elems) > 1 {
-				return nil, errExpectedSingleRow.New()
-			}
-			return elems[0], nil
-		}
-		return s.value, nil
-	}
-
-	iter, err := s.Query.RowIter(ctx)
-	if err != nil {
-		return nil, err
-	}
-
-	rows, err := sql.RowIterToRows(iter)
-	if err != nil {
-		return nil, err
-	}
-
-	if len(rows) == 0 {
-		s.value = nil
-		return nil, nil
-	}
-
-	if len(rows) > 1 {
-		return nil, errExpectedSingleRow.New()
-	}
-
-	s.value = rows[0][0]
-	return s.value, nil
-}
-
-// EvalMultiple returns all rows returned by a subquery.
-func (s *Subquery) EvalMultiple(ctx *sql.Context) ([]interface{}, error) {
-	if s.value != nil {
-		return s.value.([]interface{}), nil
-	}
-
-	iter, err := s.Query.RowIter(ctx)
-	if err != nil {
-		return nil, err
-	}
-
-	rows, err := sql.RowIterToRows(iter)
-	if err != nil {
-		return nil, err
-	}
-
-	if len(rows) == 0 {
-		s.value = []interface{}{}
-		return nil, nil
-	}
-
-	var result = make([]interface{}, len(rows))
-	for i, row := range rows {
-		result[i] = row[0]
-	}
-	s.value = result
-
-	return result, nil
-}
-
-// IsNullable implements the Expression interface.
-func (s *Subquery) IsNullable() bool {
-	return s.Query.Schema()[0].Nullable
-}
-
-func (s *Subquery) String() string {
-	return fmt.Sprintf("(%s)", s.Query)
-}
-
-// Resolved implements the Expression interface.
-func (s *Subquery) Resolved() bool {
-	return s.Query.Resolved()
-}
-
-// Type implements the Expression interface.
-func (s *Subquery) Type() sql.Type {
-	return s.Query.Schema()[0].Type
-}
-
-// WithChildren implements the Expression interface.
-func (s *Subquery) WithChildren(children ...sql.Expression) (sql.Expression, error) {
-	if len(children) != 0 {
-		return nil, sql.ErrInvalidChildrenNumber.New(s, len(children), 0)
-	}
-	return s, nil
-}
-
-// Children implements the Expression interface.
-func (s *Subquery) Children() []sql.Expression {
-	return nil
-}
-
-// WithQuery returns the subquery with the query node changed.
-func (s *Subquery) WithQuery(node sql.Node) *Subquery {
-	ns := *s
-	ns.Query = node
-	return &ns
-}
diff --git a/sql/expression/transform.go b/sql/expression/transform.go
index 05195c7..ccf3d42 100644
--- a/sql/expression/transform.go
+++ b/sql/expression/transform.go
@@ -1,8 +1,6 @@
 package expression
 
-import (
-	"github.com/src-d/go-mysql-server/sql"
-)
+import "github.com/src-d/go-mysql-server/sql"
 
 // TransformUp applies a transformation function to the given expression from the
 // bottom up.
diff --git a/sql/index/config.go b/sql/index/config.go
index dcf8462..7d5b7c9 100644
--- a/sql/index/config.go
+++ b/sql/index/config.go
@@ -24,7 +24,6 @@ func NewConfig(
 	driverID string,
 	driverConfig map[string]string,
 ) *Config {
-
 	cfg := &Config{
 		DB:          db,
 		Table:       table,
diff --git a/sql/index/pilosa/driver.go b/sql/index/pilosa/driver.go
index a9b30cf..4f9146b 100644
--- a/sql/index/pilosa/driver.go
+++ b/sql/index/pilosa/driver.go
@@ -110,6 +110,8 @@ func (*Driver) ID() string {
 	return DriverID
 }
 
+var errWriteConfigFile = errors.NewKind("unable to write indexes configuration file")
+
 // Create a new index.
 func (d *Driver) Create(
 	db, table, id string,
@@ -133,7 +135,7 @@ func (d *Driver) Create(
 	cfg := index.NewConfig(db, table, id, exprs, d.ID(), config)
 	err = index.WriteConfigFile(d.configFilePath(db, table, id), cfg)
 	if err != nil {
-		return nil, err
+		return nil, errWriteConfigFile.Wrap(err)
 	}
 
 	idx, err := d.newPilosaIndex(db, table)
@@ -146,12 +148,14 @@ func (d *Driver) Create(
 		processingFile,
 		[]byte{processingFileOnCreate},
 	); err != nil {
-		return nil, err
+		return nil, errWriteConfigFile.Wrap(err)
 	}
 
 	return newPilosaIndex(idx, cfg), nil
 }
 
+var errReadIndexes = errors.NewKind("error loading all indexes for table %s of database %s: %s")
+
 // LoadAll loads all indexes for given db and table
 func (d *Driver) LoadAll(db, table string) ([]sql.Index, error) {
 	var (
@@ -165,7 +169,7 @@ func (d *Driver) LoadAll(db, table string) ([]sql.Index, error) {
 		if os.IsNotExist(err) {
 			return indexes, nil
 		}
-		return nil, err
+		return nil, errReadIndexes.New(table, db, err)
 	}
 	for _, info := range dirs {
 		if info.IsDir() && !strings.HasPrefix(info.Name(), ".") {
@@ -187,6 +191,11 @@ func (d *Driver) LoadAll(db, table string) ([]sql.Index, error) {
 	return indexes, nil
 }
 
+var (
+	errLoadingIndexConfig = errors.NewKind("unable to load index configuration")
+	errReadIndexConfig    = errors.NewKind("unable to read index configuration")
+)
+
 func (d *Driver) loadIndex(db, table, id string) (*pilosaIndex, error) {
 	idx, err := d.newPilosaIndex(db, table)
 	if err != nil {
@@ -206,7 +215,7 @@ func (d *Driver) loadIndex(db, table, id string) (*pilosaIndex, error) {
 	processing := d.processingFilePath(db, table, id)
 	ok, err := index.ExistsProcessingFile(processing)
 	if err != nil {
-		return nil, err
+		return nil, errLoadingIndexConfig.Wrap(err)
 	}
 	if ok {
 		log := logrus.WithFields(logrus.Fields{
@@ -226,7 +235,7 @@ func (d *Driver) loadIndex(db, table, id string) (*pilosaIndex, error) {
 
 	cfg, err := index.ReadConfigFile(config)
 	if err != nil {
-		return nil, err
+		return nil, errReadIndexConfig.Wrap(err)
 	}
 	cfgDriver := cfg.Driver(DriverID)
 	if cfgDriver == nil {
@@ -382,13 +391,13 @@ func (d *Driver) Save(
 		[]byte{processingFileOnSave},
 	)
 	if err != nil {
-		return err
+		return errWriteConfigFile.Wrap(err)
 	}
 
 	cfgPath := d.configFilePath(i.Database(), i.Table(), i.ID())
 	cfg, err := index.ReadConfigFile(cfgPath)
 	if err != nil {
-		return err
+		return errReadIndexConfig.Wrap(err)
 	}
 	driverCfg := cfg.Driver(DriverID)
 
@@ -462,7 +471,7 @@ func (d *Driver) Save(
 		return errors[0]
 	}
 	if err = index.WriteConfigFile(cfgPath, cfg); err != nil {
-		return err
+		return errWriteConfigFile.Wrap(err)
 	}
 
 	observeIndex(time.Since(start), timePilosa, timeMapping, rows)
diff --git a/sql/information_schema.go b/sql/information_schema.go
index d888047..0a30478 100644
--- a/sql/information_schema.go
+++ b/sql/information_schema.go
@@ -1,4 +1,4 @@
-package sql
+package sql // import "github.com/src-d/go-mysql-server/sql"
 
 import (
 	"bytes"
diff --git a/sql/parse/indexes.go b/sql/parse/indexes.go
index a435f78..4a0ac4e 100644
--- a/sql/parse/indexes.go
+++ b/sql/parse/indexes.go
@@ -39,7 +39,7 @@ func parseShowIndex(s string) (sql.Node, error) {
 	), nil
 }
 
-func parseCreateIndex(ctx *sql.Context, s string) (sql.Node, error) {
+func parseCreateIndex(s string) (sql.Node, error) {
 	r := bufio.NewReader(strings.NewReader(s))
 
 	var name, table, driver string
@@ -78,7 +78,7 @@ func parseCreateIndex(ctx *sql.Context, s string) (sql.Node, error) {
 	var indexExprs = make([]sql.Expression, len(exprs))
 	for i, e := range exprs {
 		var err error
-		indexExprs[i], err = parseExpr(ctx, e)
+		indexExprs[i], err = parseExpr(e)
 		if err != nil {
 			return nil, err
 		}
diff --git a/sql/parse/parse.go b/sql/parse/parse.go
index 14d5e30..72a125e 100644
--- a/sql/parse/parse.go
+++ b/sql/parse/parse.go
@@ -1,4 +1,4 @@
-package parse
+package parse // import "github.com/src-d/go-mysql-server/sql/parse"
 
 import (
 	"bufio"
@@ -26,6 +26,9 @@ var (
 	// ErrUnsupportedFeature is thrown when a feature is not already supported
 	ErrUnsupportedFeature = errors.NewKind("unsupported feature: %s")
 
+	// ErrUnsupportedSubqueryExpression is thrown because subqueries are not supported, yet.
+	ErrUnsupportedSubqueryExpression = errors.NewKind("unsupported subquery expression")
+
 	// ErrInvalidSQLValType is returned when a SQLVal type is not valid.
 	ErrInvalidSQLValType = errors.NewKind("invalid SQLVal of type: %d")
 
@@ -70,7 +73,7 @@ func Parse(ctx *sql.Context, query string) (sql.Node, error) {
 	case describeTablesRegex.MatchString(lowerQuery):
 		return parseDescribeTables(lowerQuery)
 	case createIndexRegex.MatchString(lowerQuery):
-		return parseCreateIndex(ctx, s)
+		return parseCreateIndex(s)
 	case dropIndexRegex.MatchString(lowerQuery):
 		return parseDropIndex(s)
 	case showIndexRegex.MatchString(lowerQuery):
@@ -82,7 +85,7 @@ func Parse(ctx *sql.Context, query string) (sql.Node, error) {
 	case showWarningsRegex.MatchString(lowerQuery):
 		return parseShowWarnings(ctx, s)
 	case showCollationRegex.MatchString(lowerQuery):
-		return parseShowCollation(ctx, s)
+		return parseShowCollation(s)
 	case describeRegex.MatchString(lowerQuery):
 		return parseDescribeQuery(ctx, s)
 	case fullProcessListRegex.MatchString(lowerQuery):
@@ -132,13 +135,7 @@ func convert(ctx *sql.Context, stmt sqlparser.Statement, query string) (sql.Node
 	default:
 		return nil, ErrUnsupportedSyntax.New(n)
 	case *sqlparser.Show:
-		// When a query is empty it means it comes from a subquery, as we don't
-		// have the query itself in a subquery. Hence, a SHOW could not be
-		// parsed.
-		if query == "" {
-			return nil, ErrUnsupportedFeature.New("SHOW in subquery")
-		}
-		return convertShow(ctx, n, query)
+		return convertShow(n, query)
 	case *sqlparser.Select:
 		return convertSelect(ctx, n)
 	case *sqlparser.Insert:
@@ -168,7 +165,7 @@ func convertSet(ctx *sql.Context, n *sqlparser.Set) (sql.Node, error) {
 
 	var variables = make([]plan.SetVariable, len(n.Exprs))
 	for i, e := range n.Exprs {
-		expr, err := exprToExpression(ctx, e.Expr)
+		expr, err := exprToExpression(e.Expr)
 		if err != nil {
 			return nil, err
 		}
@@ -218,7 +215,7 @@ func convertSet(ctx *sql.Context, n *sqlparser.Set) (sql.Node, error) {
 	return plan.NewSet(variables...), nil
 }
 
-func convertShow(ctx *sql.Context, s *sqlparser.Show, query string) (sql.Node, error) {
+func convertShow(s *sqlparser.Show, query string) (sql.Node, error) {
 	switch s.Type {
 	case sqlparser.KeywordString(sqlparser.TABLES):
 		var dbName string
@@ -231,7 +228,7 @@ func convertShow(ctx *sql.Context, s *sqlparser.Show, query string) (sql.Node, e
 			if s.ShowTablesOpt.Filter != nil {
 				if s.ShowTablesOpt.Filter.Filter != nil {
 					var err error
-					filter, err = exprToExpression(ctx, s.ShowTablesOpt.Filter.Filter)
+					filter, err = exprToExpression(s.ShowTablesOpt.Filter.Filter)
 					if err != nil {
 						return nil, err
 					}
@@ -273,7 +270,7 @@ func convertShow(ctx *sql.Context, s *sqlparser.Show, query string) (sql.Node, e
 			}
 
 			if s.ShowTablesOpt.Filter.Filter != nil {
-				filter, err := exprToExpression(ctx, s.ShowTablesOpt.Filter.Filter)
+				filter, err := exprToExpression(s.ShowTablesOpt.Filter.Filter)
 				if err != nil {
 					return nil, err
 				}
@@ -284,7 +281,7 @@ func convertShow(ctx *sql.Context, s *sqlparser.Show, query string) (sql.Node, e
 
 		return node, nil
 	case sqlparser.KeywordString(sqlparser.TABLE):
-		return parseShowTableStatus(ctx, query)
+		return parseShowTableStatus(query)
 	default:
 		unsupportedShow := fmt.Sprintf("SHOW %s", s.Type)
 		return nil, ErrUnsupportedFeature.New(unsupportedShow)
@@ -298,19 +295,19 @@ func convertSelect(ctx *sql.Context, s *sqlparser.Select) (sql.Node, error) {
 	}
 
 	if s.Where != nil {
-		node, err = whereToFilter(ctx, s.Where, node)
+		node, err = whereToFilter(s.Where, node)
 		if err != nil {
 			return nil, err
 		}
 	}
 
-	node, err = selectToProjectOrGroupBy(ctx, s.SelectExprs, s.GroupBy, node)
+	node, err = selectToProjectOrGroupBy(s.SelectExprs, s.GroupBy, node)
 	if err != nil {
 		return nil, err
 	}
 
 	if s.Having != nil {
-		node, err = havingToHaving(ctx, s.Having, node)
+		node, err = havingToHaving(s.Having, node)
 		if err != nil {
 			return nil, err
 		}
@@ -321,7 +318,7 @@ func convertSelect(ctx *sql.Context, s *sqlparser.Select) (sql.Node, error) {
 	}
 
 	if len(s.OrderBy) != 0 {
-		node, err = orderByToSort(ctx, s.OrderBy, node)
+		node, err = orderByToSort(s.OrderBy, node)
 		if err != nil {
 			return nil, err
 		}
@@ -398,14 +395,14 @@ func convertDelete(ctx *sql.Context, d *sqlparser.Delete) (sql.Node, error) {
 	}
 
 	if d.Where != nil {
-		node, err = whereToFilter(ctx, d.Where, node)
+		node, err = whereToFilter(d.Where, node)
 		if err != nil {
 			return nil, err
 		}
 	}
 
 	if len(d.OrderBy) != 0 {
-		node, err = orderByToSort(ctx, d.OrderBy, node)
+		node, err = orderByToSort(d.OrderBy, node)
 		if err != nil {
 			return nil, err
 		}
@@ -466,19 +463,19 @@ func insertRowsToNode(ctx *sql.Context, ir sqlparser.InsertRows) (sql.Node, erro
 	case *sqlparser.Union:
 		return nil, ErrUnsupportedFeature.New("UNION")
 	case sqlparser.Values:
-		return valuesToValues(ctx, v)
+		return valuesToValues(v)
 	default:
 		return nil, ErrUnsupportedSyntax.New(ir)
 	}
 }
 
-func valuesToValues(ctx *sql.Context, v sqlparser.Values) (sql.Node, error) {
+func valuesToValues(v sqlparser.Values) (sql.Node, error) {
 	exprTuples := make([][]sql.Expression, len(v))
 	for i, vt := range v {
 		exprs := make([]sql.Expression, len(vt))
 		exprTuples[i] = exprs
 		for j, e := range vt {
-			expr, err := exprToExpression(ctx, e)
+			expr, err := exprToExpression(e)
 			if err != nil {
 				return nil, err
 			}
@@ -576,7 +573,7 @@ func tableExprToTable(
 			return nil, ErrUnsupportedSyntax.New("missed ON clause for JOIN statement")
 		}
 
-		cond, err := exprToExpression(ctx, t.Condition.On)
+		cond, err := exprToExpression(t.Condition.On)
 		if err != nil {
 			return nil, err
 		}
@@ -594,8 +591,8 @@ func tableExprToTable(
 	}
 }
 
-func whereToFilter(ctx *sql.Context, w *sqlparser.Where, child sql.Node) (*plan.Filter, error) {
-	c, err := exprToExpression(ctx, w.Expr)
+func whereToFilter(w *sqlparser.Where, child sql.Node) (*plan.Filter, error) {
+	c, err := exprToExpression(w.Expr)
 	if err != nil {
 		return nil, err
 	}
@@ -603,10 +600,10 @@ func whereToFilter(ctx *sql.Context, w *sqlparser.Where, child sql.Node) (*plan.
 	return plan.NewFilter(c, child), nil
 }
 
-func orderByToSort(ctx *sql.Context, ob sqlparser.OrderBy, child sql.Node) (*plan.Sort, error) {
+func orderByToSort(ob sqlparser.OrderBy, child sql.Node) (*plan.Sort, error) {
 	var sortFields []plan.SortField
 	for _, o := range ob {
-		e, err := exprToExpression(ctx, o.Expr)
+		e, err := exprToExpression(o.Expr)
 		if err != nil {
 			return nil, err
 		}
@@ -645,8 +642,8 @@ func limitToLimit(
 	return plan.NewLimit(rowCount, child), nil
 }
 
-func havingToHaving(ctx *sql.Context, having *sqlparser.Where, node sql.Node) (sql.Node, error) {
-	cond, err := exprToExpression(ctx, having.Expr)
+func havingToHaving(having *sqlparser.Where, node sql.Node) (sql.Node, error) {
+	cond, err := exprToExpression(having.Expr)
 	if err != nil {
 		return nil, err
 	}
@@ -673,8 +670,8 @@ func offsetToOffset(
 
 // getInt64Literal returns an int64 *expression.Literal for the value given, or an unsupported error with the string
 // given if the expression doesn't represent an integer literal.
-func getInt64Literal(ctx *sql.Context, expr sqlparser.Expr, errStr string) (*expression.Literal, error) {
-	e, err := exprToExpression(ctx, expr)
+func getInt64Literal(expr sqlparser.Expr, errStr string) (*expression.Literal, error) {
+	e, err := exprToExpression(expr)
 	if err != nil {
 		return nil, err
 	}
@@ -682,15 +679,15 @@ func getInt64Literal(ctx *sql.Context, expr sqlparser.Expr, errStr string) (*exp
 	nl, ok := e.(*expression.Literal)
 	if !ok || nl.Type() != sql.Int64 {
 		return nil, ErrUnsupportedFeature.New(errStr)
+	} else {
+		return nl, nil
 	}
-
-	return nl, nil
 }
 
 // getInt64Value returns the int64 literal value in the expression given, or an error with the errStr given if it
 // cannot.
 func getInt64Value(ctx *sql.Context, expr sqlparser.Expr, errStr string) (int64, error) {
-	ie, err := getInt64Literal(ctx, expr, errStr)
+	ie, err := getInt64Literal(expr, errStr)
 	if err != nil {
 		return 0, err
 	}
@@ -718,13 +715,8 @@ func isAggregate(e sql.Expression) bool {
 	return isAgg
 }
 
-func selectToProjectOrGroupBy(
-	ctx *sql.Context,
-	se sqlparser.SelectExprs,
-	g sqlparser.GroupBy,
-	child sql.Node,
-) (sql.Node, error) {
-	selectExprs, err := selectExprsToExpressions(ctx, se)
+func selectToProjectOrGroupBy(se sqlparser.SelectExprs, g sqlparser.GroupBy, child sql.Node) (sql.Node, error) {
+	selectExprs, err := selectExprsToExpressions(se)
 	if err != nil {
 		return nil, err
 	}
@@ -740,7 +732,7 @@ func selectToProjectOrGroupBy(
 	}
 
 	if isAgg {
-		groupingExprs, err := groupByToExpressions(ctx, g)
+		groupingExprs, err := groupByToExpressions(g)
 		if err != nil {
 			return nil, err
 		}
@@ -765,10 +757,10 @@ func selectToProjectOrGroupBy(
 	return plan.NewProject(selectExprs, child), nil
 }
 
-func selectExprsToExpressions(ctx *sql.Context, se sqlparser.SelectExprs) ([]sql.Expression, error) {
+func selectExprsToExpressions(se sqlparser.SelectExprs) ([]sql.Expression, error) {
 	var exprs []sql.Expression
 	for _, e := range se {
-		pe, err := selectExprToExpression(ctx, e)
+		pe, err := selectExprToExpression(e)
 		if err != nil {
 			return nil, err
 		}
@@ -779,7 +771,7 @@ func selectExprsToExpressions(ctx *sql.Context, se sqlparser.SelectExprs) ([]sql
 	return exprs, nil
 }
 
-func exprToExpression(ctx *sql.Context, e sqlparser.Expr) (sql.Expression, error) {
+func exprToExpression(e sqlparser.Expr) (sql.Expression, error) {
 	switch v := e.(type) {
 	default:
 		return nil, ErrUnsupportedSyntax.New(e)
@@ -791,14 +783,14 @@ func exprToExpression(ctx *sql.Context, e sqlparser.Expr) (sql.Expression, error
 			err  error
 		)
 		if v.Name != nil {
-			name, err = exprToExpression(ctx, v.Name)
+			name, err = exprToExpression(v.Name)
 		} else {
-			name, err = exprToExpression(ctx, v.StrVal)
+			name, err = exprToExpression(v.StrVal)
 		}
 		if err != nil {
 			return nil, err
 		}
-		from, err := exprToExpression(ctx, v.From)
+		from, err := exprToExpression(v.From)
 		if err != nil {
 			return nil, err
 		}
@@ -806,17 +798,17 @@ func exprToExpression(ctx *sql.Context, e sqlparser.Expr) (sql.Expression, error
 		if v.To == nil {
 			return function.NewSubstring(name, from)
 		}
-		to, err := exprToExpression(ctx, v.To)
+		to, err := exprToExpression(v.To)
 		if err != nil {
 			return nil, err
 		}
 		return function.NewSubstring(name, from, to)
 	case *sqlparser.ComparisonExpr:
-		return comparisonExprToExpression(ctx, v)
+		return comparisonExprToExpression(v)
 	case *sqlparser.IsExpr:
-		return isExprToExpression(ctx, v)
+		return isExprToExpression(v)
 	case *sqlparser.NotExpr:
-		c, err := exprToExpression(ctx, v.Expr)
+		c, err := exprToExpression(v.Expr)
 		if err != nil {
 			return nil, err
 		}
@@ -837,7 +829,7 @@ func exprToExpression(ctx *sql.Context, e sqlparser.Expr) (sql.Expression, error
 		}
 		return expression.NewUnresolvedColumn(v.Name.String()), nil
 	case *sqlparser.FuncExpr:
-		exprs, err := selectExprsToExpressions(ctx, v.Exprs)
+		exprs, err := selectExprsToExpressions(v.Exprs)
 		if err != nil {
 			return nil, err
 		}
@@ -857,50 +849,50 @@ func exprToExpression(ctx *sql.Context, e sqlparser.Expr) (sql.Expression, error
 		return expression.NewUnresolvedFunction(v.Name.Lowered(),
 			isAggregateFunc(v), exprs...), nil
 	case *sqlparser.ParenExpr:
-		return exprToExpression(ctx, v.Expr)
+		return exprToExpression(v.Expr)
 	case *sqlparser.AndExpr:
-		lhs, err := exprToExpression(ctx, v.Left)
+		lhs, err := exprToExpression(v.Left)
 		if err != nil {
 			return nil, err
 		}
 
-		rhs, err := exprToExpression(ctx, v.Right)
+		rhs, err := exprToExpression(v.Right)
 		if err != nil {
 			return nil, err
 		}
 
 		return expression.NewAnd(lhs, rhs), nil
 	case *sqlparser.OrExpr:
-		lhs, err := exprToExpression(ctx, v.Left)
+		lhs, err := exprToExpression(v.Left)
 		if err != nil {
 			return nil, err
 		}
 
-		rhs, err := exprToExpression(ctx, v.Right)
+		rhs, err := exprToExpression(v.Right)
 		if err != nil {
 			return nil, err
 		}
 
 		return expression.NewOr(lhs, rhs), nil
 	case *sqlparser.ConvertExpr:
-		expr, err := exprToExpression(ctx, v.Expr)
+		expr, err := exprToExpression(v.Expr)
 		if err != nil {
 			return nil, err
 		}
 
 		return expression.NewConvert(expr, v.Type.Type), nil
 	case *sqlparser.RangeCond:
-		val, err := exprToExpression(ctx, v.Left)
+		val, err := exprToExpression(v.Left)
 		if err != nil {
 			return nil, err
 		}
 
-		lower, err := exprToExpression(ctx, v.From)
+		lower, err := exprToExpression(v.From)
 		if err != nil {
 			return nil, err
 		}
 
-		upper, err := exprToExpression(ctx, v.To)
+		upper, err := exprToExpression(v.To)
 		if err != nil {
 			return nil, err
 		}
@@ -916,7 +908,7 @@ func exprToExpression(ctx *sql.Context, e sqlparser.Expr) (sql.Expression, error
 	case sqlparser.ValTuple:
 		var exprs = make([]sql.Expression, len(v))
 		for i, e := range v {
-			expr, err := exprToExpression(ctx, e)
+			expr, err := exprToExpression(e)
 			if err != nil {
 				return nil, err
 			}
@@ -925,19 +917,15 @@ func exprToExpression(ctx *sql.Context, e sqlparser.Expr) (sql.Expression, error
 		return expression.NewTuple(exprs...), nil
 
 	case *sqlparser.BinaryExpr:
-		return binaryExprToExpression(ctx, v)
+		return binaryExprToExpression(v)
 	case *sqlparser.UnaryExpr:
-		return unaryExprToExpression(ctx, v)
+		return unaryExprToExpression(v)
 	case *sqlparser.Subquery:
-		node, err := convert(ctx, v.Select, "")
-		if err != nil {
-			return nil, err
-		}
-		return expression.NewSubquery(node), nil
+		return nil, ErrUnsupportedSubqueryExpression.New()
 	case *sqlparser.CaseExpr:
-		return caseExprToExpression(ctx, v)
+		return caseExprToExpression(v)
 	case *sqlparser.IntervalExpr:
-		return intervalExprToExpression(ctx, v)
+		return intervalExprToExpression(v)
 	}
 }
 
@@ -1000,8 +988,8 @@ func convertVal(v *sqlparser.SQLVal) (sql.Expression, error) {
 	return nil, ErrInvalidSQLValType.New(v.Type)
 }
 
-func isExprToExpression(ctx *sql.Context, c *sqlparser.IsExpr) (sql.Expression, error) {
-	e, err := exprToExpression(ctx, c.Expr)
+func isExprToExpression(c *sqlparser.IsExpr) (sql.Expression, error) {
+	e, err := exprToExpression(c.Expr)
 	if err != nil {
 		return nil, err
 	}
@@ -1024,13 +1012,13 @@ func isExprToExpression(ctx *sql.Context, c *sqlparser.IsExpr) (sql.Expression,
 	}
 }
 
-func comparisonExprToExpression(ctx *sql.Context, c *sqlparser.ComparisonExpr) (sql.Expression, error) {
-	left, err := exprToExpression(ctx, c.Left)
+func comparisonExprToExpression(c *sqlparser.ComparisonExpr) (sql.Expression, error) {
+	left, err := exprToExpression(c.Left)
 	if err != nil {
 		return nil, err
 	}
 
-	right, err := exprToExpression(ctx, c.Right)
+	right, err := exprToExpression(c.Right)
 	if err != nil {
 		return nil, err
 	}
@@ -1067,10 +1055,10 @@ func comparisonExprToExpression(ctx *sql.Context, c *sqlparser.ComparisonExpr) (
 	}
 }
 
-func groupByToExpressions(ctx *sql.Context, g sqlparser.GroupBy) ([]sql.Expression, error) {
+func groupByToExpressions(g sqlparser.GroupBy) ([]sql.Expression, error) {
 	es := make([]sql.Expression, len(g))
 	for i, ve := range g {
-		e, err := exprToExpression(ctx, ve)
+		e, err := exprToExpression(ve)
 		if err != nil {
 			return nil, err
 		}
@@ -1081,7 +1069,7 @@ func groupByToExpressions(ctx *sql.Context, g sqlparser.GroupBy) ([]sql.Expressi
 	return es, nil
 }
 
-func selectExprToExpression(ctx *sql.Context, se sqlparser.SelectExpr) (sql.Expression, error) {
+func selectExprToExpression(se sqlparser.SelectExpr) (sql.Expression, error) {
 	switch e := se.(type) {
 	default:
 		return nil, ErrUnsupportedSyntax.New(e)
@@ -1091,7 +1079,7 @@ func selectExprToExpression(ctx *sql.Context, se sqlparser.SelectExpr) (sql.Expr
 		}
 		return expression.NewQualifiedStar(e.TableName.Name.String()), nil
 	case *sqlparser.AliasedExpr:
-		expr, err := exprToExpression(ctx, e.Expr)
+		expr, err := exprToExpression(e.Expr)
 		if err != nil {
 			return nil, err
 		}
@@ -1105,10 +1093,10 @@ func selectExprToExpression(ctx *sql.Context, se sqlparser.SelectExpr) (sql.Expr
 	}
 }
 
-func unaryExprToExpression(ctx *sql.Context, e *sqlparser.UnaryExpr) (sql.Expression, error) {
+func unaryExprToExpression(e *sqlparser.UnaryExpr) (sql.Expression, error) {
 	switch e.Operator {
 	case sqlparser.MinusStr:
-		expr, err := exprToExpression(ctx, e.Expr)
+		expr, err := exprToExpression(e.Expr)
 		if err != nil {
 			return nil, err
 		}
@@ -1120,7 +1108,7 @@ func unaryExprToExpression(ctx *sql.Context, e *sqlparser.UnaryExpr) (sql.Expres
 	}
 }
 
-func binaryExprToExpression(ctx *sql.Context, be *sqlparser.BinaryExpr) (sql.Expression, error) {
+func binaryExprToExpression(be *sqlparser.BinaryExpr) (sql.Expression, error) {
 	switch be.Operator {
 	case
 		sqlparser.PlusStr,
@@ -1135,12 +1123,12 @@ func binaryExprToExpression(ctx *sql.Context, be *sqlparser.BinaryExpr) (sql.Exp
 		sqlparser.IntDivStr,
 		sqlparser.ModStr:
 
-		l, err := exprToExpression(ctx, be.Left)
+		l, err := exprToExpression(be.Left)
 		if err != nil {
 			return nil, err
 		}
 
-		r, err := exprToExpression(ctx, be.Right)
+		r, err := exprToExpression(be.Right)
 		if err != nil {
 			return nil, err
 		}
@@ -1162,12 +1150,12 @@ func binaryExprToExpression(ctx *sql.Context, be *sqlparser.BinaryExpr) (sql.Exp
 	}
 }
 
-func caseExprToExpression(ctx *sql.Context, e *sqlparser.CaseExpr) (sql.Expression, error) {
+func caseExprToExpression(e *sqlparser.CaseExpr) (sql.Expression, error) {
 	var expr sql.Expression
 	var err error
 
 	if e.Expr != nil {
-		expr, err = exprToExpression(ctx, e.Expr)
+		expr, err = exprToExpression(e.Expr)
 		if err != nil {
 			return nil, err
 		}
@@ -1176,13 +1164,13 @@ func caseExprToExpression(ctx *sql.Context, e *sqlparser.CaseExpr) (sql.Expressi
 	var branches []expression.CaseBranch
 	for _, w := range e.Whens {
 		var cond sql.Expression
-		cond, err = exprToExpression(ctx, w.Cond)
+		cond, err = exprToExpression(w.Cond)
 		if err != nil {
 			return nil, err
 		}
 
 		var val sql.Expression
-		val, err = exprToExpression(ctx, w.Val)
+		val, err = exprToExpression(w.Val)
 		if err != nil {
 			return nil, err
 		}
@@ -1195,7 +1183,7 @@ func caseExprToExpression(ctx *sql.Context, e *sqlparser.CaseExpr) (sql.Expressi
 
 	var elseExpr sql.Expression
 	if e.Else != nil {
-		elseExpr, err = exprToExpression(ctx, e.Else)
+		elseExpr, err = exprToExpression(e.Else)
 		if err != nil {
 			return nil, err
 		}
@@ -1204,8 +1192,8 @@ func caseExprToExpression(ctx *sql.Context, e *sqlparser.CaseExpr) (sql.Expressi
 	return expression.NewCase(expr, branches, elseExpr), nil
 }
 
-func intervalExprToExpression(ctx *sql.Context, e *sqlparser.IntervalExpr) (sql.Expression, error) {
-	expr, err := exprToExpression(ctx, e.Expr)
+func intervalExprToExpression(e *sqlparser.IntervalExpr) (sql.Expression, error) {
+	expr, err := exprToExpression(e.Expr)
 	if err != nil {
 		return nil, err
 	}
@@ -1312,7 +1300,7 @@ func readString(r *bufio.Reader, single bool) []rune {
 	return result
 }
 
-func parseShowTableStatus(ctx *sql.Context, query string) (sql.Node, error) {
+func parseShowTableStatus(query string) (sql.Node, error) {
 	buf := bufio.NewReader(strings.NewReader(query))
 	err := parseFuncs{
 		expect("show"),
@@ -1354,7 +1342,7 @@ func parseShowTableStatus(ctx *sql.Context, query string) (sql.Node, error) {
 			return nil, err
 		}
 
-		expr, err := parseExpr(ctx, string(bs))
+		expr, err := parseExpr(string(bs))
 		if err != nil {
 			return nil, err
 		}
@@ -1378,7 +1366,7 @@ func parseShowTableStatus(ctx *sql.Context, query string) (sql.Node, error) {
 	}
 }
 
-func parseShowCollation(ctx *sql.Context, query string) (sql.Node, error) {
+func parseShowCollation(query string) (sql.Node, error) {
 	buf := bufio.NewReader(strings.NewReader(query))
 	err := parseFuncs{
 		expect("show"),
@@ -1411,7 +1399,7 @@ func parseShowCollation(ctx *sql.Context, query string) (sql.Node, error) {
 			return nil, err
 		}
 
-		expr, err := parseExpr(ctx, string(bs))
+		expr, err := parseExpr(string(bs))
 		if err != nil {
 			return nil, err
 		}
diff --git a/sql/parse/util.go b/sql/parse/util.go
index bfb358b..a99e7a7 100644
--- a/sql/parse/util.go
+++ b/sql/parse/util.go
@@ -251,7 +251,7 @@ func readRemaining(val *string) parseFunc {
 	}
 }
 
-func parseExpr(ctx *sql.Context, str string) (sql.Expression, error) {
+func parseExpr(str string) (sql.Expression, error) {
 	stmt, err := sqlparser.Parse("SELECT " + str)
 	if err != nil {
 		return nil, err
@@ -271,7 +271,7 @@ func parseExpr(ctx *sql.Context, str string) (sql.Expression, error) {
 		return nil, errInvalidIndexExpression.New(str)
 	}
 
-	return exprToExpression(ctx, selectExpr.Expr)
+	return exprToExpression(selectExpr.Expr)
 }
 
 func readQuotableIdent(ident *string) parseFunc {
diff --git a/sql/plan/common.go b/sql/plan/common.go
index 28e0dd9..beec461 100644
--- a/sql/plan/common.go
+++ b/sql/plan/common.go
@@ -1,4 +1,4 @@
-package plan
+package plan // import "github.com/src-d/go-mysql-server/sql/plan"
 
 import "github.com/src-d/go-mysql-server/sql"
 


Test patch:
diff --git a/engine_test.go b/engine_test.go
index 3ce2c8f..dce9066 100644
--- a/engine_test.go
+++ b/engine_test.go
@@ -1548,28 +1548,6 @@ var queries = []struct {
 			{int64(5), "there is some text in here"},
 		},
 	},
-	{
-		`SELECT i FROM mytable WHERE i = (SELECT 1)`,
-		[]sql.Row{{int64(1)}},
-	},
-	{
-		`SELECT i FROM mytable WHERE i IN (SELECT i FROM mytable)`,
-		[]sql.Row{
-			{int64(1)},
-			{int64(2)},
-			{int64(3)},
-		},
-	},
-	{
-		`SELECT i FROM mytable WHERE i NOT IN (SELECT i FROM mytable ORDER BY i ASC LIMIT 2)`,
-		[]sql.Row{
-			{int64(3)},
-		},
-	},
-	{
-		`SELECT (SELECT i FROM mytable ORDER BY i ASC LIMIT 1) AS x`,
-		[]sql.Row{{int64(1)}},
-	},
 }
 
 func TestQueries(t *testing.T) {
@@ -1923,7 +1901,7 @@ func TestInsertInto(t *testing.T) {
 			[]sql.Row{{int64(1)}},
 			"SELECT * FROM typestable WHERE id = 999;",
 			[]sql.Row{{
-				int64(999), int64(-math.MaxInt8 - 1), int64(-math.MaxInt16 - 1), int64(-math.MaxInt32 - 1), int64(-math.MaxInt64 - 1),
+				int64(999), int64(-math.MaxInt8-1), int64(-math.MaxInt16-1), int64(-math.MaxInt32-1), int64(-math.MaxInt64-1),
 				int64(0), int64(0), int64(0), int64(0),
 				float64(math.SmallestNonzeroFloat32), float64(math.SmallestNonzeroFloat64),
 				timeParse(sql.TimestampLayout, "0010-04-05 12:51:36"), timeParse(sql.DateLayout, "0101-11-07"),
@@ -1941,7 +1919,7 @@ func TestInsertInto(t *testing.T) {
 			[]sql.Row{{int64(1)}},
 			"SELECT * FROM typestable WHERE id = 999;",
 			[]sql.Row{{
-				int64(999), int64(-math.MaxInt8 - 1), int64(-math.MaxInt16 - 1), int64(-math.MaxInt32 - 1), int64(-math.MaxInt64 - 1),
+				int64(999), int64(-math.MaxInt8-1), int64(-math.MaxInt16-1), int64(-math.MaxInt32-1), int64(-math.MaxInt64-1),
 				int64(0), int64(0), int64(0), int64(0),
 				float64(math.SmallestNonzeroFloat32), float64(math.SmallestNonzeroFloat64),
 				timeParse(sql.TimestampLayout, "0010-04-05 12:51:36"), timeParse(sql.DateLayout, "0101-11-07"),
@@ -2123,7 +2101,7 @@ func TestReplaceInto(t *testing.T) {
 			[]sql.Row{{int64(1)}},
 			"SELECT * FROM typestable WHERE id = 999;",
 			[]sql.Row{{
-				int64(999), int64(-math.MaxInt8 - 1), int64(-math.MaxInt16 - 1), int64(-math.MaxInt32 - 1), int64(-math.MaxInt64 - 1),
+				int64(999), int64(-math.MaxInt8-1), int64(-math.MaxInt16-1), int64(-math.MaxInt32-1), int64(-math.MaxInt64-1),
 				int64(0), int64(0), int64(0), int64(0),
 				float64(math.SmallestNonzeroFloat32), float64(math.SmallestNonzeroFloat64),
 				timeParse(sql.TimestampLayout, "0010-04-05 12:51:36"), timeParse(sql.DateLayout, "0101-11-07"),
@@ -2141,7 +2119,7 @@ func TestReplaceInto(t *testing.T) {
 			[]sql.Row{{int64(1)}},
 			"SELECT * FROM typestable WHERE id = 999;",
 			[]sql.Row{{
-				int64(999), int64(-math.MaxInt8 - 1), int64(-math.MaxInt16 - 1), int64(-math.MaxInt32 - 1), int64(-math.MaxInt64 - 1),
+				int64(999), int64(-math.MaxInt8-1), int64(-math.MaxInt16-1), int64(-math.MaxInt32-1), int64(-math.MaxInt64-1),
 				int64(0), int64(0), int64(0), int64(0),
 				float64(math.SmallestNonzeroFloat32), float64(math.SmallestNonzeroFloat64),
 				timeParse(sql.TimestampLayout, "0010-04-05 12:51:36"), timeParse(sql.DateLayout, "0101-11-07"),
diff --git a/sql/analyzer/validation_rules_test.go b/sql/analyzer/validation_rules_test.go
index 543fbc6..1af5ad5 100644
--- a/sql/analyzer/validation_rules_test.go
+++ b/sql/analyzer/validation_rules_test.go
@@ -674,37 +674,6 @@ func TestValidateExplodeUsage(t *testing.T) {
 	}
 }
 
-func TestValidateSubqueryColumns(t *testing.T) {
-	require := require.New(t)
-	ctx := sql.NewEmptyContext()
-
-	node := plan.NewProject([]sql.Expression{
-		expression.NewSubquery(plan.NewProject(
-			[]sql.Expression{
-				lit(1),
-				lit(2),
-			},
-			dummyNode{true},
-		)),
-	}, dummyNode{true})
-
-	_, err := validateSubqueryColumns(ctx, nil, node)
-	require.Error(err)
-	require.True(ErrSubqueryColumns.Is(err))
-
-	node = plan.NewProject([]sql.Expression{
-		expression.NewSubquery(plan.NewProject(
-			[]sql.Expression{
-				lit(1),
-			},
-			dummyNode{true},
-		)),
-	}, dummyNode{true})
-
-	_, err = validateSubqueryColumns(ctx, nil, node)
-	require.NoError(err)
-}
-
 type dummyNode struct{ resolved bool }
 
 func (n dummyNode) String() string                           { return "dummynode" }
diff --git a/sql/expression/comparison_test.go b/sql/expression/comparison_test.go
index 802c367..c69d1fd 100644
--- a/sql/expression/comparison_test.go
+++ b/sql/expression/comparison_test.go
@@ -1,13 +1,10 @@
-package expression_test
+package expression
 
 import (
 	"testing"
 
 	"github.com/src-d/go-mysql-server/internal/regex"
-	"github.com/src-d/go-mysql-server/memory"
 	"github.com/src-d/go-mysql-server/sql"
-	"github.com/src-d/go-mysql-server/sql/expression"
-	"github.com/src-d/go-mysql-server/sql/plan"
 	errors "gopkg.in/src-d/go-errors.v1"
 
 	"github.com/stretchr/testify/require"
@@ -98,11 +95,11 @@ var likeComparisonCases = map[sql.Type]map[int][][]interface{}{
 func TestEquals(t *testing.T) {
 	require := require.New(t)
 	for resultType, cmpCase := range comparisonCases {
-		get0 := expression.NewGetField(0, resultType, "col1", true)
+		get0 := NewGetField(0, resultType, "col1", true)
 		require.NotNil(get0)
-		get1 := expression.NewGetField(1, resultType, "col2", true)
+		get1 := NewGetField(1, resultType, "col2", true)
 		require.NotNil(get1)
-		eq := expression.NewEquals(get0, get1)
+		eq := NewEquals(get0, get1)
 		require.NotNil(eq)
 		require.Equal(sql.Boolean, eq.Type())
 		for cmpResult, cases := range cmpCase {
@@ -125,11 +122,11 @@ func TestEquals(t *testing.T) {
 func TestLessThan(t *testing.T) {
 	require := require.New(t)
 	for resultType, cmpCase := range comparisonCases {
-		get0 := expression.NewGetField(0, resultType, "col1", true)
+		get0 := NewGetField(0, resultType, "col1", true)
 		require.NotNil(get0)
-		get1 := expression.NewGetField(1, resultType, "col2", true)
+		get1 := NewGetField(1, resultType, "col2", true)
 		require.NotNil(get1)
-		eq := expression.NewLessThan(get0, get1)
+		eq := NewLessThan(get0, get1)
 		require.NotNil(eq)
 		require.Equal(sql.Boolean, eq.Type())
 		for cmpResult, cases := range cmpCase {
@@ -152,11 +149,11 @@ func TestLessThan(t *testing.T) {
 func TestGreaterThan(t *testing.T) {
 	require := require.New(t)
 	for resultType, cmpCase := range comparisonCases {
-		get0 := expression.NewGetField(0, resultType, "col1", true)
+		get0 := NewGetField(0, resultType, "col1", true)
 		require.NotNil(get0)
-		get1 := expression.NewGetField(1, resultType, "col2", true)
+		get1 := NewGetField(1, resultType, "col2", true)
 		require.NotNil(get1)
-		eq := expression.NewGreaterThan(get0, get1)
+		eq := NewGreaterThan(get0, get1)
 		require.NotNil(eq)
 		require.Equal(sql.Boolean, eq.Type())
 		for cmpResult, cases := range cmpCase {
@@ -188,13 +185,13 @@ func testRegexpCases(t *testing.T) {
 	require := require.New(t)
 
 	for resultType, cmpCase := range likeComparisonCases {
-		get0 := expression.NewGetField(0, resultType, "col1", true)
+		get0 := NewGetField(0, resultType, "col1", true)
 		require.NotNil(get0)
-		get1 := expression.NewGetField(1, resultType, "col2", true)
+		get1 := NewGetField(1, resultType, "col2", true)
 		require.NotNil(get1)
 		for cmpResult, cases := range cmpCase {
 			for _, pair := range cases {
-				eq := expression.NewRegexp(get0, get1)
+				eq := NewRegexp(get0, get1)
 				require.NotNil(eq)
 				require.Equal(sql.Boolean, eq.Type())
 
@@ -217,9 +214,9 @@ func TestInvalidRegexp(t *testing.T) {
 	t.Helper()
 	require := require.New(t)
 
-	col1 := expression.NewGetField(0, sql.Text, "col1", true)
-	invalid := expression.NewLiteral("*col1", sql.Text)
-	r := expression.NewRegexp(col1, invalid)
+	col1 := NewGetField(0, sql.Text, "col1", true)
+	invalid := NewLiteral("*col1", sql.Text)
+	r := NewRegexp(col1, invalid)
 	row := sql.NewRow("col1")
 
 	_, err := r.Eval(sql.NewEmptyContext(), row)
@@ -237,10 +234,10 @@ func TestIn(t *testing.T) {
 	}{
 		{
 			"left is nil",
-			expression.NewLiteral(nil, sql.Null),
-			expression.NewTuple(
-				expression.NewLiteral(int64(1), sql.Int64),
-				expression.NewLiteral(int64(2), sql.Int64),
+			NewLiteral(nil, sql.Null),
+			NewTuple(
+				NewLiteral(int64(1), sql.Int64),
+				NewLiteral(int64(2), sql.Int64),
 			),
 			nil,
 			nil,
@@ -248,32 +245,32 @@ func TestIn(t *testing.T) {
 		},
 		{
 			"left and right don't have the same cols",
-			expression.NewLiteral(1, sql.Int64),
-			expression.NewTuple(
-				expression.NewTuple(
-					expression.NewLiteral(int64(1), sql.Int64),
-					expression.NewLiteral(int64(1), sql.Int64),
+			NewLiteral(1, sql.Int64),
+			NewTuple(
+				NewTuple(
+					NewLiteral(int64(1), sql.Int64),
+					NewLiteral(int64(1), sql.Int64),
 				),
-				expression.NewLiteral(int64(2), sql.Int64),
+				NewLiteral(int64(2), sql.Int64),
 			),
 			nil,
 			nil,
-			expression.ErrInvalidOperandColumns,
+			ErrInvalidOperandColumns,
 		},
 		{
 			"right is an unsupported operand",
-			expression.NewLiteral(1, sql.Int64),
-			expression.NewLiteral(int64(2), sql.Int64),
+			NewLiteral(1, sql.Int64),
+			NewLiteral(int64(2), sql.Int64),
 			nil,
 			nil,
-			expression.ErrUnsupportedInOperand,
+			ErrUnsupportedInOperand,
 		},
 		{
 			"left is in right",
-			expression.NewGetField(0, sql.Int64, "foo", false),
-			expression.NewTuple(
-				expression.NewGetField(0, sql.Int64, "foo", false),
-				expression.NewLiteral(int64(2), sql.Int64),
+			NewGetField(0, sql.Int64, "foo", false),
+			NewTuple(
+				NewGetField(0, sql.Int64, "foo", false),
+				NewLiteral(int64(2), sql.Int64),
 			),
 			sql.NewRow(int64(1)),
 			true,
@@ -281,10 +278,10 @@ func TestIn(t *testing.T) {
 		},
 		{
 			"left is not in right",
-			expression.NewGetField(0, sql.Int64, "foo", false),
-			expression.NewTuple(
-				expression.NewGetField(1, sql.Int64, "bar", false),
-				expression.NewLiteral(int64(2), sql.Int64),
+			NewGetField(0, sql.Int64, "foo", false),
+			NewTuple(
+				NewGetField(1, sql.Int64, "bar", false),
+				NewLiteral(int64(2), sql.Int64),
 			),
 			sql.NewRow(int64(1), int64(3)),
 			false,
@@ -296,96 +293,7 @@ func TestIn(t *testing.T) {
 		t.Run(tt.name, func(t *testing.T) {
 			require := require.New(t)
 
-			result, err := expression.NewIn(tt.left, tt.right).
-				Eval(sql.NewEmptyContext(), tt.row)
-			if tt.err != nil {
-				require.Error(err)
-				require.True(tt.err.Is(err))
-			} else {
-				require.NoError(err)
-				require.Equal(tt.result, result)
-			}
-		})
-	}
-}
-
-func TestInSubquery(t *testing.T) {
-	ctx := sql.NewEmptyContext()
-	table := memory.NewTable("foo", sql.Schema{
-		{Name: "t", Source: "foo", Type: sql.Text},
-	})
-
-	require.NoError(t, table.Insert(ctx, sql.Row{"one"}))
-	require.NoError(t, table.Insert(ctx, sql.Row{"two"}))
-	require.NoError(t, table.Insert(ctx, sql.Row{"three"}))
-
-	project := func(expr sql.Expression) sql.Node {
-		return plan.NewProject([]sql.Expression{
-			expr,
-		}, plan.NewResolvedTable(table))
-	}
-
-	testCases := []struct {
-		name   string
-		left   sql.Expression
-		right  sql.Node
-		row    sql.Row
-		result interface{}
-		err    *errors.Kind
-	}{
-		{
-			"left is nil",
-			expression.NewLiteral(nil, sql.Null),
-			project(
-				expression.NewLiteral(int64(1), sql.Int64),
-			),
-			nil,
-			nil,
-			nil,
-		},
-		{
-			"left and right don't have the same cols",
-			expression.NewTuple(
-				expression.NewLiteral(int64(1), sql.Int64),
-				expression.NewLiteral(int64(1), sql.Int64),
-			),
-			project(
-				expression.NewLiteral(int64(2), sql.Int64),
-			),
-			nil,
-			nil,
-			expression.ErrInvalidOperandColumns,
-		},
-		{
-			"left is in right",
-			expression.NewGetField(0, sql.Text, "foo", false),
-			project(
-				expression.NewGetField(0, sql.Text, "foo", false),
-			),
-			sql.NewRow("two"),
-			true,
-			nil,
-		},
-		{
-			"left is not in right",
-			expression.NewGetField(0, sql.Text, "foo", false),
-			project(
-				expression.NewGetField(0, sql.Text, "foo", false),
-			),
-			sql.NewRow("four"),
-			false,
-			nil,
-		},
-	}
-
-	for _, tt := range testCases {
-		t.Run(tt.name, func(t *testing.T) {
-			require := require.New(t)
-
-			result, err := expression.NewIn(
-				tt.left,
-				expression.NewSubquery(tt.right),
-			).Eval(sql.NewEmptyContext(), tt.row)
+			result, err := NewIn(tt.left, tt.right).Eval(sql.NewEmptyContext(), tt.row)
 			if tt.err != nil {
 				require.Error(err)
 				require.True(tt.err.Is(err))
@@ -408,10 +316,10 @@ func TestNotIn(t *testing.T) {
 	}{
 		{
 			"left is nil",
-			expression.NewLiteral(nil, sql.Null),
-			expression.NewTuple(
-				expression.NewLiteral(int64(1), sql.Int64),
-				expression.NewLiteral(int64(2), sql.Int64),
+			NewLiteral(nil, sql.Null),
+			NewTuple(
+				NewLiteral(int64(1), sql.Int64),
+				NewLiteral(int64(2), sql.Int64),
 			),
 			nil,
 			nil,
@@ -419,32 +327,32 @@ func TestNotIn(t *testing.T) {
 		},
 		{
 			"left and right don't have the same cols",
-			expression.NewLiteral(1, sql.Int64),
-			expression.NewTuple(
-				expression.NewTuple(
-					expression.NewLiteral(int64(1), sql.Int64),
-					expression.NewLiteral(int64(1), sql.Int64),
+			NewLiteral(1, sql.Int64),
+			NewTuple(
+				NewTuple(
+					NewLiteral(int64(1), sql.Int64),
+					NewLiteral(int64(1), sql.Int64),
 				),
-				expression.NewLiteral(int64(2), sql.Int64),
+				NewLiteral(int64(2), sql.Int64),
 			),
 			nil,
 			nil,
-			expression.ErrInvalidOperandColumns,
+			ErrInvalidOperandColumns,
 		},
 		{
 			"right is an unsupported operand",
-			expression.NewLiteral(1, sql.Int64),
-			expression.NewLiteral(int64(2), sql.Int64),
+			NewLiteral(1, sql.Int64),
+			NewLiteral(int64(2), sql.Int64),
 			nil,
 			nil,
-			expression.ErrUnsupportedInOperand,
+			ErrUnsupportedInOperand,
 		},
 		{
 			"left is in right",
-			expression.NewGetField(0, sql.Int64, "foo", false),
-			expression.NewTuple(
-				expression.NewGetField(0, sql.Int64, "foo", false),
-				expression.NewLiteral(int64(2), sql.Int64),
+			NewGetField(0, sql.Int64, "foo", false),
+			NewTuple(
+				NewGetField(0, sql.Int64, "foo", false),
+				NewLiteral(int64(2), sql.Int64),
 			),
 			sql.NewRow(int64(1)),
 			false,
@@ -452,10 +360,10 @@ func TestNotIn(t *testing.T) {
 		},
 		{
 			"left is not in right",
-			expression.NewGetField(0, sql.Int64, "foo", false),
-			expression.NewTuple(
-				expression.NewGetField(1, sql.Int64, "bar", false),
-				expression.NewLiteral(int64(2), sql.Int64),
+			NewGetField(0, sql.Int64, "foo", false),
+			NewTuple(
+				NewGetField(1, sql.Int64, "bar", false),
+				NewLiteral(int64(2), sql.Int64),
 			),
 			sql.NewRow(int64(1), int64(3)),
 			true,
@@ -467,8 +375,7 @@ func TestNotIn(t *testing.T) {
 		t.Run(tt.name, func(t *testing.T) {
 			require := require.New(t)
 
-			result, err := expression.NewNotIn(tt.left, tt.right).
-				Eval(sql.NewEmptyContext(), tt.row)
+			result, err := NewNotIn(tt.left, tt.right).Eval(sql.NewEmptyContext(), tt.row)
 			if tt.err != nil {
 				require.Error(err)
 				require.True(tt.err.Is(err))
@@ -479,98 +386,3 @@ func TestNotIn(t *testing.T) {
 		})
 	}
 }
-
-func TestNotInSubquery(t *testing.T) {
-	ctx := sql.NewEmptyContext()
-	table := memory.NewTable("foo", sql.Schema{
-		{Name: "t", Source: "foo", Type: sql.Text},
-	})
-
-	require.NoError(t, table.Insert(ctx, sql.Row{"one"}))
-	require.NoError(t, table.Insert(ctx, sql.Row{"two"}))
-	require.NoError(t, table.Insert(ctx, sql.Row{"three"}))
-
-	project := func(expr sql.Expression) sql.Node {
-		return plan.NewProject([]sql.Expression{
-			expr,
-		}, plan.NewResolvedTable(table))
-	}
-
-	testCases := []struct {
-		name   string
-		left   sql.Expression
-		right  sql.Node
-		row    sql.Row
-		result interface{}
-		err    *errors.Kind
-	}{
-		{
-			"left is nil",
-			expression.NewLiteral(nil, sql.Null),
-			project(
-				expression.NewLiteral(int64(1), sql.Int64),
-			),
-			nil,
-			nil,
-			nil,
-		},
-		{
-			"left and right don't have the same cols",
-			expression.NewTuple(
-				expression.NewLiteral(int64(1), sql.Int64),
-				expression.NewLiteral(int64(1), sql.Int64),
-			),
-			project(
-				expression.NewLiteral(int64(2), sql.Int64),
-			),
-			nil,
-			nil,
-			expression.ErrInvalidOperandColumns,
-		},
-		{
-			"left is in right",
-			expression.NewGetField(0, sql.Text, "foo", false),
-			project(
-				expression.NewGetField(0, sql.Text, "foo", false),
-			),
-			sql.NewRow("two"),
-			false,
-			nil,
-		},
-		{
-			"left is not in right",
-			expression.NewGetField(0, sql.Text, "foo", false),
-			project(
-				expression.NewGetField(0, sql.Text, "foo", false),
-			),
-			sql.NewRow("four"),
-			true,
-			nil,
-		},
-	}
-
-	for _, tt := range testCases {
-		t.Run(tt.name, func(t *testing.T) {
-			require := require.New(t)
-
-			result, err := expression.NewNotIn(
-				tt.left,
-				expression.NewSubquery(tt.right),
-			).Eval(sql.NewEmptyContext(), tt.row)
-			if tt.err != nil {
-				require.Error(err)
-				require.True(tt.err.Is(err))
-			} else {
-				require.NoError(err)
-				require.Equal(tt.result, result)
-			}
-		})
-	}
-}
-
-func eval(t *testing.T, e sql.Expression, row sql.Row) interface{} {
-	t.Helper()
-	v, err := e.Eval(sql.NewEmptyContext(), row)
-	require.NoError(t, err)
-	return v
-}
diff --git a/sql/expression/subquery_test.go b/sql/expression/subquery_test.go
deleted file mode 100644
index 0d3f353..0000000
--- a/sql/expression/subquery_test.go
+++ /dev/null
@@ -1,69 +0,0 @@
-package expression_test
-
-import (
-	"testing"
-
-	"github.com/src-d/go-mysql-server/memory"
-	"github.com/src-d/go-mysql-server/sql"
-	"github.com/src-d/go-mysql-server/sql/expression"
-	"github.com/src-d/go-mysql-server/sql/plan"
-	"github.com/stretchr/testify/require"
-)
-
-func TestSubquery(t *testing.T) {
-	require := require.New(t)
-	table := memory.NewTable("", nil)
-	require.NoError(table.Insert(sql.NewEmptyContext(), nil))
-
-	subquery := expression.NewSubquery(plan.NewProject(
-		[]sql.Expression{
-			expression.NewLiteral("one", sql.Text),
-		},
-		plan.NewResolvedTable(table),
-	))
-
-	value, err := subquery.Eval(sql.NewEmptyContext(), nil)
-	require.NoError(err)
-	require.Equal(value, "one")
-}
-
-func TestSubqueryTooManyRows(t *testing.T) {
-	require := require.New(t)
-	table := memory.NewTable("", nil)
-	require.NoError(table.Insert(sql.NewEmptyContext(), nil))
-	require.NoError(table.Insert(sql.NewEmptyContext(), nil))
-
-	subquery := expression.NewSubquery(plan.NewProject(
-		[]sql.Expression{
-			expression.NewLiteral("one", sql.Text),
-		},
-		plan.NewResolvedTable(table),
-	))
-
-	_, err := subquery.Eval(sql.NewEmptyContext(), nil)
-	require.Error(err)
-}
-
-func TestSubqueryMultipleRows(t *testing.T) {
-	require := require.New(t)
-
-	ctx := sql.NewEmptyContext()
-	table := memory.NewTable("foo", sql.Schema{
-		{Name: "t", Source: "foo", Type: sql.Text},
-	})
-
-	require.NoError(table.Insert(ctx, sql.Row{"one"}))
-	require.NoError(table.Insert(ctx, sql.Row{"two"}))
-	require.NoError(table.Insert(ctx, sql.Row{"three"}))
-
-	subquery := expression.NewSubquery(plan.NewProject(
-		[]sql.Expression{
-			expression.NewGetField(0, sql.Text, "t", false),
-		},
-		plan.NewResolvedTable(table),
-	))
-
-	values, err := subquery.EvalMultiple(ctx)
-	require.NoError(err)
-	require.Equal(values, []interface{}{"one", "two", "three"})
-}
diff --git a/sql/parse/indexes_test.go b/sql/parse/indexes_test.go
index a9d7df5..4072b7a 100644
--- a/sql/parse/indexes_test.go
+++ b/sql/parse/indexes_test.go
@@ -159,7 +159,7 @@ func TestParseCreateIndex(t *testing.T) {
 		t.Run(tt.query, func(t *testing.T) {
 			require := require.New(t)
 
-			result, err := parseCreateIndex(sql.NewEmptyContext(), strings.ToLower(tt.query))
+			result, err := parseCreateIndex(strings.ToLower(tt.query))
 			if tt.err != nil {
 				require.Error(err)
 				require.True(tt.err.Is(err))
diff --git a/sql/parse/parse_test.go b/sql/parse/parse_test.go
index be176a9..6e74dd2 100644
--- a/sql/parse/parse_test.go
+++ b/sql/parse/parse_test.go
@@ -1208,11 +1208,12 @@ func TestParse(t *testing.T) {
 }
 
 var fixturesErrors = map[string]*errors.Kind{
-	`SHOW METHEMONEY`:                           ErrUnsupportedFeature,
-	`LOCK TABLES foo AS READ`:                   errUnexpectedSyntax,
-	`LOCK TABLES foo LOW_PRIORITY READ`:         errUnexpectedSyntax,
-	`SELECT * FROM mytable LIMIT -100`:          ErrUnsupportedSyntax,
-	`SELECT * FROM mytable LIMIT 100 OFFSET -1`: ErrUnsupportedSyntax,
+	`SHOW METHEMONEY`:                                      ErrUnsupportedFeature,
+	`LOCK TABLES foo AS READ`:                              errUnexpectedSyntax,
+	`LOCK TABLES foo LOW_PRIORITY READ`:                    errUnexpectedSyntax,
+	`SELECT * FROM mytable WHERE i IN (SELECT i FROM foo)`: ErrUnsupportedSubqueryExpression,
+	`SELECT * FROM mytable LIMIT -100`:                     ErrUnsupportedSyntax,
+	`SELECT * FROM mytable LIMIT 100 OFFSET -1`:            ErrUnsupportedSyntax,
 	`SELECT * FROM files
 		JOIN commit_files
 		JOIN refs