diff options
Diffstat (limited to 'contrib/postgres_fdw/postgres_fdw.c')
-rw-r--r-- | contrib/postgres_fdw/postgres_fdw.c | 65 |
1 files changed, 49 insertions, 16 deletions
diff --git a/contrib/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c index 3e4a307880f..9d443baf02a 100644 --- a/contrib/postgres_fdw/postgres_fdw.c +++ b/contrib/postgres_fdw/postgres_fdw.c @@ -4012,6 +4012,9 @@ create_foreign_modify(EState *estate, Assert(!attr->attisdropped); + /* Ignore generated columns; they are set to DEFAULT */ + if (attr->attgenerated) + continue; getTypeOutputInfo(attr->atttypid, &typefnoid, &isvarlena); fmgr_info(typefnoid, &fmstate->p_flinfo[fmstate->p_nums]); fmstate->p_nums++; @@ -4075,8 +4078,10 @@ execute_foreign_modify(EState *estate, /* Build INSERT string with numSlots records in its VALUES clause. */ initStringInfo(&sql); - rebuildInsertSql(&sql, fmstate->orig_query, fmstate->values_end, - fmstate->p_nums, *numSlots - 1); + rebuildInsertSql(&sql, fmstate->rel, + fmstate->orig_query, fmstate->target_attrs, + fmstate->values_end, fmstate->p_nums, + *numSlots - 1); pfree(fmstate->query); fmstate->query = sql.data; fmstate->num_slots = *numSlots; @@ -4244,6 +4249,7 @@ convert_prep_stmt_params(PgFdwModifyState *fmstate, /* get following parameters from slots */ if (slots != NULL && fmstate->target_attrs != NIL) { + TupleDesc tupdesc = RelationGetDescr(fmstate->rel); int nestlevel; ListCell *lc; @@ -4255,9 +4261,13 @@ convert_prep_stmt_params(PgFdwModifyState *fmstate, foreach(lc, fmstate->target_attrs) { int attnum = lfirst_int(lc); + Form_pg_attribute attr = TupleDescAttr(tupdesc, attnum - 1); Datum value; bool isnull; + /* Ignore generated columns; they are set to DEFAULT */ + if (attr->attgenerated) + continue; value = slot_getattr(slots[i], attnum, &isnull); if (isnull) p_values[pindex] = NULL; @@ -5188,6 +5198,7 @@ postgresImportForeignSchema(ImportForeignSchemaStmt *stmt, Oid serverOid) List *commands = NIL; bool import_collate = true; bool import_default = false; + bool import_generated = true; bool import_not_null = true; ForeignServer *server; UserMapping *mapping; @@ -5207,6 +5218,8 @@ postgresImportForeignSchema(ImportForeignSchemaStmt *stmt, Oid serverOid) import_collate = defGetBoolean(def); else if (strcmp(def->defname, "import_default") == 0) import_default = defGetBoolean(def); + else if (strcmp(def->defname, "import_generated") == 0) + import_generated = defGetBoolean(def); else if (strcmp(def->defname, "import_not_null") == 0) import_not_null = defGetBoolean(def); else @@ -5270,13 +5283,24 @@ postgresImportForeignSchema(ImportForeignSchemaStmt *stmt, Oid serverOid) * include a schema name for types/functions in other schemas, which * is what we want. */ + appendStringInfoString(&buf, + "SELECT relname, " + " attname, " + " format_type(atttypid, atttypmod), " + " attnotnull, "); + + /* Generated columns are supported since Postgres 12 */ + if (PQserverVersion(conn) >= 120000) + appendStringInfoString(&buf, + " attgenerated, " + " pg_get_expr(adbin, adrelid), "); + else + appendStringInfoString(&buf, + " NULL, " + " pg_get_expr(adbin, adrelid), "); + if (import_collate) appendStringInfoString(&buf, - "SELECT relname, " - " attname, " - " format_type(atttypid, atttypmod), " - " attnotnull, " - " pg_get_expr(adbin, adrelid), " " collname, " " collnsp.nspname " "FROM pg_class c " @@ -5293,11 +5317,6 @@ postgresImportForeignSchema(ImportForeignSchemaStmt *stmt, Oid serverOid) " collnsp.oid = collnamespace "); else appendStringInfoString(&buf, - "SELECT relname, " - " attname, " - " format_type(atttypid, atttypmod), " - " attnotnull, " - " pg_get_expr(adbin, adrelid), " " NULL, NULL " "FROM pg_class c " " JOIN pg_namespace n ON " @@ -5374,6 +5393,7 @@ postgresImportForeignSchema(ImportForeignSchemaStmt *stmt, Oid serverOid) char *attname; char *typename; char *attnotnull; + char *attgenerated; char *attdefault; char *collname; char *collnamespace; @@ -5385,12 +5405,14 @@ postgresImportForeignSchema(ImportForeignSchemaStmt *stmt, Oid serverOid) attname = PQgetvalue(res, i, 1); typename = PQgetvalue(res, i, 2); attnotnull = PQgetvalue(res, i, 3); - attdefault = PQgetisnull(res, i, 4) ? (char *) NULL : + attgenerated = PQgetisnull(res, i, 4) ? (char *) NULL : PQgetvalue(res, i, 4); - collname = PQgetisnull(res, i, 5) ? (char *) NULL : + attdefault = PQgetisnull(res, i, 5) ? (char *) NULL : PQgetvalue(res, i, 5); - collnamespace = PQgetisnull(res, i, 6) ? (char *) NULL : + collname = PQgetisnull(res, i, 6) ? (char *) NULL : PQgetvalue(res, i, 6); + collnamespace = PQgetisnull(res, i, 7) ? (char *) NULL : + PQgetvalue(res, i, 7); if (first_item) first_item = false; @@ -5418,9 +5440,20 @@ postgresImportForeignSchema(ImportForeignSchemaStmt *stmt, Oid serverOid) quote_identifier(collname)); /* Add DEFAULT if needed */ - if (import_default && attdefault != NULL) + if (import_default && attdefault != NULL && + (!attgenerated || !attgenerated[0])) appendStringInfo(&buf, " DEFAULT %s", attdefault); + /* Add GENERATED if needed */ + if (import_generated && attgenerated != NULL && + attgenerated[0] == ATTRIBUTE_GENERATED_STORED) + { + Assert(attdefault != NULL); + appendStringInfo(&buf, + " GENERATED ALWAYS AS (%s) STORED", + attdefault); + } + /* Add NOT NULL if needed */ if (import_not_null && attnotnull[0] == 't') appendStringInfoString(&buf, " NOT NULL"); |