/* * downcase_truncate_identifier() --- do appropriate downcasing and * truncation of an unquoted identifier. Optionally warn of truncation. * * Returns a palloc'd string containing the adjusted identifier. * * Note: in some usages the passed string is not null-terminated. * * Note: the API of this function is designed to allow for downcasing * transformations that increase the string length, but we don't yet * support that. If you want to implement it, you'll need to fix * SplitIdentifierString() in utils/adt/varlena.c. */ char * downcase_truncate_identifier(const char *ident, int len, bool warn) { char *result; int i; result = palloc(len + 1); /* * SQL99 specifies Unicode-aware case normalization, which we don't yet * have the infrastructure for. Instead we use tolower() to provide a * locale-aware translation. However, there are some locales where this * is not right either (eg, Turkish may do strange things with 'i' and * 'I'). Our current compromise is to use tolower() for characters with * the high bit set, and use an ASCII-only downcasing for 7-bit * characters. */ for (i = 0; i < len; i++) { unsigned char ch = (unsigned char) ident[i]; if (ch >= 'A' && ch <= 'Z') ch += 'a' - 'A'; else if (IS_HIGHBIT_SET(ch) && isupper(ch)) ch = tolower(ch); result[i] = (char) ch; } result[i] = '\0'; if (i >= NAMEDATALEN) truncate_identifier(result, i, warn); return result; }
/* * makeArrayTypeName * - given a base type name, make an array type name for it * * the caller is responsible for pfreeing the result */ char * makeArrayTypeName(const char *typeName, Oid typeNamespace) { char *arr = (char *) palloc(NAMEDATALEN); int namelen = strlen(typeName); Relation pg_type_desc; int i; /* * The idea is to prepend underscores as needed until we make a name that * doesn't collide with anything... */ pg_type_desc = heap_open(TypeRelationId, AccessShareLock); for (i = 1; i < NAMEDATALEN - 1; i++) { arr[i - 1] = '_'; if (i + namelen < NAMEDATALEN) strcpy(arr + i, typeName); else { memcpy(arr + i, typeName, NAMEDATALEN - i); truncate_identifier(arr, NAMEDATALEN, false); } if (!SearchSysCacheExists(TYPENAMENSP, CStringGetDatum(arr), ObjectIdGetDatum(typeNamespace), 0, 0)) break; } heap_close(pg_type_desc, AccessShareLock); if (i >= NAMEDATALEN - 1) ereport(ERROR, (errcode(ERRCODE_DUPLICATE_OBJECT), errmsg("could not form array type name for type \"%s\"", typeName))); return arr; }