-2

I'm trying to build a regex that will identify parameters inside brackets and ignore pl/sql comments (single line --, and multiple lines /* */)

For instance:

create or replace table_name   ---sfjdslkfjslkfjslkfjdsfsdf

**(var1 in out number, var2 number)**

/* sdfls 
sfdsd jfs
 sfs f
sd f
sfsf */

AS 

BEGIN

(var1 in out number, var2 number) should be matched only. It should also account for cases where:

  • There are not comments (single or multiple lines)
  • There are only single line comments either before or after the parameters
  • There are only multiple line comments either before or after the parameters
  • There are no parameters

Assumptions:

  • Parameters are always enclosed in brackets ()
  • Procedures can sometimes have no parameters but have comments (either single or multiple line comments) before the AS BEGIN clause
  • Procedures start with create or replace table_name
  • We're only interested to read the until the AS BEGIN clause

In other words, I need to find the index of the first opening bracket '(' that is outside any comments (single or multiple lines) and that comes before the AS BEGIN clause.

UPDATE:

I have managed to match the comments using the following regex:

(?:\/\*(?:[\s\S]*?)\*\/)|(?:\-\-(?:.*)$)

For instance here it will match all the comments:

create or replace table_name 

-- sdlfksl kjs slkjslds js

/* lsdjfdkj 
s fskjfs
 sf sf
 sdf;;''
sfs fs
 */

 (hello number, var2 number)

 --sdflksf

 /*sl --sdflks s kdjfls())({fsfs */


AS

BEGIN

I can do this now in Java to identify the first opening bracket outside of any matching group. However it would be easier if I could just ignore the matching group and match the one parameters in the brackets only instead.

EDIT

This is not asking for a solution with pl/sql or sqlplus or whatever. I have a few pl/sql procedures stored in files that I need to modify and add new parameters to. I'm using Java to do that and inside Java im using a combination of loops and regexs.

bytebiscuit
  • 3,446
  • 10
  • 33
  • 53
  • 1
    Query `USER_ARGUMENTS` view. See my answer. – Lalit Kumar B Feb 20 '15 at 10:25
  • Why to do want to do that in PL/SQL? Implementing parsers in PL/SQL is PITA. Also I doubt it can be done using Regex, the calling convention is not so simple. I'm afraid you will need a real parser. – ibre5041 Feb 20 '15 at 11:27
  • Check this project: https://github.com/porcelli/plsql-parser. And use "only" generated lexer. Then iterate over tokens returned from this lexer. – ibre5041 Feb 20 '15 at 11:30
  • See Oracle SQL reference for possible procedure parameter declarations: https://docs.oracle.com/database/121/LNPLS/formal_parameter.htm#LNPLS1271 – ibre5041 Feb 20 '15 at 11:39
  • Saw your edit in the question. What is the guarantee that the PL/SQL program would compile successfully after you add the new parameters by your method? – Lalit Kumar B Feb 20 '15 at 12:28
  • I don't see how that is relevant to solving this question. – bytebiscuit Feb 20 '15 at 12:35
  • Up to you. I gave you a solution to find the arguments of a procedure. Your requirement in the questions states *I'm trying to build a regex that will identify parameters inside brackets and ignore pl/sql comments * – Lalit Kumar B Feb 20 '15 at 12:36
  • Yes and there are a number of other requirements on top of that and EDITs and UPDATEs. Thanks for the pl/sql arguments code but that does not help in this case. – bytebiscuit Feb 20 '15 at 12:40
  • I think this question could be better framed as a Java problem using regular expression. The edit conveys this as a "parting thought", yet the tools to use, Java and regular expressions, are central to what you consider a solution. – Patrick Bacon Feb 20 '15 at 15:13

2 Answers2

0

Not sure why you want to reinvent the wheel. In Oracle, you could use the *_ARGUMENTS view to get the list of all the arguments.

For example,

SQL> CREATE OR REPLACE
  2  PROCEDURE p(
  3      in_date  DATE,
  4      out_text VARCHAR2)
  5  AS
  6  BEGIN
  7    NULL;
  8  END;
  9  /

Procedure created.

SQL>
SQL> SELECT object_name,
  2    package_name,
  3    argument_name,
  4    position,
  5    data_type
  6  FROM USER_ARGUMENTS
  7  WHERE OBJECT_NAME = 'P';

OBJECT_NAM PACKAGE_NA ARGUMENT_NAME     POSITION DATA_TYPE
---------- ---------- --------------- ---------- ---------
P                     OUT_TEXT                 2 VARCHAR2
P                     IN_DATE                  1 DATE

SQL>
Lalit Kumar B
  • 47,486
  • 13
  • 97
  • 124
  • this is about editing a few pl/sql scripts. I am putting some new parameters and I need to identify the parameters with brackets first, get the index of the first opening bracket that is outside any comments and insert the new parameters there. – bytebiscuit Feb 20 '15 at 10:26
  • That's my whole question. Why do you want to do all that manually? You will get the arguments anyway using the method I suggested. – Lalit Kumar B Feb 20 '15 at 12:12
  • Im not interested in the existing arguments. I need to add new ones to the pl/sql files that are stored locally. I'm opening each file in Java and I'm trying to programmatially add new parameters to each procedure. To do that you need to account for the things I've mentioned in my original question. There thousands of files, hence the need to this programmatically. – bytebiscuit Feb 20 '15 at 12:25
  • Ok. I tried to help you with your initial requirement :-, *I'm trying to build a regex that will identify parameters inside brackets and ignore pl/sql comments* I hope it is useful to you. Not sure if you have downvoted or someone else, but I bet this is the best methid to know the arguments to your PL/SQL programs. I wish I could help you with what you need further, however, I am sorry I don't understand the requirement. Mark it as answered if you think it is worth helpful. Good luck! – Lalit Kumar B Feb 20 '15 at 15:33
0

I'm unfamiliar with Oracle's flavor of regexes, but I made a pattern that works in most regex-engines. I know MySQL has a wildly different syntax so this is quite possibly also the case in Oracle, but the general idea is this:

create or replace table_name(?:(?!AS\s+BEGIN)(?:--[^\n]*(?:\n|$)|\/\*(?:[^*]|\*(?!\/))*\*\/|(?!\/\*|--)[^(]))*\(([^)]+)

Regular expression visualization

Debuggex Demo

It's a "match this except in contexts A, B or C" approach also used here and explained in depth in this SO answer. Combined with the requirement that whatever we're matching isn't followed by AS\s+BEGIN.

You can see in the Debuggex Demo that the correct part between brackets is matched in capture group 1. As well, the 2nd create doesn't have parameters, and indeed nothing is matched (even though there's brackets in comments and after the AS BEGIN.

The task at hand is porting this to Oracle's regex flavor.

Community
  • 1
  • 1
asontu
  • 4,548
  • 1
  • 21
  • 29