ExprNode *
ElemDDLSGOptions::bindNode(BindWA * /*pBindWA*/)
{

  markAsBound();
  return this;
}
Ejemplo n.º 2
0
// 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;
}