Skip to content

Commit 4453b49

Browse files
kyleconroyclaude
andauthored
Add UserDefinedTypeCallTarget support and enable 2 SetVariable tests (#30)
- Add support for :: separator in function calls (a.b::func() syntax) - Handle UserDefinedTypeCallTarget for UDT method calls - Enable Baselines90_SetVariableStatementTests90 and SetVariableStatementTests90 tests - Update skipped_tests_by_size.txt script to exclude invalid_syntax tests - Regenerate skipped_tests_by_size.txt (576 tests remaining) Co-authored-by: Claude <[email protected]>
1 parent 4a70ce5 commit 4453b49

File tree

5 files changed

+99
-77
lines changed

5 files changed

+99
-77
lines changed

CLAUDE.md

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -39,16 +39,21 @@ Available test flags:
3939

4040
## Updating skipped_tests_by_size.txt
4141

42-
After enabling tests, regenerate the file:
42+
After enabling tests, regenerate the file. The script only includes tests that:
43+
- Have `"skip": true` in metadata.json
44+
- Do NOT have `"invalid_syntax"` in metadata.json (these can't be implemented)
45+
- Have an `ast.json` file (tests without it are unparseable)
4346

4447
```bash
4548
cd parser/testdata
46-
for dir in */; do
47-
if [ -f "$dir/metadata.json" ] && grep -q '"skip": true' "$dir/metadata.json" 2>/dev/null; then
48-
if [ -f "$dir/query.sql" ]; then
49-
size=$(wc -c < "$dir/query.sql")
50-
name="${dir%/}"
51-
echo "$size $name"
49+
ls -d */ | while read dir; do
50+
dir="${dir%/}"
51+
if [ -f "$dir/metadata.json" ] && [ -f "$dir/ast.json" ] && [ -f "$dir/query.sql" ]; then
52+
if grep -q '"skip": true' "$dir/metadata.json" 2>/dev/null; then
53+
if grep -qv '"invalid_syntax"' "$dir/metadata.json" 2>/dev/null; then
54+
size=$(wc -c < "$dir/query.sql")
55+
echo "$size $dir"
56+
fi
5257
fi
5358
fi
5459
done | sort -n > ../../skipped_tests_by_size.txt

parser/parse_select.go

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -966,6 +966,60 @@ func (p *Parser) parseColumnReferenceOrFunctionCall() (ast.ScalarExpression, err
966966
p.nextToken() // consume dot
967967
}
968968

969+
// Check for :: (user-defined type method call): a.b::func()
970+
if p.curTok.Type == TokenColonColon && len(identifiers) > 0 {
971+
p.nextToken() // consume ::
972+
973+
// Parse function name
974+
if p.curTok.Type != TokenIdent {
975+
return nil, fmt.Errorf("expected function name after ::, got %s", p.curTok.Literal)
976+
}
977+
funcName := &ast.Identifier{Value: p.curTok.Literal, QuoteType: "NotQuoted"}
978+
p.nextToken()
979+
980+
// Expect (
981+
if p.curTok.Type != TokenLParen {
982+
return nil, fmt.Errorf("expected ( after function name, got %s", p.curTok.Literal)
983+
}
984+
p.nextToken() // consume (
985+
986+
// Build SchemaObjectName from identifiers
987+
schemaObjName := identifiersToSchemaObjectName(identifiers)
988+
989+
fc := &ast.FunctionCall{
990+
CallTarget: &ast.UserDefinedTypeCallTarget{
991+
SchemaObjectName: schemaObjName,
992+
},
993+
FunctionName: funcName,
994+
UniqueRowFilter: "NotSpecified",
995+
WithArrayWrapper: false,
996+
}
997+
998+
// Parse parameters
999+
if p.curTok.Type != TokenRParen {
1000+
for {
1001+
param, err := p.parseScalarExpression()
1002+
if err != nil {
1003+
return nil, err
1004+
}
1005+
fc.Parameters = append(fc.Parameters, param)
1006+
1007+
if p.curTok.Type != TokenComma {
1008+
break
1009+
}
1010+
p.nextToken() // consume comma
1011+
}
1012+
}
1013+
1014+
// Expect )
1015+
if p.curTok.Type != TokenRParen {
1016+
return nil, fmt.Errorf("expected ) in function call, got %s", p.curTok.Literal)
1017+
}
1018+
p.nextToken()
1019+
1020+
return fc, nil
1021+
}
1022+
9691023
// If followed by ( it's a function call
9701024
if p.curTok.Type == TokenLParen {
9711025
return p.parseFunctionCallFromIdentifiers(identifiers)
@@ -1953,5 +2007,36 @@ func (p *Parser) parseBooleanPrimaryExpression() (ast.BooleanExpression, error)
19532007
}, nil
19542008
}
19552009

2010+
// identifiersToSchemaObjectName converts a slice of identifiers to a SchemaObjectName.
2011+
// For 1 identifier: BaseIdentifier
2012+
// For 2 identifiers: SchemaIdentifier.BaseIdentifier
2013+
// For 3 identifiers: DatabaseIdentifier.SchemaIdentifier.BaseIdentifier
2014+
// For 4 identifiers: ServerIdentifier.DatabaseIdentifier.SchemaIdentifier.BaseIdentifier
2015+
func identifiersToSchemaObjectName(identifiers []*ast.Identifier) *ast.SchemaObjectName {
2016+
son := &ast.SchemaObjectName{
2017+
Count: len(identifiers),
2018+
Identifiers: identifiers,
2019+
}
2020+
2021+
switch len(identifiers) {
2022+
case 1:
2023+
son.BaseIdentifier = identifiers[0]
2024+
case 2:
2025+
son.SchemaIdentifier = identifiers[0]
2026+
son.BaseIdentifier = identifiers[1]
2027+
case 3:
2028+
son.DatabaseIdentifier = identifiers[0]
2029+
son.SchemaIdentifier = identifiers[1]
2030+
son.BaseIdentifier = identifiers[2]
2031+
case 4:
2032+
son.ServerIdentifier = identifiers[0]
2033+
son.DatabaseIdentifier = identifiers[1]
2034+
son.SchemaIdentifier = identifiers[2]
2035+
son.BaseIdentifier = identifiers[3]
2036+
}
2037+
2038+
return son
2039+
}
2040+
19562041
// ======================= New Statement Parsing Functions =======================
19572042

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"skip": true}
1+
{"skip": false}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"skip": true}
1+
{"skip": false}

0 commit comments

Comments
 (0)