MCPcopy Create free account
hub / github.com/ajitpratap0/GoSQLX / parseFromClause

Method parseFromClause

pkg/sql/parser/select_clauses.go:34–113  ·  view source on GitHub ↗

parseFromClause parses the FROM clause including comma-separated table references and any subsequent JOIN clauses. Returns the primary table name (for compatibility), the full table-reference slice, and the join slice.

()

Source from the content-addressed store, hash-verified

32// and any subsequent JOIN clauses. Returns the primary table name (for compatibility),
33// the full table-reference slice, and the join slice.
34func (p *Parser) parseFromClause() (tableName string, tables []ast.TableReference, joins []ast.JoinClause, err error) {
35 // FROM is optional (e.g. SELECT 1). Validate that the next token makes sense.
36 if !p.isType(models.TokenTypeFrom) {
37 // advance() sets a zero-value sentinel (TokenType == TokenTypeEOF == 0) when
38 // currentPos goes past the end of the token slice. A real EOF token produced by
39 // the tokenizer is also TokenTypeEOF but is still within the slice.
40 // To replicate the correct behaviour we need to know what the last consumed token
41 // was: e.g. SELECT (1,2,3) ends with ')' (FROM is optional) while SELECT *
42 // ends with '*' (FROM is required). When currentPos is past the slice end,
43 // inspect the last real token directly instead of relying on currentToken.
44 if p.currentPos >= len(p.tokens) {
45 // Past end of token stream - check whether the last real token implies
46 // that FROM can legitimately be omitted.
47 if len(p.tokens) > 0 {
48 lastTokType := p.tokens[len(p.tokens)-1].Token.Type
49 if lastTokType == models.TokenTypeSemicolon ||
50 lastTokType == models.TokenTypeRParen ||
51 lastTokType == models.TokenTypeEOF ||
52 lastTokType == models.TokenTypeUnion ||
53 lastTokType == models.TokenTypeExcept ||
54 lastTokType == models.TokenTypeIntersect {
55 return "", nil, nil, nil
56 }
57 }
58 return "", nil, nil, p.expectedError("FROM, semicolon, or end of statement")
59 }
60 // Current token is still within the slice - use the normal token-type check.
61 if !p.isType(models.TokenTypeEOF) &&
62 !p.isType(models.TokenTypeSemicolon) &&
63 !p.isType(models.TokenTypeRParen) &&
64 !p.isAnyType(models.TokenTypeUnion, models.TokenTypeExcept, models.TokenTypeIntersect) &&
65 !p.isMinusSetOp() {
66 return "", nil, nil, p.expectedError("FROM, semicolon, or end of statement")
67 }
68 return "", nil, nil, nil
69 }
70
71 p.advance() // Consume FROM
72
73 if p.isType(models.TokenTypeEOF) || p.isType(models.TokenTypeSemicolon) {
74 return "", nil, nil, goerrors.ExpectedTokenError(
75 "table name",
76 p.currentToken.Token.Type.String(),
77 p.currentLocation(),
78 "FROM clause requires at least one table reference",
79 )
80 }
81
82 // First table reference
83 firstRef, e := p.parseFromTableReference()
84 if e != nil {
85 return "", nil, nil, e
86 }
87 tableName = firstRef.Name
88
89 // ClickHouse FINAL modifier — consumed after table reference, before JOINs.
90 // NOTE: FINAL only applies to the first (primary) table reference. In ClickHouse,
91 // FINAL is a per-table modifier; multi-table FROM with FINAL on a non-first

Callers 1

parseSelectStatementMethod · 0.95

Calls 10

isTypeMethod · 0.95
expectedErrorMethod · 0.95
isAnyTypeMethod · 0.95
isMinusSetOpMethod · 0.95
advanceMethod · 0.95
currentLocationMethod · 0.95
isTokenMatchMethod · 0.95
parseJoinClausesMethod · 0.95
StringMethod · 0.45

Tested by

no test coverage detected