ExprNode * ElemDDLSGOptions::bindNode(BindWA * /*pBindWA*/) { markAsBound(); return this; }
// We come here from syntax like // SELECT * FROM :hv PROTOTYPE 'cat.sch.tbl'; -- host variable, static SQL // TABLE $ev; -- env var, static or dynam // (Internally, both host vars and env vars are HostVar objects.) // // If there's an environment variable, get its value at time of compilation, // and stick that into the internal prototype value. Generator will need // to save these env var name/value pairs in the generated code; // Executor needs to use the saved compile-time value of any name that is not // defined at run-time. // // If there's a prototype value, parse it as an actual table name // (1, 2, or 3-part name) and overwrite the bogus values in *this with the // parsed prototype value. Our caller, applyDefaults, will overwrite any // remaining blank name parts. Generator needs to save the host var names // for actual input at run-time, and to save the prototype values for // similarity check at run-time. // // We avoid re-parsing and re-overwriting this CorrName by checking/setting // its bound state. Note that we do not rely on its prototype's bound state // because that is a separate, pointed at object: some Binder subroutines // make local copies of CorrNames, and any apply methods invoked on the locals // would not be propagated to the caller's originals: relying on the then True // value of the prototype's bound state would be fallacious. // // If no error in proto, node is bound and bindWA errStatus unchanged // (note that not having a proto is not an error). // If error in proto, node is left unbound and bindWA errStatus is set. // void CorrName::applyPrototype(BindWA *bindWA) { if (nodeIsBound()) return; HostVar *proto = getPrototype(); if (!proto) { markAsBound(); return; } // CMPASSERT(this == proto->getPrototypeTarget()); CMPASSERT(!proto->getName().isNull()); if (proto->isEnvVar()) { char *value = getenv(proto->getName()); if (!value) { // Environment variable has no defined value. *CmpCommon::diags() << DgSqlCode(-4086) << DgString0(proto->getName()); bindWA->setErrStatus(); return; } // upcase value returned by getenv #pragma nowarn(1506) // warning elimination Int32 len = strlen(value); #pragma warn(1506) // warning elimination char * ucValue = new (bindWA->wHeap()) char[len+1]; str_cpy_convert(ucValue, value, len, -1/*upshift*/); ucValue[len] = 0; proto->getPrototypeValue() = ucValue; // do not free "ucValue" here, it is still used in "proto" // to prevent Coverity RESOURCE_LEAK error, add the following // coverity[leaked_storage] } // defines can not be used on linux platform if (proto->isDefine()) { *CmpCommon::diags() << DgSqlCode(-4155) << DgString0(proto->getName()); bindWA->setErrStatus(); return; } CMPASSERT(!proto->getPrototypeValue().isNull()); // Some of the following code is cloned from the QualifiedName ctor above Parser parser(bindWA->currentCmpContext()); NAString ns("TABLE " + proto->getPrototypeValue() + ";", CmpCommon::statementHeap()); #pragma nowarn(1506) // warning elimination // save the current parserflags setting ULng32 savedParserFlags = Get_SqlParser_Flags (0xFFFFFFFF); StmtQuery *stmt = (StmtQuery *)parser.parseDML(ns, ns.length(), GetAnsiNameCharSet()); // Restore parser flags settings Set_SqlParser_Flags (savedParserFlags); #pragma warn(1506) // warning elimination if (stmt) { CMPASSERT(stmt->getOperatorType() == STM_QUERY); CorrName &protoCorrName = stmt->getQueryExpression()->getScanNode()->getTableName(); // Unless the hostvar type was forced directly, // copy the special table type to me, the prototype may be a // resource fork if (getSpecialType() == ExtendedQualName::NORMAL_TABLE) setSpecialType(protoCorrName); // This if-test prevents pathologies such as // SELECT col FROM :hv1 PROTOTYPE ':hv2 PROTOTYPE ''tbl'''; // but allows // SELECT col FROM :hv1 PROTOTYPE '$ev'; // // (The assertion below ensures that only host var syntax allows prototypes, // that you can't say ... FROM $ev PROTOTYPE '...'.) // HostVar *proto2 = protoCorrName.getPrototype(); CMPASSERT(!proto2 || !proto->isEnvVar()); if (!proto2 || proto2->isEnvVar()) { if (proto2) { // Here if proto2->isEnvVar. // Recurse (once only; the assertion above ensures that) // to get the value of the var, parse it and all. protoCorrName.applyPrototype(bindWA); if (bindWA->errStatus()) return; } #ifndef NDEBUG if (getenv("HV_DEBUG")) cout << "HostVar/Prototype: parsed (" << (Int32)proto->nodeIsBound() << ") " << proto->getName() << " " << protoCorrName.getExposedNameAsAnsiString() << endl; #endif // assert *before* overwriting with 0 // CMPASSERT(!getQualifiedNameObj().getNamePosition()); getQualifiedNameObj() = protoCorrName.getQualifiedNameObj(); proto->setPrototypeType(HostVar::QUALIFIEDNAME); // mark that we, the trusted CorrName, are bound markAsBound(); } } if (!nodeIsBound()) { // Clear parser syntax error and emit "Prototype value not valid" #ifndef NDEBUG if (!getenv("HV_DEBUG")) #endif CmpCommon::diags()->clear(); *CmpCommon::diags() << DgSqlCode(-4087) << DgString0(proto->getPrototypeValue()); bindWA->setErrStatus(); } delete stmt; } // applyPrototype
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; }