Проверка данных, которые «очень похожи» на предложение where - PullRequest
1 голос
/ 24 июня 2011

Я работаю над логикой проверки пользовательского ввода в отношении того, что довольно близко к предложению 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 голосов
/ 10 июля 2011

Решение, которое я наткнулся на себя, которое, как я думал, может пригодиться кому-то еще, поскольку я видел других людей с похожими вопросами ...

Если ваше предложение отформатировано как SQL, гдеВы можете проверить это предложение, сделав вызов к базе данных, используя процедуру, которая выглядит следующим образом:

SET PARSE ONLY

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

Если это проходит без ошибок, у вас есть действительное предложение sql where ...

Надеюсь, это кому-нибудь поможет.

0 голосов
/ 24 июня 2011

ПРИМЕЧАНИЕ: В ситуациях, когда пользователю необходимо сделать заявление, например: (A == B AND B != C OR (A == B OR (A == C))), ваше решение будет работать только в том случае, если вы предоставите пользователю больше опций в выпадающих списках левых и правых скобок,В раскрывающемся списке левых скобок должны быть указаны следующие параметры: '(', '((', '(((', '((((', и вы можете выделить его в 4 левых скобках подряд.Выпадающие правые скобки должны выглядеть одинаково.

Вы можете поместить свои выпадающие списки в репитер, чтобы .Net назначал каждому выпадающему уникальный идентификатор.

Код проверки:

// 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

Вы можете сделать так, чтобы была включена самая последняя строка повторителя, а все предыдущие строки были отключены, что вынуждает пользователя удалять каждую самую последнюю строку до теххочу редактировать становится активным.Это упрощает валидацию, потому что вас интересует только самая последняя строка, зная, что все предыдущие строки были проверены.Когда самая последняя строка является допустимой, будет безопасно запускать всю строку в качестве предложения SQL WHERE.

ПРИМЕЧАНИЕ: Если вы заблокируете предыдущие строки, как я предложил, то когдаПользователь удаляет самую последнюю строку, вам нужно будет проверить значение numUnclosedLeftBrackets, и для этого может потребоваться несколько иной подход, такой как: сохранение индекса строки повторителя для каждой строки, содержащей незакрытую левую скобку.

...