Skip to content

Commit 8c3a06a

Browse files
yahondaclaude
andcommitted
Fix multiline constant declaration in packages (rsim#207)
The regex in Variable.find required the semicolon to be on the same line as the variable declaration. On Oracle 19c, sys.dbms_db_version wraps the assignment to the next line: version constant pls_integer := 19; Make the semicolon and trailing assignment optional in the regex so the type name is matched regardless of line wrapping. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 412d59e commit 8c3a06a

2 files changed

Lines changed: 51 additions & 1 deletion

File tree

lib/plsql/variable.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@ def find(schema, variable, package, override_schema_name = nil)
99
AND type = 'PACKAGE'
1010
AND UPPER(text) LIKE :variable_name",
1111
override_schema_name || schema.schema_name, package, "%#{variable_upcase}%").each do |row|
12-
if row[0] =~ /^\s*#{variable_upcase}\s+(CONSTANT\s+)?([A-Z0-9_. %]+(\([\w\s,]+\))?)\s*(NOT\s+NULL)?\s*((:=|DEFAULT).*)?;\s*(--.*)?$/i
12+
if row[0] =~ /^\s*#{variable_upcase}\s+(CONSTANT\s+)?([A-Z0-9_. %]+(\([\w\s,]+\))?)\s*(NOT\s+NULL)?\s*((:=|DEFAULT).*)?;\s*(--.*)?$/i ||
13+
row[0] =~ /^\s*#{variable_upcase}\s+(CONSTANT\s+)?([A-Z0-9_. %]+(\([\w\s,]+\))?)\s*(NOT\s+NULL)?\s*(:=|DEFAULT)\s*$/i
1314
return new(schema, variable, package, $2.strip, override_schema_name)
1415
end
1516
end

spec/plsql/variable_spec.rb

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,55 @@
340340

341341
end
342342

343+
describe "constants with multiline declaration" do
344+
before(:all) do
345+
plsql.connect! CONNECTION_PARAMS
346+
plsql.execute "DROP PACKAGE test_multiline_pkg" rescue nil
347+
plsql.execute <<-SQL
348+
CREATE OR REPLACE PACKAGE test_multiline_pkg IS
349+
multiline_constant CONSTANT PLS_INTEGER :=
350+
42;
351+
END;
352+
SQL
353+
plsql.execute <<-SQL
354+
CREATE OR REPLACE PACKAGE BODY test_multiline_pkg IS
355+
END;
356+
SQL
357+
end
358+
359+
after(:all) do
360+
plsql.execute "DROP PACKAGE test_multiline_pkg" rescue nil
361+
plsql.logoff
362+
end
363+
364+
it "should get constant with multiline assignment" do
365+
expect(plsql.test_multiline_pkg.multiline_constant).to eq(42)
366+
end
367+
368+
it "should not match RECORD field as a variable" do
369+
plsql.execute "DROP PACKAGE test_record_field_pkg" rescue nil
370+
plsql.execute <<-SQL
371+
CREATE OR REPLACE PACKAGE test_record_field_pkg IS
372+
TYPE t_rec IS RECORD (
373+
some_field NUMBER,
374+
last_field VARCHAR2(50)
375+
);
376+
rec_var t_rec;
377+
END;
378+
SQL
379+
plsql.execute <<-SQL
380+
CREATE OR REPLACE PACKAGE BODY test_record_field_pkg IS
381+
END;
382+
SQL
383+
# last_field is the last field in the RECORD (no trailing comma),
384+
# which could falsely match as a variable if the semicolon is optional
385+
expect {
386+
plsql.test_record_field_pkg.last_field
387+
}.to raise_error(/No PL\/SQL procedure or variable 'LAST_FIELD' found/)
388+
plsql.execute "DROP PACKAGE test_record_field_pkg" rescue nil
389+
end
390+
end
391+
343392
describe "object type" do
344393
before(:all) do
345394
plsql.connect! CONNECTION_PARAMS

0 commit comments

Comments
 (0)