Skip to content

Commit ccbbf9c

Browse files
committed
Squash commits.
1 parent 1d4e38a commit ccbbf9c

File tree

6 files changed

+198
-1
lines changed

6 files changed

+198
-1
lines changed
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
package expressions
2+
3+
import (
4+
"bytes"
5+
"fmt"
6+
7+
"github.com/efritz/gostgres/internal/execution/engine/serialization"
8+
"github.com/efritz/gostgres/internal/execution/scan"
9+
"github.com/efritz/gostgres/internal/shared/impls"
10+
"github.com/efritz/gostgres/internal/shared/rows"
11+
)
12+
13+
type Query interface {
14+
Serialize(w serialization.IndentWriter)
15+
Optimize()
16+
Scanner(ctx impls.Context) (scan.Scanner, error)
17+
}
18+
19+
//
20+
//
21+
//
22+
23+
type existsSubqueryExpression struct {
24+
subquery Query
25+
}
26+
27+
func NewExistsSubqueryExpression(subquery Query) impls.Expression {
28+
return existsSubqueryExpression{
29+
subquery: subquery,
30+
}
31+
}
32+
33+
func (e existsSubqueryExpression) String() string { return "" } // TODO
34+
func (e existsSubqueryExpression) Equal(other impls.Expression) bool { return false } // TODO
35+
func (e existsSubqueryExpression) Children() []impls.Expression { return nil } // TODO
36+
func (e existsSubqueryExpression) Fold() impls.Expression { return e } // TODO
37+
func (e existsSubqueryExpression) Map(f func(impls.Expression) impls.Expression) impls.Expression {
38+
return e
39+
} // TODO
40+
41+
func (e existsSubqueryExpression) ValueFrom(ctx impls.Context, row rows.Row) (any, error) {
42+
// TODO - want to pull this out and do optimization before the enclosing query is executed
43+
// TODO - need to pull out serialization into separate parts in the explain output as well
44+
ctx.Log("Optimizing subquery")
45+
e.subquery.Optimize()
46+
47+
var buf bytes.Buffer
48+
w := serialization.NewIndentWriter(&buf)
49+
e.subquery.Serialize(w)
50+
ctx.Log("%s", buf.String())
51+
52+
ctx.Log("Preparing subquery")
53+
54+
s, err := e.subquery.Scanner(ctx)
55+
if err != nil {
56+
return nil, err
57+
}
58+
59+
ctx.Log("Scanning subquery")
60+
61+
rowx, err := s.Scan()
62+
if err != nil {
63+
return nil, err
64+
}
65+
66+
fmt.Printf("? %#v\n", rowx)
67+
panic("OH NO")
68+
}
69+
70+
//
71+
//
72+
//
73+
74+
type anySubqueryExpression struct {
75+
expression impls.Expression
76+
op string // TODO
77+
subquery Query
78+
}
79+
80+
func NewAnySubqueryExpression(expression impls.Expression, op string, subquery Query) impls.Expression {
81+
return anySubqueryExpression{
82+
expression: expression,
83+
op: op,
84+
subquery: subquery,
85+
}
86+
}
87+
88+
func (e anySubqueryExpression) String() string { return "" } // TODO
89+
func (e anySubqueryExpression) Equal(other impls.Expression) bool { return false } // TODO
90+
func (e anySubqueryExpression) Children() []impls.Expression { return nil } // TODO
91+
func (e anySubqueryExpression) Fold() impls.Expression { return e } // TODO
92+
func (e anySubqueryExpression) Map(f func(impls.Expression) impls.Expression) impls.Expression {
93+
return e
94+
} // TODO
95+
96+
func (e anySubqueryExpression) ValueFrom(ctx impls.Context, row rows.Row) (any, error) {
97+
return nil, fmt.Errorf("unimplemented") // TODO
98+
}
99+
100+
//
101+
//
102+
//
103+
104+
type allSubqueryExpression struct {
105+
expression impls.Expression
106+
op string // TODO
107+
subquery Query
108+
}
109+
110+
func NewAllSubqueryExpression(expression impls.Expression, op string, subquery Query) impls.Expression {
111+
return allSubqueryExpression{
112+
expression: expression,
113+
op: op,
114+
subquery: subquery,
115+
}
116+
}
117+
118+
func (e allSubqueryExpression) String() string { return "" } // TODO
119+
func (e allSubqueryExpression) Equal(other impls.Expression) bool { return false } // TODO
120+
func (e allSubqueryExpression) Children() []impls.Expression { return nil } // TODO
121+
func (e allSubqueryExpression) Fold() impls.Expression { return e } // TODO
122+
func (e allSubqueryExpression) Map(f func(impls.Expression) impls.Expression) impls.Expression {
123+
return e
124+
} // TODO
125+
126+
func (e allSubqueryExpression) ValueFrom(ctx impls.Context, row rows.Row) (any, error) {
127+
return nil, fmt.Errorf("unimplemented") // TODO
128+
}
129+
130+
//
131+
//
132+
//
133+
134+
type opSubqueryExpression struct {
135+
expression impls.Expression
136+
op string // TODO
137+
subquery Query
138+
}
139+
140+
func NewOpSubqueryExpression(expression impls.Expression, op string, subquery Query) impls.Expression {
141+
return opSubqueryExpression{
142+
expression: expression,
143+
op: op,
144+
subquery: subquery,
145+
}
146+
}
147+
148+
func (e opSubqueryExpression) String() string { return "" } // TODO
149+
func (e opSubqueryExpression) Equal(other impls.Expression) bool { return false } // TODO
150+
func (e opSubqueryExpression) Children() []impls.Expression { return nil } // TODO
151+
func (e opSubqueryExpression) Fold() impls.Expression { return e } // TODO
152+
func (e opSubqueryExpression) Map(f func(impls.Expression) impls.Expression) impls.Expression {
153+
return e
154+
} // TODO
155+
156+
func (e opSubqueryExpression) ValueFrom(ctx impls.Context, row rows.Row) (any, error) {
157+
return nil, fmt.Errorf("unimplemented") // TODO
158+
}

internal/shared/impls/context.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ func (c Context) Log(format string, args ...interface{}) {
4949
}
5050

5151
_, file, line, _ := runtime.Caller(1)
52-
parts := strings.Split(file, "/gostgres/internal/execution/queries/")
52+
parts := strings.Split(file, "/gostgres/internal/execution/")
5353
caller := fmt.Sprintf("[%s:%d]", parts[1], line)
5454

5555
fmt.Printf("%% [%s] ", caller)

internal/syntax/lexing/lex.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ var tokenSequenceReplacements = []tokenSequenceReplacement{
2828
{tokens.TokenTypeNotBetween, []tokens.TokenType{tokens.TokenTypeNot, tokens.TokenTypeBetween}},
2929
{tokens.TokenTypeNotBetweenSymmetric, []tokens.TokenType{tokens.TokenTypeNot, tokens.TokenTypeBetween, tokens.TokenTypeSymmetric}},
3030
{tokens.TokenTypeNotILike, []tokens.TokenType{tokens.TokenTypeNot, tokens.TokenTypeILike}},
31+
{tokens.TokenTypeNotIn, []tokens.TokenType{tokens.TokenTypeNot, tokens.TokenTypeIn}},
3132
{tokens.TokenTypeNotLike, []tokens.TokenType{tokens.TokenTypeNot, tokens.TokenTypeLike}},
3233
{tokens.TokenTypeNotNull, []tokens.TokenType{tokens.TokenTypeNot, tokens.TokenTypeNull}},
3334
{tokens.TokenTypePrimaryKey, []tokens.TokenType{tokens.TokenTypePrimary, tokens.TokenTypeKey}},

internal/syntax/lexing/lexer.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ var keywordSet = map[string]tokens.TokenType{
1818
"all": tokens.TokenTypeAll,
1919
"alter": tokens.TokenTypeAlter,
2020
"and": tokens.TokenTypeAnd,
21+
"any": tokens.TokenTypeAny,
2122
"as": tokens.TokenTypeAs,
2223
"asc": tokens.TokenTypeAscending,
2324
"between": tokens.TokenTypeBetween,
@@ -30,12 +31,14 @@ var keywordSet = map[string]tokens.TokenType{
3031
"desc": tokens.TokenTypeDescending,
3132
"distinct": tokens.TokenTypeDistinct,
3233
"except": tokens.TokenTypeExcept,
34+
"exists": tokens.TokenTypeExists,
3335
"explain": tokens.TokenTypeExplain,
3436
"false": tokens.TokenTypeFalse,
3537
"foreign": tokens.TokenTypeForeign,
3638
"from": tokens.TokenTypeFrom,
3739
"group": tokens.TokenTypeGroup,
3840
"ilike": tokens.TokenTypeILike,
41+
"in": tokens.TokenTypeIn,
3942
"index": tokens.TokenTypeIndex,
4043
"insert": tokens.TokenTypeInsert,
4144
"intersect": tokens.TokenTypeIntersect,
@@ -59,6 +62,7 @@ var keywordSet = map[string]tokens.TokenType{
5962
"select": tokens.TokenTypeSelect,
6063
"sequence": tokens.TokenTypeSequence,
6164
"set": tokens.TokenTypeSet,
65+
"some": tokens.TokenTypeSome,
6266
"symmetric": tokens.TokenTypeSymmetric,
6367
"table": tokens.TokenTypeTable,
6468
"true": tokens.TokenTypeTrue,

internal/syntax/parsing/expressions.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ func (p *parser) initExpressionPrefixParsers() {
5757
tokens.TokenTypeMinus: p.parseUnary(expressions.NewUnaryMinus),
5858
tokens.TokenTypeLeftParen: p.parseParenthesizedExpression,
5959
tokens.TokenTypePlus: p.parseUnary(expressions.NewUnaryPlus),
60+
tokens.TokenTypeExists: p.parseExistsExpression,
6061
}
6162
}
6263

@@ -261,3 +262,31 @@ func negate(parserFunc infixParserFunc) infixParserFunc {
261262
return expressions.NewNot(expression), nil
262263
}
263264
}
265+
266+
// exists := `EXISTS` `(` subquery `)`
267+
func (p *parser) parseExistsExpression(token tokens.Token) (impls.Expression, error) {
268+
if _, err := p.mustAdvance(isType(tokens.TokenTypeLeftParen)); err != nil {
269+
return nil, err
270+
}
271+
272+
subquery, err := p.parseSelectOrValues()
273+
if err != nil {
274+
return nil, err
275+
}
276+
277+
if _, err := p.mustAdvance(isType(tokens.TokenTypeRightParen)); err != nil {
278+
return nil, err
279+
}
280+
281+
return expressions.NewExistsSubqueryExpression(subquery), nil
282+
}
283+
284+
// IN/NOT IN (subquery) => = ANY/!= ANY
285+
// op ANY/SOME (subquery)
286+
// op ALL (subquery)
287+
288+
// TODO
289+
// row_constructor {IN / NOT IN} (subquery)
290+
// row_constructor op {ALL / ANY / SOME} (subquery)
291+
// row_constructor op ALL (subquery)
292+
// row_constructor op (single-row subquery)

internal/syntax/tokens/token_type.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ const (
1818
TokenTypeAll
1919
TokenTypeAlter
2020
TokenTypeAnd
21+
TokenTypeAny
2122
TokenTypeAs
2223
TokenTypeAscending
2324
TokenTypeBetween
@@ -30,12 +31,14 @@ const (
3031
TokenTypeDescending
3132
TokenTypeDistinct
3233
TokenTypeExcept
34+
TokenTypeExists
3335
TokenTypeExplain
3436
TokenTypeFalse
3537
TokenTypeForeign
3638
TokenTypeFrom
3739
TokenTypeGroup
3840
TokenTypeILike
41+
TokenTypeIn
3942
TokenTypeIndex
4043
TokenTypeInsert
4144
TokenTypeIntersect
@@ -58,6 +61,7 @@ const (
5861
TokenTypeSelect
5962
TokenTypeSequence
6063
TokenTypeSet
64+
TokenTypeSome
6165
TokenTypeSymmetric
6266
TokenTypeTable
6367
TokenTypeTrue
@@ -110,6 +114,7 @@ const (
110114
TokenTypeNotBetween
111115
TokenTypeNotBetweenSymmetric
112116
TokenTypeNotILike
117+
TokenTypeNotIn
113118
TokenTypeNotLike
114119
TokenTypeNotNull
115120
TokenTypePrimaryKey

0 commit comments

Comments
 (0)