Skip to content

Commit 1c32033

Browse files
author
Jaco Labuschagne
committed
Refactor PL/SQL block handling in parser
- Updated the statement listener to track the depth of PL/SQL blocks, allowing for more accurate statement counting and type identification. - Adjusted test expectations to reflect changes in PL/SQL block depth tracking, resulting in a single statement count for PL/SQL blocks. - Enhanced the listener methods to skip processing nested PL/SQL blocks and correctly manage entry and exit for various statement types.
1 parent f865b17 commit 1c32033

2 files changed

Lines changed: 89 additions & 6 deletions

File tree

internal/parser/parser.go

Lines changed: 87 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -350,10 +350,11 @@ type statementModel struct {
350350
// StatementListener listens for statements in the parse tree
351351
type StatementListener struct {
352352
*gen.BasePlSqlParserListener
353-
Statements []statementModel
354-
parser *gen.PlSqlParser
355-
tokenStream *antlr.CommonTokenStream
356-
currentType string // Track the current statement type
353+
Statements []statementModel
354+
parser *gen.PlSqlParser
355+
tokenStream *antlr.CommonTokenStream
356+
currentType string // Track the current statement type
357+
plsqlBlockDepth int // Track the nesting level of PL/SQL blocks
357358
}
358359

359360
// NewStatementListener creates a new statement listener
@@ -364,11 +365,17 @@ func NewStatementListener(parser *gen.PlSqlParser, tokenStream *antlr.CommonToke
364365
parser: parser,
365366
tokenStream: tokenStream,
366367
currentType: "",
368+
plsqlBlockDepth: 0,
367369
}
368370
}
369371

370372
// EnterUnit_statement is called when entering a unit_statement rule
371373
func (l *StatementListener) EnterUnit_statement(ctx *gen.Unit_statementContext) {
374+
// Skip if we are inside a PL/SQL block
375+
if l.plsqlBlockDepth > 0 {
376+
return
377+
}
378+
372379
// Get the start and stop tokens
373380
start := ctx.GetStart()
374381
stop := ctx.GetStop()
@@ -402,6 +409,11 @@ func (l *StatementListener) EnterUnit_statement(ctx *gen.Unit_statementContext)
402409

403410
// EnterSql_statement is called when entering a sql_statement rule
404411
func (l *StatementListener) EnterSql_statement(ctx *gen.Sql_statementContext) {
412+
// Skip if we are inside a PL/SQL block
413+
if l.plsqlBlockDepth > 0 {
414+
return
415+
}
416+
405417
// Get the start and stop tokens
406418
start := ctx.GetStart()
407419
stop := ctx.GetStop()
@@ -436,41 +448,91 @@ func (l *StatementListener) EnterSql_statement(ctx *gen.Sql_statementContext) {
436448
// EnterCreate_procedure_body is called when entering a create_procedure_body rule
437449
func (l *StatementListener) EnterCreate_procedure_body(ctx *gen.Create_procedure_bodyContext) {
438450
l.currentType = "CREATE_PROCEDURE"
451+
l.plsqlBlockDepth++
452+
}
453+
454+
// ExitCreate_procedure_body is called when exiting a create_procedure_body rule
455+
func (l *StatementListener) ExitCreate_procedure_body(ctx *gen.Create_procedure_bodyContext) {
456+
l.plsqlBlockDepth--
439457
}
440458

441459
// EnterCreate_function_body is called when entering a create_function_body rule
442460
func (l *StatementListener) EnterCreate_function_body(ctx *gen.Create_function_bodyContext) {
443461
l.currentType = "CREATE_FUNCTION"
462+
l.plsqlBlockDepth++
463+
}
464+
465+
// ExitCreate_function_body is called when exiting a create_function_body rule
466+
func (l *StatementListener) ExitCreate_function_body(ctx *gen.Create_function_bodyContext) {
467+
l.plsqlBlockDepth--
444468
}
445469

446470
// EnterCreate_package is called when entering a create_package rule
447471
func (l *StatementListener) EnterCreate_package(ctx *gen.Create_packageContext) {
448472
l.currentType = "CREATE_PACKAGE"
473+
l.plsqlBlockDepth++
474+
}
475+
476+
// ExitCreate_package is called when exiting a create_package rule
477+
func (l *StatementListener) ExitCreate_package(ctx *gen.Create_packageContext) {
478+
l.plsqlBlockDepth--
449479
}
450480

451481
// EnterCreate_package_body is called when entering a create_package_body rule
452482
func (l *StatementListener) EnterCreate_package_body(ctx *gen.Create_package_bodyContext) {
453483
l.currentType = "CREATE_PACKAGE_BODY"
484+
l.plsqlBlockDepth++
485+
}
486+
487+
// ExitCreate_package_body is called when exiting a create_package_body rule
488+
func (l *StatementListener) ExitCreate_package_body(ctx *gen.Create_package_bodyContext) {
489+
l.plsqlBlockDepth--
454490
}
455491

456492
// EnterCreate_trigger is called when entering a create_trigger rule
457493
func (l *StatementListener) EnterCreate_trigger(ctx *gen.Create_triggerContext) {
458494
l.currentType = "CREATE_TRIGGER"
495+
l.plsqlBlockDepth++
496+
}
497+
498+
// ExitCreate_trigger is called when exiting a create_trigger rule
499+
func (l *StatementListener) ExitCreate_trigger(ctx *gen.Create_triggerContext) {
500+
l.plsqlBlockDepth--
459501
}
460502

461503
// EnterCreate_type is called when entering a create_type rule
462504
func (l *StatementListener) EnterCreate_type(ctx *gen.Create_typeContext) {
463505
l.currentType = "CREATE_TYPE"
506+
l.plsqlBlockDepth++
507+
}
508+
509+
// ExitCreate_type is called when exiting a create_type rule
510+
func (l *StatementListener) ExitCreate_type(ctx *gen.Create_typeContext) {
511+
l.plsqlBlockDepth--
464512
}
465513

466514
// EnterCreate_type_body is called when the CreateTypeBody rule is encountered
467515
// Note: Update this if the exact gen.CreateTypeBodyContext name is different
468516
func (l *StatementListener) EnterCreate_type_body(ctx interface{}) {
469517
l.currentType = "CREATE_TYPE_BODY"
518+
l.plsqlBlockDepth++
519+
}
520+
521+
// ExitCreate_type_body is called when exiting a create_type_body rule
522+
func (l *StatementListener) ExitCreate_type_body(ctx interface{}) {
523+
l.plsqlBlockDepth--
470524
}
471525

472526
// EnterAnonymous_block is called when entering an anonymous_block rule
473527
func (l *StatementListener) EnterAnonymous_block(ctx *gen.Anonymous_blockContext) {
528+
// Increment the block depth counter
529+
l.plsqlBlockDepth++
530+
531+
// Skip adding the statement if it's a nested block
532+
if l.plsqlBlockDepth > 1 {
533+
return
534+
}
535+
474536
// Get the start and stop tokens
475537
start := ctx.GetStart()
476538
stop := ctx.GetStop()
@@ -499,8 +561,19 @@ func (l *StatementListener) EnterAnonymous_block(ctx *gen.Anonymous_blockContext
499561
})
500562
}
501563

564+
// ExitAnonymous_block is called when exiting an anonymous_block rule
565+
func (l *StatementListener) ExitAnonymous_block(ctx *gen.Anonymous_blockContext) {
566+
// Decrement the block depth counter
567+
l.plsqlBlockDepth--
568+
}
569+
502570
// EnterTransaction_control_statements is called when entering a transaction_control_statements rule
503571
func (l *StatementListener) EnterTransaction_control_statements(ctx *gen.Transaction_control_statementsContext) {
572+
// Skip if we are inside a PL/SQL block
573+
if l.plsqlBlockDepth > 0 {
574+
return
575+
}
576+
504577
// Get the start and stop tokens
505578
start := ctx.GetStart()
506579
stop := ctx.GetStop()
@@ -540,6 +613,16 @@ func (l *StatementListener) EnterTransaction_control_statements(ctx *gen.Transac
540613
})
541614
}
542615

616+
// EnterBlock is called when entering a block statement rule
617+
func (l *StatementListener) EnterBlock(ctx *gen.BlockContext) {
618+
l.plsqlBlockDepth++
619+
}
620+
621+
// ExitBlock is called when exiting a block statement rule
622+
func (l *StatementListener) ExitBlock(ctx *gen.BlockContext) {
623+
l.plsqlBlockDepth--
624+
}
625+
543626
// getDeterminedStatementType identifies the type of SQL statement
544627
func getDeterminedStatementType(text string) string {
545628
text = strings.ToUpper(strings.TrimSpace(text))

internal/parser/parser_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,8 +99,8 @@ BEGIN
9999
COMMIT;
100100
END;
101101
`,
102-
expectedCount: 3, // Should include the PL/SQL block and also the UPDATE and COMMIT inside
103-
expectedTypes: []string{"PLSQL_BLOCK", "UPDATE", "COMMIT"},
102+
expectedCount: 1, // With PL/SQL block depth tracking, this is now a single statement
103+
expectedTypes: []string{"PLSQL_BLOCK"},
104104
expectedErrors: 0,
105105
},
106106
{

0 commit comments

Comments
 (0)