Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
e6d65ec
feat(oracle): parse subprogram heading clauses and PL/SQL CHARACTER S…
rebelice Oct 10, 2026
de7f539
fix(oracle): gate USING in Split, classify PL/SQL types for CHARACTER…
rebelice Oct 10, 2026
5c58d12
fix(oracle): scope heading clauses by subprogram level, tighten names…
rebelice Oct 10, 2026
56e084d
fix(oracle): restrict polymorphic table function clauses, reserved un…
rebelice Oct 10, 2026
0b01856
fix(oracle): nested subprogram and SQL macro clause rules, aggregate …
rebelice Oct 10, 2026
3eced1a
fix(oracle): PIPELINED excludes AGGREGATE, no polymorphic type method…
rebelice Oct 10, 2026
78b65a7
fix(oracle): check PARALLEL_ENABLE arguments, TABLE pseudo-type, meth…
rebelice Oct 10, 2026
8c2c339
fix(oracle): PTF signatures, partition cursor types, %CHARSET sources…
rebelice Oct 10, 2026
ef953c2
fix(oracle): VALUE partition arity, quoted TABLE user type, BOOL (BYT…
rebelice Oct 10, 2026
fa2b93b
fix(oracle): COLUMNS pseudo-type and multiword predefined types (BYT-…
rebelice Oct 10, 2026
db99fae
fix(oracle): method heading checks, RESULT_CACHE parameter modes (BYT…
rebelice Oct 10, 2026
bb4997f
fix(oracle): PTF parameter defaults, RESULT_CACHE types, AUTHID, sort…
rebelice Oct 10, 2026
88f2fa2
fix(oracle): leave quoted type names to the engine in heading checks …
rebelice Oct 10, 2026
8f10302
fix(oracle): pipelined result types, RESULT_CACHE on pipelined, macro…
rebelice Oct 10, 2026
d671057
fix(oracle): quoted names in %CHARSET and sort columns, %ROWTYPE resu…
rebelice Oct 10, 2026
c2edb48
fix(oracle): quoted %CHARSET formals, RESULT_CACHE in anonymous block…
rebelice Oct 10, 2026
29a5f40
fix(oracle): CHARACTER SET on pseudo-types, PARALLEL_ENABLE on nested…
rebelice Oct 10, 2026
ca834a8
fix(oracle): check %CHARSET sources in cursor parameter lists (BYT-10…
rebelice Oct 10, 2026
dd0a593
test(oracle): pin DEFAULT (NULL) on a COLUMNS parameter as rejected (…
rebelice Oct 10, 2026
25272c6
fix(oracle): body %CHARSET sources, aggregate links, streaming USING …
rebelice Oct 10, 2026
56c28e4
fix(oracle): scope-aware %CHARSET source checks in one pass (BYT-10301)
rebelice Oct 10, 2026
7a4b762
fix(oracle): %CHARSET headings, cursor formals, qualified sources, ty…
rebelice Oct 10, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions oracle/ast/loc.go
Original file line number Diff line number Diff line change
Expand Up @@ -487,6 +487,12 @@ func NodeLoc(n Node) Loc {
return v.Loc
case *PLSQLSubtypeDecl:
return v.Loc
case *Accessor:
return v.Loc
case *ParallelEnableClause:
return v.Loc
case *StreamingClause:
return v.Loc
case *PLSQLAssign:
return v.Loc
case *PLSQLIf:
Expand Down
93 changes: 93 additions & 0 deletions oracle/ast/outfuncs.go
Original file line number Diff line number Diff line change
Expand Up @@ -591,6 +591,12 @@ func writeNode(sb *strings.Builder, node Node) {
writePLSQLTypeDecl(sb, n)
case *PLSQLSubtypeDecl:
writePLSQLSubtypeDecl(sb, n)
case *Accessor:
writeAccessor(sb, n)
case *ParallelEnableClause:
writeParallelEnableClause(sb, n)
case *StreamingClause:
writeStreamingClause(sb, n)
case *PLSQLCall:
writePLSQLCall(sb, n)

Expand Down Expand Up @@ -670,6 +676,12 @@ func writeTypeName(sb *strings.Builder, n *TypeName) {
sb.WriteString(" :arrayBounds ")
writeNode(sb, n.ArrayBounds)
}
if n.CharacterSet != "" {
sb.WriteString(fmt.Sprintf(" :characterSet %q", n.CharacterSet))
}
if n.IsPercCharset {
sb.WriteString(" :pctCharset true")
}
sb.WriteString(fmt.Sprintf(" :loc_start %d :loc_end %d", n.Loc.Start, n.Loc.End))
sb.WriteString("}")
}
Expand Down Expand Up @@ -3217,6 +3229,16 @@ func writeCreatePackageStmt(sb *strings.Builder, n *CreatePackageStmt) {
sb.WriteString(" :name ")
writeNode(sb, n.Name)
}
if n.AuthID != "" {
sb.WriteString(fmt.Sprintf(" :authID %q", n.AuthID))
}
if n.AccessibleBy != nil {
sb.WriteString(" :accessibleBy ")
writeNode(sb, n.AccessibleBy)
}
if n.DefaultCollation != "" {
sb.WriteString(fmt.Sprintf(" :defaultCollation %q", n.DefaultCollation))
}
if n.IsBody {
sb.WriteString(" :isBody true")
}
Expand Down Expand Up @@ -3256,6 +3278,13 @@ func writeCreateProcedureStmt(sb *strings.Builder, n *CreateProcedureStmt) {
sb.WriteString(" :parameters ")
writeNode(sb, n.Parameters)
}
if n.AccessibleBy != nil {
sb.WriteString(" :accessibleBy ")
writeNode(sb, n.AccessibleBy)
}
if n.DefaultCollation != "" {
sb.WriteString(fmt.Sprintf(" :defaultCollation %q", n.DefaultCollation))
}
if n.Wrapped {
sb.WriteString(" :wrapped true")
}
Expand Down Expand Up @@ -3309,21 +3338,50 @@ func writeCreateFunctionStmt(sb *strings.Builder, n *CreateFunctionStmt) {
if n.Pipelined {
sb.WriteString(" :pipelined true")
}
if n.Polymorphic != "" {
sb.WriteString(fmt.Sprintf(" :polymorphic %q", n.Polymorphic))
}
if n.Parallel {
sb.WriteString(" :parallel true")
}
if n.ParallelSpec != nil {
sb.WriteString(" :parallelSpec ")
writeNode(sb, n.ParallelSpec)
}
if n.Streaming != nil {
sb.WriteString(" :streaming ")
writeNode(sb, n.Streaming)
}
if n.ResultCache {
sb.WriteString(" :resultCache true")
}
if n.ReliesOn != nil {
sb.WriteString(" :reliesOn ")
writeNode(sb, n.ReliesOn)
}
if n.Aggregate {
sb.WriteString(" :aggregate true")
}
if n.Implementation != nil {
sb.WriteString(" :implementation ")
writeNode(sb, n.Implementation)
}
if n.SqlMacro {
sb.WriteString(" :sqlMacro true")
}
if n.SqlMacroType != "" {
sb.WriteString(fmt.Sprintf(" :sqlMacroType %q", n.SqlMacroType))
}
if n.AuthID != "" {
sb.WriteString(fmt.Sprintf(" :authID %q", n.AuthID))
}
if n.AccessibleBy != nil {
sb.WriteString(" :accessibleBy ")
writeNode(sb, n.AccessibleBy)
}
if n.DefaultCollation != "" {
sb.WriteString(fmt.Sprintf(" :defaultCollation %q", n.DefaultCollation))
}
if n.Body != nil {
sb.WriteString(" :body ")
writeNode(sb, n.Body)
Expand Down Expand Up @@ -5391,6 +5449,41 @@ func writePLSQLSubtypeDecl(sb *strings.Builder, n *PLSQLSubtypeDecl) {
sb.WriteString("}")
}

func writeAccessor(sb *strings.Builder, n *Accessor) {
sb.WriteString("{ACCESSOR")
if n.UnitKind != "" {
sb.WriteString(fmt.Sprintf(" :unitKind %q", n.UnitKind))
}
if n.Name != nil {
sb.WriteString(" :name ")
writeNode(sb, n.Name)
}
sb.WriteString(fmt.Sprintf(" :loc_start %d :loc_end %d", n.Loc.Start, n.Loc.End))
sb.WriteString("}")
}

func writeParallelEnableClause(sb *strings.Builder, n *ParallelEnableClause) {
sb.WriteString("{PARALLELENABLE")
sb.WriteString(fmt.Sprintf(" :argument %q :partitionBy %q", n.Argument, n.PartitionBy))
if n.Columns != nil {
sb.WriteString(" :columns ")
writeNode(sb, n.Columns)
}
sb.WriteString(fmt.Sprintf(" :loc_start %d :loc_end %d", n.Loc.Start, n.Loc.End))
sb.WriteString("}")
}

func writeStreamingClause(sb *strings.Builder, n *StreamingClause) {
sb.WriteString("{STREAMING")
sb.WriteString(fmt.Sprintf(" :kind %q :argument %q", n.Kind, n.Argument))
if n.Columns != nil {
sb.WriteString(" :columns ")
writeNode(sb, n.Columns)
}
sb.WriteString(fmt.Sprintf(" :loc_start %d :loc_end %d", n.Loc.Start, n.Loc.End))
sb.WriteString("}")
}

func writePLSQLCall(sb *strings.Builder, n *PLSQLCall) {
sb.WriteString("{PLSQLCALL")
if n.Name != nil {
Expand Down
142 changes: 96 additions & 46 deletions oracle/ast/parsenodes.go
Original file line number Diff line number Diff line change
Expand Up @@ -369,12 +369,14 @@ func (n *Hint) nodeTag() {}

// TypeName represents a data type reference.
type TypeName struct {
Names *List // type name parts (list of *String)
TypeMods *List // type modifiers (precision, scale)
IsPercType bool // %TYPE
IsPercRowtype bool // %ROWTYPE
ArrayBounds *List // array bounds if any
Loc Loc // start location
Names *List // type name parts (list of *String)
TypeMods *List // type modifiers (precision, scale)
IsPercType bool // %TYPE
IsPercRowtype bool // %ROWTYPE
ArrayBounds *List // array bounds if any
CharacterSet string // PL/SQL CHARACTER SET name, or the item named by item%CHARSET
IsPercCharset bool // CHARACTER SET item%CHARSET
Loc Loc // start location
}

func (n *TypeName) nodeTag() {}
Expand Down Expand Up @@ -1986,15 +1988,18 @@ func (n *TypeBodyMember) nodeTag() {}

// CreatePackageStmt represents a CREATE PACKAGE statement.
type CreatePackageStmt struct {
OrReplace bool // OR REPLACE
IfNotExists bool // IF NOT EXISTS
Editionable bool // EDITIONABLE
NonEditionable bool // NONEDITIONABLE
Sharing string // SHARING = METADATA | NONE
Name *ObjectName // package name
IsBody bool // PACKAGE BODY
Body *List // package body declarations
Loc Loc // start location
OrReplace bool // OR REPLACE
IfNotExists bool // IF NOT EXISTS
Editionable bool // EDITIONABLE
NonEditionable bool // NONEDITIONABLE
Sharing string // SHARING = METADATA | NONE
Name *ObjectName // package name
AuthID string // AUTHID CURRENT_USER | DEFINER
AccessibleBy *List // ACCESSIBLE BY accessors (list of *Accessor)
DefaultCollation string // DEFAULT COLLATION option
IsBody bool // PACKAGE BODY
Body *List // package body declarations
Loc Loc // start location
}

func (n *CreatePackageStmt) nodeTag() {}
Expand All @@ -2006,19 +2011,21 @@ func (n *CreatePackageStmt) stmtNode() {}

// CreateProcedureStmt represents a CREATE PROCEDURE statement.
type CreateProcedureStmt struct {
OrReplace bool // OR REPLACE
IfNotExists bool // IF NOT EXISTS
Editionable bool // EDITIONABLE
NonEditionable bool // NONEDITIONABLE
Sharing string // SHARING = METADATA | NONE
AuthID string // AUTHID CURRENT_USER | DEFINER
Name *ObjectName // procedure name
Parameters *List // parameter list (list of *Parameter)
Wrapped bool // WRAPPED procedure body
WrappedSource string // raw text from WRAPPED through the wrapped payload
Body StmtNode // procedure body (PL/SQL block); nil for a call spec
CallSpec *CallSpec // call spec implementing the procedure in Java or C
Loc Loc // start location
OrReplace bool // OR REPLACE
IfNotExists bool // IF NOT EXISTS
Editionable bool // EDITIONABLE
NonEditionable bool // NONEDITIONABLE
Sharing string // SHARING = METADATA | NONE
AuthID string // AUTHID CURRENT_USER | DEFINER
Name *ObjectName // procedure name
Parameters *List // parameter list (list of *Parameter)
AccessibleBy *List // ACCESSIBLE BY accessors (list of *Accessor)
DefaultCollation string // DEFAULT COLLATION option
Wrapped bool // WRAPPED procedure body
WrappedSource string // raw text from WRAPPED through the wrapped payload
Body StmtNode // procedure body (PL/SQL block); nil for a call spec
CallSpec *CallSpec // call spec implementing the procedure in Java or C
Loc Loc // start location
}

func (n *CreateProcedureStmt) nodeTag() {}
Expand Down Expand Up @@ -2056,29 +2063,72 @@ func (n *CallSpec) nodeTag() {}

// CreateFunctionStmt represents a CREATE FUNCTION statement.
type CreateFunctionStmt struct {
OrReplace bool // OR REPLACE
IfNotExists bool // IF NOT EXISTS
Editionable bool // EDITIONABLE
NonEditionable bool // NONEDITIONABLE
Sharing string // SHARING = METADATA | NONE
Name *ObjectName // function name
Parameters *List // parameter list (list of *Parameter)
ReturnType *TypeName // RETURN type
Deterministic bool // DETERMINISTIC
Pipelined bool // PIPELINED
Parallel bool // PARALLEL_ENABLE
ResultCache bool // RESULT_CACHE
Aggregate bool // AGGREGATE USING
SqlMacro bool // SQL_MACRO
AuthID string // AUTHID CURRENT_USER | DEFINER
Body StmtNode // function body (PL/SQL block); nil for a call spec
CallSpec *CallSpec // call spec implementing the function in Java or C
Loc Loc // start location
OrReplace bool // OR REPLACE
IfNotExists bool // IF NOT EXISTS
Editionable bool // EDITIONABLE
NonEditionable bool // NONEDITIONABLE
Sharing string // SHARING = METADATA | NONE
Name *ObjectName // function name
Parameters *List // parameter list (list of *Parameter)
ReturnType *TypeName // RETURN type
Deterministic bool // DETERMINISTIC
Pipelined bool // PIPELINED
Polymorphic string // PIPELINED ROW or TABLE POLYMORPHIC: ROW or TABLE
Parallel bool // PARALLEL_ENABLE
ParallelSpec *ParallelEnableClause // PARALLEL_ENABLE ( PARTITION ... ), nil without one
Streaming *List // ORDER and CLUSTER streaming clauses (list of *StreamingClause)
ResultCache bool // RESULT_CACHE
ReliesOn *List // RESULT_CACHE RELIES_ON data sources (list of *ObjectName)
Aggregate bool // AGGREGATE USING
Implementation *ObjectName // AGGREGATE or PIPELINED USING implementation type; the function then has no body
SqlMacro bool // SQL_MACRO
SqlMacroType string // SQL_MACRO ( SCALAR | TABLE ), "" without the parenthesized type
AuthID string // AUTHID CURRENT_USER | DEFINER
AccessibleBy *List // ACCESSIBLE BY accessors (list of *Accessor)
DefaultCollation string // DEFAULT COLLATION option
Body StmtNode // function body (PL/SQL block); nil for a call spec
CallSpec *CallSpec // call spec implementing the function in Java or C
Loc Loc // start location
}

func (n *CreateFunctionStmt) nodeTag() {}
func (n *CreateFunctionStmt) stmtNode() {}

// Accessor is one entry of an ACCESSIBLE BY clause.
//
// accessor ::= [ FUNCTION | PROCEDURE | PACKAGE | TRIGGER | TYPE ] [ schema. ] unit_name
type Accessor struct {
UnitKind string // FUNCTION, PROCEDURE, PACKAGE, TRIGGER, TYPE, or "" when omitted
Name *ObjectName // [schema.]unit_name
Loc Loc
}

func (n *Accessor) nodeTag() {}

// ParallelEnableClause is the partitioning of a PARALLEL_ENABLE function.
//
// ( PARTITION argument BY { ANY | { HASH | RANGE | VALUE } ( expr [, expr ]... ) } )
type ParallelEnableClause struct {
Argument string // the partitioned cursor parameter
PartitionBy string // ANY, HASH, RANGE, or VALUE
Columns *List // HASH, RANGE, or VALUE expressions
Loc Loc
}

func (n *ParallelEnableClause) nodeTag() {}

// StreamingClause orders or clusters the rows a table function receives.
//
// { ORDER | CLUSTER } argument BY ( expr [, expr ]... )
type StreamingClause struct {
Kind string // ORDER or CLUSTER
Argument string // the cursor parameter
Columns *List // the ordering or clustering expressions
Loc Loc
}

func (n *StreamingClause) nodeTag() {}

// Parameter represents a procedure/function parameter.
type Parameter struct {
Name string // parameter name
Expand Down
19 changes: 19 additions & 0 deletions oracle/ast/walk_generated.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading