溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

PostgreSQL中的?Rules有什么作用

發(fā)布時間:2021-11-09 14:21:32 來源:億速云 閱讀:155 作者:iii 欄目:關(guān)系型數(shù)據(jù)庫

本篇內(nèi)容介紹了“PostgreSQL中的Rules有什么作用”的有關(guān)知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

Flex輸入文件由四部分組成:

%{
Declarations
%}
Definitions
%%
Rules
%%
User subroutines

Rules

在Flex的模式文件中,%%和%%之間的內(nèi)容被稱為規(guī)則(rules),每一行表示一條規(guī)則,每條規(guī)則由匹配模式(pattern)和 動作(action)組成。其中模式在前面,用正則表達(dá)式表示,動作在后面,即C代碼。每當(dāng)一個模式被匹配到時,后面的C代碼將被執(zhí)行。
Flex會將規(guī)則翻譯成名為yylex的函數(shù),該函數(shù)掃描輸入文件(默認(rèn)標(biāo)準(zhǔn)輸入),當(dāng)掃描到一個完整的、最長的、可以和某條規(guī)則的正則表達(dá)式所匹配的輸入時,函數(shù)會執(zhí)行此規(guī)則后面的C代碼。如果代碼中沒有return語句,則執(zhí)行完畢后,yylex會繼續(xù)運行,開始下一輪的掃描和匹配。注意:當(dāng)有多條規(guī)則的模式被匹配到時, yylex會優(yōu)先選擇匹配長度最長的那條規(guī)則,如果有匹配長度相等的規(guī)則,則選擇排在最前面的那條規(guī)則。

PG中的規(guī)則定義如下:

%%
{whitespace}    {
                    //--------- 空白字符
                    //忽略,不作任何處理
                    /* ignore */
                }
{xcstart}        {
                    //--------- C風(fēng)格注釋
                    /* Set location in case of syntax error in comment */
                    //設(shè)置位置,以防注釋中的語法錯誤
                    SET_YYLLOC();
                    //深度
                    yyextra->xcdepth = 0;
                    //進(jìn)入xc狀態(tài)
                    BEGIN(xc);
                    /* Put back any characters past slash-star; see above */
                    //把斜杠星后的字符放回去
                    // 注意:"/*"是2個字符,從位置2(偏移從0起算)開始把之后的字符放回去
                    yyless(2);
                }
<xc>{xcstart}    {
                    //遇到下一層的注釋,深度+1
                    (yyextra->xcdepth)++;
                    /* Put back any characters past slash-star; see above */
                    //類似的,把之后的字符放回去
                    yyless(2);
                }
<xc>{xcstop}    {
                    //層次≤0,回到INITIAL狀態(tài),否則層次減1
                    if (yyextra->xcdepth <= 0)
                        BEGIN(INITIAL);
                    else
                        (yyextra->xcdepth)--;
                }
<xc>{xcinside}    {
                    //注釋里面的內(nèi)容,忽略
                    /* ignore */
                }
<xc>{op_chars}    {
                    //注釋里面的內(nèi)容,忽略
                    /* ignore */
                }
<xc>\*+            {
                    //注釋里面的內(nèi)容,忽略
                    /* ignore */
                }
<xc><<EOF>>        { yyerror("unterminated /* comment"); }//遇到結(jié)束符,出錯
{xbstart}        {
                    /* Binary bit type.
                     * At some point we should simply pass the string
                     * forward to the parser and label it there.
                     * In the meantime, place a leading "b" on the string
                     * to mark it for the input routine as a binary string.
                     */
                    //--------- 二進(jìn)制位串
                    //在某些點上,我們應(yīng)該簡單的把字符串向前傳遞給解析器并標(biāo)記它
                    //在此期間,設(shè)置一個打頭的字符"b"以標(biāo)記該輸入為二進(jìn)制串
                    SET_YYLLOC();
                    BEGIN(xb);
                    startlit();
                    addlitchar('b', yyscanner);
                }
<xb>{quotestop}    |
<xb>{quotefail} {
                    yyless(1);
                    BEGIN(INITIAL);
                    yylval->str = litbufdup(yyscanner);
                    return BCONST;
                }
<xh>{xhinside}    |
<xb>{xbinside}    {
                    addlit(yytext, yyleng, yyscanner);
                }
<xh>{quotecontinue}    |
<xb>{quotecontinue}    {
                    /* ignore */
                }
<xb><<EOF>>        { yyerror("unterminated bit string literal"); }
{xhstart}        {
                    //------------- 十六進(jìn)制串
                    /* Hexadecimal bit type.
                     * At some point we should simply pass the string
                     * forward to the parser and label it there.
                     * In the meantime, place a leading "x" on the string
                     * to mark it for the input routine as a hex string.
                     */
                    SET_YYLLOC();
                    BEGIN(xh);
                    startlit();
                    addlitchar('x', yyscanner);
                }
<xh>{quotestop}    |
<xh>{quotefail} {
                    yyless(1);
                    BEGIN(INITIAL);
                    yylval->str = litbufdup(yyscanner);
                    return XCONST;
                }
<xh><<EOF>>        { yyerror("unterminated hexadecimal string literal"); }
{xnstart}        {
                    //------------- 國家字符
                    /* National character.
                     * We will pass this along as a normal character string,
                     * but preceded with an internally-generated "NCHAR".
                     */
                    const ScanKeyword *keyword;
                    SET_YYLLOC();
                    yyless(1);    /* eat only 'n' this time */
                    keyword = ScanKeywordLookup("nchar",
                                                yyextra->keywords,
                                                yyextra->num_keywords);
                    if (keyword != NULL)
                    {
                        yylval->keyword = keyword->name;
                        return keyword->value;
                    }
                    else
                    {
                        /* If NCHAR isn't a keyword, just return "n" */
                        yylval->str = pstrdup("n");
                        return IDENT;
                    }
                }
{xqstart}        {
                    yyextra->warn_on_first_escape = true;
                    yyextra->saw_non_ascii = false;
                    SET_YYLLOC();
                    if (yyextra->standard_conforming_strings)
                        BEGIN(xq);
                    else
                        BEGIN(xe);
                    startlit();
                }
{xestart}        {
                    yyextra->warn_on_first_escape = false;
                    yyextra->saw_non_ascii = false;
                    SET_YYLLOC();
                    BEGIN(xe);
                    startlit();
                }
{xusstart}        {
                    SET_YYLLOC();
                    if (!yyextra->standard_conforming_strings)
                        ereport(ERROR,
                                (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                                 errmsg("unsafe use of string constant with Unicode escapes"),
                                 errdetail("String constants with Unicode escapes cannot be used when standard_conforming_strings is off."),
                                 lexer_errposition()));
                    BEGIN(xus);
                    startlit();
                }
<xq,xe>{quotestop}    |
<xq,xe>{quotefail} {
                    yyless(1);
                    BEGIN(INITIAL);
                    /*
                     * check that the data remains valid if it might have been
                     * made invalid by unescaping any chars.
                     */
                    if (yyextra->saw_non_ascii)
                        pg_verifymbstr(yyextra->literalbuf,
                                       yyextra->literallen,
                                       false);
                    yylval->str = litbufdup(yyscanner);
                    return SCONST;
                }
<xus>{quotestop} |
<xus>{quotefail} {
                    /* throw back all but the quote */
                    yyless(1);
                    /* xusend state looks for possible UESCAPE */
                    BEGIN(xusend);
                }
<xusend>{whitespace} {
                    /* stay in xusend state over whitespace */
                }
<xusend><<EOF>> |
<xusend>{other} |
<xusend>{xustop1} {
                    /* no UESCAPE after the quote, throw back everything */
                    yyless(0);
                    BEGIN(INITIAL);
                    yylval->str = litbuf_udeescape('\\', yyscanner);
                    return SCONST;
                }
<xusend>{xustop2} {
                    /* found UESCAPE after the end quote */
                    BEGIN(INITIAL);
                    if (!check_uescapechar(yytext[yyleng - 2]))
                    {
                        SET_YYLLOC();
                        ADVANCE_YYLLOC(yyleng - 2);
                        yyerror("invalid Unicode escape character");
                    }
                    yylval->str = litbuf_udeescape(yytext[yyleng - 2],
                                                   yyscanner);
                    return SCONST;
                }
<xq,xe,xus>{xqdouble} {
                    addlitchar('\'', yyscanner);
                }
<xq,xus>{xqinside}  {
                    addlit(yytext, yyleng, yyscanner);
                }
<xe>{xeinside}  {
                    addlit(yytext, yyleng, yyscanner);
                }
<xe>{xeunicode} {
                    pg_wchar    c = strtoul(yytext + 2, NULL, 16);
                    check_escape_warning(yyscanner);
                    if (is_utf16_surrogate_first(c))
                    {
                        yyextra->utf16_first_part = c;
                        BEGIN(xeu);
                    }
                    else if (is_utf16_surrogate_second(c))
                        yyerror("invalid Unicode surrogate pair");
                    else
                        addunicode(c, yyscanner);
                }
<xeu>{xeunicode} {
                    pg_wchar    c = strtoul(yytext + 2, NULL, 16);
                    if (!is_utf16_surrogate_second(c))
                        yyerror("invalid Unicode surrogate pair");
                    c = surrogate_pair_to_codepoint(yyextra->utf16_first_part, c);
                    addunicode(c, yyscanner);
                    BEGIN(xe);
                }
<xeu>.            { yyerror("invalid Unicode surrogate pair"); }
<xeu>\n            { yyerror("invalid Unicode surrogate pair"); }
<xeu><<EOF>>    { yyerror("invalid Unicode surrogate pair"); }
<xe,xeu>{xeunicodefail}    {
                    ereport(ERROR,
                            (errcode(ERRCODE_INVALID_ESCAPE_SEQUENCE),
                             errmsg("invalid Unicode escape"),
                             errhint("Unicode escapes must be \\uXXXX or \\UXXXXXXXX."),
                             lexer_errposition()));
                }
<xe>{xeescape}  {
                    if (yytext[1] == '\'')
                    {
                        if (yyextra->backslash_quote == BACKSLASH_QUOTE_OFF ||
                            (yyextra->backslash_quote == BACKSLASH_QUOTE_SAFE_ENCODING &&
                             PG_ENCODING_IS_CLIENT_ONLY(pg_get_client_encoding())))
                            ereport(ERROR,
                                    (errcode(ERRCODE_NONSTANDARD_USE_OF_ESCAPE_CHARACTER),
                                     errmsg("unsafe use of \\' in a string literal"),
                                     errhint("Use '' to write quotes in strings. \\' is insecure in client-only encodings."),
                                     lexer_errposition()));
                    }
                    check_string_escape_warning(yytext[1], yyscanner);
                    addlitchar(unescape_single_char(yytext[1], yyscanner),
                               yyscanner);
                }
<xe>{xeoctesc}  {
                    unsigned char c = strtoul(yytext + 1, NULL, 8);
                    check_escape_warning(yyscanner);
                    addlitchar(c, yyscanner);
                    if (c == '\0' || IS_HIGHBIT_SET(c))
                        yyextra->saw_non_ascii = true;
                }
<xe>{xehexesc}  {
                    unsigned char c = strtoul(yytext + 2, NULL, 16);
                    check_escape_warning(yyscanner);
                    addlitchar(c, yyscanner);
                    if (c == '\0' || IS_HIGHBIT_SET(c))
                        yyextra->saw_non_ascii = true;
                }
<xq,xe,xus>{quotecontinue} {
                    /* ignore */
                }
<xe>.            {
                    /* This is only needed for \ just before EOF */
                    addlitchar(yytext[0], yyscanner);
                }
<xq,xe,xus><<EOF>>        { yyerror("unterminated quoted string"); }
{dolqdelim}        {
                    SET_YYLLOC();
                    yyextra->dolqstart = pstrdup(yytext);
                    BEGIN(xdolq);
                    startlit();
                }
{dolqfailed}    {
                    SET_YYLLOC();
                    /* throw back all but the initial "$" */
                    yyless(1);
                    /* and treat it as {other} */
                    return yytext[0];
                }
<xdolq>{dolqdelim} {
                    if (strcmp(yytext, yyextra->dolqstart) == 0)
                    {
                        pfree(yyextra->dolqstart);
                        yyextra->dolqstart = NULL;
                        BEGIN(INITIAL);
                        yylval->str = litbufdup(yyscanner);
                        return SCONST;
                    }
                    else
                    {
                        /*
                         * When we fail to match $...$ to dolqstart, transfer
                         * the $... part to the output, but put back the final
                         * $ for rescanning.  Consider $delim$...$junk$delim$
                         */
                        addlit(yytext, yyleng - 1, yyscanner);
                        yyless(yyleng - 1);
                    }
                }
<xdolq>{dolqinside} {
                    addlit(yytext, yyleng, yyscanner);
                }
<xdolq>{dolqfailed} {
                    addlit(yytext, yyleng, yyscanner);
                }
<xdolq>.        {
                    /* This is only needed for $ inside the quoted text */
                    addlitchar(yytext[0], yyscanner);
                }
<xdolq><<EOF>>    { yyerror("unterminated dollar-quoted string"); }
{xdstart}        {
                    SET_YYLLOC();
                    BEGIN(xd);
                    startlit();
                }
{xuistart}        {
                    SET_YYLLOC();
                    BEGIN(xui);
                    startlit();
                }
<xd>{xdstop}    {
                    char       *ident;
                    BEGIN(INITIAL);
                    if (yyextra->literallen == 0)
                        yyerror("zero-length delimited identifier");
                    ident = litbufdup(yyscanner);
                    if (yyextra->literallen >= NAMEDATALEN)
                        truncate_identifier(ident, yyextra->literallen, true);
                    yylval->str = ident;
                    return IDENT;
                }
<xui>{dquote} {
                    yyless(1);
                    /* xuiend state looks for possible UESCAPE */
                    BEGIN(xuiend);
                }
<xuiend>{whitespace} {
                    /* stay in xuiend state over whitespace */
                }
<xuiend><<EOF>> |
<xuiend>{other} |
<xuiend>{xustop1} {
                    /* no UESCAPE after the quote, throw back everything */
                    char       *ident;
                    int            identlen;
                    yyless(0);
                    BEGIN(INITIAL);
                    if (yyextra->literallen == 0)
                        yyerror("zero-length delimited identifier");
                    ident = litbuf_udeescape('\\', yyscanner);
                    identlen = strlen(ident);
                    if (identlen >= NAMEDATALEN)
                        truncate_identifier(ident, identlen, true);
                    yylval->str = ident;
                    return IDENT;
                }
<xuiend>{xustop2}    {
                    /* found UESCAPE after the end quote */
                    char       *ident;
                    int            identlen;
                    BEGIN(INITIAL);
                    if (yyextra->literallen == 0)
                        yyerror("zero-length delimited identifier");
                    if (!check_uescapechar(yytext[yyleng - 2]))
                    {
                        SET_YYLLOC();
                        ADVANCE_YYLLOC(yyleng - 2);
                        yyerror("invalid Unicode escape character");
                    }
                    ident = litbuf_udeescape(yytext[yyleng - 2], yyscanner);
                    identlen = strlen(ident);
                    if (identlen >= NAMEDATALEN)
                        truncate_identifier(ident, identlen, true);
                    yylval->str = ident;
                    return IDENT;
                }
<xd,xui>{xddouble}    {
                    addlitchar('"', yyscanner);
                }
<xd,xui>{xdinside}    {
                    addlit(yytext, yyleng, yyscanner);
                }
<xd,xui><<EOF>>        { yyerror("unterminated quoted identifier"); }
{xufailed}    {
                    char       *ident;
                    SET_YYLLOC();
                    /* throw back all but the initial u/U */
                    yyless(1);
                    /* and treat it as {identifier} */
                    ident = downcase_truncate_identifier(yytext, yyleng, true);
                    yylval->str = ident;
                    return IDENT;
                }
{typecast}        {
                    SET_YYLLOC();
                    return TYPECAST;
                }
{dot_dot}        {
                    SET_YYLLOC();
                    return DOT_DOT;
                }
{colon_equals}    {
                    SET_YYLLOC();
                    return COLON_EQUALS;
                }
{equals_greater} {
                    SET_YYLLOC();
                    return EQUALS_GREATER;
                }
{less_equals}    {
                    SET_YYLLOC();
                    return LESS_EQUALS;
                }
{greater_equals} {
                    SET_YYLLOC();
                    return GREATER_EQUALS;
                }
{less_greater}    {
                    /* We accept both "<>" and "!=" as meaning NOT_EQUALS */
                    SET_YYLLOC();
                    return NOT_EQUALS;
                }
{not_equals}    {
                    /* We accept both "<>" and "!=" as meaning NOT_EQUALS */
                    SET_YYLLOC();
                    return NOT_EQUALS;
                }
{self}            {
                    SET_YYLLOC();
                    return yytext[0];
                }
{operator}        {
                    /*
                     * Check for embedded slash-star or dash-dash; those
                     * are comment starts, so operator must stop there.
                     * Note that slash-star or dash-dash at the first
                     * character will match a prior rule, not this one.
                     */
                    int            nchars = yyleng;
                    char       *slashstar = strstr(yytext, "/*");
                    char       *dashdash = strstr(yytext, "--");
                    if (slashstar && dashdash)
                    {
                        /* if both appear, take the first one */
                        if (slashstar > dashdash)
                            slashstar = dashdash;
                    }
                    else if (!slashstar)
                        slashstar = dashdash;
                    if (slashstar)
                        nchars = slashstar - yytext;
                    /*
                     * For SQL compatibility, '+' and '-' cannot be the
                     * last char of a multi-char operator unless the operator
                     * contains chars that are not in SQL operators.
                     * The idea is to lex '=-' as two operators, but not
                     * to forbid operator names like '?-' that could not be
                     * sequences of SQL operators.
                     */
                    if (nchars > 1 &&
                        (yytext[nchars - 1] == '+' ||
                         yytext[nchars - 1] == '-'))
                    {
                        int            ic;
                        for (ic = nchars - 2; ic >= 0; ic--)
                        {
                            char c = yytext[ic];
                            if (c == '~' || c == '!' || c == '@' ||
                                c == '#' || c == '^' || c == '&' ||
                                c == '|' || c == '`' || c == '?' ||
                                c == '%')
                                break;
                        }
                        if (ic < 0)
                        {
                            /*
                             * didn't find a qualifying character, so remove
                             * all trailing [+-]
                             */
                            do {
                                nchars--;
                            } while (nchars > 1 &&
                                 (yytext[nchars - 1] == '+' ||
                                  yytext[nchars - 1] == '-'));
                        }
                    }
                    SET_YYLLOC();
                    if (nchars < yyleng)
                    {
                        /* Strip the unwanted chars from the token */
                        yyless(nchars);
                        /*
                         * If what we have left is only one char, and it's
                         * one of the characters matching "self", then
                         * return it as a character token the same way
                         * that the "self" rule would have.
                         */
                        if (nchars == 1 &&
                            strchr(",()[].;:+-*/%^<>=", yytext[0]))
                            return yytext[0];
                        /*
                         * Likewise, if what we have left is two chars, and
                         * those match the tokens ">=", "<=", "=>", "<>" or
                         * "!=", then we must return the appropriate token
                         * rather than the generic Op.
                         */
                        if (nchars == 2)
                        {
                            if (yytext[0] == '=' && yytext[1] == '>')
                                return EQUALS_GREATER;
                            if (yytext[0] == '>' && yytext[1] == '=')
                                return GREATER_EQUALS;
                            if (yytext[0] == '<' && yytext[1] == '=')
                                return LESS_EQUALS;
                            if (yytext[0] == '<' && yytext[1] == '>')
                                return NOT_EQUALS;
                            if (yytext[0] == '!' && yytext[1] == '=')
                                return NOT_EQUALS;
                        }
                    }
                    /*
                     * Complain if operator is too long.  Unlike the case
                     * for identifiers, we make this an error not a notice-
                     * and-truncate, because the odds are we are looking at
                     * a syntactic mistake anyway.
                     */
                    if (nchars >= NAMEDATALEN)
                        yyerror("operator too long");
                    yylval->str = pstrdup(yytext);
                    return Op;
                }
{param}            {
                    SET_YYLLOC();
                    yylval->ival = atol(yytext + 1);
                    return PARAM;
                }
{integer}        {
                    SET_YYLLOC();
                    return process_integer_literal(yytext, yylval);
                }
{decimal}        {
                    SET_YYLLOC();
                    yylval->str = pstrdup(yytext);
                    return FCONST;
                }
{decimalfail}    {
                    /* throw back the .., and treat as integer */
                    yyless(yyleng - 2);
                    SET_YYLLOC();
                    return process_integer_literal(yytext, yylval);
                }
{real}            {
                    SET_YYLLOC();
                    yylval->str = pstrdup(yytext);
                    return FCONST;
                }
{realfail1}        {
                    /*
                     * throw back the [Ee], and treat as {decimal}.  Note
                     * that it is possible the input is actually {integer},
                     * but since this case will almost certainly lead to a
                     * syntax error anyway, we don't bother to distinguish.
                     */
                    yyless(yyleng - 1);
                    SET_YYLLOC();
                    yylval->str = pstrdup(yytext);
                    return FCONST;
                }
{realfail2}        {
                    /* throw back the [Ee][+-], and proceed as above */
                    yyless(yyleng - 2);
                    SET_YYLLOC();
                    yylval->str = pstrdup(yytext);
                    return FCONST;
                }
{identifier}    {
                    //---------- 標(biāo)識符
                    const ScanKeyword *keyword;
                    char       *ident;
                    SET_YYLLOC();
                    /* Is it a keyword? */
                    //是否關(guān)鍵字?
                    keyword = ScanKeywordLookup(yytext,
                                                yyextra->keywords,
                                                yyextra->num_keywords);
                    if (keyword != NULL)
                    {
                        //是,則返回關(guān)鍵字值
                        yylval->keyword = keyword->name;
                        return keyword->value;
                    }
                    /*
                     * No.  Convert the identifier to lower case, and truncate
                     * if necessary.
                     */
                    //如果不是關(guān)鍵字,則設(shè)置為小寫字母,如需要則截斷
                    ident = downcase_truncate_identifier(yytext, yyleng, true);
                    yylval->str = ident;
                    return IDENT;
                }
{other}            {
                    SET_YYLLOC();
                    return yytext[0];
                }
<<EOF>>            {
                    SET_YYLLOC();
                    yyterminate();
                }
%%

“PostgreSQL中的Rules有什么作用”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實用文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI