In something like the following code I'm wanting to pull out just the function that has more than one parameter, and want to ignore coalesce that has 2 parameters. Please help I've been working on this for a couple of days using REGEX and think that it's possible just not something that I have been able to wrap my head around. I believe that the answer is a group and the parsing that group with a sub regex or something to that effect.
AND NOT COALESCE(UPPER(FUNCTION_TO_FIND(B.PARAM, B.TEST_PARAM1, B.TEST_PARAM2, B.TEST_PARAM3,'Routine Type', ATT_TO_DATE())),'NO_VALUE') IN (UPPER('Routine Appointment Letter'))
AND NOT UPPER(DBO.FUNCTION_TO_FIND( B.PARAM , B.TEST_PARAM1 , B.TEST_PARAM2, B.TEST_PARAM3,'Routine Type', ATT_TO_DATE())) IN (UPPER('Routine Appointment Letter'))
AND NOT COALESCE(1, 3) = 2
I would expect to find
DBO.FUNCTION_TO_FIND( B.PARAM , B.TEST_PARAM1 , B.TEST_PARAM2, B.TEST_PARAM3,'Routine Type', ATT_TO_DATE())
and
FUNCTION_TO_FIND(B.PARAM, B.TEST_PARAM1, B.TEST_PARAM2, B.TEST_PARAM3,'Routine Type', ATT_TO_DATE())
Please note that the functions will not always be the same number of layers down, but they will all have more than 2 parameters.
I have tried different versions and edits of the following balanced parenthesis function but haven't been able to have it count the parameters properly to capture the entire function.
(\((?>[^()]|(?1))*\))
EDITS, CLARIFICATION BELOW
EDIT1 : Please note that when looking for functions I will not have access to the server that the SQL will be run against, this has to be done completely offline.
EDIT2 : Thinking about this further I think that this is a problem to solve in a couple parts, instead of one regex, using another tool to create regex on the fly.
- Create a list of functions that I don't want to find that are common TO_CHAR, TO_NUMBER, UPPER, LOWER, COALESCE, MIN, MAX, AND, EXISTS, COALESCE, SUM, FROM
- Find the start of any function that is used within the query string, using something like the following.
[[:alnum:]][^)( \r\n]+?\s*?\(
- Back up one character in the string and use the following code to find the matched parenthesis.
(\((?>[^()]|(?1))*\))
- ...
I will try something to the effect of above and come back with the answer. In the mean time if someone has a different idea please feel free to contribute.
2条答案
按热度按时间xeufq47z1#
Ok, I gave it a try, and
Microsoft.SqlServer.Management.SqlParser.Parser
from theMicrosoft.SqlServer.SqlManagementObjects
nuget package might be the way to go.As a result of this,
selectSpec.Xml
contains a hierarchical XML document representing theSELECT
statement.The
SqlCodeObject
s provide anAccept()
method that implement the Visitor pattern. Write a visitor and evaluate expressions of the types you are interested in:SqlNullScalarExpression
,SqlUserDefinedScalarFunctionCallExpression
, maybe more.Be aware that the parser does not recognize user-defined functions without the
dbo.
schema:versus
5gfr0r5j2#
I used the following in c# mixed with regex to accomplish this task, yes it's very rough and could use some refinement but it does work. Feel free to improved the answer however I will not be able to provide ongoing support for the code below.