diff --git a/GNUmakefile.in b/GNUmakefile.in index d37de4836..afca2d5fd 100644 --- a/GNUmakefile.in +++ b/GNUmakefile.in @@ -34,8 +34,15 @@ else install_mysql_fdw: endif +ifeq ($(enable_oracle_fdw), yes) +install_oracle_fdw: + $(MAKE) -C contrib/oracle_fdw install +else +install_oracle_fdw: +endif + ifeq ($(enable_multiple_nodes), yes) -install: install_mysql_fdw +install: install_mysql_fdw install_oracle_fdw $(MAKE) -C contrib/hstore $@ $(MAKE) -C src/distribute/kernel/extension/packages $@ $(MAKE) -C contrib/pagehack $@ @@ -45,7 +52,7 @@ install: install_mysql_fdw $(MAKE) -C src/distribute/kernel/extension/tsdb $@ +@echo "PostgreSQL installation complete." else -install: install_mysql_fdw +install: install_mysql_fdw install_oracle_fdw +@echo "openGauss installation complete." endif diff --git a/README.md b/README.md index dae1c998b..4e7f451bd 100644 --- a/README.md +++ b/README.md @@ -514,6 +514,7 @@ Compilation log: **make_compile.log** > 3. On the **ARMv8.1** platform or a later version (for example, Kunpeng 920), **-D__ARM_LSE** needs to be added to **CFLAGS**. > 4. If **binarylibs** is moved to **openGauss-server** or a soft link to **binarylibs** is created in **openGauss-server**, you do not need to specify the **--3rd** parameter. However, if you do so, please note that the file is easy to be deleted by the `git clean` command. > 5. To build with mysql_fdw, add **--enable-mysql-fdw** when configure. Note that before build mysql_fdw, MariaDB's C client library is needed. + > 6. To build with oracle_fdw, add **--enable-oracle-fdw** when configure. Note that before build oracle_fdw, Oracle's C client library is needed. 4. Run the following commands to compile openGauss: diff --git a/configure b/configure index e72c69476..c41816ff8 100755 --- a/configure +++ b/configure @@ -744,6 +744,7 @@ enable_jemalloc_debug enable_multiple_nodes enable_memory_check enable_mysql_fdw +enable_oracle_fdw enable_thread_check enable_shared default_gs_version @@ -821,6 +822,7 @@ enable_jemalloc_debug enable_multiple_nodes enable_memory_check enable_mysql_fdw +enable_oracle_fdw enable_thread_check enable_spinlocks enable_debug @@ -2869,6 +2871,28 @@ else fi +# Check whether --enable-oracle-fdw was given. +if test "${enable_oracle_fdw+set}" = set; then + enableval=$enable_oracle_fdw; + case $enableval in + yes) + : + ;; + no) + : + ;; + *) + { { $as_echo "$as_me:$LINENO: error: no argument expected for --enable-oracle-fdw option" >&5 +$as_echo "$as_me: error: no argument expected for --enable-oracle-fdw option" >&2;} + { (exit 1); exit 1; }; } + ;; + esac + +else + enable_oracle_fdw=no + +fi + # Check whether --enable-thread-check was given. if test "${enable_thread_check+set}" = set; then enableval=$enable_thread_check; diff --git a/contrib/oracle_fdw/Makefile b/contrib/oracle_fdw/Makefile new file mode 100644 index 000000000..2dad602fd --- /dev/null +++ b/contrib/oracle_fdw/Makefile @@ -0,0 +1,59 @@ +# +# Copyright (c) 2020 Huawei Technologies Co.,Ltd. +# +# openGauss is licensed under Mulan PSL v2. +# You can use this software according to the terms and conditions of the Mulan PSL v2. +# You may obtain a copy of Mulan PSL v2 at: +# +# http://license.coscl.org.cn/MulanPSL2 +# +# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, +# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, +# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. +# See the Mulan PSL v2 for more details. +# --------------------------------------------------------------------------------------- +# +# Makefile +# Makefile for the oracle_fdw +# +# IDENTIFICATION +# contrib/oracle_fdw/Makefile +# +# --------------------------------------------------------------------------------------- + +all:oracle_fdw_target +install:install-data + +top_builddir ?= ../../ +ORACLE_FDW_DIR=$(top_builddir)/third_party/dependency/oracle_fdw +ORACLE_FDW_PACKAGE=oracle_fdw-ORACLE_FDW_2_2_0 +ORACLE_FDW_PATCH=huawei_oracle_fdw-2.2.0_patch +ORACLE_FDW_MEGRED_SOURCES_DIR=$(ORACLE_FDW_DIR)/code + +.PHONY: oracle_fdw_target +oracle_fdw_target: + @$(call create_oracle_fdw_sources) + @make -C $(ORACLE_FDW_MEGRED_SOURCES_DIR)/$(ORACLE_FDW_PACKAGE) NO_PGXS=1 + +.PHONY: install-data +install-data: oracle_fdw_target + @make -C $(ORACLE_FDW_MEGRED_SOURCES_DIR)/$(ORACLE_FDW_PACKAGE) NO_PGXS=1 install + +uninstall distclean clean: + @rm -rf $(ORACLE_FDW_MEGRED_SOURCES_DIR) + +define create_oracle_fdw_sources + rm -rf $(ORACLE_FDW_MEGRED_SOURCES_DIR); \ + mkdir $(ORACLE_FDW_MEGRED_SOURCES_DIR); \ + tar xfzv $(ORACLE_FDW_DIR)/$(ORACLE_FDW_PACKAGE).tar.gz -C $(ORACLE_FDW_MEGRED_SOURCES_DIR) &> /dev/null; \ + for ((i=1;i<=99;i++)); \ + do \ + file_name="$(ORACLE_FDW_DIR)/$$i-oracle_fdw-2.2.0_patch.patch"; \ + if [ ! -f "$$file_name" ]; then \ + exit 0; \ + fi; \ + patch -p0 -d $(ORACLE_FDW_MEGRED_SOURCES_DIR)/$(ORACLE_FDW_PACKAGE) < $$file_name &> /dev/null; \ + done + rename ".c" ".cpp" $(ORACLE_FDW_MEGRED_SOURCES_DIR)/$(ORACLE_FDW_PACKAGE)/*.c; \ + patch -p0 -d $(ORACLE_FDW_MEGRED_SOURCES_DIR)/$(ORACLE_FDW_PACKAGE) < $(ORACLE_FDW_DIR)/$(ORACLE_FDW_PATCH).patch &> /dev/null; +endef diff --git a/src/Makefile.global.in b/src/Makefile.global.in index 23f197a14..273da8a6b 100644 --- a/src/Makefile.global.in +++ b/src/Makefile.global.in @@ -172,6 +172,7 @@ enable_jemalloc = @enable_jemalloc@ enable_jemalloc_debug = @enable_jemalloc_debug@ enable_multiple_nodes = @enable_multiple_nodes@ enable_mysql_fdw = @enable_mysql_fdw@ +enable_oracle_fdw = @enable_oracle_fdw@ enable_memory_check = @enable_memory_check@ enable_memory_check_core = @enable_memory_check_core@ enable_thread_check = @enable_thread_check@ diff --git a/src/common/backend/parser/analyze.cpp b/src/common/backend/parser/analyze.cpp index 68386f168..efa5a80a1 100644 --- a/src/common/backend/parser/analyze.cpp +++ b/src/common/backend/parser/analyze.cpp @@ -868,8 +868,10 @@ static void CheckUnsupportInsertSelectClause(Query* query) AssertEreport(query->commandType == CMD_INSERT, MOD_OPT, "Only deal with CMD_INSERT commondType here"); if (result->relkind == RELKIND_FOREIGN_TABLE) { - if (isMOTFromTblOid(result->relid) || isMysqlFDWFromTblOid(result->relid)) + if (isMOTFromTblOid(result->relid) || isMysqlFDWFromTblOid(result->relid) || + isOracleFDWFromTblOid(result->relid)) { return; + } if (list_length(query->rtable) == 1) ereport(ERROR, diff --git a/src/gausskernel/Makefile b/src/gausskernel/Makefile index c896bf1c9..86b64aac2 100644 --- a/src/gausskernel/Makefile +++ b/src/gausskernel/Makefile @@ -31,6 +31,10 @@ ifeq ($(enable_mysql_fdw), yes) SUBDIRS += $(top_builddir)/contrib/mysql_fdw endif +ifeq ($(enable_oracle_fdw), yes) + SUBDIRS += $(top_builddir)/contrib/oracle_fdw +endif + ifeq ($(enable_multiple_nodes), yes) SUBDIRS += ../distribute/kernel ../distribute/kernel/extension/roach_api ../distribute/kernel/extension/dimsearch/main \ ../distribute/kernel/extension/tsdb diff --git a/src/gausskernel/optimizer/plan/createplan.cpp b/src/gausskernel/optimizer/plan/createplan.cpp index d356ff945..9678c6c39 100644 --- a/src/gausskernel/optimizer/plan/createplan.cpp +++ b/src/gausskernel/optimizer/plan/createplan.cpp @@ -8462,7 +8462,8 @@ ModifyTable* make_modifytable(CmdType operation, bool canSetTag, List* resultRel Plan* subplan = (Plan*)(linitial(subplans)); ForeignScan* fscan = NULL; if ((fscan = (ForeignScan*)FindForeignScan(subplan)) != NULL) { - if (!isMOTFromTblOid(fscan->scan_relid) && !isMysqlFDWFromTblOid(fscan->scan_relid)) + if (!isMOTFromTblOid(fscan->scan_relid) && !isMysqlFDWFromTblOid(fscan->scan_relid) && + !isOracleFDWFromTblOid(fscan->scan_relid)) ereport(ERROR, (errmodule(MOD_OPT), errcode(ERRCODE_FEATURE_NOT_SUPPORTED), diff --git a/src/include/foreign/foreign.h b/src/include/foreign/foreign.h index 2b270f548..369b091bd 100644 --- a/src/include/foreign/foreign.h +++ b/src/include/foreign/foreign.h @@ -285,6 +285,9 @@ bool isWriteOnlyFt(Oid relid); #define isMysqlFDWFromTblOid(relId) \ (IsSpecifiedFDWFromRelid(relId, MYSQL_FDW)) +#define isOracleFDWFromTblOid(relId) \ + (IsSpecifiedFDWFromRelid(relId, ORACLE_FDW)) + #define IS_OBS_CSV_TXT_FOREIGN_TABLE(relId) \ (IsSpecifiedFDWFromRelid(relId, DIST_FDW) && (is_obs_protocol(HdfsGetOptionValue(relId, optLocation)))) diff --git a/src/include/postgres.h b/src/include/postgres.h index f907032e7..40ddaab0a 100644 --- a/src/include/postgres.h +++ b/src/include/postgres.h @@ -78,6 +78,10 @@ #define MYSQL_FDW "mysql_fdw" #endif +#ifndef ORACLE_FDW +#define ORACLE_FDW "oracle_fdw" +#endif + #ifndef MOT_FDW #define MOT_FDW "mot_fdw" #endif diff --git a/third_party/dependency/oracle_fdw/huawei_oracle_fdw-2.2.0_patch.patch b/third_party/dependency/oracle_fdw/huawei_oracle_fdw-2.2.0_patch.patch new file mode 100644 index 000000000..4140529a6 --- /dev/null +++ b/third_party/dependency/oracle_fdw/huawei_oracle_fdw-2.2.0_patch.patch @@ -0,0 +1,1036 @@ +diff --git Makefile Makefile +index 5f8b100..7fdd24f 100644 +--- Makefile ++++ Makefile +@@ -11,7 +11,7 @@ SHLIB_LINK = -L$(ORACLE_HOME) -L$(ORACLE_HOME)/bin -L$(ORACLE_HOME)/lib -L$(ORAC + + ifdef NO_PGXS + subdir = contrib/oracle_fdw +-top_builddir = ../.. ++top_builddir = ../../../../../ + include $(top_builddir)/src/Makefile.global + include $(top_srcdir)/contrib/contrib-global.mk + else +@@ -30,3 +30,6 @@ else + ORACLE_SHLIB=clntsh + endif + endif ++ ++exclude_option=-fPIE ++override CPPFLAGS := $(filter-out $(exclude_option),$(CPPFLAGS)) +\ No newline at end of file +diff --git oracle_fdw.cpp oracle_fdw.cpp +index e75b6ab..7e83a4f 100644 +--- oracle_fdw.cpp ++++ oracle_fdw.cpp +@@ -92,13 +92,13 @@ + #define WIDTH_THRESHOLD 1024 + #endif /* WIDTH_THRESHOLD */ + +-#if PG_VERSION_NUM < 90200 ++#if 0//PG_VERSION_NUM < 90200 + #define OLD_FDW_API + #else + #undef OLD_FDW_API + #endif /* PG_VERSION_NUM */ + +-#if PG_VERSION_NUM >= 90300 ++#if 1//PG_VERSION_NUM >= 90300 + #define WRITE_API + #else + #undef WRITE_API +@@ -153,13 +153,13 @@ PG_MODULE_MAGIC; + /* + * "true" if Oracle data have been modified in the current transaction. + */ +-static bool dml_in_transaction = false; ++static THR_LOCAL bool dml_in_transaction = false; + + /* + * PostGIS geometry type, set upon library initialization. + */ +-static Oid GEOMETRYOID = InvalidOid; +-static bool geometry_is_setup = false; ++static THR_LOCAL Oid GEOMETRYOID = InvalidOid; ++static THR_LOCAL bool geometry_is_setup = false; + + /* + * Describes the valid options for objects that use this wrapper. +@@ -219,7 +219,7 @@ static struct OracleFdwOption valid_options[] = { + * be more than one foreign table modified at the same time. + */ + +-static regproc *output_funcs; ++static THR_LOCAL regproc *output_funcs; + #endif /* WRITE_API */ + + /* +@@ -275,10 +275,10 @@ struct OracleFdwState { + /* + * SQL functions + */ +-extern PGDLLEXPORT Datum oracle_fdw_handler(PG_FUNCTION_ARGS); +-extern PGDLLEXPORT Datum oracle_fdw_validator(PG_FUNCTION_ARGS); +-extern PGDLLEXPORT Datum oracle_close_connections(PG_FUNCTION_ARGS); +-extern PGDLLEXPORT Datum oracle_diag(PG_FUNCTION_ARGS); ++extern "C" PGDLLEXPORT Datum oracle_fdw_handler(PG_FUNCTION_ARGS); ++extern "C" PGDLLEXPORT Datum oracle_fdw_validator(PG_FUNCTION_ARGS); ++extern "C" PGDLLEXPORT Datum oracle_close_connections(PG_FUNCTION_ARGS); ++extern "C" PGDLLEXPORT Datum oracle_diag(PG_FUNCTION_ARGS); + + PG_FUNCTION_INFO_V1(oracle_fdw_handler); + PG_FUNCTION_INFO_V1(oracle_fdw_validator); +@@ -306,7 +306,7 @@ static ForeignScan *oracleGetForeignPlan(PlannerInfo *root, RelOptInfo *foreignr + , Plan *outer_plan + #endif /* PG_VERSION_NUM */ + ); +-static bool oracleAnalyzeForeignTable(Relation relation, AcquireSampleRowsFunc *func, BlockNumber *totalpages); ++static bool oracleAnalyzeForeignTable(Relation relation, AcquireSampleRowsFunc *func, BlockNumber *totalpages, void* additionalData, bool estimateTableRowNum); + #endif /* OLD_FDW_API */ + static void oracleExplainForeignScan(ForeignScanState *node, ExplainState *es); + static void oracleBeginForeignScan(ForeignScanState *node, int eflags); +@@ -348,7 +348,7 @@ static struct oraTable *build_join_oratable(struct OracleFdwState *fdwState, Lis + #endif /* JOIN_API */ + static void getColumnData(Oid foreigntableid, struct oraTable *oraTable); + #ifndef OLD_FDW_API +-static int acquireSampleRowsFunc (Relation relation, int elevel, HeapTuple *rows, int targrows, double *totalrows, double *totaldeadrows); ++static int acquireSampleRowsFunc (Relation relation, int elevel, HeapTuple *rows, int targrows, double *totalrows, double *totaldeadrows, void* additionalData, bool estimateTableRowNum); + static void appendAsType(StringInfoData *dest, const char *s, Oid type); + #endif /* OLD_FDW_API */ + static char *deparseExpr(oracleSession *session, RelOptInfo *foreignrel, Expr *expr, const struct oraTable *oraTable, List **params); +@@ -375,6 +375,10 @@ static struct OracleFdwState *copyPlanData(struct OracleFdwState *orig); + static void subtransactionCallback(SubXactEvent event, SubTransactionId mySubid, SubTransactionId parentSubid, void *arg); + static void addParam(struct paramDesc **paramList, char *name, Oid pgtype, oraType oratype, int colnum); + static void setModifyParameters(struct paramDesc *paramList, TupleTableSlot *newslot, TupleTableSlot *oldslot, struct oraTable *oraTable, oracleSession *session); ++static bool hasTrigger(Relation rel, CmdType cmdtype); ++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); + #endif /* WRITE_API */ + static void transactionCallback(XactEvent event, void *arg); + static void exitHook(int code, Datum arg); +@@ -382,10 +386,7 @@ static void oracleDie(SIGNAL_ARGS); + static char *setSelectParameters(struct paramDesc *paramList, ExprContext *econtext); + static void convertTuple(struct OracleFdwState *fdw_state, Datum *values, bool *nulls, bool trunc_lob); + static void errorContextCallback(void *arg); +-static bool hasTrigger(Relation rel, CmdType cmdtype); +-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, int collation); + #endif /* IMPORT_API */ +@@ -457,7 +458,7 @@ oracle_fdw_validator(PG_FUNCTION_ARGS) + Oid catalog = PG_GETARG_OID(1); + ListCell *cell; + bool option_given[option_count] = { false }; +- int i; ++ unsigned int i; + + /* + * Check that only options supported by oracle_fdw, and allowed for the +@@ -752,9 +753,6 @@ _PG_init(void) + errmsg("PostgreSQL version \"%s\" not supported by oracle_fdw", + GetConfigOptionByName("server_version", NULL)), + errhint("You'll have to update PostgreSQL to a later minor release."))); +- +- /* register an exit hook */ +- on_proc_exit(&exitHook, PointerGetDatum(NULL)); + } + + #ifdef OLD_FDW_API +@@ -989,18 +987,18 @@ oracleGetForeignPaths(PlannerInfo *root, RelOptInfo *baserel, Oid foreigntableid + fdwState->order_clause = orderedquery.data; + + /* add the only path */ +- add_path(baserel, ++ add_path(root, baserel, + (Path *)create_foreignscan_path( + root, + baserel, + #if PG_VERSION_NUM >= 90600 + NULL, /* default pathtarget */ +-#endif /* PG_VERSION_NUM */ + baserel->rows, ++#endif /* PG_VERSION_NUM */ + fdwState->startup_cost, + fdwState->total_cost, + usable_pathkeys, +- baserel->lateral_relids, ++ NULL, + #if PG_VERSION_NUM >= 90500 + NULL, /* no extra plan */ + #endif /* PG_VERSION_NUM */ +@@ -1152,7 +1150,7 @@ ForeignScan + scan_relid = foreignrel->relid; + + /* check if the foreign scan is for an UPDATE or DELETE */ +- if (foreignrel->relid == root->parse->resultRelation && ++ if (foreignrel->relid == (unsigned int)root->parse->resultRelation && + (root->parse->commandType == CMD_UPDATE || + root->parse->commandType == CMD_DELETE)) + { +@@ -1182,8 +1180,10 @@ ForeignScan + rel = heap_open(foreigntableid, NoLock); + + /* is there an AFTER trigger FOR EACH ROW? */ +- has_trigger = (foreignrel->relid == root->parse->resultRelation) +- && hasTrigger(rel, root->parse->commandType); ++ has_trigger = (foreignrel->relid == (unsigned int)root->parse->resultRelation); ++#ifdef WRITE_API ++ has_trigger = has_trigger && hasTrigger(rel, root->parse->commandType); ++#endif + + heap_close(rel, NoLock); + +@@ -1284,7 +1284,7 @@ ForeignScan + } + + bool +-oracleAnalyzeForeignTable(Relation relation, AcquireSampleRowsFunc *func, BlockNumber *totalpages) ++oracleAnalyzeForeignTable(Relation relation, AcquireSampleRowsFunc *func, BlockNumber *totalpages, void* additionalData, bool estimateTableRowNum) + { + *func = acquireSampleRowsFunc; + /* use positive page count as a sign that the table has been ANALYZEd */ +@@ -1631,7 +1631,7 @@ oraclePlanForeignModify(PlannerInfo *root, ModifyTable *plan, Index resultRelati + #endif /* PG_VERSION_NUM */ + + /* check if the foreign table is scanned and we already planned that scan */ +- if (resultRelation < root->simple_rel_array_size ++ if (resultRelation < (unsigned int)root->simple_rel_array_size + && root->simple_rel_array[resultRelation] != NULL + && root->simple_rel_array[resultRelation]->fdw_private != NULL) + { +@@ -1682,7 +1682,7 @@ oraclePlanForeignModify(PlannerInfo *root, ModifyTable *plan, Index resultRelati + #if PG_VERSION_NUM >= 90500 + tmpset = bms_copy(rte->updatedCols); + #else +- tmpset = bms_copy(rte->modifiedCols); ++ tmpset = bms_copy(rte->updatedCols); + #endif /* PG_VERSION_NUM */ + + while ((col = bms_first_member(tmpset)) >= 0) +@@ -2492,7 +2492,7 @@ oracleImportForeignSchema(ImportForeignSchemaStmt *stmt, Oid serverOid) + struct OracleFdwState + *getFdwState(Oid foreigntableid, double *sample_percent) + { +- struct OracleFdwState *fdwState = palloc0(sizeof(struct OracleFdwState)); ++ struct OracleFdwState *fdwState = (struct OracleFdwState*)palloc0(sizeof(struct OracleFdwState)); + char *pgtablename = get_rel_name(foreigntableid); + List *options; + ListCell *cell; +@@ -3341,7 +3341,7 @@ build_join_oratable(struct OracleFdwState *fdwState, List *fdw_scan_tlist) + * exceeding this is not used by compute_scalar_stats(). + */ + int +-acquireSampleRowsFunc(Relation relation, int elevel, HeapTuple *rows, int targrows, double *totalrows, double *totaldeadrows) ++acquireSampleRowsFunc(Relation relation, int elevel, HeapTuple *rows, int targrows, double *totalrows, double *totaldeadrows, void* additionalData, bool estimateTableRowNum) + { + int collected_rows = 0, i; + struct OracleFdwState *fdw_state; +@@ -3813,7 +3813,7 @@ deparseExpr(oracleSession *session, RelOptInfo *foreignrel, Expr *expr, const st + || strcmp(opername, "|/") == 0 + || strcmp(opername, "@") == 0) + { +- left = deparseExpr(session, foreignrel, linitial(oper->args), oraTable, params); ++ left = deparseExpr(session, foreignrel, (Expr*)linitial(oper->args), oraTable, params); + if (left == NULL) + { + pfree(opername); +@@ -3823,7 +3823,7 @@ deparseExpr(oracleSession *session, RelOptInfo *foreignrel, Expr *expr, const st + if (oprkind == 'b') + { + /* binary operator */ +- right = deparseExpr(session, foreignrel, lsecond(oper->args), oraTable, params); ++ right = deparseExpr(session, foreignrel, (Expr*)lsecond(oper->args), oraTable, params); + if (right == NULL) + { + pfree(left); +@@ -3932,7 +3932,7 @@ deparseExpr(oracleSession *session, RelOptInfo *foreignrel, Expr *expr, const st + if (! canHandleType(leftargtype)) + return NULL; + +- left = deparseExpr(session, foreignrel, linitial(arrayoper->args), oraTable, params); ++ left = deparseExpr(session, foreignrel, (Expr*)linitial(arrayoper->args), oraTable, params); + if (left == NULL) + return NULL; + +@@ -4052,12 +4052,12 @@ deparseExpr(oracleSession *session, RelOptInfo *foreignrel, Expr *expr, const st + if (! canHandleType(rightargtype)) + return NULL; + +- left = deparseExpr(session, foreignrel, linitial(((NullIfExpr *)expr)->args), oraTable, params); ++ left = deparseExpr(session, foreignrel, (Expr*)linitial(((NullIfExpr *)expr)->args), oraTable, params); + if (left == NULL) + { + return NULL; + } +- right = deparseExpr(session, foreignrel, lsecond(((NullIfExpr *)expr)->args), oraTable, params); ++ right = deparseExpr(session, foreignrel, (Expr*)lsecond(((NullIfExpr *)expr)->args), oraTable, params); + if (right == NULL) + { + pfree(left); +@@ -4071,7 +4071,7 @@ deparseExpr(oracleSession *session, RelOptInfo *foreignrel, Expr *expr, const st + case T_BoolExpr: + boolexpr = (BoolExpr *)expr; + +- arg = deparseExpr(session, foreignrel, linitial(boolexpr->args), oraTable, params); ++ arg = deparseExpr(session, foreignrel, (Expr*)linitial(boolexpr->args), oraTable, params); + if (arg == NULL) + return NULL; + +@@ -4140,7 +4140,7 @@ deparseExpr(oracleSession *session, RelOptInfo *foreignrel, Expr *expr, const st + else + { + /* for CASE arg WHEN ..., use only the right branch of the equality */ +- arg = deparseExpr(session, foreignrel, lsecond(((OpExpr *)whenclause->expr)->args), oraTable, params); ++ arg = deparseExpr(session, foreignrel, (Expr*)lsecond(((OpExpr *)whenclause->expr)->args), oraTable, params); + } + + if (arg == NULL) +@@ -4245,7 +4245,7 @@ deparseExpr(oracleSession *session, RelOptInfo *foreignrel, Expr *expr, const st + + /* do nothing for implicit casts */ + if (func->funcformat == COERCE_IMPLICIT_CAST) +- return deparseExpr(session, foreignrel, linitial(func->args), oraTable, params); ++ return deparseExpr(session, foreignrel, (Expr*)linitial(func->args), oraTable, params); + + /* get function name and schema */ + tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(func->funcid)); +@@ -4325,7 +4325,7 @@ deparseExpr(oracleSession *session, RelOptInfo *foreignrel, Expr *expr, const st + first_arg = true; + foreach(cell, func->args) + { +- arg = deparseExpr(session, foreignrel, lfirst(cell), oraTable, params); ++ arg = deparseExpr(session, foreignrel, (Expr*)lfirst(cell), oraTable, params); + if (arg == NULL) + { + pfree(result.data); +@@ -4350,7 +4350,7 @@ deparseExpr(oracleSession *session, RelOptInfo *foreignrel, Expr *expr, const st + else if (strcmp(opername, "date_part") == 0) + { + /* special case: EXTRACT */ +- left = deparseExpr(session, foreignrel, linitial(func->args), oraTable, params); ++ left = deparseExpr(session, foreignrel, (Expr*)linitial(func->args), oraTable, params); + if (left == NULL) + { + pfree(opername); +@@ -4370,7 +4370,7 @@ deparseExpr(oracleSession *session, RelOptInfo *foreignrel, Expr *expr, const st + /* remove final quote */ + left[strlen(left) - 1] = '\0'; + +- right = deparseExpr(session, foreignrel, lsecond(func->args), oraTable, params); ++ right = deparseExpr(session, foreignrel, (Expr*)lsecond(func->args), oraTable, params); + if (right == NULL) + { + pfree(opername); +@@ -4608,7 +4608,7 @@ getUsedColumns(Expr *expr, struct oraTable *oraTable, int foreignrelid) + variable = (Var *)expr; + + /* ignore columns belonging to a different foreign table */ +- if (variable->varno != foreignrelid) ++ if (variable->varno != (unsigned int)foreignrelid) + break; + + /* ignore system columns */ +@@ -5195,7 +5195,7 @@ Const + struct OracleFdwState + *deserializePlanData(List *list) + { +- struct OracleFdwState *state = palloc(sizeof(struct OracleFdwState)); ++ struct OracleFdwState *state = (struct OracleFdwState*)palloc(sizeof(struct OracleFdwState)); + ListCell *cell = list_head(list); + int i, len; + struct paramDesc *param; +@@ -5213,23 +5213,23 @@ struct OracleFdwState + state->order_clause = NULL; + + /* dbserver */ +- state->dbserver = deserializeString(lfirst(cell)); ++ state->dbserver = deserializeString((Const*)lfirst(cell)); + cell = list_next(list, cell); + + /* user */ +- state->user = deserializeString(lfirst(cell)); ++ state->user = deserializeString((Const*)lfirst(cell)); + cell = list_next(list, cell); + + /* password */ +- state->password = deserializeString(lfirst(cell)); ++ state->password = deserializeString((Const*)lfirst(cell)); + cell = list_next(list, cell); + + /* nls_lang */ +- state->nls_lang = deserializeString(lfirst(cell)); ++ state->nls_lang = deserializeString((Const*)lfirst(cell)); + cell = list_next(list, cell); + + /* query */ +- state->query = deserializeString(lfirst(cell)); ++ state->query = deserializeString((Const*)lfirst(cell)); + cell = list_next(list, cell); + + /* Oracle prefetch count */ +@@ -5238,9 +5238,9 @@ struct OracleFdwState + + /* table data */ + state->oraTable = (struct oraTable *)palloc(sizeof(struct oraTable)); +- state->oraTable->name = deserializeString(lfirst(cell)); ++ state->oraTable->name = deserializeString((Const*)lfirst(cell)); + cell = list_next(list, cell); +- state->oraTable->pgname = deserializeString(lfirst(cell)); ++ state->oraTable->pgname = deserializeString((Const*)lfirst(cell)); + cell = list_next(list, cell); + state->oraTable->ncols = (int)DatumGetInt32(((Const *)lfirst(cell))->constvalue); + cell = list_next(list, cell); +@@ -5252,13 +5252,13 @@ struct OracleFdwState + for (i=0; ioraTable->ncols; ++i) + { + state->oraTable->cols[i] = (struct oraColumn *)palloc(sizeof(struct oraColumn)); +- state->oraTable->cols[i]->name = deserializeString(lfirst(cell)); ++ state->oraTable->cols[i]->name = deserializeString((Const*)lfirst(cell)); + cell = list_next(list, cell); + state->oraTable->cols[i]->oratype = (oraType)DatumGetInt32(((Const *)lfirst(cell))->constvalue); + cell = list_next(list, cell); + state->oraTable->cols[i]->scale = (int)DatumGetInt32(((Const *)lfirst(cell))->constvalue); + cell = list_next(list, cell); +- state->oraTable->cols[i]->pgname = deserializeString(lfirst(cell)); ++ state->oraTable->cols[i]->pgname = deserializeString((Const*)lfirst(cell)); + cell = list_next(list, cell); + state->oraTable->cols[i]->pgattnum = (int)DatumGetInt32(((Const *)lfirst(cell))->constvalue); + cell = list_next(list, cell); +@@ -5270,7 +5270,7 @@ struct OracleFdwState + cell = list_next(list, cell); + state->oraTable->cols[i]->pkey = (int)DatumGetInt32(((Const *)lfirst(cell))->constvalue); + cell = list_next(list, cell); +- state->oraTable->cols[i]->val_size = deserializeLong(lfirst(cell)); ++ state->oraTable->cols[i]->val_size = deserializeLong((Const*)lfirst(cell)); + cell = list_next(list, cell); + /* allocate memory for the result value */ + state->oraTable->cols[i]->val = (char *)palloc(state->oraTable->cols[i]->val_size + 1); +@@ -5288,14 +5288,14 @@ struct OracleFdwState + for (i=0; iname = deserializeString(lfirst(cell)); ++ param->name = deserializeString((Const *)lfirst(cell)); + cell = list_next(list, cell); + param->type = DatumGetObjectId(((Const *)lfirst(cell))->constvalue); + cell = list_next(list, cell); + param->bindType = (oraBindType)DatumGetInt32(((Const *)lfirst(cell))->constvalue); + cell = list_next(list, cell); + if (param->bindType == BIND_OUTPUT) +- param->value = (void *)42; /* something != NULL */ ++ param->value = (char *)42; /* something != NULL */ + else + param->value = NULL; + param->node = NULL; +@@ -5365,7 +5365,7 @@ find_em_expr_for_rel(EquivalenceClass *ec, RelOptInfo *rel) + + foreach(lc_em, ec->ec_members) + { +- EquivalenceMember *em = lfirst(lc_em); ++ EquivalenceMember *em = (EquivalenceMember*)lfirst(lc_em); + + if (bms_equal(em->em_relids, rel->relids)) + { +@@ -5511,7 +5511,7 @@ struct OracleFdwState + *copyPlanData(struct OracleFdwState *orig) + { + int i; +- struct OracleFdwState *copy = palloc(sizeof(struct OracleFdwState)); ++ struct OracleFdwState *copy = (struct OracleFdwState *)palloc(sizeof(struct OracleFdwState)); + + copy->dbserver = pstrdup(orig->dbserver); + copy->user = pstrdup(orig->user); +@@ -5565,8 +5565,8 @@ void + subtransactionCallback(SubXactEvent event, SubTransactionId mySubid, SubTransactionId parentSubid, void *arg) + { + /* rollback to the appropriate savepoint on subtransaction abort */ +- if (event == SUBXACT_EVENT_ABORT_SUB || event == SUBXACT_EVENT_PRE_COMMIT_SUB) +- oracleEndSubtransaction(arg, GetCurrentTransactionNestLevel(), event == SUBXACT_EVENT_PRE_COMMIT_SUB); ++ if (event == SUBXACT_EVENT_ABORT_SUB) ++ oracleEndSubtransaction(arg, GetCurrentTransactionNestLevel(), false); + } + + /* +@@ -5579,7 +5579,7 @@ addParam(struct paramDesc **paramList, char *name, Oid pgtype, oraType oratype, + { + struct paramDesc *param; + +- param = palloc(sizeof(struct paramDesc)); ++ param = (struct paramDesc *)palloc(sizeof(struct paramDesc)); + param->name = pstrdup(name); + param->type = pgtype; + switch (oratype) +@@ -5790,7 +5790,7 @@ setModifyParameters(struct paramDesc *paramList, TupleTableSlot *newslot, TupleT + value_len = VARSIZE(datum) - VARHDRSZ; + + /* the first 4 bytes contain the length */ +- param->value = palloc(value_len + 4); ++ param->value = (char*)palloc(value_len + 4); + memcpy(param->value, (const char *)&value_len, 4); + memcpy(param->value + 4, VARDATA(datum), value_len); + break; +@@ -5985,7 +5985,7 @@ appendReturningClause(StringInfo sql, struct OracleFdwState *fdwState) + param->name = pstrdup(paramName); + param->type = fdwState->oraTable->cols[i]->pgtype; + param->bindType = BIND_OUTPUT; +- param->value = (void *)42; /* something != NULL */ ++ param->value = (char *)42; /* something != NULL */ + param->node = NULL; + param->bindh = NULL; + param->colnum = i; +@@ -6013,20 +6013,6 @@ transactionCallback(XactEvent event, void *arg) + { + switch(event) + { +-#ifdef WRITE_API +- case XACT_EVENT_PRE_COMMIT: +-#if PG_VERSION_NUM >= 90500 +- case XACT_EVENT_PARALLEL_PRE_COMMIT: +-#endif /* PG_VERSION_NUM */ +- /* remote commit */ +- oracleEndTransaction(arg, 1, 0); +- break; +- case XACT_EVENT_PRE_PREPARE: +- ereport(ERROR, +- (errcode(ERRCODE_FDW_UNABLE_TO_CREATE_EXECUTION), +- errmsg("cannot prepare a transaction that used remote tables"))); +- break; +-#endif /* WRITE_API */ + case XACT_EVENT_COMMIT: + case XACT_EVENT_PREPARE: + #if PG_VERSION_NUM >= 90500 +@@ -6046,11 +6032,19 @@ transactionCallback(XactEvent event, void *arg) + /* remote rollback */ + oracleEndTransaction(arg, 0, 1); + break; ++ default: ++ break; + } + + dml_in_transaction = false; + } + ++void oracleProcExit(void) ++{ ++ /* register an exit hook */ ++ on_proc_exit(&exitHook, PointerGetDatum(NULL)); ++} ++ + /* + * exitHook + * Close all Oracle connections on process exit. +@@ -6254,14 +6248,14 @@ convertTuple(struct OracleFdwState *fdw_state, Datum *values, bool *nulls, bool + ora_geometry *geom = (ora_geometry *)fdw_state->oraTable->cols[index]->val; + + /* install error context callback */ +- errcb.previous = error_context_stack; +- error_context_stack = &errcb; ++ errcb.previous = t_thrd.log_cxt.error_context_stack; ++ t_thrd.log_cxt.error_context_stack = &errcb; + fdw_state->columnindex = index; + + value_len = oracleGetEWKBLen(fdw_state->session, geom); + + /* uninstall error context callback */ +- error_context_stack = errcb.previous; ++ t_thrd.log_cxt.error_context_stack = errcb.previous; + + value = NULL; /* we will fetch that later to avoid unnecessary copying */ + } +@@ -6303,8 +6297,8 @@ convertTuple(struct OracleFdwState *fdw_state, Datum *values, bool *nulls, bool + struct varlena *result = NULL; + + /* install error context callback */ +- errcb.previous = error_context_stack; +- error_context_stack = &errcb; ++ errcb.previous = t_thrd.log_cxt.error_context_stack; ++ t_thrd.log_cxt.error_context_stack = &errcb; + fdw_state->columnindex = index; + + result = (bytea *)palloc(value_len + VARHDRSZ); +@@ -6312,7 +6306,7 @@ convertTuple(struct OracleFdwState *fdw_state, Datum *values, bool *nulls, bool + SET_VARSIZE(result, value_len + VARHDRSZ); + + /* uninstall error context callback */ +- error_context_stack = errcb.previous; ++ t_thrd.log_cxt.error_context_stack = errcb.previous; + + values[j] = PointerGetDatum(result); + +@@ -6342,7 +6336,7 @@ convertTuple(struct OracleFdwState *fdw_state, Datum *values, bool *nulls, bool + if (fdw_state->oraTable->cols[index]->oratype == ORA_TYPE_INTERVALD2S + && value[0] == '-') + { +- char *newval = palloc(strlen(value) + 2); ++ char *newval = (char*)palloc(strlen(value) + 2); + char *pos = strchr(value, ' '); + + if (pos == NULL) +@@ -6367,8 +6361,8 @@ convertTuple(struct OracleFdwState *fdw_state, Datum *values, bool *nulls, bool + dat = CStringGetDatum(value); + + /* install error context callback */ +- errcb.previous = error_context_stack; +- error_context_stack = &errcb; ++ errcb.previous = t_thrd.log_cxt.error_context_stack; ++ t_thrd.log_cxt.error_context_stack = &errcb; + fdw_state->columnindex = index; + + /* for string types, check that the data are in the database encoding */ +@@ -6396,7 +6390,7 @@ convertTuple(struct OracleFdwState *fdw_state, Datum *values, bool *nulls, bool + } + + /* uninstall error context callback */ +- error_context_stack = errcb.previous; ++ t_thrd.log_cxt.error_context_stack = errcb.previous; + } + + /* free the data buffer for LOBs */ +@@ -6465,8 +6459,9 @@ oracleGetShareFileName(const char *relativename) + + get_share_path(my_exec_path, share_path); + +- result = palloc(MAXPGPATH); +- snprintf(result, MAXPGPATH, "%s/%s", share_path, relativename); ++ unsigned int result_len = strlen(share_path) + strlen(relativename) + 2; ++ result = (char*)palloc(result_len); ++ snprintf(result, result_len, "%s/%s", share_path, relativename); + + return result; + } +@@ -6655,8 +6650,7 @@ void + initializePostGIS() + { + CatCList *catlist; +- int i, argcount = 1; +- Oid argtypes[] = { INTERNALOID }; ++ int i; + + /* this needs to be done only once per database session */ + if (geometry_is_setup) +@@ -6665,10 +6659,9 @@ initializePostGIS() + geometry_is_setup = true; + + /* find all functions called "geometry_recv" with "internal" argument type */ +- catlist = SearchSysCacheList2( ++ catlist = SearchSysCacheList1( + PROCNAMEARGSNSP, +- CStringGetDatum("geometry_recv"), +- PointerGetDatum(buildoidvector(argtypes, argcount))); ++ CStringGetDatum("geometry_recv")); + + for (i = 0; i < catlist->n_members; i++) + { +diff --git oracle_fdw.h oracle_fdw.h +index c748971..a62a8b5 100644 +--- oracle_fdw.h ++++ oracle_fdw.h +@@ -223,6 +223,7 @@ extern void oracleError_i(oraError sqlstate, const char *message, int arg); + extern void oracleError(oraError sqlstate, const char *message); + extern void oracleDebug2(const char *message); + extern void initializePostGIS(void); ++extern void oracleProcExit(void); + + /* + * functions defined in oracle_gis.c +diff --git oracle_gis.cpp oracle_gis.cpp +index 31f9ea1..d97716e 100644 +--- oracle_gis.cpp ++++ oracle_gis.cpp +@@ -81,12 +81,12 @@ typedef struct + #define mapEntryValid(x) ((x)->from != 0) + + /* maps Oracle SRIDs to PostGIS SRIDs */ +-static mapEntry *srid_map = NULL; ++static THR_LOCAL mapEntry *srid_map = NULL; + + /* contains Oracle error messages, set by checkerr() */ + #define ERRBUFSIZE 500 +-static char oraMessage[ERRBUFSIZE]; +-static sb4 err_code; ++static THR_LOCAL char oraMessage[ERRBUFSIZE]; ++static THR_LOCAL sb4 err_code; + + /* + * Structures needed for managing the MDSYS.SDO_GEOMETRY Oracle type. +@@ -572,7 +572,7 @@ oracleGeometryAlloc(oracleSession *session, ora_geometry *geom) + session->envp->errhp, + session->connp->svchp, + OCI_TYPECODE_OBJECT, +- oracleGetGeometryType(session), ++ (OCIType*)oracleGetGeometryType(session), + (dvoid *)NULL, + OCI_DURATION_TRANS, + TRUE, +@@ -1419,8 +1419,8 @@ unpack(oracleSession *session, ora_geometry *geom) + oracleError(FDW_ERROR, "error converting SDO_GEOMETRY to geometry: size of SDO_ELEM_INFO must be a multiple of three"); + + /* this might be too big if some elements with etype 0 are deleted */ +- geom->elem = oracleAlloc(elemCount * sizeof(unsigned)); +- geom->coord = oracleAlloc(coordCount * sizeof(double)); ++ geom->elem = (unsigned int *)oracleAlloc(elemCount * sizeof(unsigned)); ++ geom->coord = (double *)oracleAlloc(coordCount * sizeof(double)); + + for (elem_i = 0; elem_i + 1 < elemCount; elem_i +=3) + { +@@ -1451,7 +1451,7 @@ unpack(oracleSession *session, ora_geometry *geom) + elem_pos += 3; + + /* copy ordinates for this entry */ +- for (coord_i=offset - 1; coord_i < next_offset - 1; ++coord_i) ++ for (coord_i=offset - 1; coord_i < (int)(next_offset - 1); ++coord_i) + geom->coord[coord_pos++] = coord(session, geom, coord_i); + } + } +diff --git oracle_utils.cpp oracle_utils.cpp +index 469e7b9..8d8b60e 100644 +--- oracle_utils.cpp ++++ oracle_utils.cpp +@@ -27,15 +27,15 @@ + #define LOB_CHUNK_SIZE 8132 + + /* emit no error messages when set, used for shutdown */ +-static int silent = 0; ++static THR_LOCAL int silent = 0; + + /* contains Oracle error messages, set by checkerr() */ + #define ERRBUFSIZE 500 +-static char oraMessage[ERRBUFSIZE]; +-static sb4 err_code; ++static THR_LOCAL char oraMessage[ERRBUFSIZE]; ++static THR_LOCAL sb4 err_code; + + /* set to "1" as soon as OCIEnvCreate is called */ +-static int oci_initialized = 0; ++static THR_LOCAL int oci_initialized = 0; + + /* + * Linked list for temporary Oracle handles and descriptors. +@@ -54,12 +54,12 @@ struct handleEntry + /* + * Linked list of handles for cached Oracle connections. + */ +-static struct envEntry *envlist = NULL; ++static THR_LOCAL struct envEntry *envlist = NULL; + + /* + * NULL value used for "in" callback in RETURNING clauses. + */ +-static ora_geometry null_geometry = { NULL, NULL, -1, NULL, -1, NULL }; ++static THR_LOCAL ora_geometry null_geometry = { NULL, NULL, -1, NULL, -1, NULL }; + + /* + * Helper functions +@@ -119,6 +119,11 @@ oracleSession + */ + initializePostGIS(); + ++ if (envlist == NULL) { ++ /* register an exit hook when first time connect to oracle */ ++ oracleProcExit(); ++ } ++ + /* search environment and server handle in cache */ + for (envp = envlist; envp != NULL; envp = envp->next) + { +@@ -183,7 +188,7 @@ oracleSession + } + + /* add handles to cache */ +- if ((envp = malloc(sizeof(struct envEntry))) == NULL) ++ if ((envp = (struct envEntry*)malloc(sizeof(struct envEntry))) == NULL) + { + oracleError_i(FDW_OUT_OF_MEMORY, + "error connecting to Oracle: failed to allocate %d bytes of memory", +@@ -275,7 +280,7 @@ oracleSession + } + + /* add server handle to cache */ +- if ((srvp = malloc(sizeof(struct srvEntry))) == NULL) ++ if ((srvp = (srvEntry*)malloc(sizeof(struct srvEntry))) == NULL) + { + oracleError_i(FDW_OUT_OF_MEMORY, + "error connecting to Oracle: failed to allocate %d bytes of memory", +@@ -373,8 +378,9 @@ oracleSession + sprintf(pid, "%lu", (unsigned long)getpid()); + pid[29] = '\0'; + ++ char tmpstr[30] = "postgres"; + if (checkerr( +- OCIAttrSet(userhp, OCI_HTYPE_SESSION, "postgres", (ub4)8, ++ OCIAttrSet(userhp, OCI_HTYPE_SESSION, tmpstr, (ub4)8, + OCI_ATTR_MODULE, errhp), + (dvoid *)errhp, OCI_HTYPE_ERROR) != OCI_SUCCESS) + { +@@ -394,9 +400,10 @@ oracleSession + oraMessage); + } + ++ strcpy(tmpstr, "oracle_fdw"); + /* set driver name for the Oracle session */ + if (checkerr( +- OCIAttrSet(userhp, OCI_HTYPE_SESSION, "oracle_fdw", (ub4)10, ++ OCIAttrSet(userhp, OCI_HTYPE_SESSION, tmpstr, (ub4)10, + OCI_ATTR_DRIVER_NAME, errhp), + (dvoid *)errhp, OCI_HTYPE_ERROR) != OCI_SUCCESS) + { +@@ -455,7 +462,7 @@ oracleSession + } + + /* add session handle to cache */ +- if ((connp = malloc(sizeof(struct connEntry))) == NULL) ++ if ((connp = (connEntry*)malloc(sizeof(struct connEntry))) == NULL) + { + oracleError_i(FDW_OUT_OF_MEMORY, + "error connecting to Oracle: failed to allocate %d bytes of memory", +@@ -519,7 +526,7 @@ oracleSession + } + + /* palloc a data structure pointing to the cached entries */ +- session = oracleAlloc(sizeof(struct oracleSession)); ++ session = (oracleSession*)oracleAlloc(sizeof(struct oracleSession)); + session->envp = envp; + session->srvp = srvp; + session->connp = connp; +@@ -825,7 +832,7 @@ struct oraTable + qschema = copyOraText(schema, strlen(schema), 1); + length += strlen(qschema) + 1; + } +- tablename = oracleAlloc(length + 1); ++ tablename = (char*)oracleAlloc(length + 1); + tablename[0] = '\0'; /* empty */ + if (schema != NULL) + { +@@ -839,7 +846,7 @@ struct oraTable + + /* construct a "SELECT * FROM ..." query to describe columns */ + length += 14; +- query = oracleAlloc(length + 1); ++ query = (char*)oracleAlloc(length + 1); + strcpy(query, "SELECT * FROM "); + strcat(query, tablename); + +@@ -875,7 +882,7 @@ struct oraTable + } + + /* allocate an oraTable struct for the results */ +- reply = oracleAlloc(sizeof(struct oraTable)); ++ reply = (oraTable*)oracleAlloc(sizeof(struct oraTable)); + reply->name = tablename; + reply->pgname = pgname; + reply->npgcols = 0; +@@ -955,7 +962,7 @@ struct oraTable + } + + /* create a zero-terminated copy */ +- type_name = oracleAlloc(typname_size + 1); ++ type_name = (char*)oracleAlloc(typname_size + 1); + strncpy(type_name, (char *)typname, typname_size); + type_name[typname_size] = '\0'; + +@@ -971,7 +978,7 @@ struct oraTable + } + + /* create a zero-terminated copy */ +- type_schema = oracleAlloc(typschema_size + 1); ++ type_schema = (char*)oracleAlloc(typschema_size + 1); + strncpy(type_schema, (char *)typschema, typschema_size); + type_schema[typschema_size] = '\0'; + +@@ -1211,7 +1218,7 @@ oracleExplain(oracleSession *session, const char *query, int *nrows, char ***pla + *plan = (char **)oracleRealloc(*plan, sizeof(char *) * (*nrows)); + + /* add entry */ +- (*plan)[(*nrows)-1] = oracleAlloc(strlen(res) + 1); ++ (*plan)[(*nrows)-1] = (char*)oracleAlloc(strlen(res) + 1); + strcpy((*plan)[(*nrows)-1], res); + + /* fetch next row */ +@@ -1446,7 +1453,7 @@ oracleQueryPlan(oracleSession *session, const char *query, const char *desc_quer + */ + + /* get the first part of the SQL query with '%' appended */ +- if ((p = strchr(query + 7, ' ')) == NULL) ++ if ((p = strchr(const_cast(query + 7), ' ')) == NULL) + { + oracleError(FDW_ERROR, "oracleQueryPlan internal error: no space found in query"); + } +@@ -1726,7 +1733,7 @@ oraclePrepareQuery(oracleSession *session, const char *query, const struct oraTa + + /* define the result for the named type */ + if (checkerr( +- OCIDefineObject(defnhp, session->envp->errhp, oracleGetGeometryType(session), ++ OCIDefineObject(defnhp, session->envp->errhp, (const OCIType*)oracleGetGeometryType(session), + (void **)&geom->geometry, 0, (void **)&geom->indicator, 0), + session->envp->errhp, OCI_HTYPE_ERROR) != OCI_SUCCESS) + { +@@ -1807,7 +1814,7 @@ oracleExecuteQuery(oracleSession *session, const struct oraTable *oraTable, stru + ++param_count; + + /* allocate a temporary array of indicators */ +- indicators = oracleAlloc(param_count * sizeof(sb2 *)); ++ indicators = (sb2*)oracleAlloc(param_count * sizeof(sb2 *)); + + /* bind the parameters */ + param_count = -1; +@@ -1827,13 +1834,13 @@ oracleExecuteQuery(oracleSession *session, const struct oraTable *oraTable, stru + switch (param->bindType) { + case BIND_NUMBER: + /* allocate a new NUMBER */ +- number = oracleAlloc(sizeof(OCINumber)); ++ number = (OCINumber*)oracleAlloc(sizeof(OCINumber)); + + /* + * Construct number format. + */ + value_len = strlen(param->value); +- num_format = oracleAlloc(value_len + 1); ++ num_format = (char*)oracleAlloc(value_len + 1); + /* fill everything with '9' */ + memset(num_format, '9', value_len); + num_format[value_len] = '\0'; +@@ -1955,7 +1962,7 @@ oracleExecuteQuery(oracleSession *session, const struct oraTable *oraTable, stru + + if (checkerr( + OCIBindObject((OCIBind *)param->bindh, session->envp->errhp, +- oracleGetGeometryType(session), (void **)&geom->geometry, NULL, (void **)&geom->indicator, NULL), ++ (const OCIType*)oracleGetGeometryType(session), (void **)&geom->geometry, NULL, (void **)&geom->indicator, NULL), + (dvoid *)session->envp->errhp, OCI_HTYPE_ERROR) != OCI_SUCCESS) + { + oracleError_d(FDW_UNABLE_TO_CREATE_EXECUTION, +@@ -2142,9 +2149,9 @@ oracleGetLob(oracleSession *session, void *locptr, oraType type, char **value, l + { + /* extend result buffer */ + if (*value_len == 0) +- *value = oracleAlloc(LOB_CHUNK_SIZE + 1); ++ *value = (char*)oracleAlloc(LOB_CHUNK_SIZE + 1); + else +- *value = oracleRealloc(*value, *value_len + LOB_CHUNK_SIZE + 1); ++ *value = (char*)oracleRealloc(*value, *value_len + LOB_CHUNK_SIZE + 1); + + /* + * The first time round, "amount_* = 0" tells OCILobRead to read the whole LOB. +@@ -2271,7 +2278,7 @@ int oracleGetImportColumn(oracleSession *session, char *schema, char **tabname, + { + /* the static variables will contain data returned to the caller */ + static char s_tabname[129], s_colname[129]; +- char typename[129] = { '\0' }, typeowner[129] = { '\0' }, isnull[2] = { '\0' }; ++ char type_name[129] = { '\0' }, typeowner[129] = { '\0' }, isnull[2] = { '\0' }; + int count = 0; + const char * const schema_query = "SELECT COUNT(*) FROM all_users WHERE username = :nsp"; + const char * const column_query = +@@ -2439,7 +2446,7 @@ int oracleGetImportColumn(oracleSession *session, char *schema, char **tabname, + + if (checkerr( + OCIDefineByPos(session->stmthp, &defnhp_typename, session->envp->errhp, (ub4)3, +- (dvoid *)typename, (sb4)129, ++ (dvoid *)type_name, (sb4)129, + SQLT_STR, (dvoid *)&ind_typename, + (ub2 *)&len_typename, NULL, OCI_DEFAULT), + (dvoid *)session->envp->errhp, OCI_HTYPE_ERROR) != OCI_SUCCESS) +@@ -2563,53 +2570,53 @@ int oracleGetImportColumn(oracleSession *session, char *schema, char **tabname, + *nullable = (isnull[0] == 'Y'); + + /* figure out correct data type */ +- if (strncmp(typename, "VARCHAR", 7) == 0) ++ if (strncmp(type_name, "VARCHAR", 7) == 0) + *type = ORA_TYPE_VARCHAR2; +- else if (strcmp(typename, "NUMBER") == 0) ++ else if (strcmp(type_name, "NUMBER") == 0) + *type = ORA_TYPE_NUMBER; +- else if (strcmp(typename, "DATE") == 0) ++ else if (strcmp(type_name, "DATE") == 0) + *type = ORA_TYPE_DATE; +- else if (strcmp(typename, "CHAR") == 0) ++ else if (strcmp(type_name, "CHAR") == 0) + *type = ORA_TYPE_CHAR; +- else if (strncmp(typename, "TIMESTAMP", 9) == 0) ++ else if (strncmp(type_name, "TIMESTAMP", 9) == 0) + { +- if (strlen(typename) < 17) ++ if (strlen(type_name) < 17) + *type = ORA_TYPE_TIMESTAMP; + else + *type = ORA_TYPE_TIMESTAMPTZ; + } +- else if (strcmp(typename, "RAW") == 0) ++ else if (strcmp(type_name, "RAW") == 0) + *type = ORA_TYPE_RAW; +- else if (strcmp(typename, "BLOB") == 0) ++ else if (strcmp(type_name, "BLOB") == 0) + *type = ORA_TYPE_BLOB; +- else if (strcmp(typename, "CLOB") == 0) ++ else if (strcmp(type_name, "CLOB") == 0) + *type = ORA_TYPE_CLOB; +- else if (strcmp(typename, "BFILE") == 0) ++ else if (strcmp(type_name, "BFILE") == 0) + *type = ORA_TYPE_BFILE; +- else if (strcmp(typename, "LONG") == 0) ++ else if (strcmp(type_name, "LONG") == 0) + *type = ORA_TYPE_LONG; +- else if (strcmp(typename, "LONG RAW") == 0) ++ else if (strcmp(type_name, "LONG RAW") == 0) + *type = ORA_TYPE_LONGRAW; +- else if (strcmp(typename, "SDO_GEOMETRY") == 0 ++ else if (strcmp(type_name, "SDO_GEOMETRY") == 0 + && ind_typeowner == OCI_IND_NOTNULL && strcmp(typeowner, "MDSYS") == 0) + *type = ORA_TYPE_GEOMETRY; +- else if (strcmp(typename, "XMLTYPE") == 0 ++ else if (strcmp(type_name, "XMLTYPE") == 0 + && ind_typeowner == OCI_IND_NOTNULL + && (strcmp(typeowner, "PUBLIC") == 0 || strcmp(typeowner, "SYS") == 0)) + *type = ORA_TYPE_XMLTYPE; +- else if (strcmp(typename, "FLOAT") == 0) ++ else if (strcmp(type_name, "FLOAT") == 0) + *type = ORA_TYPE_FLOAT; +- else if (strncmp(typename, "NVARCHAR", 8) == 0) ++ else if (strncmp(type_name, "NVARCHAR", 8) == 0) + *type = ORA_TYPE_NVARCHAR2; +- else if (strcmp(typename, "NCHAR") == 0) ++ else if (strcmp(type_name, "NCHAR") == 0) + *type = ORA_TYPE_NCHAR; +- else if (strncmp(typename, "INTERVAL DAY", 12) == 0) ++ else if (strncmp(type_name, "INTERVAL DAY", 12) == 0) + *type = ORA_TYPE_INTERVALD2S; +- else if (strncmp(typename, "INTERVAL YEAR", 13) == 0) ++ else if (strncmp(type_name, "INTERVAL YEAR", 13) == 0) + *type = ORA_TYPE_INTERVALY2M; +- else if (strcmp(typename, "BINARY_FLOAT") == 0) ++ else if (strcmp(type_name, "BINARY_FLOAT") == 0) + *type = ORA_TYPE_BINARYFLOAT; +- else if (strcmp(typename, "BINARY_DOUBLE") == 0) ++ else if (strcmp(type_name, "BINARY_DOUBLE") == 0) + *type = ORA_TYPE_BINARYDOUBLE; + else + *type = ORA_TYPE_OTHER; +@@ -2673,7 +2680,7 @@ char + /* if "string" is parenthized, return a copy */ + if (string[0] == '(' && string[size-1] == ')') + { +- result = oracleAlloc(size + 1); ++ result = (char*)oracleAlloc(size + 1); + memcpy(result, string, size); + result[size] = '\0'; + return result; +@@ -2688,7 +2695,7 @@ char + } + } + +- result = oracleAlloc(resultsize + 1); ++ result = (char*)oracleAlloc(resultsize + 1); + if (quote) + result[++j] = '"'; + for (i=0; i