Skip to content

Commit

Permalink
Adds the "collation" option to IMPORT FOREIGN SCHEMA
Browse files Browse the repository at this point in the history
It's discussed in #329
  • Loading branch information
Sahap Asci committed Jun 28, 2019
1 parent 302eb0c commit 161e620
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 11 deletions.
11 changes: 8 additions & 3 deletions README.oracle_fdw
Original file line number Diff line number Diff line change
Expand Up @@ -476,14 +476,19 @@ following:
ALL_TAB_COLUMNS. That includes tables, views and materialized views,
but not synonyms.

- There are two supported options for IMPORT FOREIGN SCHEMA:
- **case**: controls case folding for table and column names during import.
- There are three supported options for IMPORT FOREIGN SCHEMA:
- **case**: controls case folding for table and column names during import.
The possible values are:
- `keep`: leave the names as they are in Oracle, usually in upper case.
- `lower`: translate all table and column names to lower case.
- `smart`: only translate names that are all upper case in Oracle
(this is the default).
- **readonly** (boolean): controls if imported tables can be modified.
- **collation**: controls case folding collation for table and column names during import.
Default value is `default` which is collation of working database.
Possible values refer to the `collname` values in
[pg_collation](https://www.postgresql.org/docs/current/catalog-pg-collation.html).
Only collations in pg_catalog schema are supported.
- **readonly** (boolean): controls if imported tables can be modified.
If set to `true`, all imported tables are created with the foreign
table option **readonly** set to `true` (see the [Options](#3-options)
section).
Expand Down
37 changes: 29 additions & 8 deletions oracle_fdw.c
Original file line number Diff line number Diff line change
Expand Up @@ -378,7 +378,7 @@ static void buildInsertQuery(StringInfo sql, struct OracleFdwState *fdwState);
static void buildUpdateQuery(StringInfo sql, struct OracleFdwState *fdwState, List *targetAttrs);
static void appendReturningClause(StringInfo sql, struct OracleFdwState *fdwState);
#ifdef IMPORT_API
static char *fold_case(char *name, fold_t foldcase);
static char *fold_case(char *name, fold_t foldcase, int collation);
#endif /* IMPORT_API */

#define REL_ALIAS_PREFIX "r"
Expand Down Expand Up @@ -2203,6 +2203,7 @@ oracleImportForeignSchema(ImportForeignSchemaStmt *stmt, Oid serverOid)
fold_t foldcase = CASE_SMART;
StringInfoData buf;
bool readonly = false, firstcol = true;
int collation = DEFAULT_COLLATION_OID;

/* get the foreign server, the user mapping and the FDW */
server = GetForeignServer(serverOid);
Expand Down Expand Up @@ -2248,6 +2249,26 @@ oracleImportForeignSchema(ImportForeignSchemaStmt *stmt, Oid serverOid)
errhint("Valid values in this context are: %s", "keep, lower, smart")));
continue;
}
else if (strcmp(def->defname, "collation") == 0)
{
char *s = ((Value *) (def->arg))->val.str;
if (pg_strcasecmp(s, "default") != 0) {

/* look up collation within pg_catalog namespace with the name */

collation = GetSysCacheOid3(COLLNAMEENCNSP,
PointerGetDatum(s),
Int32GetDatum(Int32GetDatum(-1)),
ObjectIdGetDatum(PG_CATALOG_NAMESPACE));

if (!OidIsValid(collation))
ereport(ERROR,
(errcode(ERRCODE_FDW_INVALID_ATTRIBUTE_VALUE),
errmsg("invalid value for option \"%s\"", def->defname),
errhint("Check pg_collation catalog to get valid values")));
}
continue;
}
else if (strcmp(def->defname, "readonly") == 0)
{
char *s = ((Value *) (def->arg))->val.str;
Expand All @@ -2269,7 +2290,7 @@ oracleImportForeignSchema(ImportForeignSchemaStmt *stmt, Oid serverOid)
ereport(ERROR,
(errcode(ERRCODE_FDW_INVALID_OPTION_NAME),
errmsg("invalid option \"%s\"", def->defname),
errhint("Valid options in this context are: %s", "case, readonly")));
errhint("Valid options in this context are: %s", "case, collation, readonly")));
}

elog(DEBUG1, "oracle_fdw: import schema \"%s\" from foreign server \"%s\"", stmt->remote_schema, server->servername);
Expand Down Expand Up @@ -2320,7 +2341,7 @@ oracleImportForeignSchema(ImportForeignSchemaStmt *stmt, Oid serverOid)
{
/* start a new CREATE FOREIGN TABLE statement */
resetStringInfo(&buf);
foldedname = fold_case(tabname, foldcase);
foldedname = fold_case(tabname, foldcase, collation);
appendStringInfo(&buf, "CREATE FOREIGN TABLE \"%s\" (", foldedname);
pfree(foldedname);

Expand All @@ -2340,7 +2361,7 @@ oracleImportForeignSchema(ImportForeignSchemaStmt *stmt, Oid serverOid)
appendStringInfo(&buf, ", ");

/* column name */
foldedname = fold_case(colname, foldcase);
foldedname = fold_case(colname, foldcase, collation);
appendStringInfo(&buf, "\"%s\" ", foldedname);
pfree(foldedname);

Expand Down Expand Up @@ -6373,21 +6394,21 @@ errorContextCallback(void *arg)
* Returns a palloc'ed string that is the case-folded first argument.
*/
char *
fold_case(char *name, fold_t foldcase)
fold_case(char *name, fold_t foldcase, int collation)
{
if (foldcase == CASE_KEEP)
return pstrdup(name);

if (foldcase == CASE_LOWER)
return str_tolower(name, strlen(name), DEFAULT_COLLATION_OID);
return str_tolower(name, strlen(name), collation);

if (foldcase == CASE_SMART)
{
char *upstr = str_toupper(name, strlen(name), DEFAULT_COLLATION_OID);
char *upstr = str_toupper(name, strlen(name), collation);

/* fold case only if it does not contain lower case characters */
if (strcmp(upstr, name) == 0)
return str_tolower(name, strlen(name), DEFAULT_COLLATION_OID);
return str_tolower(name, strlen(name), collation);
else
return pstrdup(name);
}
Expand Down

0 comments on commit 161e620

Please sign in to comment.