| /* -*-C++-*- |
| // @@@ START COPYRIGHT @@@ |
| // |
| // Licensed to the Apache Software Foundation (ASF) under one |
| // or more contributor license agreements. See the NOTICE file |
| // distributed with this work for additional information |
| // regarding copyright ownership. The ASF licenses this file |
| // to you under the Apache License, Version 2.0 (the |
| // "License"); you may not use this file except in compliance |
| // with the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, |
| // software distributed under the License is distributed on an |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| // KIND, either express or implied. See the License for the |
| // specific language governing permissions and limitations |
| // under the License. |
| // |
| // @@@ END COPYRIGHT @@@ |
| ***************************************************************************** |
| * |
| * File: ParNameLocList.cpp |
| * Description: definitions of non-inline methods for classes |
| * ParNameLoc and ParNameLocList |
| * |
| * Also contains the definition of global (file |
| * scope) functions relating to ParNameLocList |
| * or ParNameLocListPtr (defined in SqlParser.y). |
| * |
| * Created: 5/30/96 |
| * Language: C++ |
| * |
| * |
| * |
| * |
| ***************************************************************************** |
| */ |
| |
| #ifndef SQLPARSERGLOBALS_NAMES_AND_TOKENS |
| #define SQLPARSERGLOBALS_NAMES_AND_TOKENS |
| #endif |
| #ifndef SQLPARSERGLOBALS_CONTEXT_AND_DIAGS |
| #define SQLPARSERGLOBALS_CONTEXT_AND_DIAGS |
| #endif |
| #define SQLPARSERGLOBALS_NADEFAULTS |
| #include "SqlParserGlobals.h" |
| |
| #include "ComOperators.h" |
| #include "ComSmallDefs.h" |
| #include "CmpContext.h" |
| #include "ElemDDLConstraintCheck.h" |
| #include "StmtDDLCreateView.h" |
| #include "StmtDDLCreateTrigger.h" |
| #include "StmtDDLCreateMV.h" |
| #include "StmtDDLCreateTable.h" |
| |
| // ----------------------------------------------------------------------- |
| // definition of global (file scope) function ParInsertNameLoc() |
| // ----------------------------------------------------------------------- |
| |
| void ParInsertNameLoc(const StringPos namePos, const size_t nameLen) |
| { |
| if (ParNameLocListPtr NEQ NULL) |
| { |
| ParNameLocListPtr->insert(ParNameLoc(namePos, nameLen)); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| // definition of global (file scope) function ParInsertNameLocInOrder() |
| // ----------------------------------------------------------------------- |
| |
| void ParInsertNameLocInOrder(const StringPos namePos, const size_t nameLen) |
| { |
| if (ParNameLocListPtr NEQ NULL) |
| { |
| ParNameLocListPtr->insertInOrder(ParNameLoc(namePos, nameLen)); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| // definition of global (file scope) function ParInsertNameLocForStar() |
| // ----------------------------------------------------------------------- |
| |
| void ParInsertNameLocForStar(ColRefName * pColRefName) |
| { |
| if (ParNameLocListPtr EQU NULL) |
| { |
| return; |
| } |
| |
| const char *pInputStr = ParNameLocListPtr->getInputStringPtr(); |
| ComASSERT(pInputStr NEQ NULL); |
| |
| // |
| // Gets the position of the star (asterisk) |
| // from the ParScannedTokenQueue. Note that |
| // the parser may look ahead one token. |
| // So the most recently scanned token (with |
| // 0th index) may not be the star. If the |
| // 0th indexed token is not, then the -1th |
| // indexed token (the token scanned before |
| // the most-recently-scanned token) is. |
| // |
| |
| StringPos starPos; |
| const ParScannedTokenQueue::scannedTokenInfo &tokInfo |
| = ParScannedTokens->getScannedTokenInfo(0); |
| if (tokInfo.tokenStrLen EQU (size_t)1 AND |
| NAString(&pInputStr[tokInfo.tokenStrPos], (size_t)1) EQU "*") |
| { |
| starPos = tokInfo.tokenStrPos; |
| } |
| else |
| { |
| const ParScannedTokenQueue::scannedTokenInfo &prevTokInfo |
| = ParScannedTokens->getScannedTokenInfo(-1); |
| ComASSERT(prevTokInfo.tokenStrLen EQU (size_t)1 AND |
| NAString(&pInputStr[prevTokInfo.tokenStrPos], (size_t)1) EQU "*"); |
| starPos = prevTokInfo.tokenStrPos; |
| } |
| |
| pColRefName->setNamePosition(starPos, FALSE); |
| ComASSERT(!pColRefName->isDelimited()); |
| |
| ParNameLocListPtr->insert(ParNameLoc(starPos, 1/*star length*/)); |
| } |
| |
| // ----------------------------------------------------------------------- |
| // definitions of global (file scope) functions ParSetTextEndPos() |
| // ----------------------------------------------------------------------- |
| |
| NABoolean ParSetTextEndPos(ElemDDLConstraintCheck * pCkCnstrntNode) |
| { |
| ParNameLocList &nameLocList = pCkCnstrntNode->getNameLocList(); |
| const char *pInputStr = nameLocList.getInputStringPtr(); |
| ComASSERT(pInputStr NEQ NULL); |
| |
| const ParScannedTokenQueue::scannedTokenInfo *tokInfo |
| = ParScannedTokens->getScannedTokenInfoPtr(0); |
| NAString tokStr(&pInputStr[tokInfo->tokenStrPos], tokInfo->tokenStrLen); |
| |
| if (IsNAStringSpace(tokStr)) |
| { |
| tokInfo = ParScannedTokens->getScannedTokenInfoPtr(-1); |
| tokStr = NAString(&pInputStr[tokInfo->tokenStrPos], |
| tokInfo->tokenStrLen); |
| } |
| TrimNAStringSpace(tokStr); |
| if (tokStr NEQ ")") return TRUE; // syntax error |
| pCkCnstrntNode->setEndPosition(tokInfo->tokenStrPos + |
| tokInfo->tokenStrLen - 1); |
| return FALSE; // no error |
| } |
| |
| NABoolean ParSetTextEndPos(ElemDDLDivisionClause * pDivClauseParseNode) |
| { |
| if (pDivClauseParseNode == NULL) |
| return TRUE; // error |
| |
| ParNameLocList &nameLocList = pDivClauseParseNode->getNameLocList(); |
| const char *pInputStr = nameLocList.getInputStringPtr(); |
| ComASSERT(pInputStr NEQ NULL); |
| |
| // Case #1: |
| // TOK_DIVISION TOK_BY '(' sort_by_value_expression_list ')' ...current_position... |
| // |
| // Case #2: |
| // TOK_DIVISION TOK_BY '(' TOK_USING '(' sort_by_value_expression_list ')' ...current_position... |
| |
| Int32 tokIndex = 0; |
| const ParScannedTokenQueue::scannedTokenInfo * pTokInfo |
| = ParScannedTokens->getScannedTokenInfoPtr(tokIndex); |
| NAString tokStr((size_t)50); // pre-allocate 50-byte memory space |
| tokStr.append(&pInputStr[pTokInfo->tokenStrPos], pTokInfo->tokenStrLen); |
| TrimNAStringSpace(tokStr); |
| |
| while (ParScannedTokens->isQueueIndexWithinRange(tokIndex) AND tokStr NEQ ")") |
| { |
| tokIndex--; |
| if (ParScannedTokens->isQueueIndexOutOfRange(tokIndex)) |
| break; |
| // Go backward and skip over tokens until a right-parenthesis token found |
| pTokInfo = ParScannedTokens->getScannedTokenInfoPtr(tokIndex); |
| tokStr.replace(0, tokStr.length(), &pInputStr[pTokInfo->tokenStrPos], pTokInfo->tokenStrLen); |
| TrimNAStringSpace(tokStr); |
| } |
| if (ParScannedTokens->isQueueIndexOutOfRange(tokIndex) OR tokStr NEQ ")") |
| return TRUE; // syntax error |
| pDivClauseParseNode->setEndPosition(pTokInfo->tokenStrPos + |
| pTokInfo->tokenStrLen - 1); |
| return FALSE; // no error |
| } |
| |
| NABoolean ParSetTextEndPos(StmtDDLCreateView * pCreateViewParseNode) |
| { |
| ParNameLocList &nameLocList = pCreateViewParseNode->getNameLocList(); |
| const char *pInputStr = nameLocList.getInputStringPtr(); |
| ComASSERT(pInputStr NEQ NULL); |
| |
| // the token trailing a stand-alone Create View statement |
| // should be either a semicolon or a null token (the end- |
| // of-input-string character). |
| // |
| // For CREATE VIEW statement appearing within a Create |
| // Schema statement, the terminating token can also be |
| // the token Alter, Create, or Grant. |
| // |
| // If the Create View statement contains the optional |
| // With ... Check Option clause, the view_definition |
| // production may be reduced before the terminating |
| // token (for Create View statement) is scanned. |
| |
| const ParScannedTokenQueue::scannedTokenInfo *tokInfo |
| = ParScannedTokens->getScannedTokenInfoPtr(0); |
| NAString tokStr(&pInputStr[tokInfo->tokenStrPos], tokInfo->tokenStrInputLen); |
| size_t finalTokenPos = tokInfo->tokenStrPos; |
| Int32 isoOffset = 0; |
| tokStr.toUpper(); |
| NABoolean isEndOfInputStr = tokStr.isNull(); |
| if (NOT isEndOfInputStr AND |
| tokStr NEQ ";" AND |
| tokStr NEQ "ALTER" AND |
| tokStr NEQ "CREATE" AND |
| tokStr NEQ "GRANT" AND |
| tokStr NEQ "OPTION" ) |
| return TRUE; // syntax error |
| |
| // |
| // The following logic locates the last (non-blank) token |
| // in the Create View statement. |
| // |
| // Note that when the WITH [ LOCAL | CASCADED ] CHECK OPTION |
| // clause appears in the create view statement, the parser |
| // (currently) stops the scanning right at the keyword OPTION; |
| // therefore, the most-recently-scanned token is OPTION, the |
| // last token in the Create View statement. Of course, this |
| // may change if someone changes the grammar productions |
| // relating to view definitions in the future, and the logic |
| // in this routine will need to be updated accordingly. |
| // |
| |
| if (isEndOfInputStr OR tokStr NEQ "OPTION") |
| { |
| // 1. The most-recently-scanned token is a null character OR |
| // 2. The most-recently-scanned token is either a semicolon |
| // or the keyword Alter, Create, or Grant. |
| // |
| // Sets tokInfo and tokStr to the previous scanned token |
| // which can be either white space(s) or the last token |
| // in the Create View statement |
| // |
| tokInfo = ParScannedTokens->getScannedTokenInfoPtr(-1); |
| // must allow for the offsets of string qualifiers if _ISO88591 or _UCS2 or ... was specified |
| NAString isoStr(&pInputStr[tokInfo->tokenStrPos], finalTokenPos-tokInfo->tokenStrPos); |
| isoStr.resize(9); // only check the first 9 characters in case these are in the string |
| isoStr.toUpper(); |
| if(isoStr.contains("_ISO88591")) |
| isoOffset = 11; |
| else if(isoStr.contains("_UCS2") || isoStr.contains("_UTF8") || isoStr.contains("_SJIS")) |
| isoOffset = 7; |
| tokStr = NAString(&pInputStr[tokInfo->tokenStrPos], |
| tokInfo->tokenStrInputLen+isoOffset); |
| |
| // |
| // if the last token in create view statement is white |
| // space(s), excludes it from the statement. Note that |
| // there might not be any white space(s) between the |
| // Create View statement and the terminating semicolon. |
| // |
| if (IsNAStringSpace(tokStr)) |
| { |
| // Sets tokInfo to token preceding the white space(s). |
| // This token should be the last token in the create view |
| // statement. |
| tokInfo = ParScannedTokens->getScannedTokenInfoPtr(-2); |
| } |
| } |
| |
| pCreateViewParseNode->setEndPosition(tokInfo->tokenStrPos + |
| tokInfo->tokenStrInputLen - 1 + isoOffset); |
| return FALSE; // no error |
| } |
| |
| |
| NABoolean ParSetTextEndPos(StmtDDLCreateTrigger * pCreateTriggerParseNode) |
| { |
| ParNameLocList &nameLocList = pCreateTriggerParseNode->getNameLocList(); |
| const char *pInputStr = nameLocList.getInputStringPtr(); |
| ComASSERT(pInputStr NEQ NULL); |
| |
| const ParScannedTokenQueue::scannedTokenInfo *tokInfo |
| = ParScannedTokens->getScannedTokenInfoPtr(0); |
| NAString tokStr(&pInputStr[tokInfo->tokenStrPos], tokInfo->tokenStrLen); |
| tokStr.toUpper(); |
| NABoolean isEndOfInputStr = tokStr.isNull(); |
| |
| // If the most-recently-scanned token is a semicolon, |
| // set tokInfo and tokStr to the previous scanned token |
| // which can be either white space(s) or the last token |
| // in the create trigger statement. Note that this if |
| // statement only fails if the action of the trigger |
| // is a SIGNAL statement. For a SIGNAL action, The |
| // parser (currently) stops the scanning right at |
| // the token ")" of the SIGNAL action. |
| |
| TrimNAStringSpace(tokStr); |
| if (tokStr EQU ";") |
| { |
| tokInfo = ParScannedTokens->getScannedTokenInfoPtr(-1); |
| tokStr = NAString(&pInputStr[tokInfo->tokenStrPos], tokInfo->tokenStrLen); |
| tokStr.toUpper(); |
| } |
| |
| pCreateTriggerParseNode->setEndPosition(tokInfo->tokenStrPos + |
| tokInfo->tokenStrLen - 1); |
| return FALSE; // no error |
| } |
| |
| // ----------------------------------------------------------------------- |
| // definition of global (file scope) function |
| // ParSetTextStartPosForCreateTrigger() |
| // ----------------------------------------------------------------------- |
| |
| void ParSetTextStartPosForCreateTrigger(ParNameLocList * pNameLocList) |
| { |
| ComASSERT(pNameLocList EQU ParNameLocListPtr AND |
| pNameLocList NEQ NULL); |
| |
| const char *pInputStr = pNameLocList->getInputStringPtr(); |
| ComASSERT(pInputStr NEQ NULL); |
| |
| // |
| // locates the TRIGGER token information record |
| // from ParScannedTokens circular queue |
| // |
| |
| Int32 triggerTokIndex = 0 /*index of most-recently-scanned token*/; |
| const ParScannedTokenQueue::scannedTokenInfo &tokInfo |
| = ParScannedTokens->getScannedTokenInfo(triggerTokIndex); |
| NAString tokStr(&pInputStr[tokInfo.tokenStrPos], tokInfo.tokenStrLen); |
| tokStr.toUpper(); |
| |
| if (tokStr NEQ "TRIGGER") // If not on "TRIGGER", try one step back |
| { |
| triggerTokIndex = -1; |
| ComASSERT(ParScannedTokens->isQueueIndexWithinRange(triggerTokIndex)); |
| const ParScannedTokenQueue::scannedTokenInfo &triggerTokInfo |
| = ParScannedTokens->getScannedTokenInfo(triggerTokIndex); |
| tokStr = NAString(&pInputStr[triggerTokInfo.tokenStrPos], |
| triggerTokInfo.tokenStrLen); |
| tokStr.toUpper(); |
| ComASSERT(tokStr EQU "TRIGGER"); |
| } |
| |
| // |
| // the token before the "TRIGGER" token should be white space(s) |
| // |
| |
| Int32 prevTokIndex = triggerTokIndex - 1; |
| ComASSERT(ParScannedTokens->isQueueIndexWithinRange(prevTokIndex)); |
| const ParScannedTokenQueue::scannedTokenInfo &prevTokInfo |
| = ParScannedTokens->getScannedTokenInfo(prevTokIndex); |
| NAString prevTokStr(&pInputStr[prevTokInfo.tokenStrPos], |
| prevTokInfo.tokenStrLen); |
| ComASSERT(IsNAStringSpace(prevTokStr)); |
| |
| // |
| // locates the CREATE token information record |
| // from ParScannedTokens circular queue |
| // |
| |
| Int32 createTokIndex = triggerTokIndex - 2; |
| ComASSERT(ParScannedTokens->isQueueIndexWithinRange(createTokIndex)); |
| const ParScannedTokenQueue::scannedTokenInfo &createTokInfo |
| = ParScannedTokens->getScannedTokenInfo(createTokIndex); |
| NAString createTokStr(&pInputStr[createTokInfo.tokenStrPos], |
| createTokInfo.tokenStrLen); |
| createTokStr.toUpper(); |
| ComASSERT(createTokStr EQU "CREATE"); |
| |
| // |
| // the starting position of the CREATE token is also the |
| // starting position of the CREATE TRIGGER statement. |
| // |
| |
| pNameLocList->setTextStartPosition(createTokInfo.tokenStrPos); |
| |
| } // ParSetTextStartPosForCreateTrigger |
| |
| |
| // Keep (in a global var) the position of the closing parenthesis |
| // of the optional view column list |
| void ParSetEndOfOptionalColumnListPos(ParNameLocList * pNameLocList) |
| { |
| ComASSERT(pNameLocList EQU ParNameLocListPtr AND pNameLocList NEQ NULL); |
| |
| const char *pInputStr = pNameLocList->getInputStringPtr(); |
| ComASSERT(pInputStr NEQ NULL); |
| |
| // locates the ')' token |
| Int32 MVTokIndex = 0; /* index of most-recently-scanned token */ |
| const ParScannedTokenQueue::scannedTokenInfo &tokInfo |
| = ParScannedTokens->getScannedTokenInfo(MVTokIndex); |
| NAString tokStr(&pInputStr[tokInfo.tokenStrPos], tokInfo.tokenStrLen); |
| tokStr.toUpper(); |
| |
| TrimNAStringSpace(tokStr); |
| if (tokStr NEQ ")" ) // Just in case: If not on ")" --->>> try one step back |
| { |
| MVTokIndex = -1; |
| ComASSERT(ParScannedTokens->isQueueIndexWithinRange(MVTokIndex)); |
| const ParScannedTokenQueue::scannedTokenInfo &MVTokInfo |
| = ParScannedTokens->getScannedTokenInfo(MVTokIndex); |
| tokStr = NAString(&pInputStr[MVTokInfo.tokenStrPos], |
| MVTokInfo.tokenStrLen); |
| tokStr.toUpper(); |
| ComASSERT(tokStr EQU ")"); |
| // Store position of ')' in global variable |
| ParEndOfOptionalColumnListPos = MVTokInfo.tokenStrPos; |
| return; |
| } |
| // Store position of ')' in global variable |
| ParEndOfOptionalColumnListPos = tokInfo.tokenStrPos; |
| } |
| |
| // --------------------------------------------------------------------- |
| // Keep (in a global var) the position of the begining of the optional |
| // file-options list. (Called in the "enable/disable rewrite" section; |
| // adjusts the position forward if this section was not empty.) |
| void ParSetBeginingOfFileOptionsListPos(ParNameLocList * pNameLocList) |
| { |
| ComASSERT(pNameLocList EQU ParNameLocListPtr AND pNameLocList NEQ NULL); |
| |
| const char *pInputStr = pNameLocList->getInputStringPtr(); |
| ComASSERT(pInputStr NEQ NULL); |
| |
| Int32 MVTokIndex = 0; /* index of most-recently-scanned token */ |
| const ParScannedTokenQueue::scannedTokenInfo &tokInfo |
| = ParScannedTokens->getScannedTokenInfo(MVTokIndex); |
| NAString tokStr(&pInputStr[tokInfo.tokenStrPos], tokInfo.tokenStrLen); |
| tokStr.toUpper(); |
| |
| // Store current position in global variable |
| ParBeginingOfFileOptionsListPos = tokInfo.tokenStrPos; |
| |
| NAString rewriteStr = NAString("REWRITE"); |
| |
| if ( tokStr EQU rewriteStr ) { // "enable/disable rewrite" was specified |
| ParBeginingOfFileOptionsListPos += rewriteStr.length() ; // skip this token |
| } |
| } |
| |
| |
| |
| //---------------------------------------------------------------------------- |
| // Keep (in a global var) the position of the beginning of the MV query text |
| void ParSetBeginOfMVQueryPos(ParNameLocList * pNameLocList) |
| { |
| ComASSERT(pNameLocList EQU ParNameLocListPtr AND |
| NULL NEQ pNameLocList ); |
| |
| const char *pInputStr = pNameLocList->getInputStringPtr(); |
| |
| ComASSERT(pInputStr NEQ NULL); |
| |
| Int32 MVTokIndex = 0; // index of most-recently-scanned token |
| |
| const ParScannedTokenQueue::scannedTokenInfo &tokInfo |
| = ParScannedTokens->getScannedTokenInfo(MVTokIndex); |
| |
| NAString tokStr(&pInputStr[tokInfo.tokenStrPos], tokInfo.tokenStrLen); |
| |
| tokStr.toUpper(); |
| |
| ComASSERT("AS" == tokStr); |
| |
| Int32 nextWhiteSpacePos = tokInfo.tokenStrPos + sizeof("AS") - 1; |
| |
| NAString space(&pInputStr[nextWhiteSpacePos], 1); |
| |
| ComASSERT(IsNAStringSpace(space)); |
| |
| ParBeginingOfMVQueryPos = nextWhiteSpacePos; |
| } // ParSetBeginOfMVQueryPos |
| |
| |
| //---------------------------------------------------------------------------- |
| // Keep (in a global var) the position of the end of the list of columns |
| // of the select clause of the create MV stmt |
| void ParSetEndOfSelectColumnListPos(ParNameLocList * pNameLocList) |
| { |
| ComASSERT(pNameLocList EQU ParNameLocListPtr AND pNameLocList NEQ NULL); |
| |
| const char *pInputStr = pNameLocList->getInputStringPtr(); |
| ComASSERT(pInputStr NEQ NULL); |
| |
| // current token should be 'FROM' |
| Int32 MVTokIndex = 0; /* index of most-recently-scanned token */ |
| const ParScannedTokenQueue::scannedTokenInfo &tokInfo |
| = ParScannedTokens->getScannedTokenInfo(MVTokIndex); |
| NAString tokStr(&pInputStr[tokInfo.tokenStrPos], tokInfo.tokenStrLen); |
| tokStr.toUpper(); |
| |
| if (tokStr NEQ "FROM" ) return; // can't be valid .... |
| |
| // must step one token back; need to point to white space |
| // that follows the last item in the select list. |
| // Need to handle the special case - Ex: ... AS SELECT *FROM |
| MVTokIndex = -1; |
| ComASSERT(ParScannedTokens->isQueueIndexWithinRange(MVTokIndex)); |
| const ParScannedTokenQueue::scannedTokenInfo &MVTokInfo |
| = ParScannedTokens->getScannedTokenInfo(MVTokIndex); |
| tokStr = NAString(&pInputStr[MVTokInfo.tokenStrPos], |
| MVTokInfo.tokenStrLen); |
| |
| if (IsNAStringSpace(tokStr)) |
| { |
| // Store position in the global variable |
| ParEndOfSelectColumnListPos = MVTokInfo.tokenStrPos; |
| } |
| else |
| { // Special cases: |
| // Ex #1: CREATE MV ... AS SELECT *FROM ... |
| // Ex #2: CREATE MV ... AS SELECT COUNT(*)FROM ... |
| |
| // Store position in the global variable |
| ParEndOfSelectColumnListPos = tokInfo.tokenStrPos; |
| } |
| } |
| |
| // --------------------------------------------------------------------- |
| // Keep (in a global var) the position of the end of the file-options list. |
| void ParSetEndOfFileOptionsListPos(ParNameLocList * pNameLocList) |
| { |
| ComASSERT(pNameLocList EQU ParNameLocListPtr AND pNameLocList NEQ NULL); |
| |
| const char *pInputStr = pNameLocList->getInputStringPtr(); |
| ComASSERT(pInputStr NEQ NULL); |
| |
| Int32 MVTokIndex = 0; /* index of most-recently-scanned token */ |
| const ParScannedTokenQueue::scannedTokenInfo &tokInfo |
| = ParScannedTokens->getScannedTokenInfo(MVTokIndex); |
| NAString tokStr(&pInputStr[tokInfo.tokenStrPos], tokInfo.tokenStrLen); |
| tokStr.toUpper(); // tokStr is Only for debugging |
| // ComASSERT(tokStr EQU "AS"); |
| |
| // Store the current (end) position in the global variable |
| ParEndOfFileOptionsListPos = tokInfo.tokenStrPos; |
| |
| ComASSERT( ParEndOfFileOptionsListPos > ParBeginingOfFileOptionsListPos ); |
| ComASSERT( ParBeginingOfFileOptionsListPos > 0 ); |
| } |
| |
| // --------------------------------------------------------------------- |
| // Store the end-of-text position in the StmtDDLCreateMV node. |
| // Also copy into the the StmtDDLCreateMV node the other tree globaly |
| // kept positions: End of columns list, begining+end of file options. |
| NABoolean ParSetTextEndPos(StmtDDLCreateMV * pCreateMVParseNode) |
| { |
| ParNameLocList &nameLocList = pCreateMVParseNode->getNameLocList(); |
| const char *pInputStr = nameLocList.getInputStringPtr(); |
| ComASSERT(pInputStr NEQ NULL); |
| |
| const ParScannedTokenQueue::scannedTokenInfo *tokInfo |
| = ParScannedTokens->getScannedTokenInfoPtr(0); |
| NAString tokStr(&pInputStr[tokInfo->tokenStrPos], tokInfo->tokenStrLen); |
| tokStr.toUpper(); |
| NABoolean isEndOfInputStr = tokStr.isNull(); |
| |
| pCreateMVParseNode->setEndPosition(tokInfo->tokenStrPos + |
| tokInfo->tokenStrLen - 1); |
| |
| // Now the node exists; copy the rest of the globals into this node |
| pCreateMVParseNode-> |
| setEndOptionalColumnListPosition(ParEndOfOptionalColumnListPos); |
| pCreateMVParseNode->setFileOptionsPositions(ParBeginingOfFileOptionsListPos, |
| ParEndOfFileOptionsListPos); |
| pCreateMVParseNode->setStartOfMVQueryPosition(ParBeginingOfMVQueryPos); |
| pCreateMVParseNode-> |
| setEndSelectColumnListPosition(ParEndOfSelectColumnListPos); |
| return FALSE; // no error |
| } |
| |
| // --------------------------------------------------------------------------- |
| // definition of global (file scope) function ParSetTextStartPosForCreateMV() |
| // --------------------------------------------------------------------------- |
| |
| void ParSetTextStartPosForCreateMV(ParNameLocList * pNameLocList) |
| { |
| ComASSERT(pNameLocList EQU ParNameLocListPtr AND pNameLocList NEQ NULL); |
| |
| const char *pInputStr = pNameLocList->getInputStringPtr(); |
| ComASSERT(pInputStr NEQ NULL); |
| |
| // |
| // locates the MV token information record |
| // from ParScannedTokens circular queue |
| // |
| |
| Int32 MVTokIndex = 0; /* index of most-recently-scanned token */ |
| const ParScannedTokenQueue::scannedTokenInfo &tokInfo |
| = ParScannedTokens->getScannedTokenInfo(MVTokIndex); |
| NAString tokStr(&pInputStr[tokInfo.tokenStrPos], tokInfo.tokenStrLen); |
| tokStr.toUpper(); |
| |
| if (tokStr NEQ "MV" && // If not on "MV" --->>> try one step back |
| tokStr NEQ "VIEW" ) // and if not on "MATERIALIZED VIEW" |
| { |
| MVTokIndex = -1; |
| ComASSERT(ParScannedTokens->isQueueIndexWithinRange(MVTokIndex)); |
| const ParScannedTokenQueue::scannedTokenInfo &MVTokInfo |
| = ParScannedTokens->getScannedTokenInfo(MVTokIndex); |
| tokStr = NAString(&pInputStr[MVTokInfo.tokenStrPos], |
| MVTokInfo.tokenStrLen); |
| tokStr.toUpper(); |
| ComASSERT(tokStr EQU "MV" || tokStr EQU "VIEW" ); |
| |
| } |
| |
| // In case of the two-word "MATERIALIZED VIEW" token |
| if ( tokStr EQU "VIEW" ) { // step back behind the "MATERIALIZED" token |
| MVTokIndex -= 2 ; // need 2 to skip white space token as well |
| ComASSERT(ParScannedTokens->isQueueIndexWithinRange(MVTokIndex)); |
| const ParScannedTokenQueue::scannedTokenInfo &MVTokInfo |
| = ParScannedTokens->getScannedTokenInfo(MVTokIndex); |
| tokStr = NAString(&pInputStr[MVTokInfo.tokenStrPos], |
| MVTokInfo.tokenStrLen); |
| tokStr.toUpper(); |
| ComASSERT( tokStr EQU "MATERIALIZED" ); |
| } |
| |
| // |
| // the token before the "MV" token should be white space(s) |
| // |
| |
| Int32 prevTokIndex = MVTokIndex - 1; |
| ComASSERT(ParScannedTokens->isQueueIndexWithinRange(prevTokIndex)); |
| const ParScannedTokenQueue::scannedTokenInfo &prevTokInfo |
| = ParScannedTokens->getScannedTokenInfo(prevTokIndex); |
| NAString prevTokStr(&pInputStr[prevTokInfo.tokenStrPos], |
| prevTokInfo.tokenStrLen); |
| ComASSERT(IsNAStringSpace(prevTokStr)); |
| |
| // |
| // Locate the "CREATE" token. There may be an intervening "GHOST" token. |
| // |
| |
| Int32 createTokIndex; |
| Int32 ghostTokIndex = MVTokIndex - 2; |
| ComASSERT(ParScannedTokens->isQueueIndexWithinRange(ghostTokIndex)); |
| const ParScannedTokenQueue::scannedTokenInfo &ghostTokInfo |
| = ParScannedTokens->getScannedTokenInfo(ghostTokIndex); |
| NAString ghostTokStr(&pInputStr[ghostTokInfo.tokenStrPos], |
| ghostTokInfo.tokenStrLen); |
| ghostTokStr.toUpper(); |
| |
| // Check for "GHOST" token |
| if ( ghostTokStr EQU "GHOST" ) { |
| // |
| // The token before "GHOST" should be white space(s) |
| // |
| prevTokIndex = ghostTokIndex - 1; |
| ComASSERT(ParScannedTokens->isQueueIndexWithinRange(prevTokIndex)); |
| const ParScannedTokenQueue::scannedTokenInfo &prevTokInfo |
| = ParScannedTokens->getScannedTokenInfo(prevTokIndex); |
| prevTokStr = NAString(&pInputStr[prevTokInfo.tokenStrPos], |
| prevTokInfo.tokenStrLen); |
| ComASSERT(IsNAStringSpace(prevTokStr)); |
| // |
| // The token before the white space should be "CREATE". |
| // |
| createTokIndex = prevTokIndex - 1; |
| } |
| else |
| createTokIndex = ghostTokIndex; |
| |
| // |
| // Now we must have the "CREATE" token. |
| // |
| |
| ComASSERT(ParScannedTokens->isQueueIndexWithinRange(createTokIndex)); |
| const ParScannedTokenQueue::scannedTokenInfo &createTokInfo |
| = ParScannedTokens->getScannedTokenInfo(createTokIndex); |
| NAString createTokStr(&pInputStr[createTokInfo.tokenStrPos], |
| createTokInfo.tokenStrLen); |
| createTokStr.toUpper(); |
| |
| ComASSERT(createTokStr EQU "CREATE"); |
| |
| // |
| // the starting position of the CREATE token is also the |
| // starting position of the CREATE MV statement. |
| // |
| |
| pNameLocList->setTextStartPosition(createTokInfo.tokenStrPos); |
| |
| } // ParSetTextStartPosForCreateMV |
| |
| //---------------------------------------------------------------------------- |
| // Keep (in a global var) the position of the beginning of the MV query text |
| void ParSetBeginOfCreateTableAsQueryPos(ParNameLocList * pNameLocList) |
| { |
| ComASSERT(pNameLocList EQU ParNameCTLocListPtr AND |
| NULL NEQ pNameLocList ); |
| |
| const char *pInputStr = pNameLocList->getInputStringPtr(); |
| |
| ComASSERT(pInputStr NEQ NULL); |
| |
| Int32 CTTokIndex = 0; // index of most-recently-scanned token |
| |
| const ParScannedTokenQueue::scannedTokenInfo &tokInfo |
| = ParScannedTokens->getScannedTokenInfo(CTTokIndex); |
| |
| NAString tokStr(&pInputStr[tokInfo.tokenStrPos], tokInfo.tokenStrLen); |
| |
| tokStr.toUpper(); |
| |
| ComASSERT("AS" == tokStr); |
| |
| Int32 nextWhiteSpacePos = tokInfo.tokenStrPos + sizeof("AS") - 1; |
| |
| NAString space(&pInputStr[nextWhiteSpacePos], 1); |
| |
| ComASSERT(IsNAStringSpace(space)); |
| |
| ParBeginingOfCreateTableQueryPos = nextWhiteSpacePos; |
| } // ParSetBeginOfCreateTableAsQueryPos |
| |
| //---------------------------------------------------------------------------- |
| // Keep (in a global var) the position of the beginning attr list of |
| // a create table as stmt. |
| void ParSetBeginOfCreateTableAsAttrList(ParNameLocList * pNameLocList) |
| { |
| ComASSERT(pNameLocList EQU ParNameCTLocListPtr AND |
| NULL NEQ pNameLocList ); |
| |
| const char *pInputStr = pNameLocList->getInputStringPtr(); |
| |
| ComASSERT(pInputStr NEQ NULL); |
| |
| Int32 CTTokIndex = 0; // index of most-recently-scanned token |
| |
| const ParScannedTokenQueue::scannedTokenInfo &tokInfo |
| = ParScannedTokens->getScannedTokenInfo(CTTokIndex); |
| |
| NAString tokStr(&pInputStr[tokInfo.tokenStrPos], tokInfo.tokenStrLen); |
| |
| tokStr.toUpper(); |
| |
| Int32 nextPos = 0; |
| if (")" == tokStr) |
| { |
| nextPos = tokInfo.tokenStrPos + sizeof(")") - 1; |
| } |
| else |
| nextPos = tokInfo.tokenStrPos; |
| |
| ParBeginingOfCreateTableAsAttrList = nextPos; |
| } // ParSetBeginOfCreateTableAsAttrList |
| |
| //---------------------------------------------------------------------------- |
| // Keep (in a global var) the position of the beginning attr list of |
| // a create table as stmt. |
| void ParSetEndOfCreateTableAsAttrList(ParNameLocList * pNameLocList) |
| { |
| ComASSERT(pNameLocList EQU ParNameCTLocListPtr AND |
| NULL NEQ pNameLocList ); |
| |
| const char *pInputStr = pNameLocList->getInputStringPtr(); |
| |
| ComASSERT(pInputStr NEQ NULL); |
| |
| Int32 CTTokIndex = 0; // index of most-recently-scanned token |
| |
| const ParScannedTokenQueue::scannedTokenInfo &tokInfo |
| = ParScannedTokens->getScannedTokenInfo(CTTokIndex); |
| |
| NAString tokStr(&pInputStr[tokInfo.tokenStrPos], tokInfo.tokenStrLen); |
| |
| tokStr.toUpper(); |
| |
| Int32 nextPos = 0; |
| /* if ("NO" == tokStr) |
| { |
| nextPos = tokInfo.tokenStrPos + sizeof("NO") - 1; |
| } |
| else if ("LOAD" == tokStr) |
| { |
| nextPos = tokInfo.tokenStrPos + sizeof("LOAD") - 1; |
| } |
| else*/ |
| nextPos = tokInfo.tokenStrPos; |
| |
| ParEndOfCreateTableAsAttrList = nextPos; |
| } // ParSetEndOfCreateTableAsAttrList |
| |
| // --------------------------------------------------------------------- |
| // Store the start of query position in the StmtDDLCreateTable node. |
| NABoolean ParSetTextEndPos(StmtDDLCreateTable * pCreateCTParseNode) |
| { |
| pCreateCTParseNode-> |
| setStartOfCreateTableQueryPosition(ParBeginingOfCreateTableQueryPos); |
| pCreateCTParseNode-> |
| setStartOfCreateTableAsAttrListPosition(ParBeginingOfCreateTableAsAttrList); |
| pCreateCTParseNode-> |
| setEndOfCreateTableAsAttrListPosition(ParEndOfCreateTableAsAttrList); |
| pCreateCTParseNode-> |
| setCreateTableAsScannedInputCharset((Int32)ParScannedInputCharset); |
| pCreateCTParseNode-> |
| setCreateTableAsIsoMapping((Int32)SqlParser_ISO_MAPPING); |
| return FALSE; // no error |
| } |
| |
| // ----------------------------------------------------------------------- |
| // definition of global (file scope) function |
| // ParSetTextStartPosForCheckConstraint() |
| // ----------------------------------------------------------------------- |
| |
| void ParSetTextStartPosForCheckConstraint(ParNameLocList * pNameLocList) |
| { |
| ComASSERT(pNameLocList EQU ParNameLocListPtr AND |
| pNameLocList NEQ NULL); |
| |
| const char *pInputStr = pNameLocList->getInputStringPtr(); |
| ComASSERT(pInputStr NEQ NULL); |
| |
| // |
| // locates the left parenthesis token information record |
| // from ParScannedTokens circular queue |
| // |
| |
| Int32 leftParenTokIndex = 0; // index of most-recently-scanned token |
| const ParScannedTokenQueue::scannedTokenInfo &tokInfo |
| = ParScannedTokens->getScannedTokenInfo(leftParenTokIndex); |
| NAString tokStr(&pInputStr[tokInfo.tokenStrPos], 1);// only looking for open paren |
| StringPos leftParenStrPos = tokInfo.tokenStrPos; |
| |
| TrimNAStringSpace(tokStr); |
| if (tokStr NEQ "(") |
| { |
| leftParenTokIndex = -1; |
| ComASSERT(ParScannedTokens->isQueueIndexWithinRange(leftParenTokIndex)); |
| const ParScannedTokenQueue::scannedTokenInfo &leftParenTokInfo |
| = ParScannedTokens->getScannedTokenInfo(leftParenTokIndex); |
| tokStr = ""; |
| tokStr.append(&pInputStr[leftParenTokInfo.tokenStrPos], |
| leftParenTokInfo.tokenStrLen); |
| TrimNAStringSpace(tokStr); |
| PARSERASSERT(tokStr EQU "("); |
| leftParenStrPos = leftParenTokInfo.tokenStrPos; |
| } |
| |
| // |
| // the position of the left parenthesis token is the starting |
| // position of the check constraint search condition. |
| // |
| |
| pNameLocList->setTextStartPosition(leftParenStrPos); |
| |
| #ifndef NDEBUG |
| // |
| // The following code is for sanity checking only. |
| // It is not really needed. |
| // |
| // the tokens before the left parenthesis token should be |
| // optional white space(s) and "CHECK" |
| // |
| |
| Int32 prevTokIndex = leftParenTokIndex - 1; |
| ComASSERT(ParScannedTokens->isQueueIndexWithinRange(prevTokIndex)); |
| const ParScannedTokenQueue::scannedTokenInfo &prevTokInfo |
| = ParScannedTokens->getScannedTokenInfo(prevTokIndex); |
| NAString prevTokStr(&pInputStr[prevTokInfo.tokenStrPos], |
| prevTokInfo.tokenStrLen); |
| prevTokStr.toUpper(); |
| if (prevTokStr NEQ "CHECK") |
| { |
| ComASSERT(IsNAStringSpace(prevTokStr)); |
| |
| Int32 prevTokIndex = leftParenTokIndex - 2; |
| ComASSERT(ParScannedTokens->isQueueIndexWithinRange(prevTokIndex)); |
| const ParScannedTokenQueue::scannedTokenInfo &prevTokInfo |
| = ParScannedTokens->getScannedTokenInfo(prevTokIndex); |
| NAString prevTokStr(&pInputStr[prevTokInfo.tokenStrPos], |
| prevTokInfo.tokenStrLen); |
| prevTokStr.toUpper(); |
| ComASSERT(prevTokStr EQU "CHECK"); |
| } |
| #endif |
| |
| } // ParSetTextStartPosForCheckConstraint |
| |
| // ----------------------------------------------------------------------- |
| // definition of global (file scope) function |
| // ParSetTextStartPosForDivisionClause() |
| // ----------------------------------------------------------------------- |
| |
| void ParSetTextStartPosForDivisionByClause(ParNameLocList * pNameLocList) |
| { |
| ComASSERT(pNameLocList EQU ParNameDivByLocListPtr AND |
| pNameLocList NEQ NULL); |
| |
| const char *pInputStr = pNameLocList->getInputStringPtr(); |
| ComASSERT(pInputStr NEQ NULL); |
| |
| // TOK_DIVISION TOK_BY '(' ...current_position... |
| // or |
| // TOK_DIVISION TOK_BY '(' TOK_USING '(' ...current_position... |
| // |
| // Example #1: |
| // |
| // DIVISION BY ( store_id / 2 ) |
| // ^...current_position... |
| // |
| // Example #2: |
| // |
| // DIVISION BY (USING (store_id/2) NAMED AS ... |
| // ^...current_position... |
| |
| // |
| // locates the left parenthesis (the one following the BY or USING keyword) |
| // token information record from ParScannedTokens circular queue |
| // |
| |
| Int32 leftParenTokIndex = 0; |
| const ParScannedTokenQueue::scannedTokenInfo * pLeftParenTokInfo = NULL; |
| |
| Int32 tokIndex = 0; // index of most-recently-scanned token |
| const ParScannedTokenQueue::scannedTokenInfo * pTokInfo |
| = ParScannedTokens->getScannedTokenInfoPtr(tokIndex); |
| NAString tokStr((size_t)50); // pre-allocate 50 bytes memory space |
| tokStr.append(&pInputStr[pTokInfo->tokenStrPos], pTokInfo->tokenStrLen); |
| TrimNAStringSpace(tokStr); |
| tokStr.toUpper(); |
| while (ParScannedTokens->isQueueIndexWithinRange(tokIndex) |
| AND tokStr NEQ "BY" AND tokStr NEQ "USING") |
| { |
| if (tokStr EQU "(") |
| { |
| leftParenTokIndex = tokIndex; // maybe the one :-) |
| pLeftParenTokInfo = pTokInfo; |
| } |
| tokIndex--; // Going backward one token |
| if (ParScannedTokens->isQueueIndexOutOfRange(tokIndex)) |
| break; |
| pTokInfo = ParScannedTokens->getScannedTokenInfoPtr(tokIndex); |
| tokStr.replace(0, tokStr.length(), &pInputStr[pTokInfo->tokenStrPos], pTokInfo->tokenStrLen); |
| TrimNAStringSpace(tokStr); |
| tokStr.toUpper(); |
| } |
| PARSERASSERT(ParScannedTokens->isQueueIndexWithinRange(tokIndex) |
| AND (tokStr EQU "BY" OR tokStr EQU "USING") |
| AND pLeftParenTokInfo NEQ NULL); |
| |
| // |
| // the position of the left parenthesis token is the starting |
| // position of the division expression. |
| // |
| |
| pNameLocList->setTextStartPosition(pLeftParenTokInfo->tokenStrPos); |
| |
| // We are done ... |
| |
| #ifndef NDEBUG |
| |
| // Additional checking in the DEBUG version of the software |
| |
| if (tokStr EQU "USING") // DIVISION BY ( USING ( ... |
| { // ^...we_are_here... |
| // Go backward and skip over the USING token |
| tokIndex--; |
| if (ParScannedTokens->isQueueIndexOutOfRange(tokIndex)) |
| return; |
| pTokInfo = ParScannedTokens->getScannedTokenInfoPtr(tokIndex); |
| tokStr.replace(0, tokStr.length(), &pInputStr[pTokInfo->tokenStrPos], pTokInfo->tokenStrLen); |
| if (IsNAStringSpace(tokStr)) |
| { |
| // Go backward and skip over the white space(s) token |
| tokIndex--; |
| if (ParScannedTokens->isQueueIndexOutOfRange(tokIndex)) |
| return; |
| pTokInfo = ParScannedTokens->getScannedTokenInfoPtr(tokIndex); |
| tokStr.remove(0); // set to an empty string |
| tokStr.append(&pInputStr[pTokInfo->tokenStrPos], pTokInfo->tokenStrLen); |
| } |
| TrimNAStringSpace(tokStr); // DIVISION BY ( USING ( ... |
| PARSERASSERT(tokStr EQU "("); // ^...we_are_here... |
| |
| // Go backward and skip over the left-parenthesis token |
| tokIndex--; |
| if (ParScannedTokens->isQueueIndexOutOfRange(tokIndex)) |
| return; |
| pTokInfo = ParScannedTokens->getScannedTokenInfoPtr(tokIndex); |
| tokStr.replace(0, tokStr.length(), &pInputStr[pTokInfo->tokenStrPos], pTokInfo->tokenStrLen); |
| if (IsNAStringSpace(tokStr)) |
| { |
| // Go backward and skip over the white space(s) token |
| tokIndex--; |
| if (ParScannedTokens->isQueueIndexOutOfRange(tokIndex)) |
| return; |
| pTokInfo = ParScannedTokens->getScannedTokenInfoPtr(tokIndex); |
| tokStr.replace(0, tokStr.length(), &pInputStr[pTokInfo->tokenStrPos], pTokInfo->tokenStrLen); |
| } |
| tokStr.toUpper(); // DIVISION BY ( USING ( ... |
| PARSERASSERT(tokStr EQU "BY"); // ^...we_are_here... |
| } |
| |
| // Go backward and skip over the BY token |
| tokIndex--; |
| if (ParScannedTokens->isQueueIndexOutOfRange(tokIndex)) |
| return; |
| pTokInfo = ParScannedTokens->getScannedTokenInfoPtr(tokIndex); |
| tokStr.replace(0, tokStr.length(), &pInputStr[pTokInfo->tokenStrPos], pTokInfo->tokenStrLen); |
| if (IsNAStringSpace(tokStr)) |
| { |
| // Go backward and skip over the white space(s) token |
| tokIndex--; |
| if (ParScannedTokens->isQueueIndexOutOfRange(tokIndex)) |
| return; |
| pTokInfo = ParScannedTokens->getScannedTokenInfoPtr(tokIndex); |
| tokStr.replace(0, tokStr.length(), &pInputStr[pTokInfo->tokenStrPos], pTokInfo->tokenStrLen); |
| } // DIVISION BY ( USING ( ... |
| tokStr.toUpper(); // DIVISION BY ( ... |
| PARSERASSERT(tokStr EQU "DIVISION"); // ^...we_are_here... |
| #endif |
| |
| } // ParSetTextStartPosForDivisionByClause |
| |
| // ----------------------------------------------------------------------- |
| // definition of global (file scope) function |
| // ParSetTextStartPosForCreateView() |
| // ----------------------------------------------------------------------- |
| |
| void ParSetTextStartPosForCreateView(ParNameLocList * pNameLocList) |
| { |
| ComASSERT(pNameLocList EQU ParNameLocListPtr AND |
| pNameLocList NEQ NULL); |
| |
| const char *pInputStr = pNameLocList->getInputStringPtr(); |
| ComASSERT(pInputStr NEQ NULL); |
| |
| // |
| // locates the VIEW token information record |
| // from ParScannedTokens circular queue |
| // |
| |
| Int32 viewTokIndex = 0 /*index of most-recently-scanned token*/; |
| |
| // The maximum number of tokens that can exist in this sytax are: |
| // TOK_CREATE<sp><TOK_OR><sp><TOK_REPLACE><sp><TOK_VIEW><sp><TOK_CASCADE> |
| // 1 2 3 4 5 6 7 8 9 |
| // If the purpose of this function is to find the position of the token |
| // TOK_CREATE then all we have to do is scan maximum of 8 tokens before |
| // the current most-recently-scanned token and we should find the token |
| // for CREATE. |
| |
| ParScannedTokenQueue::scannedTokenInfo tokInfo; |
| Int32 maxCount=9; // This will change when the syntax changes. |
| Int32 toksScanned = 0; // counter for number of tokens scanned. |
| NABoolean foundCreate=FALSE; |
| NAString tokStr; |
| while((foundCreate==FALSE) || (toksScanned < maxCount)) |
| { |
| ComASSERT(ParScannedTokens->isQueueIndexWithinRange(viewTokIndex)); |
| ComASSERT(toksScanned < maxCount); |
| tokInfo = ParScannedTokens->getScannedTokenInfo(viewTokIndex); |
| tokStr = NAString(&pInputStr[tokInfo.tokenStrPos], tokInfo.tokenStrLen); |
| tokStr.toUpper(); |
| |
| if (tokStr EQU "CREATE") |
| { |
| // |
| // the starting position of the CREATE token is also the |
| // starting position of the CREATE VIEW statement. |
| // |
| foundCreate = TRUE; |
| pNameLocList->setTextStartPosition(tokInfo.tokenStrPos); |
| return; |
| } |
| else |
| { |
| toksScanned = toksScanned + 1; |
| viewTokIndex = viewTokIndex -1; // get the previous token |
| } |
| } |
| return; // It will never come here unless the maxCount is wrong. |
| // We should assert in the above ComAssert checks. Or we |
| // should return with CREATE. |
| } // ParSetTextStartPosForCreateView |
| |
| void ParSetTextStartPosForDisplayExplain(ParNameLocList * pNameLocList) |
| { |
| ComASSERT(pNameLocList EQU ParNameLocListPtr AND |
| pNameLocList NEQ NULL); |
| |
| const char *pInputStr = pNameLocList->getInputStringPtr(); |
| ComASSERT(pInputStr NEQ NULL); |
| |
| // |
| // locates the left parenthesis token information record |
| // from ParScannedTokens circular queue |
| // |
| |
| Int32 leftParenTokIndex = 0; // index of most-recently-scanned token |
| const ParScannedTokenQueue::scannedTokenInfo &tokInfo |
| = ParScannedTokens->getScannedTokenInfo(leftParenTokIndex); |
| NAString tokStr(&pInputStr[tokInfo.tokenStrPos], tokInfo.tokenStrLen); |
| StringPos qryStrPos = tokInfo.tokenStrPos; |
| |
| Int32 c; |
| c = tokStr.compareTo("EXPLAIN", NAString::ignoreCase); |
| if ((c != 0) && |
| (tokStr.data()[0] NEQ '\'')) |
| { |
| leftParenTokIndex = -2; |
| ComASSERT(ParScannedTokens->isQueueIndexWithinRange(leftParenTokIndex)); |
| const ParScannedTokenQueue::scannedTokenInfo &leftParenTokInfo |
| = ParScannedTokens->getScannedTokenInfo(leftParenTokIndex); |
| tokStr = NAString(&pInputStr[leftParenTokInfo.tokenStrPos], |
| leftParenTokInfo.tokenStrLen); |
| |
| c = tokStr.compareTo("EXPLAIN", NAString::ignoreCase); |
| qryStrPos = leftParenTokInfo.tokenStrPos; |
| } |
| |
| c = tokStr.compareTo("EXPLAIN", NAString::ignoreCase); |
| if (c == 0) |
| qryStrPos = qryStrPos + strlen("EXPLAIN"); |
| else |
| { |
| // At this point, tokStr contains the token that follows the "options" |
| // key word for the stmt "explain options '<str>' ..." |
| // Skip string that follows the "options" keyword |
| char * trailingQ = strchr((char*)tokStr.data()+1, '\''); |
| Int32 len = trailingQ - tokStr.data() + 1; |
| qryStrPos = qryStrPos + len; |
| } |
| |
| // |
| // the position of the left parenthesis token is the starting |
| // position of the check constraint search condition. |
| // |
| |
| pNameLocList->setTextStartPosition(qryStrPos); |
| |
| } // ParSetTextStartPosForDisplayExplain |
| |
| NABoolean ParGetTextStartEndPosForDisplayExplain( |
| ParNameLocList * pNameLocList, |
| StringPos &start, StringPos &end) |
| { |
| const char *pInputStr = pNameLocList->getInputStringPtr(); |
| ComASSERT(pInputStr NEQ NULL); |
| |
| const ParScannedTokenQueue::scannedTokenInfo *tokInfo |
| = ParScannedTokens->getScannedTokenInfoPtr(0); |
| NAString tokStr(&pInputStr[tokInfo->tokenStrPos], tokInfo->tokenStrLen); |
| |
| if ((NOT IsNAStringSpace(tokStr)) && |
| (tokStr NEQ ")") && |
| (tokStr NEQ ";")) |
| { |
| tokInfo = ParScannedTokens->getScannedTokenInfoPtr(-1); |
| tokStr = NAString(&pInputStr[tokInfo->tokenStrPos], |
| tokInfo->tokenStrLen); |
| |
| if ((NOT IsNAStringSpace(tokStr)) && |
| (tokStr NEQ ")") && |
| (tokStr NEQ ";")) |
| return TRUE; |
| } |
| start = pNameLocList->getTextStartPosition(); |
| end = tokInfo->tokenStrPos; |
| |
| return FALSE; // no error |
| } |
| |
| // Used by MULTI-COMMIT Delete to keep track of the start of the |
| // WHERE clause of the delete statement. |
| // |
| void ParSetTextStartPosForMultiCommit(ParNameLocList * pNameLocList) |
| { |
| ComASSERT(pNameLocList EQU ParNameLocListPtr AND |
| pNameLocList NEQ NULL); |
| |
| const char *pInputStr = pNameLocList->getInputStringPtr(); |
| ComASSERT(pInputStr NEQ NULL); |
| |
| // |
| // locates the start of WHERE clause in the |
| // ParScannedTokens circular queue |
| // |
| |
| // index of most-recently-scanned token |
| const ParScannedTokenQueue::scannedTokenInfo &tokInfo |
| = ParScannedTokens->getScannedTokenInfo(0); |
| |
| // Get the string of the most recent token |
| NAString tokStr(&pInputStr[tokInfo.tokenStrPos], tokInfo.tokenStrLen); |
| |
| // The position of this token in the query text. |
| StringPos qryStrPos = tokInfo.tokenStrPos; |
| |
| // Check to see if we have the WHERE clause. |
| Int32 c; |
| c = tokStr.compareTo("WHERE", NAString::ignoreCase); |
| if (c == 0) |
| { |
| // |
| // the position of the WHERE token is the starting |
| // position of the multi commit search condition. |
| // |
| pNameLocList->setWhereStartPosition(qryStrPos); |
| } |
| |
| } // ParSetTextStartPosForMultCommit |
| |
| // Used by MULTI-COMMIT Delete to keep track of the start and end of the |
| // WHERE clause of the delete statement. |
| // |
| // Find the end of the WHERE clause and return the start and the end positions |
| // |
| NABoolean ParGetTextStartEndPosForMultiCommit( |
| ParNameLocList * pNameLocList, |
| StringPos &start, StringPos &end) |
| { |
| const char *pInputStr = pNameLocList->getInputStringPtr(); |
| ComASSERT(pInputStr NEQ NULL); |
| |
| // Get the most recently scanned token. |
| const ParScannedTokenQueue::scannedTokenInfo *tokInfo |
| = ParScannedTokens->getScannedTokenInfoPtr(0); |
| |
| // Get the start position, previously stored. |
| start = pNameLocList->getWhereStartPosition(); |
| |
| // Get the end position of the WHERE clause. |
| end = tokInfo->tokenStrPos; |
| |
| return FALSE; // no error |
| } |
| |
| |
| // ----------------------------------------------------------------------- |
| // definition of function ParUpdateNameLocForDotStar() |
| // ----------------------------------------------------------------------- |
| |
| void ParUpdateNameLocForDotStar(const ColRefName * pColRefName) |
| { |
| if (ParNameLocListPtr EQU NULL) |
| { |
| return; |
| } |
| |
| const char *pInputStr = ParNameLocListPtr->getInputStringPtr(); |
| ComASSERT(pInputStr NEQ NULL); |
| |
| // |
| // Gets the position of the dot-star (period-asterisk) |
| // from the ParScannedTokenQueue. Note that the parser |
| // may look ahead one token. So the most recently |
| // scanned token (with 0th index) may not be the star. |
| // If the 0th indexed token is not, then the -1th |
| // indexed token (the token scanned before the most- |
| // recently-scanned token) is. |
| // |
| // Note that the scanner currently does not allow |
| // white spaces between the dot (period) and the |
| // star (asterisk) as of 6/5/96. |
| // |
| |
| StringPos dotStarPos; |
| const ParScannedTokenQueue::scannedTokenInfo &tokInfo |
| = ParScannedTokens->getScannedTokenInfo(0/*token index*/); |
| if (tokInfo.tokenStrLen EQU (size_t)2 AND |
| NAString(&pInputStr[tokInfo.tokenStrPos], (size_t)2) EQU ".*") |
| { |
| dotStarPos = tokInfo.tokenStrPos; |
| } |
| else |
| { |
| const ParScannedTokenQueue::scannedTokenInfo &prevTokInfo |
| = ParScannedTokens->getScannedTokenInfo(-1/*token index*/); |
| ComASSERT(prevTokInfo.tokenStrLen EQU (size_t)2 AND |
| NAString(&pInputStr[prevTokInfo.tokenStrPos], (size_t)2) |
| EQU ".*"); |
| dotStarPos = prevTokInfo.tokenStrPos; |
| } |
| |
| ParNameLoc *pNameLoc |
| = ParNameLocListPtr->getNameLocPtr(pColRefName->getCorrNameObj(). |
| getNamePosition()); |
| ComASSERT(pNameLoc NEQ NULL); |
| |
| // |
| // pNameLoc->getNameLength() used to contain the length of the |
| // correlation name. Updates it to include the dot-star symbol. |
| // |
| pNameLoc->setNameLength(dotStarPos - pNameLoc->getNamePosition() + 2); |
| } |
| |
| // ----------------------------------------------------------------------- |
| // definitions of non-inline methods of class ParNameLoc |
| // ----------------------------------------------------------------------- |
| |
| // |
| // virtual destructor |
| // |
| |
| ParNameLoc::~ParNameLoc() |
| { |
| } |
| |
| |
| // |
| // operators |
| // |
| |
| ParNameLoc & |
| ParNameLoc::operator=(const ParNameLoc &rhs) |
| { |
| if (this EQU &rhs) |
| { |
| return *this; |
| } |
| |
| namePos_ = rhs.namePos_; |
| nameLen_ = rhs.nameLen_; |
| expandedName_ = rhs.expandedName_; |
| |
| return *this; |
| } |
| |
| const NABoolean |
| ParNameLoc::operator==(const ParNameLoc &rhs) const |
| { |
| if (this EQU &rhs) |
| { |
| return TRUE; |
| } |
| |
| return (namePos_ EQU rhs.namePos_ AND |
| nameLen_ EQU rhs.nameLen_ AND |
| expandedName_ EQU rhs.expandedName_); |
| } |
| |
| // ----------------------------------------------------------------------- |
| // definitions of non-inline methods of class ParNameLocList |
| // ----------------------------------------------------------------------- |
| |
| // |
| // constructors |
| // |
| |
| ParNameLocList::ParNameLocList ( const char * const pInputString // default is NULL |
| , CharInfo::CharSet inputStrCS // default is CharInfo::ISO88591 or UTF8 |
| , const NAWchar * const pInputStrInUTF16 // default is NULL |
| , CollHeap * heap // default is PARSERHEAP() |
| ) |
| : LIST(ParNameLoc *)(heap), |
| pInputString_(pInputString), // shallow copy |
| inputStrCharSet_(inputStrCS), |
| pwInputString_(pInputStrInUTF16), // shallow copy |
| textStartPos_(0), |
| heap_(heap) |
| { |
| } |
| |
| ParNameLocList::ParNameLocList(const ParNameLocList &rhs, |
| CollHeap *heap) |
| : LIST(ParNameLoc *)(heap), |
| heap_(heap) |
| { |
| copy(rhs) ; |
| } |
| |
| // |
| // virtual destructor |
| // |
| |
| ParNameLocList::~ParNameLocList() |
| { |
| for (CollIndex i = 0; i < entries(); i++) |
| { |
| NADELETE(&operator[](i), ParNameLoc, heap_); |
| } |
| } |
| |
| // |
| // operator |
| // |
| |
| ParNameLocList & |
| ParNameLocList::operator=(const ParNameLocList &rhs) |
| { |
| if (this EQU &rhs) return *this; |
| clear(); |
| copy(rhs); |
| return *this; |
| } |
| |
| // |
| // accessor |
| // |
| |
| // |
| // given the position (of the first character) of the name, |
| // searches the list for a match and then returns the pointer |
| // to the name location element in the list if found; returns |
| // the NULL pointer value otherwise. |
| // |
| ParNameLoc * |
| ParNameLocList::getNameLocPtr(const StringPos namePos) |
| { |
| for (CollIndex i = 0; i < entries(); i++) |
| { |
| if (operator[](i).getNamePosition() EQU namePos) |
| { |
| return &operator[](i); |
| } |
| } |
| return NULL; |
| } |
| |
| // |
| // mutators |
| // |
| |
| void |
| ParNameLocList::clear() |
| { |
| for (CollIndex i = 0; i < entries(); i++) |
| { |
| //KSKSKS |
| delete &operator[](i); |
| // NADELETE(&operator[](i), ParNameLoc, heap_); |
| //KSKSKS |
| } |
| LIST(ParNameLoc *)::clear(); |
| pInputString_ = NULL; |
| inputStrCharSet_ = CharInfo::UnknownCharSet; |
| pwInputString_ = NULL; |
| textStartPos_ = 0; |
| // leave data member heap_ alone (it's only set once, by the constructor). |
| } |
| |
| void |
| ParNameLocList::copy(const ParNameLocList &rhs) |
| { |
| if (this EQU &rhs) |
| return; |
| |
| pInputString_ = rhs.pInputString_; // shallow copy |
| inputStrCharSet_ = rhs.inputStrCharSet_; |
| pwInputString_ = rhs.pwInputString_; // shallow copy |
| textStartPos_ = rhs.textStartPos_; |
| // DO NOT set the heap_ field. |
| // It's already been set by the constructor |
| // heap_ = rhs.heap_; |
| |
| for (CollIndex i = 0; i < rhs.entries(); i++) |
| { // deep copy |
| insert(rhs[i]); // insert() allocates space from heap_ |
| } |
| } |
| |
| NABoolean |
| ParNameLocList::insert(const ParNameLoc &nameLoc) |
| { |
| ParNameLoc *pNameLoc = getNameLocPtr(nameLoc.getNamePosition()); |
| if (pNameLoc EQU NULL) // not found |
| { |
| // ok to insert |
| pNameLoc = new(heap_) ParNameLoc(nameLoc); |
| CMPASSERT(pNameLoc NEQ NULL); |
| LIST(ParNameLoc *)::insert(pNameLoc); |
| return TRUE; |
| } |
| return FALSE; |
| } |
| |
| // This function allows UDF names to be added to the list in the |
| // order in which they appear in the query text with other objects |
| // (such as tables). |
| NABoolean |
| ParNameLocList::insertInOrder(const ParNameLoc &nameLoc) |
| { |
| ParNameLoc *pNameLoc = getNameLocPtr(nameLoc.getNamePosition()); |
| if (pNameLoc EQU NULL) // not found |
| { |
| // ok to insert |
| pNameLoc = new(heap_) ParNameLoc(nameLoc); |
| CMPASSERT(pNameLoc NEQ NULL); |
| |
| CollIndex ci=0; |
| while (ci < LIST(ParNameLoc *)::entries() && |
| LIST(ParNameLoc *)::at(ci)->getNamePosition() < nameLoc.getNamePosition()) |
| ci++; |
| LIST(ParNameLoc *)::insertAt(ci, pNameLoc); |
| return TRUE; |
| } |
| return FALSE; |
| } |
| // |
| // End of File |
| // |