//LCOV_EXCL_START /* : cnu -- not used on Linux */ // ----------------------------------------------------------------------- // makeSafeFilenamePart() and // QualifiedName::getQualifiedNameAsAnsiNTFilenameString() // // Genesis 10-990113-5782 // Make sure that the end result of this function results in a valid // file name for the system -- whether NT or OSS. // // Convert any invalid NT filename characters to underscores. // // A valid NT (or OSS) filename may be up to 255 characters including spaces. // The characters // \/:*?<>|" // are not allowed in the filename at all. // Furthermore, a POSIX shell (MKS KornShell on NT, OSS on NSK) // treats the following specially, so they do not make good chars for filenames: // $%&();' and space // // SQL identifiers can be up to 128 characters long in regular or // delimited format. // // Regular identifiers begin with A-Z or a-z and can contain digits 0-9 or // underscores. Regular identifiers are not case sensitive. Reserved words // may not be used in a regular identifier. // // Delimited identifiers always begin with a " character, and can contain // both upper and lowercase Latin-1 characters, as well as // \/|<>*?:" // $%&();' and space // +-=[],. // digits 0-9 and underscore // // This routine will convert all non-alphanumeric chars // to the underscore character, and result in a filename which when treated // as an Ansi qualified name (a MODULE name), is composed only of regular // identifiers -- no "quoting" needed. // // The length of a module name that might get generated // could be a string of over 255 characters. 128 for each of the three parts. // 2 characters for each part if delimited plus the period separators not // counting any quotes which are embedded and doubled which might be // singled again. // // There might still be problems because NT is not case sensitive but // SQL is where delimited identifiers are concerned and that is not being // addressed here. We're just going to assume that we won't have two // catalogs and schemas that are the same delimited if case is not considered // that will cause problems in NT. We will be replacing all characters // that cause the name to be delimited with underscore. // // If we need to truncate any one of the three parts (not generally the // user supplied portion (mainly just the module name portion), then we // will need to verify that the truncated result does not result in a // reserved word. Might possibly happen depending on how we decide to // handle the case where the length of 2 of the parts nears the 255 // character file name limit for NT and we decide to truncate one part // down to a size that might result in a reserved word. // ----------------------------------------------------------------------- // static void makeSafeFilenamePart(NAString &ns, const NAString &prefix) { size_t len = ns.length(); for (size_t i=0; i<len; i++) { if (!isalnum(ns[i]) && ns[i] != '_') ns[i] = '_'; } if (!len || !isalpha(ns[(size_t)0])) // must begin with an alphabetic ns.prepend(prefix); }
// Name parts return in string parameters, defaulted if not yet present; // this object is not modified. // Function return value is the number of names that match the default, // {0, 1, 2} = {no matches, catalog matches, catalog&schema match}. // // If NAMETYPE is NSK, the SchemaDB puts the current MPLOC into the defCatSch; // so this method has to handle **only one** tiny NSK naming detail. // Int32 QualifiedName::extractAndDefaultNameParts(const SchemaName& defCatSch , NAString& catName // OUT , NAString& schName // OUT , NAString& objName // OUT ) const { catName = getCatalogName(); schName = getSchemaName(); objName = getObjectName(); CMPASSERT(NOT objName.isNull()); // no default for this! { if (catName.isNull()) { if((ActiveSchemaDB()->getDefaults().schSetToUserID()) && (SqlParser_NAMETYPE == DF_SHORTANSI)) { // If NAMETYPE is SHORTANSI and schema is not set // in DEFAULTS table or by user, for dml, catName // gets \SYS.$VOL from set or default MPLOC. catName = SqlParser_MPLOC.getSysDotVol(); } else { // If NAMETYPE NSK, catName will become \SYS.$VOL catName = defCatSch.getCatalogName(); } } else if (SqlParser_NAMETYPE == DF_NSK && *catName.data() == '$' && SqlParser_MPLOC.hasSystemName()) { // If user specified only a $VOL, fill in the current default \SYS. catName.prepend(SqlParser_MPLOC.getSystemName() + "."); } if (schName.isNull()) { if((ActiveSchemaDB()->getDefaults().schSetToUserID()) && (SqlParser_NAMETYPE == DF_SHORTANSI)) { // If NAMETYPE is SHORTANSI and schema is not set // in DEFAULTS table or by user, for dml, schName // gets subvol from set or default MPLOC. schName = SqlParser_MPLOC.getSubvolName(); } else schName = defCatSch.getSchemaName(); } } CMPASSERT(NOT catName.isNull()); CMPASSERT(NOT schName.isNull()); Int32 defaultMatches = 0; if (catName == defCatSch.getCatalogName()) { defaultMatches++; if (schName == defCatSch.getSchemaName()) defaultMatches++; } // Next comes support for table name resolution for SHORTANSI nametype, // implemented as internal feature for ODBC use only. // // For the name resolution of table name when nametype is SHORTANSI, // check is made to see if schName contains an '_', thus ensuring // the method applyShortAnsiDefault is called only once. // Correct syntax for schName is "systemName_volumeName_subvolName" // of the MPLoc where the objName is actually located. // Complete syntax checking is done inside applyShortAnsiDefault. // if (SqlParser_NAMETYPE == DF_SHORTANSI && schName.first('_') != NA_NPOS) { applyShortAnsiDefault(catName, schName); } return defaultMatches; }