Lng32 ExExeUtilTcb::extractParts (char * objectName, char ** paramParts0, char ** paramParts1, char ** paramParts2 ) { char * parts[4]; Lng32 numParts = 0; Lng32 rc = 0; // We want to ignore any "." dots within a delimited // name. The AnsiOrNskName object is ultimately deleted // in the ExExeUtilMainObjectTcb destructor. if (extractedPartsObj_) delete extractedPartsObj_; extractedPartsObj_ = new (getHeap()) AnsiOrNskName(objectName); if ((rc = extractedPartsObj_->extractParts(numParts, parts)) != 0 || (numParts != 3)) { *getDiagsArea() << DgSqlCode(-CLI_INTERNAL_ERROR); return -1; } char * parts0 = NULL; char * parts1 = NULL; char * parts2 = NULL; Lng32 parts0Len = strlen(parts[0]); Lng32 parts1Len = strlen(parts[1]); Lng32 parts2Len = strlen(parts[2]); Lng32 parts0OffsetLen = 0; Lng32 parts1OffsetLen = 0; Lng32 parts2OffsetLen = 0; Lng32 foundParts0 = 0; Lng32 foundParts1 = 0; Lng32 foundParts2 = 0; char * testParts = NULL; char * ptr = NULL; testParts = parts[0]; ptr = (char *) strchr (testParts, '\''); while (ptr != NULL) { foundParts0++; ptr = (char *) strchr (ptr+1,'\''); } testParts = parts[1]; ptr = (char *) strchr (testParts, '\''); while (ptr != NULL) { foundParts1++; ptr = (char *) strchr (ptr+1,'\''); } testParts = parts[2]; ptr = (char *) strchr (testParts, '\''); while (ptr != NULL) { foundParts2++; ptr = (char *) strchr (ptr+1,'\''); } Lng32 lenToCopy = 0; char * beginTestParts = NULL; char * formattedParts = NULL; Lng32 totalLen = 0; if (foundParts0) { totalLen = parts0Len + foundParts0 + 1; parts0 = new(getHeap()) char[totalLen]; for (Int32 i = 0; i < totalLen; i++) parts0[i] = ' '; parts0[totalLen-1] = '\0'; testParts = parts[0]; ptr = NULL; ptr = (char *) strchr (testParts, '\''); while (ptr != NULL) { lenToCopy = ptr - testParts; strncpy(parts0 + parts0OffsetLen,testParts,++lenToCopy); strncpy(parts0 + parts0OffsetLen + lenToCopy, "'",1); testParts = testParts + lenToCopy; parts0OffsetLen += lenToCopy; parts0OffsetLen++; ptr = (char *) strchr (ptr+1,'\''); } strncpy(parts0 + parts0OffsetLen, testParts,strlen(testParts)); parts0[totalLen-1] = '\0'; } else { totalLen = parts0Len + 1; parts0 = new(getHeap()) char[totalLen]; strcpy(parts0, parts[0]); } if (foundParts1) { totalLen = parts1Len + foundParts1 + 1; parts1 = new(getHeap()) char[totalLen]; for (Int32 i = 0; i < totalLen; i++) parts1[i] = ' '; parts1[totalLen-1] = '\0'; testParts = parts[1]; ptr = NULL; ptr = (char *) strchr (testParts, '\''); while (ptr != NULL) { lenToCopy = ptr - testParts; strncpy(parts1 + parts1OffsetLen,testParts,++lenToCopy); strncpy(parts1 + parts1OffsetLen + lenToCopy, "'",1); testParts = testParts + lenToCopy; parts1OffsetLen += lenToCopy; parts1OffsetLen++; ptr = (char *) strchr (ptr+1,'\''); } strncpy(parts1 + parts1OffsetLen, testParts,strlen(testParts)); parts1[totalLen-1] = '\0'; } else { totalLen = parts1Len + 1; parts1 = new(getHeap()) char[totalLen]; strcpy(parts1, parts[1]); } if (foundParts2) { totalLen = parts2Len + foundParts2 + 1; parts2 = new(getHeap()) char[totalLen]; for (Int32 i = 0; i < totalLen; i++) parts2[i] = ' '; parts2[totalLen-1] = '\0'; testParts = parts[2]; ptr = NULL; ptr = (char *) strchr (testParts, '\''); while (ptr != NULL) { lenToCopy = ptr - testParts; strncpy(parts2 + parts2OffsetLen,testParts,++lenToCopy); strncpy(parts2 + parts2OffsetLen + lenToCopy, "'",1); testParts = testParts + lenToCopy; parts2OffsetLen += lenToCopy; parts2OffsetLen++; ptr = (char *) strchr (ptr+1,'\''); } strncpy(parts2 + parts2OffsetLen, testParts,strlen(testParts)); parts2[totalLen-1] = '\0'; } else { totalLen = parts2Len + 1; parts2 = new(getHeap()) char[totalLen]; strcpy(parts2, parts[2]); } /* The AnsiOrNskName() method strips out the leading and ending double quotes. The following code is no longer needed. // // Strip out the delimited name quotes. // If these are not stripped out, then a maximum // name of 128 characters will cause an overflow // by actually having 130 characters. char maxName[129]; maxName[0] = '\0'; if (parts0[0] == '"') { strncpy(maxName,parts0+1,strlen(parts0) -2); maxName[strlen(parts0)-2] = '\0'; strncpy(parts0,maxName,strlen(parts0) -2); parts0[strlen(maxName)] = '\0'; } maxName[0] = '\0'; if (parts1[0] == '"') { strncpy(maxName,parts1+1,strlen(parts1) -2); maxName[strlen(parts1)-2] = '\0'; strncpy(parts1,maxName,strlen(parts1) -2); parts1[strlen(maxName)] = '\0'; } maxName[0] = '\0'; if (parts2[0] == '"') { strncpy(maxName,parts2+1,strlen(parts2) -2); maxName[strlen(parts2)-2] = '\0'; strncpy(parts2,maxName,strlen(parts2) -2); parts2[strlen(maxName)] = '\0'; } maxName[0] = '\0'; */ *paramParts0 = parts0; *paramParts1 = parts1; *paramParts2 = parts2; return 0; }
// ---------------------------------------------------------------------------- // Method: registerUser // // registers a user in the Trafodion metadata // // Input: parse tree containing a definition of the user // Output: the global diags area is set up with the result // ---------------------------------------------------------------------------- void CmpSeabaseDDLuser::registerUser(StmtDDLRegisterUser * pNode) { // Set up a global try/catch loop to catch unexpected errors try { // Verify user is authorized verifyAuthority(); // Verify that the specified user name is not reserved // TBD - add the isCatman concept if (isAuthNameReserved(pNode->getDbUserName())) { *CmpCommon::diags() << DgSqlCode (-CAT_AUTH_NAME_RESERVED) << DgString0(pNode->getDbUserName().data()); DDLException excp (CAT_AUTH_NAME_RESERVED, NULL, 0); excp.throwException(); } // set up class members from parse node setAuthDbName(pNode->getDbUserName()); setAuthExtName(pNode->getExternalUserName()); setAuthImmutable(pNode->isImmutable()); setAuthType(COM_USER_CLASS); // we are a user setAuthValid(true); // assume a valid user Int64 createTime = NA_JulianTimestamp(); setAuthCreateTime(createTime); setAuthRedefTime(createTime); // make redef time the same as create time // Make sure db user has not already been registered if (authExists()) { *CmpCommon::diags() << DgSqlCode(-CAT_AUTHID_ALREADY_EXISTS) << DgString0(getAuthDbName().data()); DDLException excp (CAT_AUTHID_ALREADY_EXISTS, NULL, 0); excp.throwException(); } // Make sure external user has not already been registered if (authExists(true)) { *CmpCommon::diags() << DgSqlCode(-CAT_LDAP_USER_ALREADY_EXISTS) << DgString0(getAuthExtName().data()); DDLException excp (CAT_LDAP_USER_ALREADY_EXISTS, NULL, 0); excp.throwException(); } DBUserAuth::AuthenticationConfiguration configurationNumber = DBUserAuth::DefaultConfiguration; DBUserAuth::AuthenticationConfiguration foundConfigurationNumber = DBUserAuth::DefaultConfiguration; if (!validateExternalUsername(pNode->getExternalUserName().data(), configurationNumber, foundConfigurationNumber)) return; // Get a unique auth ID number // TBD - check a parserflag (or something) to add DB__ROOT Int32 userID = 0; if (getAuthDbName() == DB__ROOT) userID = SUPER_USER; else userID = getUniqueUserID(); setAuthID (userID); // If the BY clause was specified, then register the user on behalf of the // authorization ID specified in this clause. // Need to translate the creator name to its authID if (pNode->getOwner() == NULL) { // get effective user from the Context // TBD - replace this call with SQL_EXEC_ call Int32 *pUserID = GetCliGlobals()->currContext()->getDatabaseUserID(); setAuthCreator(*pUserID); } else { const NAString creatorName = pNode->getOwner()->getAuthorizationIdentifier(); // TBD: get the authID for the creatorName // TBD: verify creator can register users setAuthCreator(NA_UserIdDefault); } // Add the user to AUTHS table insertRow(); } catch (...) { // At this time, an error should be in the diags area. // If there is no error, set up an internal error Int32 numErrors = CmpCommon::diags()->getNumber(DgSqlCode::ERROR_); if (numErrors == 0) *CmpCommon::diags() << DgSqlCode (-CAT_INTERNAL_EXCEPTION_ERROR) << DgInt0(__LINE__) << DgString0("register user"); } }
// ----------------------------------------------------------------------- // Method for creating NAType from desc_struct. // ----------------------------------------------------------------------- NABoolean NAColumn::createNAType(columns_desc_struct *column_desc /*IN*/, const NATable *table /*IN*/, NAType *&type /*OUT*/, NAMemory *heap /*IN*/, Lng32 * errorCode ) { // // Compute the NAType for this column // #define REC_INTERVAL REC_MIN_INTERVAL DataType datatype = column_desc->datatype; if (REC_MIN_INTERVAL <= datatype && datatype <= REC_MAX_INTERVAL) datatype = REC_INTERVAL; Lng32 charCount = column_desc->length; if ( DFS2REC::isAnyCharacter(column_desc->datatype) ) { if ( CharInfo::isCharSetSupported(column_desc->character_set) == FALSE ) { if (!errorCode) { *CmpCommon::diags() << DgSqlCode(-4082) << DgTableName(makeTableName(table, column_desc)); } else { *errorCode = 4082; } return TRUE; // error } if ( CharInfo::is_NCHAR_MP(column_desc->character_set) ) charCount /= SQL_DBCHAR_SIZE; } switch (datatype) { case REC_BPINT_UNSIGNED : type = new (heap) SQLBPInt(column_desc->precision, column_desc->null_flag, FALSE, heap); break; case REC_BIN8_SIGNED: if (column_desc->precision > 0) type = new (heap) SQLNumeric(column_desc->length, column_desc->precision, column_desc->scale, TRUE, column_desc->null_flag, heap ); else type = new (heap) SQLTiny(TRUE, column_desc->null_flag, heap ); break; case REC_BIN8_UNSIGNED: if (column_desc->precision > 0) type = new (heap) SQLNumeric(column_desc->length, column_desc->precision, column_desc->scale, FALSE, column_desc->null_flag, heap ); else type = new (heap) SQLTiny(FALSE, column_desc->null_flag, heap ); break; case REC_BIN16_SIGNED: if (column_desc->precision > 0) type = new (heap) SQLNumeric(column_desc->length, column_desc->precision, column_desc->scale, TRUE, column_desc->null_flag, heap ); else type = new (heap) SQLSmall(TRUE, column_desc->null_flag, heap ); break; case REC_BIN16_UNSIGNED: if (column_desc->precision > 0) type = new (heap) SQLNumeric(column_desc->length, column_desc->precision, column_desc->scale, FALSE, column_desc->null_flag, heap ); else type = new (heap) SQLSmall(FALSE, column_desc->null_flag, heap ); break; case REC_BIN32_SIGNED: if (column_desc->precision > 0) type = new (heap) SQLNumeric(column_desc->length, column_desc->precision, column_desc->scale, TRUE, column_desc->null_flag, heap ); else type = new (heap) SQLInt(TRUE, column_desc->null_flag, heap ); break; case REC_BIN32_UNSIGNED: if (column_desc->precision > 0) type = new (heap) SQLNumeric(column_desc->length, column_desc->precision, column_desc->scale, FALSE, column_desc->null_flag, heap ); else type = new (heap) SQLInt(FALSE, column_desc->null_flag, heap ); break; case REC_BIN64_SIGNED: if (column_desc->precision > 0) type = new (heap) SQLNumeric(column_desc->length, column_desc->precision, column_desc->scale, TRUE, column_desc->null_flag, heap ); else type = new (heap) SQLLargeInt(TRUE, column_desc->null_flag, heap ); break; case REC_BIN64_UNSIGNED: if (column_desc->precision > 0) type = new (heap) SQLNumeric(column_desc->length, column_desc->precision, column_desc->scale, FALSE, column_desc->null_flag, heap ); else type = new (heap) SQLLargeInt(FALSE, column_desc->null_flag, heap ); break; case REC_DECIMAL_UNSIGNED: type = new (heap) SQLDecimal(column_desc->length, column_desc->scale, FALSE, column_desc->null_flag, heap ); break; case REC_DECIMAL_LSE: type = new (heap) SQLDecimal(column_desc->length, column_desc->scale, TRUE, column_desc->null_flag, heap ); break; case REC_NUM_BIG_UNSIGNED: type = new (heap) SQLBigNum(column_desc->precision, column_desc->scale, TRUE, // is a real bignum FALSE, column_desc->null_flag, heap ); break; case REC_NUM_BIG_SIGNED: type = new (heap) SQLBigNum(column_desc->precision, column_desc->scale, TRUE, // is a real bignum TRUE, column_desc->null_flag, heap ); break; case REC_FLOAT32: type = new (heap) SQLReal(column_desc->null_flag, heap, column_desc->precision); break; case REC_FLOAT64: type = new (heap) SQLDoublePrecision(column_desc->null_flag, heap, column_desc->precision); break; case REC_BYTE_F_DOUBLE: charCount /= SQL_DBCHAR_SIZE; // divide the storage length by 2 type = new (heap) SQLChar(charCount, column_desc->null_flag, column_desc->upshift, column_desc->caseinsensitive, FALSE, column_desc->character_set, column_desc->collation_sequence, CharInfo::IMPLICIT ); break; case REC_BYTE_F_ASCII: if (column_desc->character_set == CharInfo::UTF8 || (column_desc->character_set == CharInfo::SJIS && column_desc->encoding_charset == CharInfo::SJIS)) { Lng32 maxBytesPerChar = CharInfo::maxBytesPerChar(column_desc->character_set); Lng32 sizeInChars = charCount ; // Applies when CharLenUnit == BYTES if ( column_desc->precision > 0 ) sizeInChars = column_desc->precision; type = new (heap) SQLChar(CharLenInfo(sizeInChars, charCount/*in_bytes*/), column_desc->null_flag, column_desc->upshift, column_desc->caseinsensitive, FALSE, // varLenFlag column_desc->character_set, column_desc->collation_sequence, CharInfo::IMPLICIT, // Coercibility column_desc->encoding_charset ); } else // keep the old behavior type = new (heap) SQLChar(charCount, column_desc->null_flag, column_desc->upshift, column_desc->caseinsensitive, FALSE, column_desc->character_set, column_desc->collation_sequence, CharInfo::IMPLICIT ); break; case REC_BYTE_V_DOUBLE: charCount /= SQL_DBCHAR_SIZE; // divide the storage length by 2 // fall thru case REC_BYTE_V_ASCII: if (column_desc->character_set == CharInfo::SJIS || column_desc->character_set == CharInfo::UTF8) { Lng32 maxBytesPerChar = CharInfo::maxBytesPerChar(column_desc->character_set); Lng32 sizeInChars = charCount ; // Applies when CharLenUnit == BYTES if ( column_desc->precision > 0 ) sizeInChars = column_desc->precision; type = new (heap) SQLVarChar(CharLenInfo(sizeInChars, charCount/*in_bytes*/), column_desc->null_flag, column_desc->upshift, column_desc->caseinsensitive, column_desc->character_set, column_desc->collation_sequence, CharInfo::IMPLICIT, // Coercibility column_desc->encoding_charset ); } else // keep the old behavior type = new (heap) SQLVarChar(charCount, column_desc->null_flag, column_desc->upshift, column_desc->caseinsensitive, column_desc->character_set, column_desc->collation_sequence, CharInfo::IMPLICIT ); break; case REC_BYTE_V_ASCII_LONG: type = new (heap) SQLLongVarChar(charCount, FALSE, column_desc->null_flag, column_desc->upshift, column_desc->caseinsensitive, column_desc->character_set, column_desc->collation_sequence, CharInfo::IMPLICIT ); break; case REC_DATETIME: type = DatetimeType::constructSubtype( column_desc->null_flag, column_desc->datetimestart, column_desc->datetimeend, column_desc->datetimefractprec, heap ); CMPASSERT(type); if (!type->isSupportedType()) { column_desc->defaultClass = COM_NO_DEFAULT; // can't set a default for these, either. // 4030 Column is an unsupported combination of datetime fields if (!errorCode) { *CmpCommon::diags() << DgSqlCode(4030) << DgColumnName(makeColumnName(table, column_desc)) << DgInt0(column_desc->datetimestart) << DgInt1(column_desc->datetimeend) << DgInt2(column_desc->datetimefractprec); } else { *errorCode = 4030; } } break; case REC_INTERVAL: type = new (heap) SQLInterval(column_desc->null_flag, column_desc->datetimestart, column_desc->intervalleadingprec, column_desc->datetimeend, column_desc->datetimefractprec, heap ); CMPASSERT(type); if (! ((SQLInterval *)type)->checkValid(CmpCommon::diags())) return TRUE; // error if (!type->isSupportedType()) { column_desc->defaultClass = COM_NO_DEFAULT; // can't set a default for these, either. if (!errorCode) *CmpCommon::diags() << DgSqlCode(3044) << DgString0(column_desc->colname); else *errorCode = 3044; } break; case REC_BLOB : type = new (heap) SQLBlob(column_desc->precision, Lob_Invalid_Storage, column_desc->null_flag); break; case REC_CLOB : type = new (heap) SQLClob(column_desc->precision, Lob_Invalid_Storage, column_desc->null_flag); break; default: { // 4031 Column %s is an unknown data type, %d. if (!errorCode) { *CmpCommon::diags() << DgSqlCode(-4031) << DgColumnName(makeColumnName(table, column_desc)) << DgInt0(column_desc->datatype); } else { *errorCode = 4031; } return TRUE; // error } } // end switch (column_desc->datatype) CMPASSERT(type); if (type->getTypeQualifier() == NA_CHARACTER_TYPE) { CharInfo::Collation co = ((CharType *)type)->getCollation(); // a "mini-cache" to avoid proc call, for perf static THREAD_P CharInfo::Collation cachedCO = CharInfo::UNKNOWN_COLLATION; static THREAD_P Int32 cachedFlags = CollationInfo::ALL_NEGATIVE_SYNTAX_FLAGS; if (cachedCO != co) { cachedCO = co; cachedFlags = CharInfo::getCollationFlags(co); } if (cachedFlags & CollationInfo::ALL_NEGATIVE_SYNTAX_FLAGS) { // //## The NCHAR/COLLATE NSK-Rel1 project is forced to disallow all user- // defined collations here. What we can't handle is: // - full support! knowledge of how to really collate! // - safe predicate-ability of collated columns, namely // . ORDER/SEQUENCE/SORT BY // MIN/MAX // < <= > >= // These *would* have been disallowed by the // CollationInfo::ORDERED_CMP_ILLEGAL flag. // . DISTINCT // GROUP BY // = <> // These *would* have been disallowed by the // CollationInfo::EQ_NE_CMP_ILLEGAL flag. // . SELECTing a collated column which is a table or index key // We *would* have done full table scan only, based on flag // . INS/UPD/DEL involving a collated column which is a key // We *would* have had to disallow this, based on flag; // otherwise we would position in wrong and corrupt either // our partitioning or b-trees or both. // See the "MPcollate.doc" document, and // see sqlcomp/DefaultValidator.cpp ValidateCollationList comments. // { // 4069 Column TBL.COL uses unsupported collation COLLAT. if (!errorCode) { *CmpCommon::diags() << DgSqlCode(-4069) << DgColumnName(makeColumnName(table, column_desc)); } else { *errorCode= 4069; } return TRUE; // error } } } return FALSE; // no error } // createNAType()
// Apply defaults to self, and then (ANSI 12.1 SR 3) apply self to SchemaDB. NABoolean StmtModule::applyDefaults(NABoolean wantR18behavior) { NABoolean err = FALSE; if (charSet().isNull()) charSet() = CharInfo::getCharSetName(CharInfo::DefaultCharSet); if (CharInfo::isCharSetSupported(charSet())) { // Get charset name in canonical format (the name of the enum of the name). charSet() = CharInfo::getCharSetName(CharInfo::getCharSetEnum(charSet())); } else { *CmpCommon::diags() << DgSqlCode(-3010) << DgString0(charSet()); err = TRUE; } if (!CharInfo::isModuleCharSetSupported(CharInfo::getCharSetEnum(charSet()))) { *CmpCommon::diags() << DgSqlCode(-3404) << DgString0(charSet()); err = TRUE; } // Here we're using internal-format names if (name().getCatalogName().isNull()) { // Must be an Ansi name, not an MPLOC. const SchemaName& defcs = ActiveSchemaDB()->getDefaultSchema( SchemaDB::REFRESH_CACHE | SchemaDB::FORCE_ANSI_NAMETYPE); if (name().getSchemaName().isNull()) { if (name().getObjectName().isNull()) { name().setObjectName("SQLMX_DEFAULT_MODULE_"); } name().setSchemaName(defcs.getSchemaName()); } name().setCatalogName(defcs.getCatalogName()); } if (wantR18behavior) { // And now we use external-format names, for the ANSI 12.1 SR 3 stuff. NAString catName(name().getCatalogNameAsAnsiString()); if (!ActiveSchemaDB()->getDefaults().setCatalog(catName)) err = TRUE; NAString schName(name().getUnqualifiedSchemaNameAsAnsiString()); if (!ActiveSchemaDB()->getDefaults().setSchema(schName)) err = TRUE; } else { // want R2 (correct) behavior // We used to take the catalog & schema of the module directive and apply // them above as the default catalog & schema. This was a misguided // attempt to "use external-format names, for the ANSI 12.1 SR 3 stuff" // in the SQL92 std. // // In SQL99, this has been clarified in section 13.1 of ISO/IEC FDIS // 9075-2:1999 (aka the 1999 Foundation doc) where syntax rules 3 & 4 // specify that: // // "If the explicit or implicit <schema name> does not specify a <catalog // name>, then an implementation-defined <catalog name> is implicit." // // "The implicit or explicit <catalog name> is the implicit <catalog name> // for all unqualified <schema name>s in the <SQL-client module // definition>." // // Three observations may be worth pointing out here: // 1) SQL/MX client modules do not have a <module authorization clause> as // specified by the SQL99 std. // 2) Even if (in the future) SQL/MX tries to conform to the SQL99 std for // client module definition(s), the SQL99 std itself (syntax rule 3) // allows us to use "an implementation-defined <catalog name>" to // implicitly qualify unqualified <schema name>s. // 3) This current "implementation is a deviation from ANSI in // that the module name is a 3-part name. This deviation and the use of // cat/sch name to qualify unqualified SQL objects in the module are // also 'valid' implementation of the 2 syntax rules 13.1, rules 3 & 4 // of ANSI." // Similar logic can be applied to using an implementation-defined // <schema name> to implicitly qualify unqualified table names, etc. // // In other words, our technique of using CQD default CATALOG & SCHEMA // settings to qualify unqualified table names, view names, etc is allowed // for by the SQL99 std. // // Deleting the old code that was here is part of the fix to genesis // cases 10-030725-8215, 10-030730-8326, 10-030826-0792. } return err; }
Lng32 AddKeyGroups() { HSGlobalsClass *hs_globals = GetHSContext(); if (HSGlobalsClass::isHiveCat(hs_globals->objDef->getCatName())) { // HSHiveTableDef::getKeyList()/getIndexArray() not yet implemented. *CmpCommon::diags() << DgSqlCode(-UERR_NO_ONEVERYKEY) << DgString0("hive"); return -1; } Lng32 retcode = 0; Lng32 numColsInGroup = 0; HSColumnStruct col; NAString tempColList = ""; NAString tempCol; NAString autoGroup; ULng32 numKeys; ULng32 i, j; NATable* naTbl = hs_globals->objDef->getNATable(); HSLogMan *LM = HSLogMan::Instance(); // ---------------------------------------------------------- // Generate histograms for KEY // ---------------------------------------------------------- // The clustering index is included in the list of indices returned by // NATable::getIndexList(), so we store its pointer so we can skip it // when the other indexes are processed below. NAFileSet* clusteringIndex = naTbl->getClusteringIndex(); const NAColumnArray& keyCols = clusteringIndex->getIndexKeyColumns(); Lng32 colPos; numKeys = keyCols.entries(); if (numKeys == 1) // SINGLE-COLUMN KEY { colPos = keyCols[0]->getPosition(); if (LM->LogNeeded()) { sprintf(LM->msg, "\t\tKEY:\t\t(%s)", hs_globals->objDef->getColName(colPos)); LM->Log(LM->msg); } if (ColumnExists(colPos)) // avoid duplicates { LM->Log("\t\t** duplicate column group has been ignored."); } else // add to single-column group list { retcode = AddSingleColumn(colPos); } } else if (numKeys > 1) // MULTI-COLUMN KEY { // Create multiple MC group(s) if numkeys > 1. Subset MC groups will // also be created if numkeys > 2, E.g. If numkeys = 5, then // MC groups with 5, 4, 3, and 2 columns will be created using // the key columns. Note that if numkeys is larger than CQD // USTAT_NUM_MC_GROUPS_FOR_KEYS (default = 5), then the number // of groups created will be limited by this value. So, e.g. if // numkeys = 10, then MC groups with 5, 4, 3, and 2 columns will // be created (that is, 5 groups will be created - incl the single). ULng32 minMCGroupSz = 2; ULng32 maxMCGroups = (ULng32) CmpCommon::getDefaultNumeric(USTAT_NUM_MC_GROUPS_FOR_KEYS); // Generate no MCs with more cols than specified by the cqd. if (numKeys > maxMCGroups) numKeys = maxMCGroups; // For salted table, generate only the longest MC for the key (subject // to max cols determined above) unless a cqd is set to gen all MCs of // allowable sizes. if (CmpCommon::getDefault(USTAT_ADD_SALTED_KEY_PREFIXES_FOR_MC) == DF_OFF && hs_globals->objDef->getColNum("_SALT_", FALSE) >= 0) minMCGroupSz = numKeys; while (numKeys >= minMCGroupSz) // Create only MC groups not single cols { HSColSet colSet; autoGroup = "("; for (j = 0; j < numKeys; j++) { colPos = keyCols[j]->getPosition(); col = hs_globals->objDef->getColInfo(colPos); col.colnum = colPos; colSet.insert(col); autoGroup += col.colname->data(); autoGroup += ","; } if (LM->LogNeeded()) { autoGroup.replace(autoGroup.length()-1,1,")"); // replace comma with close parenthesis sprintf(LM->msg, "\t\tKEY:\t\t%s", autoGroup.data()); LM->Log(LM->msg); } if (retcode = AddColumnSet(colSet)) { HSHandleError(retcode); } numKeys--; } } // ---------------------------------------------------------- // Generate histograms for all INDEXES // ---------------------------------------------------------- const NAFileSetList& indexes = naTbl->getIndexList(); NAFileSet* index; for (i = 0; i < indexes.entries(); i++ ) { index = indexes[i]; if (index == clusteringIndex) continue; // clustering index processed above already const NAColumnArray& keyCols = index->getIndexKeyColumns(); numKeys = keyCols.entries(); if (numKeys == 1) // SINGLE-COLUMN INDEX { colPos = keyCols[0]->getPosition(); if (LM->LogNeeded()) { sprintf(LM->msg, "\t\tINDEX[%d]\t(%s)", i, hs_globals->objDef->getColName(colPos)); LM->Log(LM->msg); } if (ColumnExists(colPos)) // avoid duplicates { LM->Log("\t\t*** duplicate column group has been ignored."); } else // add to single-column group list { retcode = AddSingleColumn(colPos); } } else // MULTI-COLUMN INDEX { // Create multiple MC group(s) if numkeys > 1. Subset MC groups will // also be created if numkeys > 2, E.g. If numkeys = 5, then // MC groups with 5, 4, 3, and 2 columns will be created using // the key columns. Note that if numkeys is larger than CQD // USTAT_NUM_MC_GROUPS_FOR_KEYS (default = 5), then the number // of groups created will be limited by this value. So, e.g. if // numkeys = 10, then MC groups with 10, 9, 8, 7, 6 columns will // be created (that is, 5 groups will be created). ULng32 minMCGroupSz = 2; ULng32 maxMCGroups = (ULng32) CmpCommon::getDefaultNumeric(USTAT_NUM_MC_GROUPS_FOR_KEYS); if (numKeys > maxMCGroups) minMCGroupSz = numKeys - maxMCGroups + 1; while (numKeys >= minMCGroupSz) // MinMCGroupSz is greater than 1. { HSColSet colSet; tempColList = ""; autoGroup = "("; for (j = 0; j < numKeys; j++) { colPos = keyCols[j]->getPosition(); tempCol = "."; tempCol += LongToNAString(colPos); tempCol += "."; // Eliminate duplicate columns in the index; // They may have been introduced by appending the key to the specified index. if (!tempColList.contains(tempCol)) { col = hs_globals->objDef->getColInfo(colPos); col.colnum = colPos; colSet.insert((const struct HSColumnStruct) col); tempColList += tempCol.data(); numColsInGroup++; autoGroup += col.colname->data(); autoGroup += ","; } } if (colSet.entries()) { if (numColsInGroup > 1) { if (LM->LogNeeded()) { autoGroup.replace(autoGroup.length()-1,1,")"); // replace comma with close parenthesis sprintf(LM->msg, "\t\tINDEX[%d]\t%s", i, autoGroup.data()); LM->Log(LM->msg); } if (retcode = AddColumnSet(colSet)) { HSHandleError(retcode); } } numColsInGroup = 0; } numKeys--; } } } return retcode; }
ExprNode * ElemDDLPartitionSystem::bindNode(BindWA * /*pBindWA*/) { // // location // ComLocationName defaultLocName; // empty object if (getLocationName().isNull()) // // location clause not specified (only allowed for primary partition) // guardianLocation_ = defaultLocName.getGuardianFullyQualifiedName(); else // LOCATION clause was specified { ComLocationName locName; // empty object switch (getLocationNameType()) { case ElemDDLLocation::LOCATION_GUARDIAN_NAME : locName.copy(getLocationName(), ComLocationName::GUARDIAN_LOCATION_NAME_FORMAT); if (NOT locName.isValid()) { // Illegal location name format. *SqlParser_Diags << DgSqlCode(-3061) << DgString0(getLocationName()); guardianLocation_ = defaultLocName.getGuardianFullyQualifiedName(); } else // valid location guardianLocation_ = locName.getGuardianFullyQualifiedName(); break; case ElemDDLLocation::LOCATION_OSS_NAME : locName.copy(getLocationName(), ComLocationName::OSS_LOCATION_NAME_FORMAT); if (NOT locName.isValid()) { // Illegal location name format. *SqlParser_Diags << DgSqlCode(-3061) << DgString0(getLocationName()); guardianLocation_ = defaultLocName.getGuardianFullyQualifiedName(); } else // valid location guardianLocation_ = locName.getGuardianFullyQualifiedName(); break; #if 0 // // Currently we do not handle this case // The grammar productions don't accept this syntax. // So comment out the following code for now. // case ElemDDLLocation::LOCATION_ENVIRONMENT_VARIABLE : { NAString envVarName(getLocationName()); // // if the specified OSS environment variable has the // dollar sign prefix, removes it. // if (envVarName[(size_t) 0] EQU '$') // NT_PORT FIX SK 07/15/96 { envVarName = envVarName(1/*startpos*/, envVarName.length() - 1); } const char * pEnvVarValue = getenv((const char *)envVarName); NAString locationName; if (pEnvVarValue NEQ NULL) { locationName = pEnvVarValue; } if (locationName.isNull()) { guardianLocation_ = defaultLocName. getGuardianFullyQualifiedName(); } else { guardianLocationName = locationName; if (guardianLocationName.isValid()) { guardianLocation_ = (guardianLocationName. getGuardianFullyQualifiedName()); } else { ossLocationName = locationName; if (ossLocationName.isValid()) { guardianLocation_ = (ossLocationName. getGuardianFullyQualifiedName()); } else { // OSS environment variable $1~string1 contains illegal // location name $0~string0. *SqlParser_Diags << DgSqlCode(-3061) << DgString0(locationName) << DgString1(envVarName) ; } } } } break; #endif // 0 default : NAAbort("ElemDDLPartition.C", __LINE__, "internal logic error"); break; } } markAsBound(); return this; }
// return next token ExtQualModuleNames::tokenType ExtQualModuleNames::scanner() { currentToken_ = ""; if (atEnd()) { return SCANEOF; } while (!atEnd()) { const char cc = returnAdvanceChar(); if (isspace((unsigned char)cc)) { // For VS2003... continue; // do nothing } else if (isalpha(cc)) { // regular identifier currentToken_ += cc; while (isalnum(currentChar()) || currentChar() == '_') { currentToken_ += currentChar(); advanceChar(); } // convert id to internal format (ie, uppercase it) NAString id(currentToken_.c_str()); if (ToInternalIdentifier(id) != 0) { *mxCUMptr << FAIL << DgSqlCode(-2215) << DgString0(currentToken_.c_str()); } currentToken_ = id.data(); return checkReserved(); } currentToken_ += cc; switch (cc) { case '{' : case '}' : case ',' : case '.' : case '=' : return tokenType(cc); case '"': // "delimited identifier" specified by \"([^\"]|"\"\"")*\" while (!atEnd()) { const char c1 = returnAdvanceChar(); currentToken_ += c1; if (c1 == '"') { if (currentChar() == '"') { currentToken_ += currentChar(); } else { // end of delimited identifier // convert delimited id to internal format NAString id(currentToken_.c_str()); if (ToInternalIdentifier(id, FALSE, TRUE) != 0) { *mxCUMptr << FAIL << DgSqlCode(-2209) << DgString0(currentToken_.c_str()); } currentToken_ = id.data(); return ID; } } } *mxCUMptr << FAIL << DgSqlCode(-2210); // unterminated string return ID; default: advanceChar(); *mxCUMptr << FAIL << DgSqlCode(-2211) << DgString0(currentToken_.c_str()); return SCANERROR; } } return SCANEOF; }
short CmpSeabaseDDL::validateRoutine(ExeCliInterface *cliInterface, const char * className, const char * methodName, const char * externalPath, char * signature, Int32 numSqlParam, Int32 maxResultSets, const char * optionalSig) { // // Now proceed with the internal CALL statement... // Lng32 sigLen = 0; if (signature) sigLen = str_len(signature) + 1; char * query = new(STMTHEAP) char[2000+sigLen]; str_sprintf(query, "call %s.\"%s\".%s ('%s', '%s', '%s', '%s', %d, %d, %d, ?x, ?y, ?z)", getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_VALIDATE_SPJ, className, methodName, externalPath, signature, numSqlParam, maxResultSets, optionalSig ? 1 : 0); Lng32 cliRC = cliInterface->fetchRowsPrologue(query, TRUE/*no exec*/); if (cliRC < 0) { cliInterface->retrieveSQLDiagnostics(CmpCommon::diags()); return -1; } cliRC = cliInterface->clearExecFetchClose(NULL, 0); if (cliRC < 0) { cliInterface->retrieveSQLDiagnostics(CmpCommon::diags()); return -1; } NADELETEBASIC(query, STMTHEAP); char * ptr = NULL; Lng32 len = 0; Int32 errCode = 0; cliInterface->getPtrAndLen(1, ptr, len); str_cpy_all(signature, ptr, len); signature[len] = '\0'; cliInterface->getPtrAndLen(2, ptr, len); errCode = *(Int32 *)ptr; // in code below methodName may need to be added to the signature that is printed // out in some error messages. // Check for errors returned from VALIDATEROUTINE switch (errCode) { case 0://Success - Check to see if returned signature is null if (signature[0] NEQ '\0') return 0; else return -1; break; case 11205://Class not found *CmpCommon::diags() << DgSqlCode(-errCode) << DgString0(className) << DgString1(externalPath); break; case 11206://Class definition not found *CmpCommon::diags() << DgSqlCode(-errCode) << DgString0(className); break; case 11230://Overloaded methods were found *CmpCommon::diags() << DgSqlCode(-errCode) << DgString0(methodName) << DgString1(className); break; case 11239://No compatible methods were found *CmpCommon::diags() << DgSqlCode(-errCode) << DgString0(methodName) << DgString1(className); break; case 11231://Method found but not public if(signature[0] NEQ '\0') *CmpCommon::diags() << DgSqlCode(-errCode) << DgString0(signature) << DgString1(className); break; case 11232://Method found but not static if(signature[0] NEQ '\0') *CmpCommon::diags() << DgSqlCode(-errCode) << DgString0(signature) << DgString1(className); break; case 11233://Method found but not void if(signature[0] NEQ '\0') *CmpCommon::diags() << DgSqlCode(-errCode) << DgString0(signature) << DgString1(className); break; case 11234://Method not found if(signature[0] NEQ '\0') *CmpCommon::diags() << DgSqlCode(-errCode) << DgString0(signature) << DgString1(className); break; default://Unknown error code break ; } return -1; } // CmpSeabaseDDL::validateRoutine
void CmpSeabaseDDL::createSeabaseLibrary( StmtDDLCreateLibrary * createLibraryNode, NAString &currCatName, NAString &currSchName) { Lng32 retcode = 0; ComObjectName libraryName(createLibraryNode->getLibraryName()); ComAnsiNamePart currCatAnsiName(currCatName); ComAnsiNamePart currSchAnsiName(currSchName); libraryName.applyDefaults(currCatAnsiName, currSchAnsiName); const NAString catalogNamePart = libraryName.getCatalogNamePartAsAnsiString(); const NAString schemaNamePart = libraryName.getSchemaNamePartAsAnsiString(TRUE); const NAString objectNamePart = libraryName.getObjectNamePartAsAnsiString(TRUE); const NAString extLibraryName = libraryName.getExternalName(TRUE); const NAString extNameForHbase = catalogNamePart + "." + schemaNamePart + "." + objectNamePart; // Verify that the requester has MANAGE_LIBRARY privilege. if (isAuthorizationEnabled() && !ComUser::isRootUserID()) { NAString privMgrMDLoc; CONCAT_CATSCH(privMgrMDLoc, getSystemCatalog(), SEABASE_PRIVMGR_SCHEMA); PrivMgrComponentPrivileges componentPrivileges(std::string(privMgrMDLoc.data()),CmpCommon::diags()); if (!componentPrivileges.hasSQLPriv (ComUser::getCurrentUser(),SQLOperation::MANAGE_LIBRARY,true)) { *CmpCommon::diags() << DgSqlCode(-CAT_NOT_AUTHORIZED); processReturn (); return; } } // Check to see if user has the authority to create the library ExeCliInterface cliInterface(STMTHEAP, NULL, NULL, CmpCommon::context()->sqlSession()->getParentQid()); Int32 objectOwnerID = SUPER_USER; Int32 schemaOwnerID = SUPER_USER; ComSchemaClass schemaClass; retcode = verifyDDLCreateOperationAuthorized(&cliInterface, SQLOperation::CREATE_LIBRARY, catalogNamePart, schemaNamePart, schemaClass, objectOwnerID, schemaOwnerID); if (retcode != 0) { handleDDLCreateAuthorizationError(retcode,catalogNamePart,schemaNamePart); return; } ExpHbaseInterface * ehi = NULL; ehi = allocEHI(); if (ehi == NULL) { processReturn(); return; } retcode = existsInSeabaseMDTable(&cliInterface, catalogNamePart, schemaNamePart, objectNamePart, COM_LIBRARY_OBJECT, TRUE, FALSE); if (retcode < 0) { deallocEHI(ehi); processReturn(); return; } if (retcode == 1) // already exists { *CmpCommon::diags() << DgSqlCode(-1390) << DgString0(extLibraryName); deallocEHI(ehi); processReturn(); return; } NAString libFileName = createLibraryNode->getFilename() ; // strip blank spaces libFileName = libFileName.strip(NAString::both, ' '); if (validateLibraryFileExists(libFileName, FALSE)) { deallocEHI(ehi); processReturn(); return; } ComTdbVirtTableTableInfo * tableInfo = new(STMTHEAP) ComTdbVirtTableTableInfo[1]; tableInfo->tableName = NULL, tableInfo->createTime = 0; tableInfo->redefTime = 0; tableInfo->objUID = 0; tableInfo->objOwnerID = objectOwnerID; tableInfo->schemaOwnerID = schemaOwnerID; tableInfo->isAudited = 1; tableInfo->validDef = 1; tableInfo->hbaseCreateOptions = NULL; tableInfo->numSaltPartns = 0; tableInfo->rowFormat = COM_UNKNOWN_FORMAT_TYPE; tableInfo->objectFlags = 0; Int64 objUID = -1; if (updateSeabaseMDTable(&cliInterface, catalogNamePart, schemaNamePart, objectNamePart, COM_LIBRARY_OBJECT, "N", tableInfo, 0, NULL, 0, NULL, 0, NULL, objUID)) { deallocEHI(ehi); processReturn(); return; } if (objUID == -1) { deallocEHI(ehi); processReturn(); return; } char * query = new(STMTHEAP) char[1000]; str_sprintf(query, "insert into %s.\"%s\".%s values (%Ld, '%s', %d)", getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_LIBRARIES, objUID, libFileName.data(), createLibraryNode->getVersion()); Lng32 cliRC = cliInterface.executeImmediate(query); NADELETEBASIC(query, STMTHEAP); if (cliRC < 0) { cliInterface.retrieveSQLDiagnostics(CmpCommon::diags()); processReturn(); return; } // hope to remove this call soon by setting thevalid flag to Y sooner if (updateObjectValidDef(&cliInterface, catalogNamePart, schemaNamePart, objectNamePart, COM_LIBRARY_OBJECT_LIT, "Y")) { deallocEHI(ehi); processReturn(); return; } processReturn(); return; }
// constructor ElemDDLColDef::ElemDDLColDef( const NAString *columnFamily, const NAString *columnName, NAType * pColumnDataType, ElemDDLNode * pColAttrList, CollHeap * heap) : ElemDDLNode(ELM_COL_DEF_ELEM), columnName_(*columnName, heap), columnDataType_(pColumnDataType), defaultClauseStatus_(DEFAULT_CLAUSE_NOT_SPEC), isNewAdjustedDefaultConstValueNode_(FALSE), pDefault_(NULL), isHeadingSpec_(FALSE), heading_(heap), columnClass_(COM_USER_COLUMN), isNotNullSpec_(FALSE), isNotNullNondroppable_(FALSE), isLoggableSpec_(FALSE), isLoggable_(TRUE), pConstraintNotNull_(NULL), isPrimaryKeySpec_(FALSE), pConstraintPK_(NULL), columnConstraintArray_(heap), primaryKeyColRefArray_(heap), direction_(COM_OUTPUT_COLUMN), pSGOptions_(NULL), pSGLocation_(NULL), isDivisionColumn_(FALSE), divisionColumnSeqNum_(-1), isLobAttrsSpec_(FALSE), lobStorage_(Lob_HDFS_File), isSeabaseSerializedSpec_(FALSE), seabaseSerialized_(FALSE), isColDefaultSpec_(FALSE) { // ComASSERT(pColumnDataType NEQ NULL); if (columnFamily) columnFamily_ = *columnFamily; if (pColumnDataType NEQ NULL) { const NAString dataTypeName = pColumnDataType->getTypeName(); // Create table with data type DATETIME not supported. Must check for DATE, // TIME, and TIMESTAMP as well since DATETIME might be converted into these, if( dataTypeName == "DATETIME" || dataTypeName == "DATE" || dataTypeName == "TIME" || dataTypeName == "TIMESTAMP" ) { // Check flag to see if DATETIME originally specified if( ((DatetimeIntervalCommonType *)pColumnDataType)-> getDTIFlag(DatetimeIntervalCommonType::UNSUPPORTED_DDL_DATA_TYPE)) { // Only put error into diags if it doesn't already contain it if(!SqlParser_Diags->contains(-3195)) { *SqlParser_Diags << DgSqlCode(-3195) << DgString0("DATETIME"); } return; } } // Create table with data type INTERVAL with FRACTION field(s) not supported else if (dataTypeName == "INTERVAL") { // Check flag to see if FRACTION was originally specified if( ((DatetimeIntervalCommonType *)pColumnDataType)-> getDTIFlag(DatetimeIntervalCommonType::UNSUPPORTED_DDL_DATA_TYPE)) { // Only put error into diags if it doesn't already contain it if(!SqlParser_Diags->contains(-3195)) { *SqlParser_Diags << DgSqlCode(-3195) << DgString0("INTERVAL with FRACTION field(s)"); } return; } // Check to see if interval second is specified with leading // precision of 0 if(!((SQLInterval *)pColumnDataType)->isSupportedType()) { // Only put error into diags if it doesn't already contain it if(!SqlParser_Diags->contains(-3195)) { *SqlParser_Diags << DgSqlCode(-3195) << DgString0("INTERVAL SECOND with leading precision 0"); } return; } } } setChild(INDEX_ELEM_DDL_COL_ATTR_LIST, pColAttrList); // initialize data member pDefault_ ComBoolean isIdentityColumn = FALSE; // // Traverse the list of column attributes to check for duplicate // HEADING clause and duplicate NOT NULL column constraint definition // if (pColAttrList NEQ NULL) { for (CollIndex index = 0; index < pColAttrList->entries(); index++) { setColumnAttribute((*pColAttrList)[index]); } } // At this point we will know if the user // has specified NOT NULL NOT DROPPABLE for IDENTITY // column. If not specified, then automatically add // it. if (pSGOptions_) //isIdentityColumn { // if NOT NULL not specified, then specify it here. if(NOT getIsConstraintNotNullSpecified()) isNotNullSpec_ = TRUE; // [NOT] DROPPABLE is the only attribute for NOT NULL. if (pConstraintNotNull_) { // if DROPPABLE was specified explicity then raise an error. if (pConstraintNotNull_->isDroppableSpecifiedExplicitly()) { *SqlParser_Diags << DgSqlCode(-3413) << DgColumnName(ToAnsiIdentifier(getColumnName())); return; } else { // add the NOT DROPPABLE attribute to the NOT NULL . pConstraintNotNull_->setConstraintAttributes (new (PARSERHEAP()) ElemDDLConstraintAttrDroppable(FALSE)); } } else { // by default NOT NULLs are NOT DROPPABLEs as well in SQL/MX pConstraintNotNull_ = new (PARSERHEAP()) ElemDDLConstraintNotNull(PARSERHEAP()); pConstraintNotNull_->setConstraintAttributes (new (PARSERHEAP()) ElemDDLConstraintAttrDroppable(FALSE)); } } //if isIdentityColumn // // All column attributes has been checked and saved. // If there exists a NOT NULL NONDROPPABLE constraint // associating with the currently defined column, makes // sure that the associating NAType (data type) parse // node does not allow null values. // if (getIsConstraintNotNullSpecified() AND NOT getConstraintNotNull()->isDroppable()) { isNotNullNondroppable_ = TRUE; if (columnDataType_) columnDataType_->setNullable(FALSE); } } // ElemDDLColDef()
void CmpSeabaseDDL::dropSeabaseRoutine(StmtDDLDropRoutine * dropRoutineNode, NAString &currCatName, NAString &currSchName) { Lng32 retcode = 0; ComObjectName routineName(dropRoutineNode->getRoutineName()); ComAnsiNamePart currCatAnsiName(currCatName); ComAnsiNamePart currSchAnsiName(currSchName); routineName.applyDefaults(currCatAnsiName, currSchAnsiName); const NAString catalogNamePart = routineName.getCatalogNamePartAsAnsiString(); const NAString schemaNamePart = routineName.getSchemaNamePartAsAnsiString(TRUE); const NAString objectNamePart = routineName.getObjectNamePartAsAnsiString(TRUE); const NAString extRoutineName = routineName.getExternalName(TRUE); ExpHbaseInterface * ehi = NULL; ExeCliInterface cliInterface(STMTHEAP, NULL, NULL, CmpCommon::context()->sqlSession()->getParentQid()); ehi = allocEHI(); if (ehi == NULL) { processReturn(); return; } retcode = existsInSeabaseMDTable(&cliInterface, catalogNamePart, schemaNamePart, objectNamePart, COM_USER_DEFINED_ROUTINE_OBJECT, TRUE, FALSE); if (retcode < 0) { deallocEHI(ehi); processReturn(); return; } if (retcode == 0) // does not exist { *CmpCommon::diags() << DgSqlCode(-1389) << DgString0(extRoutineName); deallocEHI(ehi); processReturn(); return; } // get objectOwner Int64 objUID = 0; Int32 objectOwnerID = 0; Int32 schemaOwnerID = 0; Int64 objectFlags = 0; // see if routine is cached BindWA bindWA(ActiveSchemaDB(), CmpCommon::context(), FALSE/*inDDL*/); NARoutineDB *pRoutineDBCache = ActiveSchemaDB()->getNARoutineDB(); QualifiedName qualRoutineName(routineName, STMTHEAP); NARoutineDBKey key(qualRoutineName, STMTHEAP); NARoutine *cachedNARoutine = pRoutineDBCache->get(&bindWA, &key); if (cachedNARoutine) { objUID = cachedNARoutine->getRoutineID(); objectOwnerID = cachedNARoutine->getObjectOwner(); schemaOwnerID = cachedNARoutine->getSchemaOwner(); } else { objUID = getObjectInfo(&cliInterface, catalogNamePart.data(), schemaNamePart.data(), objectNamePart.data(), COM_USER_DEFINED_ROUTINE_OBJECT, objectOwnerID,schemaOwnerID,objectFlags); if (objUID < 0 || objectOwnerID == 0 || schemaOwnerID == 0) { deallocEHI(ehi); processReturn(); return; } } // Verify user has privilege to drop routine if (!isDDLOperationAuthorized(SQLOperation::DROP_ROUTINE,objectOwnerID,schemaOwnerID)) { *CmpCommon::diags() << DgSqlCode(-CAT_NOT_AUTHORIZED); deallocEHI(ehi); processReturn (); return; } // Determine if this function is referenced by any other objects. Lng32 cliRC = 0; Queue * usingViewsQueue = NULL; if (dropRoutineNode->getDropBehavior() == COM_RESTRICT_DROP_BEHAVIOR) { NAString usingObjName; cliRC = getUsingObject(&cliInterface, objUID, usingObjName); if (cliRC < 0) { deallocEHI(ehi); processReturn(); return; } if (cliRC != 100) // found an object { *CmpCommon::diags() << DgSqlCode(-CAT_DEPENDENT_VIEW_EXISTS) << DgTableName(usingObjName); deallocEHI(ehi); processReturn(); return; } } else if (dropRoutineNode->getDropBehavior() == COM_CASCADE_DROP_BEHAVIOR) { cliRC = getUsingViews(&cliInterface, objUID, usingViewsQueue); if (cliRC < 0) { deallocEHI(ehi); processReturn(); return; } } if (usingViewsQueue) { usingViewsQueue->position(); for (int idx = 0; idx < usingViewsQueue->numEntries(); idx++) { OutputInfo * vi = (OutputInfo*)usingViewsQueue->getNext(); char * viewName = vi->get(0); if (dropOneTableorView(cliInterface,viewName,COM_VIEW_OBJECT,false)) { deallocEHI(ehi); processReturn(); return; } } } // Removed routine from metadata if (dropSeabaseObject(ehi, dropRoutineNode->getRoutineName(), currCatName, currSchName, COM_USER_DEFINED_ROUTINE_OBJECT, TRUE, FALSE)) { deallocEHI(ehi); processReturn(); return; } // Remove cached entries in other processes pRoutineDBCache->removeNARoutine(qualRoutineName, NARoutineDB::REMOVE_FROM_ALL_USERS, objUID); deallocEHI(ehi); processReturn(); return; }
void ElemDDLColDef::setColumnAttribute(ElemDDLNode * pColAttr) { switch(pColAttr->getOperatorType()) { case ELM_COL_HEADING_ELEM : if (isHeadingSpec_) { // Duplicate HEADING clauses in column definition. *SqlParser_Diags << DgSqlCode(-3051) << DgColumnName(ToAnsiIdentifier(getColumnName())); } ComASSERT(pColAttr->castToElemDDLColHeading() NEQ NULL); heading_ = pColAttr->castToElemDDLColHeading()->getColumnHeading(); isHeadingSpec_ = TRUE; // Report an error if heading_ is too long. if (heading_.length() > ElemDDLColHeading::maxHeadingLength) { *SqlParser_Diags << DgSqlCode(-3132) << DgColumnName(ToAnsiIdentifier(getColumnName())); } break; case ELM_CONSTRAINT_CHECK_ELEM : ComASSERT(pColAttr->castToElemDDLConstraintCheck() NEQ NULL); columnConstraintArray_.insert(pColAttr->castToElemDDLConstraint()); break; case ELM_CONSTRAINT_NOT_NULL_ELEM : ComASSERT(pColAttr->castToElemDDLConstraintNotNull() NEQ NULL); if (isNotNullSpec_) { // Duplicate NOT NULL clauses in column definition. *SqlParser_Diags << DgSqlCode(-3052) << DgString0("NOT NULL") << DgColumnName(ToAnsiIdentifier(getColumnName())); } isNotNullSpec_ = TRUE; pConstraintNotNull_ = pColAttr->castToElemDDLConstraintNotNull(); if (NOT pConstraintNotNull_->isDroppable()) { isNotNullNondroppable_ = TRUE; if (columnDataType_) columnDataType_->setNullable(FALSE); } // Note that we do not insert pConstraintNotNull_ into // columnConstraintArray_ even though Not Null constraint is // also a column constraint. The user can use the accessors // getIsConstraintNotNullSpecified and getConstraintNotNull // instead. break; case ELM_LOGGABLE: ComASSERT( NULL NEQ pColAttr->castToElemDDLLoggable()) if(TRUE == isLoggableSpec_) { // Duplicate LOGGABLE in column definition. *SqlParser_Diags << DgSqlCode(-12064) << DgColumnName(ToAnsiIdentifier(getColumnName())); } isLoggableSpec_ = TRUE; isLoggable_ = pColAttr->castToElemDDLLoggable()->getIsLoggable(); break; case ELM_CONSTRAINT_PRIMARY_KEY_COLUMN_ELEM : { ComASSERT(pColAttr->castToElemDDLConstraintPKColumn() NEQ NULL); ComASSERT(pColAttr->castToElemDDLConstraintPKColumn() ->getConstraintKind() EQU ElemDDLConstraint::COLUMN_CONSTRAINT_DEF); if (isPrimaryKeySpec_) { // Duplicate PRIMARY KEY clauses in column definition. *SqlParser_Diags << DgSqlCode(-3053) << DgColumnName(ToAnsiIdentifier(getColumnName())); } isPrimaryKeySpec_ = TRUE; ElemDDLConstraintPKColumn * pColPKConstraint = pColAttr->castToElemDDLConstraintPKColumn(); // // Copies the pointer to the parse node representing the column // primary key constraint to pConstraintPK_ so the user (caller) // can access the information easier. Note that this pointer is // not inserted into columnConstraintArray_ because primary key // constraint is special. (There can only be one primary key // constraint associating with a table.) The user (caller) can // use method getIsConstraintPKSpecified() and getConstraintPK() // to get the primary key constraint information. // pConstraintPK_ = pColPKConstraint; // The column name is not specified in the column primary key // constraint definition. To make the user (caller) to access // to this information easier, creates a parse node containing // the column name. ComASSERT(pColPKConstraint->getColumnRefList() EQU NULL); ElemDDLColRef * pColRef = new(PARSERHEAP()) ElemDDLColRef(getColumnName(), pColPKConstraint-> getColumnOrdering(), PARSERHEAP()); pColPKConstraint->setColumnRefList(pColRef); primaryKeyColRefArray_.insert(pColRef); } break; case ELM_CONSTRAINT_REFERENTIAL_INTEGRITY_ELEM : { ComASSERT(pColAttr->castToElemDDLConstraintRI() NEQ NULL); ComASSERT(pColAttr->castToElemDDLConstraintRI()->getConstraintKind() EQU ElemDDLConstraint::COLUMN_CONSTRAINT_DEF); columnConstraintArray_.insert(pColAttr->castToElemDDLConstraint()); // // The column name is not specified in the column referential // integrity constraint definition. To make the user (caller) // to access to this information easier, creates a parse node // containing the column name. // ElemDDLConstraintRI * pColRIConstraint = pColAttr->castToElemDDLConstraintRI(); ComASSERT(pColRIConstraint->getReferencingColumnNameList() EQU NULL); ElemDDLColName * pColName = new(PARSERHEAP()) ElemDDLColName(getColumnName()); pColRIConstraint->setReferencingColumnNameList(pColName); } break; case ELM_CONSTRAINT_UNIQUE_ELEM : { ComASSERT(pColAttr->castToElemDDLConstraintUnique() NEQ NULL); ComASSERT(pColAttr->castToElemDDLConstraintUnique()->getConstraintKind() EQU ElemDDLConstraint::COLUMN_CONSTRAINT_DEF); columnConstraintArray_.insert(pColAttr->castToElemDDLConstraint()); // // The column name is not specified in the column unique // constraint definition. To make the user (caller) to access // to this information easier, creates a parse node containing // the column name. // ElemDDLConstraintUnique * pColUniqueConstraint = pColAttr->castToElemDDLConstraintUnique(); ComASSERT(pColUniqueConstraint->getColumnRefList() EQU NULL); ElemDDLColRef * pColRef = new(PARSERHEAP()) ElemDDLColRef(getColumnName(), COM_ASCENDING_ORDER, PARSERHEAP()); pColUniqueConstraint->setColumnRefList(pColRef); } break; case ELM_LOBATTRS: { ComASSERT( NULL NEQ pColAttr->castToElemDDLLobAttrs()) if(TRUE == isLobAttrsSpec_) { // Duplicate LOB attrs in column definition. *SqlParser_Diags << DgSqlCode(-3052) << DgString0("LOB") << DgColumnName(ToAnsiIdentifier(getColumnName())); } isLobAttrsSpec_ = TRUE; lobStorage_ = pColAttr->castToElemDDLLobAttrs()->getLobStorage(); } break; case ELM_SEABASE_SERIALIZED: { ComASSERT( NULL NEQ pColAttr->castToElemDDLSeabaseSerialized()) if(TRUE == isSeabaseSerializedSpec_) { // Duplicate SERIALIZED attrs in column definition. *SqlParser_Diags << DgSqlCode(-3052) << DgString0("SERIALIZED") << DgColumnName(ToAnsiIdentifier(getColumnName())); } isSeabaseSerializedSpec_ = TRUE; seabaseSerialized_ = pColAttr->castToElemDDLSeabaseSerialized()->serialized(); } break; case ELM_COL_DEFAULT_ELEM: { ComASSERT( NULL NEQ pColAttr->castToElemDDLColDefault()); if(TRUE == isColDefaultSpec_) { // Duplicate DEFAULT attrs in column definition. *SqlParser_Diags << DgSqlCode(-3052) << DgString0("DEFAULT") << DgColumnName(ToAnsiIdentifier(getColumnName())); } isColDefaultSpec_ = TRUE; setDefaultAttribute(pColAttr->castToElemDDLColDefault()); } break; default : ABORT("internal logic error"); break; } // switch }
void ElemDDLColDef::setDefaultAttribute(ElemDDLNode * pColDefaultNode) { ElemDDLColDefault * pColDefault = NULL; ComBoolean isIdentityColumn = FALSE; NAType * pColumnDataType = columnDataType_; if (pColDefaultNode NEQ NULL) { ComASSERT(pColDefaultNode->castToElemDDLColDefault() NEQ NULL); pColDefault = pColDefaultNode->castToElemDDLColDefault(); } if (pColDefault NEQ NULL) { switch (pColDefault->getColumnDefaultType()) { case ElemDDLColDefault::COL_NO_DEFAULT: defaultClauseStatus_ = NO_DEFAULT_CLAUSE_SPEC; break; case ElemDDLColDefault::COL_DEFAULT: { defaultClauseStatus_ = DEFAULT_CLAUSE_SPEC; if (pColDefault->getSGOptions()) { isIdentityColumn = TRUE; pSGOptions_ = pColDefault->getSGOptions(); pSGLocation_ = pColDefault->getSGLocation(); } else { ComASSERT(pColDefault->getDefaultValueExpr() NEQ NULL); pDefault_ = pColDefault->getDefaultValueExpr(); } // The cast ItemExpr to ConstValue for (ConstValue *)pDefault_; // statement below sets arbitary value for the isNULL_. // Bypass these checks for ID column (basically ITM_IDENTITY). ConstValue *cvDef = (ConstValue *)pDefault_; if ((cvDef && !cvDef->isNull()) && (!isIdentityColumn)) { const NAType *cvTyp = cvDef->getType(); NABoolean isAnErrorAlreadyIssued = FALSE; if ( cvTyp->getTypeQualifier() == NA_CHARACTER_TYPE ) { CharInfo::CharSet defaultValueCS = ((const CharType *)cvTyp)->getCharSet(); // Always check for INFER_CHARSET setting before the ICAT setting. NAString inferCharSetFlag; if (getCharSetInferenceSetting(inferCharSetFlag) == TRUE && NOT cvDef->isStrLitWithCharSetPrefixSpecified()) { if (pColumnDataType->getTypeQualifier() == NA_CHARACTER_TYPE && ((const CharType *)pColumnDataType)->getCharSet() == CharInfo::UCS2 && SqlParser_DEFAULT_CHARSET == CharInfo::UCS2 && defaultValueCS == CharInfo::ISO88591 ) { *SqlParser_Diags << DgSqlCode(-1186) << DgColumnName(ToAnsiIdentifier(getColumnName())) << DgString0(pColumnDataType->getTypeSQLname(TRUE/*terse*/)) << DgString1(cvTyp->getTypeSQLname(TRUE/*terse*/)); isAnErrorAlreadyIssued = TRUE; } else { cvTyp = cvDef -> pushDownType(*columnDataType_, NA_CHARACTER_TYPE); } } else if (CmpCommon::getDefault(ALLOW_IMPLICIT_CHAR_CASTING) == DF_ON && NOT cvDef->isStrLitWithCharSetPrefixSpecified() && cvTyp->getTypeQualifier() == NA_CHARACTER_TYPE && SqlParser_DEFAULT_CHARSET == CharInfo::ISO88591 && defaultValueCS == CharInfo::UnknownCharSet) { cvTyp = cvDef -> pushDownType(*columnDataType_, NA_CHARACTER_TYPE); } } // column default value has character data type if (NOT isAnErrorAlreadyIssued && pColumnDataType->getTypeQualifier() == NA_CHARACTER_TYPE && cvTyp->getTypeQualifier() == NA_CHARACTER_TYPE && ( CmpCommon::getDefault(ALLOW_IMPLICIT_CHAR_CASTING) == DF_ON || NOT cvDef->isStrLitWithCharSetPrefixSpecified())) { const CharType *cdCharType = (const CharType *)pColumnDataType; const CharType *cvCharType = (const CharType *)cvTyp; CharInfo::CharSet cdCharSet = cdCharType->getCharSet(); // cd = column definition CharInfo::CharSet cvCharSet = cvCharType->getCharSet(); // cv = constant value if (cvCharSet == CharInfo::ISO88591) // default value is a _ISO88591 str lit { } else if ( (cvCharSet == CharInfo::UNICODE || // default value is a _UCS2 string literal cvCharSet == CharInfo::UTF8) && // or a _UTF8 string literal cdCharSet != cvCharSet ) { // // Check to see if all characters in the specified column default // string literal value can be successfully converted/translated // to the actual character set of the column. // char buf[2032]; // the output buffer - should be big enough buf[0] = '\0'; enum cnv_charset eCnvCS = convertCharsetEnum( cdCharSet ); const char * pInStr = cvDef->getRawText()->data(); Int32 inStrLen = cvDef->getRawText()->length(); char * p1stUnstranslatedChar = NULL; UInt32 outStrLenInBytes = 0; unsigned charCount = 0; // number of characters translated/converted Int32 cnvErrStatus = 0; char *pSubstitutionChar = NULL; Int32 convFlags = 0; if ( cvCharSet == CharInfo::UNICODE ) { cnvErrStatus = UTF16ToLocale ( cnv_version1 // in - const enum cnv_version version , pInStr // in - const char *in_bufr , inStrLen // in - const int in_len , buf // out - const char *out_bufr , 2016 // in - const int out_len , eCnvCS // in - enum cnv_charset charset , p1stUnstranslatedChar // out - char * & first_untranslated_char , &outStrLenInBytes // out - unsigned int *output_data_len_p , convFlags // in - const int cnv_flags , (Int32)TRUE // in - const int addNullAtEnd_flag , (Int32)FALSE // in - const int allow_invalids , &charCount // out - unsigned int * translated_char_cnt_p , pSubstitutionChar // in - const char *substitution_char ); } else // cvCharSet must be CharInfo::UTF8 { cnvErrStatus = UTF8ToLocale ( cnv_version1 // in - const enum cnv_version version , pInStr // in - const char *in_bufr , inStrLen // in - const int in_len , buf // out - const char *out_bufr , 2016 // in - const int out_len , eCnvCS // in - enum cnv_charset charset , p1stUnstranslatedChar // out - char * & first_untranslated_char , &outStrLenInBytes // out - unsigned int *output_data_len_p , (Int32)TRUE // in - const int addNullAtEnd_flag , (Int32)FALSE // in - const int allow_invalids , &charCount // out - unsigned int * translated_char_cnt_p , pSubstitutionChar // in - const char *substitution_char ); } switch (cnvErrStatus) { case 0: // success case CNV_ERR_NOINPUT: // an empty input string will get this error code { ConstValue *pMBStrLitConstValue ; // convert the string literal saved in cvDef (column default value) // from UNICODE (e.g. UTF16) to the column character data type if ( cdCharSet != CharInfo::UNICODE) { NAString mbs2(buf, PARSERHEAP()); // note that buf is NULL terminated pMBStrLitConstValue = new(PARSERHEAP()) ConstValue ( mbs2 , cdCharSet // use this for str lit prefix , CharInfo::DefaultCollation , CharInfo::COERCIBLE , PARSERHEAP() ); } else { NAWString mbs2((NAWchar*)buf, PARSERHEAP()); // note that buf is NULL terminated pMBStrLitConstValue = new(PARSERHEAP()) ConstValue ( mbs2 , cdCharSet // use this for str lit prefix , CharInfo::DefaultCollation , CharInfo::COERCIBLE , PARSERHEAP() ); } delete pDefault_; // deallocate the old ConstValue object cvDef = NULL; // do not use cvDef anymore pDefault_ = pMBStrLitConstValue; pColDefault->setDefaultValueExpr(pDefault_); } break; case CNV_ERR_INVALID_CHAR: { // 1401 == CAT_UNABLE_TO_CONVERT_COLUMN_DEFAULT_VALUE_TO_CHARSET *SqlParser_Diags << DgSqlCode(-1401) << DgColumnName(ToAnsiIdentifier(getColumnName())) << DgString0(CharInfo::getCharSetName(cdCharSet)); } break; case CNV_ERR_BUFFER_OVERRUN: // output buffer not big enough case CNV_ERR_INVALID_CS: default: CMPABORT_MSG("Parser internal logic error"); break; } // switch } else if(!pColumnDataType->isCompatible(*cvTyp)) { if (NOT isAnErrorAlreadyIssued) { *SqlParser_Diags << DgSqlCode(-1186) << DgColumnName(ToAnsiIdentifier(getColumnName())) << DgString0(pColumnDataType->getTypeSQLname(TRUE/*terse*/)) << DgString1(cvTyp->getTypeSQLname(TRUE/*terse*/)); isAnErrorAlreadyIssued = TRUE; } } } // column has character data type else // if interval data type, the default value must have the same // interval qualifier as the column. if (NOT isAnErrorAlreadyIssued && (!pColumnDataType->isCompatible(*cvTyp) || (pColumnDataType->getTypeQualifier() == NA_INTERVAL_TYPE && pColumnDataType->getFSDatatype() != cvTyp->getFSDatatype()))) { *SqlParser_Diags << DgSqlCode(-1186) << DgColumnName(ToAnsiIdentifier(getColumnName())) << DgString0(pColumnDataType->getTypeSQLname(TRUE/*terse*/)) << DgString1(cvTyp->getTypeSQLname(TRUE/*terse*/)); isAnErrorAlreadyIssued = TRUE; } } } break; case ElemDDLColDefault::COL_COMPUTED_DEFAULT: { defaultClauseStatus_ = DEFAULT_CLAUSE_SPEC; computedDefaultExpr_ = pColDefault->getComputedDefaultExpr(); } break; default: CMPABORT_MSG("Parser internal logic error"); break; } } }
short PhysSample::codeGen(Generator *generator) { // Get a local handle on some of the generator objects. // CollHeap *wHeap = generator->wHeap(); Space *space = generator->getSpace(); MapTable *mapTable = generator->getMapTable(); ExpGenerator *expGen = generator->getExpGenerator(); // Allocate a new map table for this node. This must be done // before generating the code for my child so that this local // map table will be sandwiched between the map tables already // generated and the map tables generated by my offspring. // // Only the items available as output from this node will // be put in the local map table. Before exiting this function, all of // my offsprings map tables will be removed. Thus, none of the outputs // from nodes below this node will be visible to nodes above it except // those placed in the local map table and those that already exist in // my ancestors map tables. This is the standard mechanism used in the // generator for managing the access to item expressions. // MapTable *localMapTable = generator->appendAtEnd(); // Since this operation doesn't modify the row on the way down the tree, // go ahead and generate the child subtree. Capture the given composite row // descriptor and the child's returned TDB and composite row descriptor. // ex_cri_desc * givenCriDesc = generator->getCriDesc(Generator::DOWN); child(0)->codeGen(generator); ComTdb *childTdb = (ComTdb*)generator->getGenObj(); ex_cri_desc * childCriDesc = generator->getCriDesc(Generator::UP); ExplainTuple *childExplainTuple = generator->getExplainTuple(); // Geneate the sampling expression. // ex_expr *balExpr = NULL; Int32 returnFactorOffset = 0; ValueId val; val = balanceExpr().init(); if(balanceExpr().next(val)) expGen->generateSamplingExpr(val, &balExpr, returnFactorOffset); // Alias the sampleColumns() so that they reference the underlying // expressions directly. This is done to avoid having to generate and // execute a project expression that simply moves the columns from // one tupp to another to reflect the application of the sampledCol // function. // // ValueId valId; // for(valId = sampledColumns().init(); // sampledColumns().next(valId); // sampledColumns().advance(valId)) // { // MapInfo *mapInfoChild = localMapTable->getMapInfoAsIs // (valId.getItemExpr()->child(0)->castToItemExpr()->getValueId()); // GenAssert(mapInfoChild, "Sample::codeGen -- no child map info."); // Attributes *attr = mapInfoChild->getAttr(); // MapInfo *mapInfo = localMapTable->addMapInfoToThis(valId, attr); // mapInfo->codeGenerated(); // } // check if any of the columns inthe sampled columns are lob columns. If so, return an error. ValueId valId; for(valId = sampledColumns().init(); sampledColumns().next(valId); sampledColumns().advance(valId)) { const NAType &colType = valId.getType(); if ((colType.getFSDatatype() == REC_BLOB) || (colType.getFSDatatype() == REC_CLOB)) { *CmpCommon::diags() << DgSqlCode(-4322); GenExit(); } } // Now, remove all attributes from the map table except the // the stuff in the local map table -- the result of this node. // // localMapTable->removeAll(); // Generate the expression to evaluate predicate on the sampled row. // ex_expr *postPred = 0; if (!selectionPred().isEmpty()) { ItemExpr * newPredTree = selectionPred().rebuildExprTree(ITM_AND,TRUE,TRUE); expGen->generateExpr(newPredTree->getValueId(), ex_expr::exp_SCAN_PRED, &postPred); } // Construct the Sample TDB. // ComTdbSample *sampleTdb = new(space) ComTdbSample(NULL, balExpr, returnFactorOffset, postPred, childTdb, givenCriDesc, childCriDesc, (queue_index)getDefault(GEN_SAMPLE_SIZE_DOWN), (queue_index)getDefault(GEN_SAMPLE_SIZE_UP)); generator->initTdbFields(sampleTdb); if(!generator->explainDisabled()) { generator-> setExplainTuple(addExplainInfo(sampleTdb, childExplainTuple, 0, generator)); } generator->setCriDesc(givenCriDesc, Generator::DOWN); generator->setCriDesc(childCriDesc, Generator::UP); generator->setGenObj(this, sampleTdb); return 0; }
NABoolean CmpSqlSession::validateVolatileQualifiedName(QualifiedName &inName) { if (NOT Get_SqlParser_Flags(ALLOW_VOLATILE_SCHEMA_IN_TABLE_NAME)) { if (NOT inName.getCatalogName().isNull()) { // cannot be a 3-part name *CmpCommon::diags() << DgSqlCode(-4192); return FALSE; } if (NOT inName.getSchemaName().isNull()) { // validate that the schemaName part is the currentUserName if (inName.getSchemaName() != externalUserName_) { *CmpCommon::diags() << DgSqlCode(-4191) << DgString0(inName.getSchemaName()) << DgString1(externalUserName_); return FALSE; } } } else { // Volatile schema name is allowed. // Make sure that it is a valid volatile 3 part name. if ((NOT inName.getCatalogName().isNull()) && (NOT inName.getSchemaName().isNull())) { // move to a temp to upcase ComSchemaName csn(inName.getSchemaName()); ULng32 len = MINOF(strlen(csn.getSchemaNamePartAsAnsiString().data()), strlen(COM_VOLATILE_SCHEMA_PREFIX)); NAString upSch(csn.getSchemaNamePartAsAnsiString().data()); upSch.toUpper(); if ((len < strlen(COM_VOLATILE_SCHEMA_PREFIX)) || (strncmp(upSch.data(), COM_VOLATILE_SCHEMA_PREFIX, len) != 0)) { *CmpCommon::diags() << DgSqlCode(-4192); return FALSE; } } else if (NOT inName.getSchemaName().isNull()) { // 2 part name // validate that the schemaName part is the currentUserName if (inName.getSchemaName() != externalUserName_) { *CmpCommon::diags() << DgSqlCode(-4191) << DgString0(inName.getSchemaName()) << DgString1(externalUserName_); return FALSE; } } } return TRUE; }
void CmpSeabaseDDL::dropSeabaseLibrary(StmtDDLDropLibrary * dropLibraryNode, NAString &currCatName, NAString &currSchName) { Lng32 cliRC = 0; Lng32 retcode = 0; const NAString &objName = dropLibraryNode->getLibraryName(); ComObjectName libraryName(objName); ComAnsiNamePart currCatAnsiName(currCatName); ComAnsiNamePart currSchAnsiName(currSchName); libraryName.applyDefaults(currCatAnsiName, currSchAnsiName); const NAString catalogNamePart = libraryName. getCatalogNamePartAsAnsiString(); const NAString schemaNamePart = libraryName. getSchemaNamePartAsAnsiString(TRUE); const NAString objectNamePart = libraryName. getObjectNamePartAsAnsiString(TRUE); const NAString extLibraryName = libraryName.getExternalName(TRUE); ExeCliInterface cliInterface(STMTHEAP, NULL, NULL, CmpCommon::context()->sqlSession()->getParentQid()); ExpHbaseInterface * ehi = allocEHI(); if (ehi == NULL) return; retcode = existsInSeabaseMDTable(&cliInterface, catalogNamePart, schemaNamePart, objectNamePart, COM_LIBRARY_OBJECT, TRUE, FALSE); if (retcode < 0) { deallocEHI(ehi); processReturn(); return; } if (retcode == 0) // does not exist { *CmpCommon::diags() << DgSqlCode(-1389) << DgString0(extLibraryName); deallocEHI(ehi); processReturn(); return; } Int32 objectOwnerID = 0; Int32 schemaOwnerID = 0; Int64 objectFlags = 0; Int64 objUID = getObjectInfo(&cliInterface, catalogNamePart.data(), schemaNamePart.data(), objectNamePart.data(), COM_LIBRARY_OBJECT, objectOwnerID,schemaOwnerID,objectFlags); if (objUID < 0 || objectOwnerID == 0 || schemaOwnerID == 0) { deallocEHI(ehi); processReturn(); return; } if (!isDDLOperationAuthorized(SQLOperation::DROP_LIBRARY, objectOwnerID, schemaOwnerID)) { *CmpCommon::diags() << DgSqlCode(-CAT_NOT_AUTHORIZED); processReturn (); return; } Queue * usingRoutinesQueue = NULL; cliRC = getUsingRoutines(&cliInterface, objUID, usingRoutinesQueue); if (cliRC < 0) { deallocEHI(ehi); processReturn(); return; } // If RESTRICT and the library is being used, return an error if (cliRC != 100 && dropLibraryNode->getDropBehavior() == COM_RESTRICT_DROP_BEHAVIOR) { *CmpCommon::diags() << DgSqlCode(-CAT_DEPENDENT_ROUTINES_EXIST); deallocEHI(ehi); processReturn(); return; } for (size_t i = 0; i < usingRoutinesQueue->numEntries(); i++) { usingRoutinesQueue->position(); OutputInfo * rou = (OutputInfo*)usingRoutinesQueue->getNext(); char * routineName = rou->get(0); ComObjectType objectType = PrivMgr::ObjectLitToEnum(rou->get(1)); if (dropSeabaseObject(ehi, routineName, currCatName, currSchName, objectType, TRUE, FALSE)) { deallocEHI(ehi); processReturn(); return; } } // can get a slight perf. gain if we pass in objUID if (dropSeabaseObject(ehi, objName, currCatName, currSchName, COM_LIBRARY_OBJECT, TRUE, FALSE)) { deallocEHI(ehi); processReturn(); return; } deallocEHI(ehi); processReturn(); return; }
ExWorkProcRetcode ExCancelTcb::work() { ExMasterStmtGlobals *masterGlobals = getGlobals()->castToExExeStmtGlobals()->castToExMasterStmtGlobals(); CliGlobals *cliGlobals = masterGlobals->getCliGlobals(); while ((qparent_.down->isEmpty() == FALSE) && (qparent_.up->isFull() == FALSE)) { ex_queue_entry *pentry_down = qparent_.down->getHeadEntry(); switch (step_) { case NOT_STARTED: { if (pentry_down->downState.request == ex_queue::GET_NOMORE) step_ = DONE; else { retryCount_ = 0; // Priv checking is done during compilation. To support // REVOKE, prevent a prepared CANCEL/SUSPEND/ACTIVATE // that was compiled more than 1 second ago from executing // by raising the 8734 error to force an AQR. Int64 microSecondsSinceCompile = NA_JulianTimestamp() - masterGlobals->getStatement()->getCompileEndTime(); if (microSecondsSinceCompile > 1000*1000) { ComDiagsArea *diagsArea = ComDiagsArea::allocate(getGlobals()->getDefaultHeap()); *diagsArea << DgSqlCode(-CLI_INVALID_QUERY_PRIVS); reportError(diagsArea); step_ = DONE; break; } // Figure out which MXSSMP broker to use. if (cancelTdb().getAction() == ComTdbCancel::CancelByPname) { int nid = -1; int rc = msg_mon_get_process_info(cancelTdb().getCancelPname(), &nid, &pid_); switch (rc) { case XZFIL_ERR_OK: cpu_ = (short) nid; break; case XZFIL_ERR_NOTFOUND: case XZFIL_ERR_BADNAME: case XZFIL_ERR_NOSUCHDEV: { ComDiagsArea *diagsArea = ComDiagsArea::allocate(getGlobals()->getDefaultHeap()); *diagsArea << DgSqlCode(-EXE_CANCEL_PROCESS_NOT_FOUND); *diagsArea << DgString0(cancelTdb().getCancelPname()); reportError(diagsArea); step_ = DONE; break; } default: { char buf[200]; str_sprintf(buf, "Unexpected error %d returned from " "msg_mon_get_process_info", rc); ex_assert(0, buf); } } if (step_ != NOT_STARTED) break; } else if (cancelTdb().getAction() == ComTdbCancel::CancelByNidPid) { cpu_ = (short) cancelTdb().getCancelNid(); pid_ = cancelTdb().getCancelPid(); // check that process exists, if not report error. char processName[MS_MON_MAX_PROCESS_NAME]; int rc = msg_mon_get_process_name(cpu_, pid_, processName); if (XZFIL_ERR_OK == rc) ; // good. nid & pid are valid. else { if ((XZFIL_ERR_NOTFOUND != rc) && (XZFIL_ERR_BADNAME != rc) && (XZFIL_ERR_NOSUCHDEV != rc)) { // Log rc in case it needs investigation later. char buf[200]; str_sprintf(buf, "Unexpected error %d returned from " "msg_mon_get_process_name", rc); SQLMXLoggingArea::logExecRtInfo(__FILE__, __LINE__, buf, 0); } char nid_pid_str[32]; str_sprintf(nid_pid_str, "%d, %d", cpu_, pid_); ComDiagsArea *diagsArea = ComDiagsArea::allocate(getGlobals()->getDefaultHeap()); *diagsArea << DgSqlCode(-EXE_CANCEL_PROCESS_NOT_FOUND); *diagsArea << DgString0(nid_pid_str); reportError(diagsArea); step_ = DONE; break; } } else { char * qid = cancelTdb().qid_; Lng32 qid_len = str_len(qid); // This static method is defined in SqlStats.cpp. It side-effects // the nodeName and cpu_ according to the input qid. if (getMasterCpu( qid, qid_len, nodeName_, sizeof(nodeName_) - 1, cpu_) == -1) { ComDiagsArea *diagsArea = ComDiagsArea::allocate(getGlobals()->getDefaultHeap()); *diagsArea << DgSqlCode(-EXE_RTS_INVALID_QID); reportError(diagsArea); step_ = DONE; break; } } // Testpoints for hard to reproduce problems: bool fakeError8028 = false; fakeError8028 = (getenv("HP_FAKE_ERROR_8028") != NULL); if ((cliGlobals->getCbServerClass() == NULL) || fakeError8028) { ComDiagsArea *diagsArea = ComDiagsArea::allocate(getGlobals()->getDefaultHeap()); *diagsArea << DgSqlCode(-EXE_CANCEL_PROCESS_NOT_FOUND); *diagsArea << DgString0("$ZSM000"); reportError(diagsArea); step_ = DONE; break; } ComDiagsArea *diagsArea = NULL; bool fakeError2024 = false; fakeError2024 = (getenv("HP_FAKE_ERROR_2024") != NULL); if (fakeError2024) { cbServer_ = NULL; diagsArea = ComDiagsArea::allocate(getGlobals()->getDefaultHeap()); if (getenv("HP_FAKE_ERROR_8142")) { *diagsArea << DgSqlCode(-8142); *diagsArea << DgString0(__FILE__); *diagsArea << DgString1("cbServer_ is NULL"); } else *diagsArea << DgSqlCode(-2024); } else cbServer_ = cliGlobals->getCbServerClass()->allocateServerProcess( &diagsArea, cliGlobals->getEnvironment()->getHeap(), nodeName_, cpu_, IPC_PRIORITY_DONT_CARE, FALSE, // usesTransactions TRUE, // waitedCreation 2 // maxNowaitRequests -- cancel+(1 extra). ); if (cbServer_ == NULL || cbServer_->getControlConnection() == NULL) { ex_assert(diagsArea != NULL, "allocateServerProcess failed, but no diags"); // look for SQLCode 2024 // "*** ERROR[2024] Server Process $0~string0 // is not running or could not be created. Operating System // Error $1~int0 was returned." // Remap to cancel-specfic error 8028. if (diagsArea->contains(-2024) && cancelTdb().actionIsCancel()) { diagsArea->deleteError(diagsArea->returnIndex(-2024)); reportError(diagsArea, true, EXE_CANCEL_PROCESS_NOT_FOUND, nodeName_, cpu_); } else reportError(diagsArea); step_ = DONE; break; } // the reportError method was not called -- see break above. if (diagsArea != NULL) diagsArea->decrRefCount(); //Create the stream on the IpcHeap, since we don't dispose // of it immediately. We just add it to the list of completed // messages in the IpcEnv, and it is disposed of later. cancelStream_ = new (cliGlobals->getIpcHeap()) CancelMsgStream(cliGlobals->getEnvironment(), this); cancelStream_->addRecipient(cbServer_->getControlConnection()); } step_ = SEND_MESSAGE; break; } // end case NOT_STARTED #pragma warning (disable : 4291) case SEND_MESSAGE: { RtsHandle rtsHandle = (RtsHandle) this; if (cancelTdb().actionIsCancel()) { Int64 cancelStartTime = JULIANTIMESTAMP(); Lng32 firstEscalationInterval = cliGlobals->currContext()-> getSessionDefaults()->getCancelEscalationInterval(); Lng32 secondEscalationInterval = cliGlobals->currContext()-> getSessionDefaults()->getCancelEscalationMxosrvrInterval(); NABoolean cancelEscalationSaveabend = cliGlobals->currContext()-> getSessionDefaults()->getCancelEscalationSaveabend(); bool cancelLogging = (TRUE == cliGlobals->currContext()-> getSessionDefaults()->getCancelLogging()); CancelQueryRequest *cancelMsg = new (cliGlobals->getIpcHeap()) CancelQueryRequest(rtsHandle, cliGlobals->getIpcHeap(), cancelStartTime, firstEscalationInterval, secondEscalationInterval, cancelEscalationSaveabend, cancelTdb().getCommentText(), str_len(cancelTdb().getCommentText()), cancelLogging, cancelTdb().action_ != ComTdbCancel::CancelByQid, pid_, cancelTdb().getCancelPidBlockThreshold()); #pragma warning (default : 4291) *cancelStream_ << *cancelMsg; cancelMsg->decrRefCount(); } else if (ComTdbCancel::Suspend == cancelTdb().action_) { bool suspendLogging = (TRUE == cliGlobals->currContext()-> getSessionDefaults()->getSuspendLogging()); #pragma warning (disable : 4291) SuspendQueryRequest * suspendMsg = new (cliGlobals->getIpcHeap()) SuspendQueryRequest(rtsHandle, cliGlobals->getIpcHeap(), ComTdbCancel::Force == cancelTdb().forced_, suspendLogging); #pragma warning (default : 4291) *cancelStream_ << *suspendMsg; suspendMsg->decrRefCount(); } else { ex_assert( ComTdbCancel::Activate == cancelTdb().action_, "invalid action for ExCancelTcb"); bool suspendLogging = (TRUE == cliGlobals->currContext()-> getSessionDefaults()->getSuspendLogging()); #pragma warning (disable : 4291) ActivateQueryRequest * activateMsg = new (cliGlobals->getIpcHeap()) ActivateQueryRequest(rtsHandle, cliGlobals->getIpcHeap(), suspendLogging); #pragma warning (default : 4291) *cancelStream_ << *activateMsg; activateMsg->decrRefCount(); } if ((cancelTdb().getAction() != ComTdbCancel::CancelByPname) && (cancelTdb().getAction() != ComTdbCancel::CancelByNidPid)) { char * qid = cancelTdb().qid_; Lng32 qid_len = str_len(qid); #pragma warning (disable : 4291) RtsQueryId *rtsQueryId = new (cliGlobals->getIpcHeap()) RtsQueryId( cliGlobals->getIpcHeap(), qid, qid_len); #pragma warning (default : 4291) *cancelStream_ << *rtsQueryId; rtsQueryId->decrRefCount(); } // send a no-wait request to the cancel broker. cancelStream_->send(FALSE); step_ = GET_REPLY; // Come back when I/O completes. return WORK_OK; break; } // end case SEND_MESSAGE case GET_REPLY: { // Handle general IPC error. bool fakeError201 = false; fakeError201 = (getenv("HP_FAKE_ERROR_201") != NULL); if ((cbServer_->getControlConnection()->getErrorInfo() != 0) || fakeError201) { ComDiagsArea *diagsArea = ComDiagsArea::allocate(getGlobals()->getDefaultHeap()); cbServer_->getControlConnection()-> populateDiagsArea( diagsArea, getGlobals()->getDefaultHeap()); if (fakeError201) { *diagsArea << DgSqlCode(-2034) << DgInt0(201) << DgString0("I say") << DgString1("control broker"); } if (diagsArea->contains(-8921)) { // Should not get timeout error 8921. Get a core-file // of the SSMP and this process too so that this can be // debugged. cbServer_->getControlConnection()-> dumpAndStopOtherEnd(true, false); genLinuxCorefile("Unexpected timeout error"); } reportError(diagsArea); step_ = DONE; break; } // See if stream has the reply yet. if (!cancelStream_->moreObjects()) return WORK_OK; #pragma warning (disable : 4291) ControlQueryReply *reply = new (cliGlobals->getIpcHeap()) ControlQueryReply(INVALID_RTS_HANDLE, cliGlobals->getIpcHeap()); #pragma warning (default : 4291) *cancelStream_ >> *reply; if (reply->didAttemptControl()) { // yeaah! cancelStream_->clearAllObjects(); } else { if (cancelStream_->moreObjects() && cancelStream_->getNextObjType() == IPC_SQL_DIAG_AREA) { ComDiagsArea *diagsArea = ComDiagsArea::allocate(getGlobals()->getDefaultHeap()); *cancelStream_ >> *diagsArea; cancelStream_->clearAllObjects(); if ( retryQidNotActive_ && (diagsArea->mainSQLCODE() == -EXE_SUSPEND_QID_NOT_ACTIVE) && (++retryCount_ <= 60)) { SQLMXLoggingArea::logExecRtInfo(__FILE__, __LINE__, "Retrying error 8672.", 0); DELAY(500); diagsArea->decrRefCount(); step_ = SEND_MESSAGE; break; } reportError(diagsArea); } else ex_assert(0, "Control failed, but no diagnostics."); } step_ = DONE; break; } case DONE: { if (cancelStream_) { cancelStream_->addToCompletedList(); cancelStream_ = NULL; } if (cbServer_) { cbServer_->release(); cbServer_ = NULL; } ex_queue_entry * up_entry = qparent_.up->getTailEntry(); up_entry->copyAtp(pentry_down); up_entry->upState.parentIndex = pentry_down->downState.parentIndex; up_entry->upState.downIndex = qparent_.down->getHeadIndex(); up_entry->upState.setMatchNo(1); up_entry->upState.status = ex_queue::Q_NO_DATA; qparent_.up->insert(); qparent_.down->removeHead(); step_ = NOT_STARTED; break; } default: ex_assert( 0, "Unknown step_."); }
void CmpSeabaseDDL::createSeabaseRoutine( StmtDDLCreateRoutine * createRoutineNode, NAString &currCatName, NAString &currSchName) { Lng32 retcode = 0; ComObjectName routineName(createRoutineNode->getRoutineName()); ComAnsiNamePart currCatAnsiName(currCatName); ComAnsiNamePart currSchAnsiName(currSchName); routineName.applyDefaults(currCatAnsiName, currSchAnsiName); const NAString catalogNamePart = routineName.getCatalogNamePartAsAnsiString(); const NAString schemaNamePart = routineName.getSchemaNamePartAsAnsiString(TRUE); const NAString objectNamePart = routineName.getObjectNamePartAsAnsiString(TRUE); const NAString extRoutineName = routineName.getExternalName(TRUE); ComRoutineType rType = createRoutineNode->getRoutineType(); ComRoutineLanguage language = createRoutineNode->getLanguageType(); ComRoutineParamStyle ddlStyle = createRoutineNode->getParamStyle(); ComRoutineParamStyle style = ddlStyle; NABoolean isJava = (language == COM_LANGUAGE_JAVA); // Check to see if user has the authority to create the routine ExeCliInterface cliInterface(STMTHEAP, NULL, NULL, CmpCommon::context()->sqlSession()->getParentQid()); Int32 objectOwnerID = SUPER_USER; Int32 schemaOwnerID = SUPER_USER; ComSchemaClass schemaClass; retcode = verifyDDLCreateOperationAuthorized(&cliInterface, SQLOperation::CREATE_ROUTINE, catalogNamePart, schemaNamePart, schemaClass, objectOwnerID, schemaOwnerID); if (retcode != 0) { handleDDLCreateAuthorizationError(retcode,catalogNamePart,schemaNamePart); return; } ExpHbaseInterface * ehi = NULL; ehi = allocEHI(); if (ehi == NULL) { processReturn(); return; } retcode = existsInSeabaseMDTable(&cliInterface, catalogNamePart, schemaNamePart, objectNamePart, COM_USER_DEFINED_ROUTINE_OBJECT, TRUE, FALSE); if (retcode < 0) { deallocEHI(ehi); processReturn(); return; } if (retcode == 1) // already exists { *CmpCommon::diags() << DgSqlCode(-1390) << DgString0(extRoutineName); deallocEHI(ehi); processReturn(); return; } ComObjectName libName(createRoutineNode-> getLibraryName().getQualifiedNameAsAnsiString()); libName.applyDefaults(currCatAnsiName, currSchAnsiName); NAString libCatNamePart = libName.getCatalogNamePartAsAnsiString(); NAString libSchNamePart = libName.getSchemaNamePartAsAnsiString(TRUE); NAString libObjNamePart = libName.getObjectNamePartAsAnsiString(TRUE); const NAString extLibraryName = libName.getExternalName(TRUE); char externalPath[512] ; Lng32 cliRC = 0; // this call needs to change Int64 libUID = getObjectUID(&cliInterface, libCatNamePart, libSchNamePart, libObjNamePart, COM_LIBRARY_OBJECT_LIT); if (libUID < 0) { processReturn(); return; } if (libUID == 0) // does not exist { *CmpCommon::diags() << DgSqlCode(-1361) << DgString0(extLibraryName); deallocEHI(ehi); processReturn(); return; } // read the library path name from the LIBRARIES metadata table char * buf = new(STMTHEAP) char[200]; str_sprintf(buf, "select library_filename from %s.\"%s\".%s" " where library_uid = %Ld for read uncommitted access", getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_LIBRARIES, libUID); cliRC = cliInterface.fetchRowsPrologue(buf, TRUE/*no exec*/); if (cliRC < 0) { cliInterface.retrieveSQLDiagnostics(CmpCommon::diags()); deallocEHI(ehi); processReturn(); return; } cliRC = cliInterface.clearExecFetchClose(NULL, 0); if (cliRC < 0) { cliInterface.retrieveSQLDiagnostics(CmpCommon::diags()); deallocEHI(ehi); processReturn(); return; } if (cliRC == 100) // did not find the row { *CmpCommon::diags() << DgSqlCode(-1231) << DgString0(extRoutineName); deallocEHI(ehi); processReturn(); return; } char * ptr = NULL; Lng32 len = 0; cliInterface.getPtrAndLen(1, ptr, len); str_cpy_all(externalPath, ptr, len); externalPath[len] = '\0'; // determine language and parameter styles based on the library // type, unless already specified if (!createRoutineNode->isLanguageTypeSpecified()) { NAString extPath(externalPath); size_t lastDot = extPath.last('.'); NAString libSuffix; if (lastDot != NA_NPOS) libSuffix = extPath(lastDot,extPath.length()-lastDot); libSuffix.toUpper(); if (libSuffix == ".JAR") { isJava = TRUE; language = COM_LANGUAGE_JAVA; } else if (libSuffix == ".SO" || libSuffix == ".DLL") { // a known C/C++ library, set // language and parameter style below } else { // language not specified and library name // is inconclusive, issue an error *CmpCommon::diags() << DgSqlCode( -3284 ) << DgString0( externalPath ); processReturn(); } } // set parameter style and also language, if not already // specified, based on routine type and type of library if (isJava) { // library is a jar file if (rType == COM_PROCEDURE_TYPE) // Java stored procedures use the older Java style style = COM_STYLE_JAVA_CALL; else // Java UDFs use the newer Java object style style = COM_STYLE_JAVA_OBJ; } else { // assume the library is a DLL with C or C++ code if (rType == COM_TABLE_UDF_TYPE && (language == COM_LANGUAGE_CPP || !createRoutineNode->isLanguageTypeSpecified())) { // Table UDFs (TMUDFs) default to the C++ interface language = COM_LANGUAGE_CPP; style = COM_STYLE_CPP_OBJ; } else if (rType == COM_SCALAR_UDF_TYPE && (language == COM_LANGUAGE_C || !createRoutineNode->isLanguageTypeSpecified())) { // scalar UDFs default to C and SQL parameter style language = COM_LANGUAGE_C; style = COM_STYLE_SQL; } else { // some invalid combination of routine type, language and // library type *CmpCommon::diags() << DgSqlCode(-3286); processReturn(); return; } } // C/C++ DLL if (createRoutineNode->isParamStyleSpecified() && ddlStyle != style) { // An unsupported PARAMETER STYLE was specified *CmpCommon::diags() << DgSqlCode(-3280); processReturn(); return; } NAString externalName; if (language == COM_LANGUAGE_JAVA && style == COM_STYLE_JAVA_CALL) { // the external name is a Java method signature externalName = createRoutineNode->getJavaClassName(); externalName += "." ; externalName += createRoutineNode->getJavaMethodName(); } else // the external name is a C/C++ entry point or a // Java class name externalName = createRoutineNode->getExternalName(); // Verify that current user has authority to create the routine // User must be DB__ROOT or have privileges if (isAuthorizationEnabled() && !ComUser::isRootUserID()) { // For now, go get privileges directly. If we ever cache routines, then // make sure privileges are stored in the cache. NAString privMgrMDLoc; CONCAT_CATSCH(privMgrMDLoc, getSystemCatalog(), SEABASE_PRIVMGR_SCHEMA); PrivMgrCommands privInterface(privMgrMDLoc.data(), CmpCommon::diags()); PrivMgrUserPrivs privs; PrivStatus retcode = privInterface.getPrivileges(libUID, COM_LIBRARY_OBJECT, ComUser::getCurrentUser(), privs); if (retcode != STATUS_GOOD) { if (CmpCommon::diags()->getNumber(DgSqlCode::ERROR_) == 0) SEABASEDDL_INTERNAL_ERROR("checking routine privilege"); processReturn(); return; } // Requester must have USAGE privilege on the library NABoolean hasPriv = TRUE; if ( !privs.hasUsagePriv() ) { *CmpCommon::diags() << DgSqlCode( -4481 ) << DgString0( "USAGE" ) << DgString1( extLibraryName.data()); processReturn(); return; } } ElemDDLParamDefArray &routineParamArray = createRoutineNode->getParamArray(); Lng32 numParams = routineParamArray.entries(); if ((createRoutineNode->getRoutineType() == COM_SCALAR_UDF_TYPE) && (numParams > 32)) { *CmpCommon::diags() << DgSqlCode( -1550 ) << DgString0( extRoutineName ) << DgInt0( numParams ); deallocEHI(ehi); processReturn(); return; } #define MAX_SIGNATURE_LENGTH 8193 // Allocate buffer for generated signature char sigBuf[MAX_SIGNATURE_LENGTH]; sigBuf[0] = '\0'; if (style == COM_STYLE_JAVA_CALL) { // validate routine for Java call based on signature Lng32 numJavaParam = 0; ComFSDataType *paramType = new ComFSDataType[numParams]; ComUInt32 *subType = new ComUInt32 [numParams]; ComColumnDirection *direction = new ComColumnDirection[numParams]; NAType *genericType; // Gather the param attributes for LM from the paramDefArray previously // populated and from the routineparamList generated from paramDefArray. for (CollIndex i = 0; (Int32)i < numParams; i++) { paramType[i] = (ComFSDataType)routineParamArray[i]->getParamDataType()->getFSDatatype(); subType[i] = 0; // default // Set subType for special cases detected by LM switch ( paramType[i] ) { case COM_SIGNED_BIN16_FSDT : case COM_SIGNED_BIN32_FSDT : case COM_SIGNED_BIN64_FSDT : case COM_UNSIGNED_BIN16_FSDT : case COM_UNSIGNED_BIN32_FSDT : case COM_UNSIGNED_BPINT_FSDT : { genericType = routineParamArray[i]->getParamDataType() ; if (genericType->getTypeName() == LiteralNumeric) subType[i] = genericType->getPrecision(); else subType[i] = 0 ; break; } case COM_DATETIME_FSDT : { genericType = routineParamArray[i]->getParamDataType() ; DatetimeType & datetimeType = (DatetimeType &) *genericType; if (datetimeType.getSimpleTypeName() EQU "DATE") subType[i] = 1 ; else if (datetimeType.getSimpleTypeName() EQU "TIME") subType[i] = 2; else if (datetimeType.getSimpleTypeName() EQU "TIMESTAMP") subType[i] = 3; } } // end switch paramType[i] direction[i] = (ComColumnDirection) routineParamArray[i]->getParamDirection(); } // If the syntax specified a signature, pass that to LanguageManager. NAString specifiedSig( createRoutineNode->getJavaSignature() ); char* optionalSig; if ( specifiedSig.length() == 0 ) optionalSig = NULL; else optionalSig = (char *)specifiedSig.data(); ComBoolean isJavaMain = ((str_cmp_ne(createRoutineNode->getJavaMethodName(), "main") == 0) ? TRUE : FALSE); LmResult createSigResult; LmJavaSignature *lmSignature = new (STMTHEAP) LmJavaSignature(NULL, STMTHEAP); createSigResult = lmSignature->createSig(paramType, subType, direction, numParams, COM_UNKNOWN_FSDT, 0, createRoutineNode->getMaxResults(), optionalSig, isJavaMain, sigBuf, MAX_SIGNATURE_LENGTH, CmpCommon::diags()); NADELETE(lmSignature, LmJavaSignature, STMTHEAP); delete [] paramType; delete [] subType; delete [] direction; // Lm returned error. Lm fills diags area, so no need to worry about diags. if (createSigResult == LM_ERR) { *CmpCommon::diags() << DgSqlCode(-1231) << DgString0(extRoutineName); deallocEHI(ehi); processReturn(); return; } numJavaParam = (isJavaMain ? 1 : numParams); if (validateRoutine(&cliInterface, createRoutineNode->getJavaClassName(), createRoutineNode->getJavaMethodName(), externalPath, sigBuf, numJavaParam, createRoutineNode->getMaxResults(), optionalSig)) { *CmpCommon::diags() << DgSqlCode(-1231) << DgString0(extRoutineName); deallocEHI(ehi); processReturn(); return; } } else if (style == COM_STYLE_JAVA_OBJ || style == COM_STYLE_CPP_OBJ) { // validate existence of the C++ or Java class in the library Int32 routineHandle = NullCliRoutineHandle; NAString externalPrefix(externalPath); NAString externalNameForValidation(externalName); NAString containerName; if (language == COM_LANGUAGE_C || language == COM_LANGUAGE_CPP) { // separate the actual DLL name from the prefix char separator = '/'; size_t separatorPos = externalPrefix.last(separator); if (separatorPos != NA_NPOS) { containerName = externalPrefix(separatorPos+1, externalPrefix.length()-separatorPos-1); externalPrefix.remove(separatorPos, externalPrefix.length()-separatorPos); } else { // assume the entire string is a local name containerName = externalPrefix; externalPrefix = "."; } } else { // For Java, the way the language manager works is that the // external path is the fully qualified name of the jar and // the container is the class name (external name). We load // the container (the class) by searching in the path (the // jar). The external name is the method name, which in this // case is the constructor of the class, <init>. // leave externalPrevix unchanged, fully qualified jar file containerName = externalName; externalNameForValidation = "<init>"; } // use a CLI call to validate that the library contains the routine if (cliInterface.getRoutine( NULL, // No InvocationInfo specified in this step 0, NULL, 0, (Int32) language, (Int32) style, externalNameForValidation.data(), containerName.data(), externalPrefix.data(), extLibraryName.data(), &routineHandle, CmpCommon::diags()) != LME_ROUTINE_VALIDATED) { if (routineHandle != NullCliRoutineHandle) cliInterface.putRoutine(routineHandle, CmpCommon::diags()); CMPASSERT(CmpCommon::diags()->mainSQLCODE() < 0); processReturn(); return; } cliInterface.putRoutine(routineHandle, CmpCommon::diags()); } ComTdbVirtTableColumnInfo * colInfoArray = (ComTdbVirtTableColumnInfo*) new(STMTHEAP) ComTdbVirtTableColumnInfo[numParams]; if (buildColInfoArray(&routineParamArray, colInfoArray)) { processReturn(); return; } ComTdbVirtTableTableInfo * tableInfo = new(STMTHEAP) ComTdbVirtTableTableInfo[1]; tableInfo->tableName = NULL, tableInfo->createTime = 0; tableInfo->redefTime = 0; tableInfo->objUID = 0; tableInfo->objOwnerID = objectOwnerID; tableInfo->schemaOwnerID = schemaOwnerID; tableInfo->isAudited = 1; tableInfo->validDef = 1; tableInfo->hbaseCreateOptions = NULL; tableInfo->numSaltPartns = 0; tableInfo->rowFormat = COM_UNKNOWN_FORMAT_TYPE; tableInfo->objectFlags = 0; Int64 objUID = -1; if (updateSeabaseMDTable(&cliInterface, catalogNamePart, schemaNamePart, objectNamePart, COM_USER_DEFINED_ROUTINE_OBJECT, "N", tableInfo, numParams, colInfoArray, 0, NULL, 0, NULL, objUID)) { deallocEHI(ehi); processReturn(); return; } if (objUID == -1) { deallocEHI(ehi); processReturn(); return; } NAString udrType; getRoutineTypeLit(createRoutineNode->getRoutineType(), udrType); NAString languageType; getLanguageTypeLit(language, languageType); NAString sqlAccess; getSqlAccessLit(createRoutineNode->getSqlAccess(), sqlAccess); NAString paramStyle; getParamStyleLit(style, paramStyle); NAString transactionAttributes; getTransAttributesLit(createRoutineNode->getTransactionAttributes(), transactionAttributes); NAString parallelism; getParallelismLit(createRoutineNode->getParallelism(), parallelism); NAString externalSecurity; getExternalSecurityLit(createRoutineNode->getExternalSecurity(), externalSecurity); NAString executionMode; getExecutionModeLit(createRoutineNode->getExecutionMode(), executionMode); char * query = new(STMTHEAP) char[2000+MAX_SIGNATURE_LENGTH]; str_sprintf(query, "insert into %s.\"%s\".%s values (%Ld, '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', %d, %d, '%s', '%s', '%s', '%s', '%s', %Ld, '%s' )", getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_ROUTINES, objUID, udrType.data(), languageType.data(), createRoutineNode->isDeterministic() ? "Y" : "N" , sqlAccess.data(), createRoutineNode->isCallOnNull() ? "Y" : "N" , createRoutineNode->isIsolate() ? "Y" : "N" , paramStyle.data(), transactionAttributes.data(), createRoutineNode->getMaxResults(), createRoutineNode->getStateAreaSize(), externalName.data(), parallelism.data(), createRoutineNode->getUserVersion().data(), externalSecurity.data(), executionMode.data(), libUID, sigBuf); cliRC = cliInterface.executeImmediate(query); NADELETEBASIC(query, STMTHEAP); if (cliRC < 0) { cliInterface.retrieveSQLDiagnostics(CmpCommon::diags()); processReturn(); return; } char * query1 = new(STMTHEAP) char[1000]; str_sprintf(query1, "insert into %s.\"%s\".%s values (%Ld, %Ld)", getSystemCatalog(), SEABASE_MD_SCHEMA, SEABASE_LIBRARIES_USAGE, libUID, objUID); cliRC = cliInterface.executeImmediate(query1); NADELETEBASIC(query1, STMTHEAP); if (cliRC < 0) { cliInterface.retrieveSQLDiagnostics(CmpCommon::diags()); processReturn(); return; } // hope to remove this call soon by setting the valid flag to Y sooner if (updateObjectValidDef(&cliInterface, catalogNamePart, schemaNamePart, objectNamePart, COM_USER_DEFINED_ROUTINE_OBJECT_LIT, "Y")) { deallocEHI(ehi); processReturn(); return; } processReturn(); return; }
// static helper function to generate one list of disks // (returns an array of ExScratchDiskDrive objects) static ExScratchDiskDrive * genScratchDisks(const NAString &def, Lng32 &numDirs, Generator *generator, const char *defName) { ExScratchDiskDrive *result = NULL; // temporary // numDrives = 0; // return result; // end temporary const char *str = def.data(); if (!str || str[0]=='\0') { numDirs = 0; return result; // fast return if empty NADefaults val } // --------------------------------------------------------------------- // Convert the strings into a temporary list of ExScratchDiskDrive // objects (temporary because we want to make the final list a // contiguous array) // --------------------------------------------------------------------- CollHeap *heap = generator->wHeap(); Space *space = generator->getSpace(); LIST(ExScratchDiskDrive *) tempList(heap); struct stat st; Lng32 nodeNum; char *token,*saveptr = NULL; //save the pointer to this since token will keep changing. char *sep = (char *)":"; token = strtok_r((char *)str,sep,&saveptr); while (token != NULL) { //validate the directory if ((stat(token,&st) != 0 ) && !S_ISDIR(st.st_mode) ) //&& (numDirs > MAX_SCRATCH_LOCATIONS)) { // syntax error in default, issue a warning (not an error) *CmpCommon::diags() << DgSqlCode(2055) << DgString0(def) << DgString1(defName); // don't continue after a syntax error str = NULL; } else { tempList.insert(new(heap) ExScratchDiskDrive( token, strlen(token) )); } token = strtok_r(NULL,sep,&saveptr); } token = NULL; // --------------------------------------------------------------------- // Calculate total generated space needed and allocate it // --------------------------------------------------------------------- numDirs = tempList.entries(); Lng32 allDirNamesLen = 0; char *generatedDirNames = NULL; Int32 i=0; for (; i<numDirs; i++) { allDirNamesLen += str_len(tempList[i]->getDirName())+1; } if (numDirs >0) { result = new(space) ExScratchDiskDrive[numDirs]; generatedDirNames = new(space) char[allDirNamesLen]; } // --------------------------------------------------------------------- // Loop over the temporary list and copy it into the generated space // --------------------------------------------------------------------- for (i=0; i<numDirs; i++) { ExScratchDiskDrive *src = tempList[i]; Lng32 dirNameLen = src->getDirNameLength(); str_cpy_all(generatedDirNames, src->getDirName(), dirNameLen); generatedDirNames[dirNameLen] = 0; result[i].setDirName(generatedDirNames); result[i].setDirNameLength(dirNameLen); generatedDirNames += dirNameLen+1; } return result; }
// read and return procedure location table area (header + entries) Int32 readPLTArea (fstream &mf, // (IN) : binary module file module_header_struct &latestModHdr,// (IN) : its module header NAHeap &heap, // (IN) : allocate PLT area from here const char * name, // (IN) : module name (for error msg) ComDiagsArea &diags, // (IN) : deposit any error msg here plt_header_struct *&pltArea) // (OUT): plt header + entries { // make sure we have reasonable arguments if (latestModHdr.plt_area_offset <= 0 || latestModHdr.plt_area_length <= 0 || latestModHdr.plt_hdr_length <= 0 || latestModHdr.plt_entry_length <= 0) return -1; // allocate space for PLT header plt_header_struct pltHdrCls, *latestPLTHdr, *plt; plt = (plt_header_struct *) heap.allocateMemory(latestModHdr.plt_hdr_length); // read procedure location table header mf.seekg(latestModHdr.plt_area_offset, ios::beg); mf.read((char *)plt, latestModHdr.plt_hdr_length); if (mf.fail()) { diags << DgSqlCode(-CLI_READ_ERROR) << DgString0(name); return -1; } // give versioning a chance to massage/migrate it to this version latestPLTHdr = (plt_header_struct*)plt->driveUnpack(plt, &pltHdrCls,NULL); if (!latestPLTHdr) { // error: version is no longer supported diags << DgSqlCode(-CLI_MOD_PLT_HDR_VERSION_ERROR) << DgString0(name); return -1; } pltArea = latestPLTHdr; Int32 num_procs = latestPLTHdr->num_procedures; if (num_procs >= 1) { // allocate space for PLT header + entries heap.deallocateMemory(plt); plt = (plt_header_struct *) heap.allocateMemory((size_t)latestModHdr.plt_area_length); // read procedure location table header + entries mf.seekg(latestModHdr.plt_area_offset, ios::beg); mf.read((char *)plt, (Int32)latestModHdr.plt_area_length); if (mf.fail()) { diags << DgSqlCode(-CLI_READ_ERROR) << DgString0(name); return -1; } // give versioning a chance to massage/migrate it to this version latestPLTHdr = (plt_header_struct*)plt->driveUnpack(plt, &pltHdrCls, NULL); if (!latestPLTHdr) { // error: version is no longer supported diags << DgSqlCode(-CLI_MOD_PLT_HDR_VERSION_ERROR) << DgString0(name); return -1; } pltArea = latestPLTHdr; } // verify its validity Lng32 errCode = pltArea->RtduStructIsCorrupt(); if (errCode) { // the module file is corrupted or has invalid data diags << DgSqlCode(errCode) << DgString0(name); heap.deallocateMemory(plt); return -1; } return num_procs; }
// ---------------------------------------------------------------------------- // method: getPrivileges // // If authorization is enabled, set privs based on the passed in priv_desc // and set up query invalidation (security) keys for the routine. // ---------------------------------------------------------------------------- void NARoutine::getPrivileges(TrafDesc *priv_desc) { if ( !CmpCommon::context()->isAuthorizationEnabled() || ComUser::isRootUserID()) { privInfo_ = new(heap_) PrivMgrUserPrivs; privInfo_->setOwnerDefaultPrivs(); return; } NAString privMDLoc = CmpSeabaseDDL::getSystemCatalogStatic(); privMDLoc += ".\""; privMDLoc += SEABASE_PRIVMGR_SCHEMA; privMDLoc += "\""; PrivMgrCommands privInterface(privMDLoc.data(), CmpCommon::diags(),PrivMgr::PRIV_INITIALIZED); if (priv_desc == NULL) { privInfo_ = new(heap_) PrivMgrUserPrivs; CmpSeabaseDDL cmpSBD(STMTHEAP); if (cmpSBD.switchCompiler(CmpContextInfo::CMPCONTEXT_TYPE_META)) { if (CmpCommon::diags()->getNumber(DgSqlCode::ERROR_) == 0) *CmpCommon::diags() << DgSqlCode( -4400 ); return; } ComObjectType objectType = (UDRType_ == COM_PROCEDURE_TYPE ? COM_STORED_PROCEDURE_OBJECT : COM_USER_DEFINED_ROUTINE_OBJECT); std::vector <ComSecurityKey *>* secKeyVec = new(heap_) std::vector<ComSecurityKey *>; if (privInterface.getPrivileges(objectUID_, objectType, ComUser::getCurrentUser(), *privInfo_, secKeyVec) != STATUS_GOOD) { NADELETE(privInfo_, PrivMgrUserPrivs, heap_); privInfo_ = NULL; } cmpSBD.switchBackCompiler(); if (privInfo_) { for (std::vector<ComSecurityKey*>::iterator iter = secKeyVec->begin(); iter != secKeyVec->end(); iter++) { // Insertion of the dereferenced pointer results in NASet making // a copy of the object, and then we delete the original. routineSecKeySet_.insert(**iter); delete *iter; } } } else { // get roles granted to current user // SQL_EXEC_GetRoleList returns the list of roles from the CliContext std::vector<int32_t> myRoles; Int32 numRoles = 0; Int32 *roleIDs = NULL; if (SQL_EXEC_GetRoleList(numRoles, roleIDs) < 0) { *CmpCommon::diags() << DgSqlCode(-1034); return; } // At this time we should have at least one entry in roleIDs (PUBLIC_USER) CMPASSERT (roleIDs && numRoles > 0); for (Int32 i = 0; i < numRoles; i++) myRoles.push_back(roleIDs[i]); privInfo_ = new (heap_) PrivMgrUserPrivs; privInfo_->initUserPrivs(myRoles, priv_desc, ComUser::getCurrentUser(),objectUID_, routineSecKeySet_); } }
short ExTupleFlowTcb::work() { // This is some sort of a hack to fix the problems with the number of rows // inserted returned to the user for packed tables. For these tables, rows // are packed (by the Pack node which is the left child of this tuple flow) // before they are sent off to DP2. DP2 has no idea that it's actually // inserting multiple logical rows (as perceived by the user). However, // there is actually a hidden count of logical rows stored as the first 4 // bytes of the packed row. This counter is supposed to keep track of a sum // of this number in each packed row it gets from the left. When all // insertions are done, this sum is used to override what's stored by the // PA node in the executor global area the number of rows inserted. This is // not a very good place to have this fix, but since this is a low-priority // problem at this time, here we are. // // // NB: The code introduced for this fix // could be safely removed if desired. Also, all changes are within // this file. // if (qParent_.down->isEmpty()) return WORK_OK; ex_queue_entry * pentry_down = qParent_.down->getHeadEntry(); ExTupleFlowPrivateState & pstate = *((ExTupleFlowPrivateState*) pentry_down->pstate); if ((tflowTdb().userSidetreeInsert()) && (pentry_down->downState.request == ex_queue::GET_EOD) && (NOT pstate.parentEOD_)) { pstate.step_ = MOVE_EOD_TO_TGT_; } else if ((pstate.step_ != DONE_) && (pstate.step_ != CANCELLED_) && (pentry_down->downState.request == ex_queue::GET_NOMORE)) { if (pstate.step_ == EMPTY_) pstate.step_ = DONE_; else pstate.step_ = CANCELLED_; } while (1) { switch (pstate.step_) { case EMPTY_: { if (qSrc_.down->isFull()) return WORK_OK; ex_queue_entry * src_entry = qSrc_.down->getTailEntry(); src_entry->downState.request = pentry_down->downState.request; src_entry->downState.requestValue = pentry_down->downState.requestValue; if ((tflowTdb().firstNRows() >= 0) && (pentry_down->downState.request != ex_queue::GET_N)) { src_entry->downState.request = ex_queue::GET_N; src_entry->downState.requestValue = tflowTdb().firstNRows(); } src_entry->downState.parentIndex = qParent_.down->getHeadIndex(); src_entry->passAtp(pentry_down); qSrc_.down->insert(); // just checking to make sure we got a diags area from the CLI if we are // executing a non-tomic insert. This is done now so that we don't have to do it in multiple // places later. if (tflowTdb().isNonFatalErrorTolerated()) { ComDiagsArea *cliDiagsArea = pentry_down->getDiagsArea(); ex_assert(cliDiagsArea, "In Tupleflow : Non-Atomic insert received no diags area from the CLI"); } pstate.parentEOD_ = FALSE; pstate.srcEOD_ = FALSE; pstate.matchCount_ = 0; pstate.tgtRequests_ = 0; pstate.tgtRowsSent_ = FALSE; pstate.noOfUnPackedRows_ = 0; pstate.srcRequestCount_ = -1; pstate.nonFatalErrorSeen_ = FALSE; // Set startRightIndex_ so that CancelReques doesn't do anything. pstate.startRightIndex_ = pstate.srcRequestCount_; pstate.step_ = MOVE_SRC_TO_TGT_; } break; case MOVE_SRC_TO_TGT_: { // if there are some rows in source up queue, move them to target. while ((! qSrc_.up->isEmpty()) && (! qTgt_.down->isFull()) && (pstate.step_ != HANDLE_ERROR_)) { ex_queue_entry * src_entry = qSrc_.up->getHeadEntry(); ex_queue_entry * tgt_entry = qTgt_.down->getTailEntry(); switch (src_entry->upState.status) { case ex_queue::Q_OK_MMORE: { // move this source row to target. // LCOV_EXCL_START // BEGIN: - Read note at beginning of work(). // if (tcbSrc_->getNodeType() == ComTdb::ex_PACKROWS) { char* packTuppPtr = src_entry->getTupp(src_entry->numTuples()-1) .getDataPointer(); Int32 noOfRows = *((Int32 *)packTuppPtr); pstate.noOfUnPackedRows_ += (noOfRows - 1); } // // END:- Read note at beginning of work(). // LCOV_EXCL_STOP pstate.srcRequestCount_++; tgt_entry->downState.request = pentry_down->downState.request; tgt_entry->downState.requestValue = pentry_down->downState.requestValue; tgt_entry->downState.parentIndex = (Lng32) pstate.srcRequestCount_; tgt_entry->copyAtp(src_entry); qTgt_.down->insert(); pstate.tgtRequests_++; pstate.tgtRowsSent_ = TRUE; qSrc_.up->removeHead(); } break; case ex_queue::Q_NO_DATA: { if ((tflowTdb().vsbbInsertOn()) && (pstate.tgtRowsSent_ == TRUE)) { if (tflowTdb().userSidetreeInsert()) { tgt_entry->downState.request = ex_queue::GET_EOD_NO_ST_COMMIT; } else { tgt_entry->downState.request = ex_queue::GET_EOD; } tgt_entry->downState.requestValue = pentry_down->downState.requestValue; tgt_entry->downState.parentIndex = (Lng32) pstate.srcRequestCount_; tgt_entry->copyAtp(src_entry); qTgt_.down->insert(); pstate.tgtRequests_++; } // LCOV_EXCL_START if ((pstate.tgtRowsSent_ == FALSE) && (src_entry->getDiagsArea())) { // a warning is returned with EOD and // nothing else was returned from source. // Move warning to parent's up queue. if (qParent_.up->isFull()) return WORK_OK; ex_queue_entry * up_entry = qParent_.up->getTailEntry(); up_entry->setDiagsArea(src_entry->getDiagsArea()); } // LCOV_EXCL_STOP qSrc_.up->removeHead(); pstate.srcEOD_ = TRUE; // LCOV_EXCL_START if (tflowTdb().sendEODtoTgt()) pstate.step_ = MOVE_EOD_TO_TGT_; // LCOV_EXCL_STOP } break; case ex_queue::Q_SQLERROR: { if (qParent_.up->isFull()) return WORK_OK; ex_queue_entry * pentry = qParent_.up->getTailEntry(); ComDiagsArea * da = src_entry->getDiagsArea(); ex_assert(da, "We have a Q_SQLERROR in Tupleflow but no diags area"); if (tflowTdb().isNonFatalErrorTolerated() && (da->getNextRowNumber(ComCondition::NONFATAL_ERROR) == ComCondition::NONFATAL_ERROR)) { pstate.nonFatalErrorSeen_ = TRUE; } else { pstate.step_ = HANDLE_ERROR_; pstate.nonFatalErrorSeen_ = FALSE; } pstate.srcRequestCount_++; if(tflowTdb().isRowsetIterator()) da->setAllRowNumber((Lng32) pstate.srcRequestCount_); ComDiagsArea *accumulatedDiagsArea = pentry->getDiagsArea(); if (accumulatedDiagsArea) { accumulatedDiagsArea->mergeAfter(*da); if (!(accumulatedDiagsArea->canAcceptMoreErrors()) && tflowTdb().isNonFatalErrorTolerated()) { pstate.nonFatalErrorSeen_ = FALSE; pstate.step_ = HANDLE_ERROR_; } } else { pentry->setDiagsArea(da); da->incrRefCount(); accumulatedDiagsArea = da ; if (tflowTdb().isNonFatalErrorTolerated()) { ComDiagsArea *cliDiagsArea = pentry_down->getDiagsArea(); da->setLengthLimit(cliDiagsArea->getLengthLimit()); } } // For Non-Fatal errors we will remove this Q_SQLERROR reply from the // left child right below as we will continue to stay in this state (MOVE_SRC_TO_TGT_). // For fatal errors this Q_SQLERROR reply is removed in HANDLE_ERROR step to which // we will transition immediately. if (pstate.nonFatalErrorSeen_ == TRUE) qSrc_.up->removeHead(); } break; case ex_queue::Q_REC_SKIPPED: { pstate.srcRequestCount_++; ComDiagsArea * da = src_entry->getDiagsArea(); if (da) pstate.nonFatalErrorSeen_ = TRUE; qSrc_.up->removeHead(); } break; default: { ex_assert(0, "ExTupleFlowTcb::work() Error returned from src"); // LCOV_EXCL_LINE } break; } // switch } // while // if the child reply is not an Q_SQLERROR, then process target if ((pstate.step_ != HANDLE_ERROR_) && (pstate.step_ != MOVE_EOD_TO_TGT_)) pstate.step_ = PROCESS_TGT_; } // MOVE_SRC_TO_TGT break; case MOVE_EOD_TO_TGT_: { pstate.parentEOD_ = TRUE; if (qTgt_.down->isFull()) return WORK_OK; ex_queue_entry * tgt_entry = qTgt_.down->getTailEntry(); tgt_entry->downState.request = ex_queue::GET_EOD; tgt_entry->downState.requestValue = pentry_down->downState.requestValue; tgt_entry->downState.parentIndex = qParent_.down->getHeadIndex(); //tgt_entry->passAtp(pentry_down); qTgt_.down->insert(); pstate.tgtRequests_++; // LCOV_EXCL_START if (tflowTdb().sendEODtoTgt()) pstate.srcEOD_ = TRUE; // LCOV_EXCL_STOP else pstate.srcEOD_ = FALSE; pstate.step_ = PROCESS_TGT_; } break; case PROCESS_TGT_: { while (! qTgt_.up->isEmpty() && pstate.step_ != HANDLE_ERROR_) { ex_queue_entry * tgt_entry = qTgt_.up->getHeadEntry(); switch (tgt_entry->upState.status) { case ex_queue::Q_OK_MMORE: { if (!tflowTdb().isNonFatalErrorTolerated()) { // ex_assert(0, "ExTupleFlowTcb::work() OK_MMORE from tgt"); if (qParent_.up->isFull()) return WORK_OK; ex_queue_entry * pentry = qParent_.up->getTailEntry(); pentry->upState.status = ex_queue::Q_OK_MMORE; pentry->upState.downIndex = qParent_.down->getHeadIndex(); pentry->upState.parentIndex = pentry_down->downState.parentIndex; pentry->upState.setMatchNo(pstate.matchCount_); // copy input tupps from parent request pentry->copyAtp(pentry_down); // copy child's atp to // the output atp (to parent's up queue) pentry->copyAtp(tgt_entry); // insert into parent up queue qParent_.up->insert(); } else { ComDiagsArea * da = tgt_entry->getDiagsArea(); ex_assert(da, "We have a Q_OK_MMORE in Tupleflow but no diags area"); if (da->mainSQLCODE() != 0) { // Non-atomic Rowsets sends OK_MMORE with non-empty diags from child // empty diags (mainsqlcode == 0) implies OK_MMORE sent by ignoreDupKey code // when NAR is on, for -8102 error. Just consume the OK_MMORE. if(tflowTdb().isRowsetIterator()) { da->setAllRowNumber(Lng32 (tgt_entry->upState.parentIndex)); } pstate.nonFatalErrorSeen_ = TRUE; ex_queue_entry * pentry = qParent_.up->getTailEntry(); ComDiagsArea *accumulatedDiagsArea = pentry->getDiagsArea(); if (accumulatedDiagsArea) { accumulatedDiagsArea->mergeAfter(*da); if (!(accumulatedDiagsArea->canAcceptMoreErrors()) && tflowTdb().isNonFatalErrorTolerated()) { pstate.nonFatalErrorSeen_ = FALSE; pstate.step_ = HANDLE_ERROR_; } } else { pentry->setDiagsArea(da); da->incrRefCount(); if (tflowTdb().isNonFatalErrorTolerated()) { ComDiagsArea *cliDiagsArea = pentry_down->getDiagsArea(); da->setLengthLimit(cliDiagsArea->getLengthLimit()); } } } } qTgt_.up->removeHead(); } break; case ex_queue::Q_NO_DATA: { ComDiagsArea * da = tgt_entry->getDiagsArea(); if (da) { ex_queue_entry * pentry = qParent_.up->getTailEntry(); ComDiagsArea *accumulatedDiagsArea = pentry->getDiagsArea(); if (accumulatedDiagsArea) accumulatedDiagsArea->mergeAfter(*da); else { pentry->setDiagsArea(da); da->incrRefCount(); if (tflowTdb().isNonFatalErrorTolerated()) { ComDiagsArea *cliDiagsArea = pentry_down->getDiagsArea(); da->setLengthLimit(cliDiagsArea->getLengthLimit()); } } } pstate.matchCount_ += tgt_entry->upState.getMatchNo(); qTgt_.up->removeHead(); pstate.tgtRequests_--; pstate.startRightIndex_++; } break; case ex_queue::Q_SQLERROR: { if (qParent_.up->isFull()) return WORK_OK; ex_queue_entry * pentry = qParent_.up->getTailEntry(); pentry->copyAtp(tgt_entry); pstate.nonFatalErrorSeen_ = FALSE; pstate.step_ = HANDLE_ERROR_; if(tflowTdb().isRowsetIterator()) { ex_queue_entry * pentry = qParent_.up->getTailEntry(); ComDiagsArea *da = pentry->getDiagsArea(); ex_assert(da, "To set RowNumber, an error condition must be present in the diags area"); da->setAllRowNumber(Lng32 (tgt_entry->upState.parentIndex)); } } break; default: { ex_assert(0, "ExTupleFlowTcb::work() Error returned from tgt"); // LCOV_EXCL_LINE } break; } // switch } // while if (pstate.step_ == HANDLE_ERROR_) break; // if source has returned EOD, // and there are no pending requests in target's down // queue, then we are done with this parent request. if (((pstate.srcEOD_ == TRUE) || (pstate.parentEOD_ == TRUE)) && (qTgt_.down->isEmpty())) pstate.step_ = DONE_; else { if (NOT pstate.parentEOD_) pstate.step_ = MOVE_SRC_TO_TGT_; if (qSrc_.up->isEmpty() || qTgt_.down->isFull()) return WORK_OK; else return WORK_CALL_AGAIN; } } break; case HANDLE_ERROR_: { ex_queue_entry * pentry = qParent_.up->getTailEntry(); pentry->upState.status = ex_queue::Q_SQLERROR; pentry->upState.downIndex = qParent_.down->getHeadIndex(); pentry->upState.parentIndex = pentry_down->downState.parentIndex; pentry->upState.setMatchNo(pstate.matchCount_); ComDiagsArea *da = pentry->getDiagsArea(); if (tflowTdb().isNonFatalErrorTolerated() && !(da->canAcceptMoreErrors())) { ComDiagsArea *cliDiagsArea = pentry_down->getDiagsArea(); da->removeLastErrorCondition(); *da << DgSqlCode(-EXE_NONATOMIC_FAILURE_LIMIT_EXCEEDED) << DgInt0(cliDiagsArea->getLengthLimit()); } // insert into parent up queue qParent_.up->insert(); pstate.step_ = CANCELLED_; } break; case CANCELLED_: { qSrc_.down->cancelRequestWithParentIndex(qParent_.down->getHeadIndex()); // Cancel all the outstanding requests that have been sent to the target. // Cancel all requests within given range (inclusive) qTgt_.down->cancelRequestWithParentIndexRange((queue_index)pstate.startRightIndex_+1, (queue_index)pstate.srcRequestCount_); pstate.startRightIndex_ = pstate.srcRequestCount_; //ignore all rows from source child, till Q_NO_DATA is reached while ((pstate.srcEOD_ != TRUE) && (!qSrc_.up->isEmpty())) { ex_queue_entry * src_entry = qSrc_.up->getHeadEntry(); switch(src_entry->upState.status) { case ex_queue::Q_OK_MMORE: case ex_queue::Q_SQLERROR: case ex_queue::Q_REC_SKIPPED: { qSrc_.up->removeHead(); } break; case ex_queue::Q_NO_DATA: { pstate.srcEOD_ = TRUE; qSrc_.up->removeHead(); } break; default: { ex_assert(0, "ExTupleFlowTcb::work() Error returned from src"); // LCOV_EXCL_LINE } break; } } //ignore all rows from target child, till Q_NO_DATA is reached while (pstate.tgtRequests_ && !qTgt_.up->isEmpty()) { ex_queue_entry * tgt_entry = qTgt_.up->getHeadEntry(); switch(tgt_entry->upState.status) { case ex_queue::Q_OK_MMORE: case ex_queue::Q_SQLERROR: { qTgt_.up->removeHead(); } break; case ex_queue::Q_NO_DATA: { qTgt_.up->removeHead(); pstate.tgtRequests_--; } break; default: { ex_assert(0, "ExTupleFlowTcb::work() Error returned from tgt"); // LCOV_EXCL_LINE } break; } } // if both source and target returned all the rows, // insert Q_SQLERROR into the parent up queue if ((pstate.srcEOD_ == TRUE) && !pstate.tgtRequests_) { pstate.step_ = DONE_; } else return WORK_OK; } break; case DONE_: { if (qParent_.up->isFull()) return WORK_OK; ex_queue_entry * pentry = qParent_.up->getTailEntry(); if (pstate.nonFatalErrorSeen_) { ComDiagsArea *da = pentry->getDiagsArea(); ComDiagsArea *cliDiagsArea = pentry_down->getDiagsArea(); ex_assert((da || cliDiagsArea), "We have non-fatal errors in Tupleflow but no diags area"); if (cliDiagsArea) { if (da) da->mergeAfter(*cliDiagsArea); else { pentry->setDiagsArea(cliDiagsArea); cliDiagsArea->incrRefCount(); } } if (cliDiagsArea->canAcceptMoreErrors()) { ComDiagsArea *mergedDiagsArea = pentry->getDiagsArea(); // used to make mainSQLCODE() return 30022 or 30035. mergedDiagsArea->setNonFatalErrorSeen(TRUE); NABoolean anyRowsAffected = FALSE; // This tupleflow should be in the master for // non-atomic rowsets. ExMasterStmtGlobals *g = getGlobals()-> castToExExeStmtGlobals()->castToExMasterStmtGlobals(); ex_assert(g, "Rowset insert has a flow node that is not in the master executor"); if (g->getRowsAffected() > 0) anyRowsAffected = TRUE; if (anyRowsAffected) *mergedDiagsArea << DgSqlCode(EXE_NONFATAL_ERROR_SEEN); else *mergedDiagsArea << DgSqlCode(EXE_NONFATAL_ERROR_ON_ALL_ROWS); } // we exceeded the Nonfatal error limit when merging with the CLI diags area else { pstate.step_ = HANDLE_ERROR_; // will prevent us from merging the diags areas again pstate.nonFatalErrorSeen_ = FALSE ; break ; } } pentry->upState.status = ex_queue::Q_NO_DATA; pentry->upState.downIndex = qParent_.down->getHeadIndex(); pentry->upState.parentIndex = pentry_down->downState.parentIndex; pentry->upState.setMatchNo(pstate.matchCount_); // LCOV_EXCL_START // BEGIN: Read note at beginning of work(). // if(pstate.noOfUnPackedRows_ != 0) { ComDiagsArea *da = pentry->getDiagsArea(); if (da == NULL) { da = ComDiagsArea::allocate(getGlobals()->getDefaultHeap()); pentry->setDiagsArea(da); } da->addRowCount(pstate.noOfUnPackedRows_); pstate.noOfUnPackedRows_ = 0; } // // END: - Read note at beginning of work(). // LCOV_EXCL_STOP // if stats are to be collected, collect them. if (getStatsEntry()) { // nothing yet returned from right child or returned // to parent. getStatsEntry()->setActualRowsReturned(0); } // insert into parent up queue qParent_.up->insert(); pstate.step_ = EMPTY_; qParent_.down->removeHead(); return WORK_CALL_AGAIN; // check for more down requests } break; } // switch pstate.step_ } // while #pragma nowarn(203) // warning elimination return 0; #pragma warn(203) // warning elimination }
////////////////////////////////////////////////////// // work() for ExTimeoutTcb ////////////////////////////////////////////////////// short ExTimeoutTcb::work() { while (1) { // if no parent request, return if (qparent_.down->isEmpty()) return WORK_OK; // if no room in up queue, won't be able to return data/status. // Come back later. if (qparent_.up->isFull()) return WORK_OK; ex_queue_entry * pentry_down = qparent_.down->getHeadEntry(); ExTimeoutPrivateState & pstate = *((ExTimeoutPrivateState*) pentry_down->pstate); // Calculate the timeout actual value Lng32 timeoutValue = 0; NABoolean goodTimeoutValue = TRUE ; if (timeoutValueExpr()) { if ( timeoutValueExpr()->eval(pentry_down->getAtp(), workAtp_) == ex_expr::EXPR_ERROR ) { // expression did not yield a valid value handleErrors(pentry_down, pentry_down->getAtp()->getDiagsArea()); goodTimeoutValue = FALSE ; } else { tupp TP = workAtp_->getTupp(timeoutTdb().workCriDesc_->noTuples()-1); timeoutValue = *(Lng32 *)TP.getDataPointer(); // pointer is (char *) } } /****************************************************/ /******** Do the actual SET TIMEOUT work ********/ /** **/ /** The scope of the work is only making changes **/ /** to the global timeout data kept at the context **/ /****************************************************/ // Get the global timeout-data object ContextCli * currContext = getGlobals()->castToExExeStmtGlobals()-> castToExMasterStmtGlobals()->getStatement()->getContext(); TimeoutData * GlobalTimeouts = currContext->getTimeouts(); #if _DEBUG // For debugging only !!!!! if ( getenv("DEBUG_TIMEOUT") ) { ComDiagsArea* diagsArea = ComDiagsArea::allocate (getGlobals()->getDefaultHeap()); char errmsg[120]; if ( timeoutTdb().isStream() ) { // it was a SET STREAM TIMEOUT if ( GlobalTimeouts->isStreamTimeoutSet() ) { sprintf(errmsg, "Stream timeout set to %d\n", GlobalTimeouts->getStreamTimeout() ); } else sprintf(errmsg, "Stream timeout was NOT SET ! \n"); } // lock timeout -- not stream else { if ( theTableName_[0] == '*' ) { // For all tables sprintf(errmsg, "Number of lock timeouts set: %d\n", GlobalTimeouts->entries() ); } else { Lng32 timeoutValue; NABoolean found = GlobalTimeouts->getLockTimeout(theTableName_, timeoutValue ); if ( ! found ) sprintf(errmsg, "Lock timeout for table %s was NOT SET ! \n", theTableName_ ); else sprintf(errmsg, "Lock timeout for table %s is %d \n", theTableName_ , timeoutValue ); } } // emit message as an error ( msg 3066 has no text of its own ) *diagsArea << DgSqlCode(-3066) << DgString0(errmsg) ; ExHandleArkcmpErrors(qparent_, pentry_down, 0, getGlobals(), diagsArea, (ExeErrorCode) -3066 ); } // end of debugging section else #endif if ( goodTimeoutValue ) { // Update the globals as needed if ( timeoutTdb().isStream() ) { // it was a SET STREAM TIMEOUT if ( timeoutTdb().isReset() ) // it was a RESET GlobalTimeouts->resetStreamTimeout(); else // it was a SET (with a value) GlobalTimeouts->setStreamTimeout(timeoutValue); } else { // setting a LOCK TIMEOUT // TBD =============>>> Check if FORALL string includes CAT.SCH ...... if ( theTableName_[0] == '*' ) { // For all tables if ( timeoutTdb().isReset() ) // it was a RESET GlobalTimeouts->resetAllLockTimeout(); else GlobalTimeouts->setAllLockTimeout(timeoutValue); } else { // per specific table if ( timeoutTdb().isReset() ) // it was a RESET GlobalTimeouts->resetTableLockTimeout( theTableName_ ); else GlobalTimeouts->setTableLockTimeout(theTableName_,timeoutValue); } } // execution of every SET TIMEOUT stmt increments the change counter !! currContext->incrementTimeoutChangeCounter(); // clear up (i.e. deallocate) the global timeout data, if possible if ( GlobalTimeouts->noLockTimeoutsSet() && ! GlobalTimeouts->isStreamTimeoutSet() ) currContext->clearTimeoutData(); } // end of if ( goodTimeoutValue ) /********** at this point the actual work is done ******************/ // all ok. Return EOF. ex_queue_entry * up_entry = qparent_.up->getTailEntry(); up_entry->upState.parentIndex = pentry_down->downState.parentIndex; up_entry->upState.setMatchNo(0); up_entry->upState.status = ex_queue::Q_NO_DATA; // insert into parent qparent_.up->insert(); qparent_.down->removeHead(); } return WORK_OK; }
LmResult LmRoutineCppObj::invokeRoutineMethod( /* IN */ tmudr::UDRInvocationInfo::CallPhase phase, /* IN */ const char *serializedInvocationInfo, /* IN */ Int32 invocationInfoLen, /* OUT */ Int32 *invocationInfoLenOut, /* IN */ const char *serializedPlanInfo, /* IN */ Int32 planInfoLen, /* IN */ Int32 planNum, /* OUT */ Int32 *planInfoLenOut, /* IN */ char *inputParamRow, /* IN */ Int32 inputParamRowLen, /* OUT */ char *outputRow, /* IN */ Int32 outputRowLen, /* IN/OUT */ ComDiagsArea *da) { LmResult result = LM_OK; // initialize out parameters *invocationInfoLenOut = 0; *planInfoLenOut = 0; // some parameter checks if (invocationInfoLen <= 0 && invocationInfo_ == NULL) { // we need to have an Invocation info *da << DgSqlCode(-LME_OBJECT_INTERFACE_ERROR) << DgString0(getNameForDiags()) << DgString1(tmudr::UDRInvocationInfo::callPhaseToString( tmudr::UDRInvocationInfo::COMPILER_INITIAL_CALL)) << DgString2("LmRoutineCppObj::invokeRoutineMethod()") << DgString3("Missing UDRInvocationInfo"); } try { if (invocationInfoLen > 0) { if (invocationInfo_ == NULL) invocationInfo_ = new tmudr::UDRInvocationInfo; // unpack the invocation info invocationInfo_->deserializeObj(serializedInvocationInfo, invocationInfoLen); } if (planInfoLen > 0) { if (!planInfos_.used(planNum)) planInfos_.insertAt(planNum, new tmudr::UDRPlanInfo(invocationInfo_, planNum)); // unpack the invocation info planInfos_[planNum]->deserializeObj(serializedPlanInfo, planInfoLen); } // some parameter checks if (inputParamRowLen < inputParamRowLen_) return LM_ERR; // test to do for scalar UDFs // if (outputRowLen < invocationInfo_->out().getRecordLength()) // return LM_ERR; if (inputParamRow && inputParamRowLen_ > 0) // copy parameter row memcpy(invocationInfo_->par().getRowPtr(), inputParamRow, inputParamRowLen_); invocationInfo_->callPhase_ = phase; switch (phase) { case tmudr::UDRInvocationInfo::COMPILER_INITIAL_CALL: if (invocationInfo_->getDebugFlags() & tmudr::UDRInvocationInfo::PRINT_INVOCATION_INFO_INITIAL) invocationInfo_->print(); if (invocationInfo_->getDebugFlags() & tmudr::UDRInvocationInfo::DEBUG_INITIAL_COMPILE_TIME_LOOP) if (invocationInfo_->getSessionUser() == ComUser::getRootUserName()) interfaceObj_->debugLoop(); else if (da) *da << DgSqlCode(1260); // warning, only root user can debug interfaceObj_->describeParamsAndColumns(*invocationInfo_); break; case tmudr::UDRInvocationInfo::COMPILER_DATAFLOW_CALL: interfaceObj_->describeDataflowAndPredicates(*invocationInfo_); break; case tmudr::UDRInvocationInfo::COMPILER_CONSTRAINTS_CALL: interfaceObj_->describeConstraints(*invocationInfo_); break; case tmudr::UDRInvocationInfo::COMPILER_STATISTICS_CALL: interfaceObj_->describeStatistics(*invocationInfo_); break; case tmudr::UDRInvocationInfo::COMPILER_DOP_CALL: interfaceObj_->describeDesiredDegreeOfParallelism( *invocationInfo_, *planInfos_[planNum]); break; case tmudr::UDRInvocationInfo::COMPILER_PLAN_CALL: interfaceObj_->describePlanProperties(*invocationInfo_, *planInfos_[planNum]); break; case tmudr::UDRInvocationInfo::COMPILER_COMPLETION_CALL: interfaceObj_->completeDescription(*invocationInfo_, *planInfos_[planNum]); if (invocationInfo_->getDebugFlags() & tmudr::UDRInvocationInfo::PRINT_INVOCATION_INFO_END_COMPILE) { invocationInfo_->print(); printf("\n"); for (CollIndex i=0; i<planInfos_.getUsedLength(); i++) if (planInfos_.used(i)) { if (i == planNum) printf("++++++++++ Chosen plan: ++++++++++\n"); else printf("-------- Plan not chosen: --------\n"); planInfos_[i]->print(); } } break; case tmudr::UDRInvocationInfo::RUNTIME_WORK_CALL: { if (invocationInfo_->getDebugFlags() & tmudr::UDRInvocationInfo::PRINT_INVOCATION_INFO_AT_RUN_TIME) { invocationInfo_->print(); planInfos_[planNum]->print(); } if ((invocationInfo_->getDebugFlags() & tmudr::UDRInvocationInfo::DEBUG_INITIAL_RUN_TIME_LOOP_ALL) || (invocationInfo_->getDebugFlags() & tmudr::UDRInvocationInfo::DEBUG_INITIAL_RUN_TIME_LOOP_ONE && invocationInfo_->getMyInstanceNum() == 0)) interfaceObj_->debugLoop(); interfaceObj_->processData(*invocationInfo_, *planInfos_[planNum]); if (result == LM_OK) { if (invocationInfo_->getDebugFlags() & tmudr::UDRInvocationInfo::TRACE_ROWS) printf("(%d) Emitting EOD\n", invocationInfo_->getMyInstanceNum()); // call emitRow to indicate EOD, something the // C interface would do inside the UDF SQLUDR_Q_STATE qstate = SQLUDR_Q_EOD; (*interfaceObj_->emitRowPtr_)( invocationInfo_->out().getRowPtr(), 0, &qstate); } } break; default: *da << DgSqlCode(-11111) << DgString0("Invalid call phase in LmRoutineCppObj::invokeRoutineMethod()"); result = LM_ERR; break; } // return length of updated invocation and plan info for // compile-time phases if (invocationInfo_ && phase < tmudr::UDRInvocationInfo::RUNTIME_WORK_CALL) { *invocationInfoLenOut = invocationInfo_->serializedLength(); if (planInfos_.used(planNum)) *planInfoLenOut = planInfos_[planNum]->serializedLength(); } } catch (tmudr::UDRException e) { // Check the returned SQLSTATE value and raise appropriate // SQL code. Valid SQLSTATE values begin with "38" except "38000" const char *sqlState = e.getSQLState(); if ((strncmp(sqlState, "38", 2) == 0) && (strncmp(sqlState, "38000", 5) != 0)) { *da << DgSqlCode(-LME_CUSTOM_ERROR) << DgString0(e.getMessage().c_str()) << DgString1(sqlState); *da << DgCustomSQLState(sqlState); } else { *da << DgSqlCode(-LME_UDF_ERROR) << DgString0(invocationInfo_->getUDRName().c_str()) << DgString1(sqlState) << DgString2(e.getMessage().c_str()); } result = LM_ERR; } catch (...) { *da << DgSqlCode(-LME_OBJECT_INTERFACE_ERROR) << DgString0(getNameForDiags()) << DgString1(invocationInfo_->callPhaseToString(phase)) << DgString2("LmRoutineCppObj::invokeRoutineMethod()") << DgString3("general exception"); result = LM_ERR; } invocationInfo_->callPhase_ = tmudr::UDRInvocationInfo::UNKNOWN_CALL_PHASE; return result; }
void processALoadMessage(UdrGlobals *UdrGlob, UdrServerReplyStream &msgStream, UdrLoadMsg &request, IpcEnvironment &env) { const char *moduleName = "processALoadMessage"; char errorText[MAXERRTEXT]; ComDiagsArea *diags = ComDiagsArea::allocate(UdrGlob->getIpcHeap()); doMessageBox(UdrGlob, TRACE_SHOW_DIALOGS, UdrGlob->showLoad_, moduleName); NABoolean showLoadLogic = (UdrGlob->verbose_ && UdrGlob->traceLevel_ >= TRACE_IPMS && UdrGlob->showLoad_); if (showLoadLogic) { ServerDebug("[UdrServ (%s)] Processing load request", moduleName); } // UDR_LOAD message always comes with transaction and they are out // side Enter Tx and Exit Tx pair. Make sure we are under correct // transaction. msgStream.activateCurrentMsgTransaction(); // // Check to see if the incoming UDR handle has already been seen // NABoolean handleAlreadyExists = FALSE; SPInfo *sp = UdrGlob->getSPList()->spFind(request.getHandle()); if (sp) { handleAlreadyExists = TRUE; if (showLoadLogic) { ServerDebug(" Duplicate handle arrived"); ServerDebug(" SPInfoState is %s", sp->getSPInfoStateString()); } if (sp->getSPInfoState() != SPInfo::UNLOADING) { // // An SPInfo exists but it is not one of the token instances to // represent an out-of-sequence LOAD/UNLOAD. This is an internal // error. Something has been botched in the message protocol. // char buf[100]; convertInt64ToAscii(request.getHandle(), buf); *diags << DgSqlCode(-UDR_ERR_DUPLICATE_LOADS); *diags << DgString0(buf); } else { // The LOAD/UNLOAD requests for this handle arrived // out-of-sequence. Nothing to do at this point. An empty reply // will be generated later in this function. } } if (!handleAlreadyExists) { if (!UdrHandleIsValid(request.getHandle())) { *diags << DgSqlCode(-UDR_ERR_MISSING_UDRHANDLE); *diags << DgString0("Load Message"); } else { // // First process the metadata in the LOAD requests and then // contact Language Manager to load the SP. // sp = processLoadParameters(UdrGlob, request, *diags); if (showLoadLogic) { ServerDebug("[UdrServ (%s)] About to call LM::getRoutine", moduleName); } if (sp == NULL) { *diags << DgSqlCode(-UDR_ERR_UNABLE_TO_ALLOCATE_MEMORY); *diags << DgString0("SPInfo"); } else { UdrGlob->setCurrSP(sp); LmRoutine *lmRoutine; LmResult lmResult; LmLanguageManager *lm = UdrGlob->getOrCreateLM(lmResult, sp->getLanguage(), diags); LmHandle emitRowFuncPtr; if (sp->getParamStyle() == COM_STYLE_CPP_OBJ) emitRowFuncPtr = (LmHandle)&SpInfoEmitRowCpp; else emitRowFuncPtr = (LmHandle)&SpInfoEmitRow; if (lm) { if (sp->getParamStyle() == COM_STYLE_JAVA_OBJ || sp->getParamStyle() == COM_STYLE_CPP_OBJ) { lmResult = lm->getObjRoutine( request.getUDRSerInvocationInfo(), request.getUDRSerInvocationInfoLen(), request.getUDRSerPlanInfo(), request.getUDRSerPlanInfoLen(), sp->getLanguage(), sp->getParamStyle(), sp->getExternalName(), sp->getContainerName(), sp->getExternalPathName(), sp->getLibrarySqlName(), &lmRoutine, diags); if (lmRoutine) { LmRoutineCppObj *objRoutine = static_cast<LmRoutineCppObj *>(lmRoutine); if (sp->getParamStyle() == COM_STYLE_CPP_OBJ) // set function pointers for functions provided // by tdm_udrserv objRoutine->setFunctionPtrs(SpInfoGetNextRow, SpInfoEmitRowCpp); // add items to the UDRInvocationInfo that are not // known at compile time (total # of instances is // kind of known, but we want to give the executor a // chance to change it) lmRoutine->setRuntimeInfo(request.getParentQid(), request.getNumInstances(), request.getInstanceNum()); #ifndef NDEBUG int debugLoop = 2; if (objRoutine->getInvocationInfo()->getDebugFlags() & tmudr::UDRInvocationInfo::DEBUG_LOAD_MSG_LOOP) debugLoop = 1; // go into a loop to allow the user to attach a debugger, // if requested, set debugLoop = 2 in the debugger to get out while (debugLoop < 2) debugLoop = 1-debugLoop; #endif } } else lmResult = lm->getRoutine(sp->getNumParameters(), sp->getLmParameters(), sp->getNumTables(), sp->getLmTables(), sp->getReturnValue(), sp->getParamStyle(), sp->getTransactionAttrs(), sp->getSQLAccessMode(), sp->getParentQid(), sp->getRequestRowSize(), sp->getReplyRowSize(), sp->getSqlName(), sp->getExternalName(), sp->getRoutineSig(), sp->getContainerName(), sp->getExternalPathName(), sp->getLibrarySqlName(), UdrGlob->getCurrentUserName(), UdrGlob->getSessionUserName(), sp->getExternalSecurity(), sp->getRoutineOwnerId(), &lmRoutine, (LmHandle)&SpInfoGetNextRow, emitRowFuncPtr, sp->getMaxNumResultSets(), diags); } if (lmResult == LM_OK) { if (lmRoutine == NULL) { *diags << DgSqlCode(-UDR_ERR_MISSING_LMROUTINE); *diags << DgString0("error: returned a null LM handle"); *diags << DgInt1((Int32)0); } else { sp->setLMHandle(lmRoutine); // Retrieve any optional data from UdrLoadMsg. copyRoutineOptionalData(request, sp); reportLoadResults(UdrGlob, sp, lmRoutine); sp->setSPInfoState(SPInfo::LOADED); } } // lmResult == LM_OK if (showLoadLogic) { if (lmResult == LM_OK) { sprintf(errorText, "[UdrServ (%.30s)] LM::getRoutine was successful.", moduleName); } else { sprintf(errorText, "[UdrServ (%.30s)] LM::getRoutine resulted in error.", moduleName); } ServerDebug(errorText); doMessageBox(UdrGlob, TRACE_SHOW_DIALOGS, UdrGlob->showMain_, errorText); } if (sp && !(sp->isLoaded())) { sp->setSPInfoState(SPInfo::LOAD_FAILED); } } // if (sp == NULL) else ... } // if (handle is not valid) else ... } // !handleAlreadyExists // build a reply and send it msgStream.clearAllObjects(); UdrLoadReply *reply = new (UdrGlob->getIpcHeap()) UdrLoadReply(UdrGlob->getIpcHeap()); if (reply == NULL) { // no reply buffer build... controlErrorReply(UdrGlob, msgStream, UDR_ERR_MESSAGE_PROCESSING, INVOKE_ERR_NO_REPLY_BUFFER, NULL); return; } // Only return a valid UDR Handle if diagnostics are not present and // no LM errors occurred. We also return a valid handle if this LOAD // arrived out-of-sequence after the UNLOAD and no diagnostics have // been generated yet. if (diags && diags->getNumber() > 0) { reply->setHandle(INVALID_UDR_HANDLE); } else if (sp) { if (sp->isLoaded() || handleAlreadyExists) { reply->setHandle(sp->getUdrHandle()); } else { reply->setHandle(INVALID_UDR_HANDLE); } } msgStream << *reply; if (diags && diags->getNumber() > 0) { msgStream << *diags; UdrGlob->numErrUDR_++; UdrGlob->numErrSP_++; UdrGlob->numErrLoadSP_++; if (showLoadLogic) dumpDiagnostics(diags, 2); } if (showLoadLogic) { ServerDebug("[UdrServ (%s)] About to send LOAD reply", moduleName); } #ifdef NA_DEBUG_C_RUNTIME if (UdrGlob && UdrGlob->getJavaLM()) { sleepIfPropertySet(*(UdrGlob->getJavaLM()), "MXUDR_LOAD_DELAY", diags); } #endif // NA_DEBUG_C_RUNTIME sendControlReply(UdrGlob, msgStream, sp); if (diags) { diags->decrRefCount(); } reply->decrRefCount(); } // processALoadMessage
LmResult LmRoutineCppObj::getRoutineInvocationInfo( /* IN/OUT */ char *serializedInvocationInfo, /* IN */ Int32 invocationInfoMaxLen, /* OUT */ Int32 *invocationInfoLenOut, /* IN/OUT */ char *serializedPlanInfo, /* IN */ Int32 planInfoMaxLen, /* IN */ Int32 planNum, /* OUT */ Int32 *planInfoLenOut, /* IN/OUT */ ComDiagsArea *da) { LmResult result = LM_OK; // Retrieve updated invocation and plan info. // The invokeRoutineMethod provided the required buffer // space, so there is no excuse for having insufficient // buffer when calling this, and doing so will raise // an exception in the try block below. try { if (invocationInfo_ && invocationInfoMaxLen > 0) { char *tempiibuf = serializedInvocationInfo; int tempiilen = invocationInfoMaxLen; *invocationInfoLenOut = invocationInfo_->serialize( tempiibuf, tempiilen); } else *invocationInfoLenOut = 0; if (planInfos_.used(planNum) && planInfoMaxLen > 0) { char *temppibuf = serializedPlanInfo; int temppilen = planInfoMaxLen; *planInfoLenOut = planInfos_[planNum]->serialize( temppibuf, temppilen); } else *planInfoLenOut = 0; } catch (tmudr::UDRException e) { // this UDRException is generated by Trafodion code and // it is an internal error to fail serializing the structs, // even though the user might have caused it by corrupting // these structs *da << DgSqlCode(-LME_OBJECT_INTERFACE_ERROR) << DgString0(getNameForDiags()) << DgString1(invocationInfo_->callPhaseToString(invocationInfo_->getCallPhase())) << DgString2("LmRoutineCppObj::getRoutineInvocationInfo()") << DgString3(e.getMessage().c_str()); result = LM_ERR; } catch (...) { *da << DgSqlCode(-LME_OBJECT_INTERFACE_ERROR) << DgString0(getNameForDiags()) << DgString1(invocationInfo_->callPhaseToString(invocationInfo_->getCallPhase())) << DgString2("LmRoutineCppObj::getRoutineInvocationInfo()") << DgString3("general exception"); result = LM_ERR; } return result; }
// ---------------------------------------------------------------------------- // method: unregisterUser // // This method removes a user from the database // // Input: parse tree containing a definition of the user // Output: the global diags area is set up with the result // ---------------------------------------------------------------------------- void CmpSeabaseDDLuser::unregisterUser (StmtDDLRegisterUser * pNode) { try { verifyAuthority(); // CASCADE option not yet supported if (pNode->getDropBehavior() == COM_CASCADE_DROP_BEHAVIOR) { *CmpCommon::diags() << DgSqlCode (-CAT_ONLY_SUPPORTING_RESTRICT_DROP_BEHAVIOR); DDLException excp (CAT_ONLY_SUPPORTING_RESTRICT_DROP_BEHAVIOR, NULL, 0); excp.throwException(); } // Verify that the specified user name is not reserved // TBD - add the isCatman concept if (isAuthNameReserved(pNode->getDbUserName())) { *CmpCommon::diags() << DgSqlCode (-CAT_AUTH_NAME_RESERVED) << DgString0(pNode->getDbUserName().data()); DDLException excp (CAT_AUTH_NAME_RESERVED, NULL, 0); excp.throwException(); } // set up class members from parse node // Read the row from the AUTHS table const NAString dbUserName(pNode->getDbUserName()); NAString sysCat = CmpSeabaseDDL::getSystemCatalogStatic(); char buf[1000]; str_sprintf(buf, "select auth_id, auth_db_name, auth_ext_name, auth_type, auth_creator, auth_is_valid, auth_create_time, auth_redef_time from %s.\"%s\".%s where auth_db_name = '%s' ", sysCat.data(), SEABASE_MD_SCHEMA, SEABASE_AUTHS, dbUserName.data()); NAString cmd (buf); if (!selectExactRow(cmd)) { // TBD - add CQD to return okay if user has already been unregistered *CmpCommon::diags() << DgSqlCode(-CAT_USER_NOT_EXIST) << DgString0(dbUserName.data()); DDLException excp (CAT_USER_NOT_EXIST, NULL, 0); excp.throwException(); } // Cannot unregister immutable users if (isAuthImmutable()) { *CmpCommon::diags() << DgSqlCode(-1387); DDLException excp (1387, NULL, 0); excp.throwException(); } // TBD, check to see if the user owns anything before removing // delete the row deleteRow(getAuthDbName()); } catch (...) { // At this time, an error should be in the diags area. // If there is no error, set up an internal error Int32 numErrors = CmpCommon::diags()->getNumber(DgSqlCode::ERROR_); if (numErrors == 0) *CmpCommon::diags() << DgSqlCode (-CAT_INTERNAL_EXCEPTION_ERROR) << DgInt0(__LINE__) << DgString0("unregister user"); } }
void ex_queue::injectErrorOrCancel() { #ifdef _DEBUG ex_queue_entry *qe = getQueueEntry(tail_-1); // DO the ol' switcheroo, but not every time. ULng32 freq = insertSubtask_->getTcb()->getGlobals()->getInjectErrorAtQueue(); if (freq == 0) return; if (upDown_ == UP_QUEUE) { if ((rand() & (freq-1)) != 0) return; NABoolean needsError = FALSE; switch (qe->upState.status) { case Q_OK_MMORE: { needsError = TRUE; qe->upState.status = Q_SQLERROR; cerr << "Converting a Q_OK_MMORE to a Q_SQLERROR, from " << NodeTypeToString(unblockSubtask_->getTcb()->getNodeType()) << "(" << unblockSubtask_->getTcb() << ")" << " to " << NodeTypeToString(insertSubtask_->getTcb()->getNodeType()) << "(" << insertSubtask_->getTcb() << ")" << endl; break; } case Q_NO_DATA: if (!isFull()) { needsError = TRUE; qe->upState.status = Q_SQLERROR; ex_queue_entry *newQNODATA = getTailEntry(); newQNODATA->upState = qe->upState; newQNODATA->upState.status = Q_NO_DATA; newQNODATA->getAtp()->copyAtp(qe->getAtp()); tail_++; cerr << "Injecting a Q_SQLERROR before a Q_NO_DATA, from " << NodeTypeToString(unblockSubtask_->getTcb()->getNodeType()) << "(" << unblockSubtask_->getTcb() << ")" << " to " << NodeTypeToString(insertSubtask_->getTcb()->getNodeType()) << "(" << insertSubtask_->getTcb() << ")" << endl; } break; default: break; } if (needsError) { ComDiagsArea * da = qe->getDiagsArea(); if (!da) da = ComDiagsArea::allocate(insertSubtask_->getTcb()->getHeap()); else da = da->copy(); qe->setDiagsArea(da); *da << DgSqlCode(-EXE_ERROR_INJECTED) << DgString0(__FILE__) << DgInt0(__LINE__); } } #endif return; }
void EspNewIncomingConnectionStream::actOnReceive(IpcConnection *connection) { // check for OS errors if (getState() == ERROR_STATE) { ex_assert(FALSE,"Error while receiving first message from client"); } // check for protocol errors bool willPassTheAssertion = (getType() == IPC_MSG_SQLESP_DATA_REQUEST OR getType() == IPC_MSG_SQLESP_CANCEL_REQUEST) AND getVersion() == CurrEspRequestMessageVersion AND moreObjects(); if (!willPassTheAssertion) { char *doCatchBugCRx = getenv("ESP_BUGCATCHER_CR_NONUMBER"); if (!doCatchBugCRx || *doCatchBugCRx != '0') { connection->dumpAndStopOtherEnd(true, false); environment_->getControlConnection()-> castToGuaReceiveControlConnection()-> getConnection()->dumpAndStopOtherEnd(true, false); } } ex_assert((getType() == IPC_MSG_SQLESP_DATA_REQUEST OR getType() == IPC_MSG_SQLESP_CANCEL_REQUEST) AND getVersion() == CurrEspRequestMessageVersion AND moreObjects(), "Invalid first message from client"); // take a look at the type of the first object in the message IpcMessageObjType nextObjType = getNextObjType(); switch (nextObjType) { case ESP_OPEN_HDR: case ESP_LATE_CANCEL_HDR: { ExFragKey key; Lng32 remoteInstNum; NABoolean isParallelExtract = false; // peek at the message header to see for whom it is if (nextObjType == ESP_OPEN_HDR) { ExEspOpenReqHeader reqHdr((NAMemory *) NULL); *this >> reqHdr; key = reqHdr.key_; remoteInstNum = reqHdr.myInstanceNum_; if (reqHdr.getOpenType() == ExEspOpenReqHeader::PARALLEL_EXTRACT) { isParallelExtract = true; } } else { // note that the late cancel request may or may not // arrive as the first request (only in the former case // will we reach here) ExEspLateCancelReqHeader reqHdr((NAMemory *) NULL); *this >> reqHdr; key = reqHdr.key_; remoteInstNum = reqHdr.myInstanceNum_; } if (!isParallelExtract) { ExFragInstanceHandle handle = espFragInstanceDir_->findHandle(key); if (handle != NullFragInstanceHandle) { // the send bottom node # myInstanceNum of this downloaded fragment // is the true recipient of this open request ex_split_bottom_tcb * receivingTcb = espFragInstanceDir_->getTopTcb(handle); ex_send_bottom_tcb *receivingSendTcb = receivingTcb->getSendNode(remoteInstNum); // Check the connection for a co-located client, and if so, // tell the split bottom, because it may prefer this send // bottom when using skew buster uniform distribution. if (espFragInstanceDir_-> getEnvironment()-> getMyOwnProcessId(IPC_DOM_GUA_PHANDLE).match( connection->getOtherEnd().getNodeName(), connection->getOtherEnd().getCpuNum())) receivingTcb->setLocalSendBottom(remoteInstNum); // Portability note for the code above: we pass IPC_DOM_GUA_PHANDLE // for IpcEnvironment::getMyOwnProcessId, even though that method // can be called with the default param (IpcNetworkDomain // IPC_DOM_INVALID). In fact it would probably be better // to call the object without specifying the IpcNetworkDomain so // that it can decide for itself what domain it is using. // But there is a problem with the Windows implementation // of IpcEnvironment::getMyOwnProcessId, it seems to assume // that its domain is IPC_DOM_INTERNET and so this will // cause the botch of an assertion that its control connection // (which is type EspGuaControlConnection) can be cast to a // SockControlConnection. When this problem is fixed, the // IPC_DOM_GUA_PHANDLE param above can be removed. Also, // when this code is ported to run it a domain other than // "guardian", it will be necessary to fix this and to // fix IpcEnvironment::getMyOwnProcessId to work properly on // windows. receivingSendTcb->setClient(connection); receivingSendTcb->routeMsg(*this); } else { connection->dumpAndStopOtherEnd(true, false); ex_assert(FALSE,"entry not found, set diagnostics area and reply"); } } // normal case, not parallel extract else { // The OPEN request is from a parallel extract consumer. The // incoming request contains a user ID which we will compare // against the current user ID for this ESP. // NOTE: The user ID for the extract security check is // currently sent and compared as a C string. On Linux it is // possible to send and compare integers which would lead to // simpler code. The code to send/compare strings is still // used because it works on all platforms. char errorStr[150]; // check if next msg is of securityInfo type. ex_assert(moreObjects(), "expected object not received"); ex_assert(getNextObjType() == ESP_SECURITY_INFO, "received message for unknown message type"); // unpack security info ExMsgSecurityInfo secInfo(environment_->getHeap()); *this >> secInfo; // Get the auth ID of this ESP in text form and compare it // to the auth ID that arrived in the message. Skip this // step in the debug build if an environment variable is // set. NABoolean doAuthIdCheck = TRUE; Int32 status = 0; #ifdef NA_DEBUG_C_RUNTIME const char *envvar = getenv("NO_EXTRACT_AUTHID_CHECK"); if (envvar && envvar[0]) doAuthIdCheck = FALSE; #endif if (doAuthIdCheck) { // Get user ID from ExMsgSecurityInfo -> (secUserID) // the user ID is the integer value made into a string // Convert it back into its integer value short userIDLen = (short) str_len(secInfo.getAuthID()); Int32 secUserID = str_atoi(secInfo.getAuthID(), userIDLen); // Get the current user ID Int32 curUserID = ComUser::getSessionUser(); // Report an error if the user ID is not valid if (curUserID == NA_UserIdDefault || secUserID == NA_UserIdDefault) { str_cpy_c(errorStr, "Producer ESP could not authenticate the consumer, " "no valid current user."); status = -1; } // Make sure user id passed in ExMsgSecurityInfo matches // the user id associated with the current session #if defined(NA_DEBUG_C_RUNTIME) NABoolean doDebug = (getenv("DBUSER_DEBUG") ? TRUE : FALSE); if (doDebug) printf("[DBUSER:%d] ESP extract user ID: " "local [%d], msg [%d]\n", (int) getpid(), curUserID, secUserID); #endif // Compare user ID, Report an error, if comparison fails if (curUserID != secUserID) { str_cpy_c(errorStr, "Producer ESP could not authenticate the consumer, " "user named passed in ExMsgSecurityInfo is not the " "current user"); status = -1; } } // if (doAuthIdCheck) // get the split bottom TCB that matches the securityKey ex_split_bottom_tcb *receivingTcb = NULL; if (status == 0) { receivingTcb = espFragInstanceDir_->getExtractTop(secInfo.getSecurityKey()); if (receivingTcb == NULL) { str_cpy_c(errorStr, "Producer ESP could not locate extract node"); status = -1; } } // get the sendBottom TCB if not already connected to a client ex_send_bottom_tcb *receivingSendTcb = NULL; if (status == 0) { receivingSendTcb = receivingTcb->getConsumerSendBottom(); if (receivingSendTcb == NULL) { str_cpy_c(errorStr, "Producer ESP already connected to a client"); status = -1; } } // send the error message to the consumer if (status != 0) { clearAllObjects(); setType(IPC_MSG_SQLESP_DATA_REPLY); NAMemory *heap = environment_->getHeap(); IpcMessageObj* baseObj = new(heap)IpcMessageObj(IPC_SQL_DIAG_AREA, CurrEspReplyMessageVersion); *this << *baseObj; // prepare proper error message char phandle[100]; MyGuaProcessHandle myHandle; myHandle.toAscii(phandle, 100); ComDiagsArea *diags = ComDiagsArea::allocate(heap); *diags << DgSqlCode(-EXE_PARALLEL_EXTRACT_OPEN_ERROR) << DgString0(phandle) << DgString1(errorStr); *this << *diags; diags->decrRefCount(); send(TRUE /* TRUE indicates waited */); } // if everything okay, then make the connection if (status == 0) { receivingSendTcb->setClient(connection); receivingSendTcb->routeMsg(*this); } } // parallel extract case } // open or cancel header
Int32 SqlciEnv::executeCommands(InputStmt *& input_stmt) { Int32 retval = 0; Int32 ignore_toggle = 0; SqlciNode * sqlci_node = 0; NABoolean inputPassedIn = (input_stmt ? TRUE : FALSE); try { while (!retval) { total_opens = 0; total_closes = 0; // This is new'd here, deleted when history buffer fills up, // in SqlciStmts::add/StmtEntry::set if (NOT inputPassedIn) input_stmt = new InputStmt(this); Int32 read_error = 0; if (NOT inputPassedIn) read_error = input_stmt->readStmt(NULL/*i.e. input is stdin*/); prev_err_flush_input = 0; if (cin.eof() || read_error == -99) { // allow the other thread to process Sleep(50); // milliseconds if (!input_stmt->isEmpty()) { // Unterminated statement in input file (redirected stdin). // Make the parser emit an error message. if (!isInteractiveSession()) input_stmt->display((UInt16)0); input_stmt->logStmt(); input_stmt->syntaxErrorOnEof(); displayDiagnostics(); sqlci_DA.clear(); } char command[10]; strcpy(command, ">>exit;"); if (!isInteractiveSession()) get_logfile()->WriteAll(command); else if (get_logfile()->IsOpen()) #pragma nowarn(1506) // warning elimination get_logfile()->Write(command, strlen(command)); #pragma warn(1506) // warning elimination sqlci_parser(&command[2], &command[2], &sqlci_node,this); if (sqlci_node) { retval = sqlci_node->process(this); delete sqlci_node; sqlci_node = NULL; } } else { if (!isInteractiveSession()) input_stmt->display((UInt16)0); if (logCommands()) get_logfile()->setNoLog(FALSE); input_stmt->logStmt(); if (logCommands()) get_logfile()->setNoLog(TRUE); if (!input_stmt->sectionMatches()) { Int32 ignore_stmt = input_stmt->isIgnoreStmt(); if (ignore_stmt) ignore_toggle = ~ignore_toggle; if (ignore_stmt || ignore_toggle || input_stmt->ignoreJustThis()) { // ignore until stmt following the untoggling ?ignore sqlci_DA.clear(); } else { getSqlciStmts()->add(input_stmt); if (!read_error) { retval = sqlci_parser(input_stmt->getPackedString(), input_stmt->getPackedString(), &sqlci_node, this); if (sqlci_node) { retval = sqlci_node->process(this); delete sqlci_node; sqlci_node = NULL; if (retval == SQL_Canceled) retval = 0; } else { // pure MXCI synatax error. Reset retval retval = 0; } } if (retval > 0) { if (!eol_seen_on_input) { prev_err_flush_input = -1; } retval = 0; } } // else }// if } // else if ( read_error == -20) { sqlci_DA << DgSqlCode(SQLCI_BREAK_RECEIVED, DgSqlCode::WARNING_); } if (read_error == SqlciEnv::MAX_FRAGMENT_LEN_OVERFLOW && !eolSeenOnInput() ) setPrevErrFlushInput(); displayDiagnostics(); sqlci_DA.clear(); // Clear the DiagnosticsArea for the next command... if (total_opens != total_closes) { char buf[100]; sprintf(buf, "total opens = %d, total closes = %d", total_opens, total_closes); #pragma nowarn(1506) // warning elimination get_logfile()->WriteAll(buf, strlen(buf)); #pragma warn(1506) // warning elimination } // Delete the stmt if not one of those we saved on the history list if (!input_stmt->isInHistoryList()) delete input_stmt; if (inputPassedIn) retval = 1; } // while if (retval == SQL_Canceled) return SQL_Canceled; else return 0; } catch(EHBreakException&) { sqlci_DA << DgSqlCode(SQLCI_BREAK_RECEIVED, DgSqlCode::WARNING_); displayDiagnostics(); sqlci_DA.clear(); // Clear the DiagnosticsArea for the next command... if (sqlci_node) delete sqlci_node; sqlci_node = NULL; cin.clear(); // NOTE: EnterCriticalSection has been done in ThrowBreakException() LeaveCriticalSection(&g_CriticalSection); return -1; } catch(...) { return 1; } } // executeCommands