验证“非常类似于”where子句的数据

时间:2011-06-24 15:34:40

标签: .net regex parsing validation where-clause

我正在研究用户输入的验证逻辑,它非常接近sql where子句。

在页面上,用户可以从下拉列表的组合中进行选择(其中' - '字符代表最后一个句子中的空白字符):

DropDown1   DropDown2       DropDown3   DropDown4   DropDown5  DropDown6

-           -               -           -           -          -
(           SomeCriteria    =           Value       )          AND
                            <>                                 OR

不幸的是我对如何验证这个子句没有任何硬性要求,除了它应该'表现得像sql where子句':(

应该通过验证的一些

(Criteria = Value)
(criteria1 = Value1 OR Criteria2 <> value2)
(criteria1 = value1) AND (Criteria2 = value2)
(criteria1 = value1) OR (Criteria2 = value2 AND criteria3 = value3)

一些应该验证失败的人:

)Criteria = value) (first character is not  '(' )
(Criteria = value(  (last character is not  ')' )
((Criteria = value)  (# of '(' does not match # of ')' )

(Criteria = Value (AND Criteria1 = value1))  ( 'AND' and 'OR' should not be immediately preceded  or followed by a '('  or ')' character.

任何有关编写正则表达式以验证这些选择的帮助都将非常感激。在探讨之后,我看到其他人谈到sql解析器,这对于这个“受限制的”where子句来说是更好的解决方案吗?

2 个答案:

答案 0 :(得分:0)

注意:对于用户需要发表如下语句的情况:(A == B AND B != C OR (A == B OR (A == C))),只有在左侧括号下拉列表和右侧为用户提供更多选项时,您的解决方案才有效括号下拉列表。左括号下拉列表应包含以下选项:'(', '((', '(((', '((((',您可以在连续4个左括号中将其封闭。右括号下拉列表应该看起来一样。

您可以将您的下拉列表放在Repeater中,以便.Net为每个下拉列表分配一个唯一的ID。

验证码:

// this will keep track of left brackets that have not been closed
int numUnclosedLeftBrackets = 0;


// changing dropdown instance names for clarity
ddlLeftBracket == DropDown1;
ddlCriteria == DropDown2;
ddlConOperator == DropDown3;
ddlValue == DropDown4;
ddlRightBracket = DropDown5;
ddlExtension == DropDown6;

Boolean isValidStmt = false;
Boolean areValidBrackets = false;
Boolean addAnotherStmt = false;

// conditional operator dropdown cannot be blank
if(ddlConOperator.SelectedIndex > 0)
{
    if(ddlConOperator.SelectedValue == "=" && ddlCriteria.SelectedValue == ddlValue.SelectedValue)
        isValidStmt = true;
    if(ddlConOperator.SelectedValue == "<>" && ddlCriteria.SelectedValue != ddlValue.SelectedValue)
        isValidStmt = true;

    // check if both left and right brackets exist, or if both do not exist.
    if((ddlLeftBracket.SelectedIndex == 0 && ddlRightBracket.SelectedIndex == 0) || 
               (ddlLeftBracket.SelectedIndex > 0 && ddlRightBracket.SelectedIndex > 0)) 
        areValidBrackets = true;

    // check if AND, or OR is attached
    if(ddlExtension.SelectedIndex != 0)
    {
        addAnotherStmt = true;

        // check if brackets need to be validated now that the where clause will continue on
        if(!areValidBrackets) 
        {
            // check if left bracket but no right bracket
            if(ddlLeftBracket.SelectedIndex > 0 && ddlRightBracket.SelectedIndex == 0)
            {
                areValidBrackets = true;
                numUnclosedLeftBrackets += ddlLeftBracket.SelectedIndex;
            }
            // check if right bracket but no left bracket
            if(ddlLeftBracket.SelectedIndex == 0 && ddlRightBracket.SelectedIndex > 0)
            {
                // check if left bracket needs closing in a previous value/criteria row and make sure user is not trying to add more right closing brackets than allowed
                if(numUnclosedLeftBrackets > 0 && (numUnclosedLeftBrackets - ddlRightBracket.SelectedIndex) > -1)
                {
                    areValidBrackets = true;
                    numUnclosedLeftBrackets -= ddlRightBracket.SelectedIndex;
                }
            }
        }
    }
    else
    {
        // Since the user has not selected AND or OR, check that there are no unclosed left brackets remaining
        if(numUnclosedLeftBrackets > 0)
            areValidBrackets = false;
    }
}
if(!areValidBrackets)
    // brackets not valid
else
    if(!isValidStmt)
        // not a valid statement
    else
        if(addAnotherStmt)
            // create a new row
        else
            // finished and valid - allow saving valid 'WHERE clause' string

您可以将其设置为启用最新的转发器行并禁用所有先前的行,从而强制用户删除每个最新的行,直到他们要编辑的行变为启用状态。这简化了验证,b / c然后您只关心最近的行,知道所有先前的行都经过验证。当最新的行有效时,将整个字符串作为SQL WHERE子句运行是安全的。

注意:如果您像我建议的那样锁定以前的行,那么当用户删除最近的行时,您必须检查numUnclosedLeftBrackets的值,这可能需要稍微不同的方法,例如:为包含未关闭的左括号的每一行存储转发器行索引。

答案 1 :(得分:0)

我偶然发现自己的一个解决方案,我认为可能对其他人有用,因为我见过其他有类似问题的人......

如果您的子句的格式类似于sql where子句,则可以使用以下过程对数据库进行调用来验证它:

SET PARSE ONLY

SELECT 1
FROM sys.objects
WHERE [user generated clause]

如果没有任何错误,你有一个有效的sql where子句......

希望这有助于某人。