const NAString QualifiedName::getQualifiedNameAsAnsiNTFilenameString() const { // Preallocate a result buffer that'll be big enough most of the time // (so += won't reallocate+copy most of the time). NAString result((NASize_T)40, CmpCommon::statementHeap()); NAString catName(CmpCommon::statementHeap()); NAString schName(CmpCommon::statementHeap()); NAString objName(CmpCommon::statementHeap()); formatAsAnsiIdentifier = TRUE; // put quotes on delimited identifiers if ( NOT getCatalogName().isNull() ) { catName = FORMAT(getCatalogName()); makeSafeFilenamePart(catName, "SQLMX_DEFAULT_CATALOG_"); } if ( NOT getSchemaName().isNull() ) { schName = FORMAT(getSchemaName()); makeSafeFilenamePart(schName, "SQLMX_DEFAULT_SCHEMA_"); } if ( NOT getObjectName().isNull() ) { objName = FORMAT(getObjectName()); } makeSafeFilenamePart(objName, "SQLMX_DEFAULT_FILE_"); formatAsAnsiIdentifier = FALSE; // reset to initial value size_t totlen = catName.length() + schName.length() + objName.length() + 2; if ( totlen > 255 ) { // need to truncate // +1 so round off doesn't give us less than what we need to chop size_t chopLen = totlen - 255 + 1; if ( catName.length() - chopLen/2 <= 0 ) // cat too short schName.remove( schName.length() - chopLen ); else if ( schName.length() - chopLen/2 <= 0 ) // sch too short catName.remove( catName.length() - chopLen ); else { // chop from both // remember position starts at 0 and length is 1 more chopLen /= 2; catName.remove( catName.length() - chopLen - 1 ); schName.remove( schName.length() - chopLen - 1 ); } } if (NOT catName.isNull()) { result = catName; result += "."; } if (NOT schName.isNull()) { result += schName; result += "."; } result += objName; return result; }
// 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; }