*
* foreign.h
* support for foreign-data wrappers, servers and user mappings.
*
*
* Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
*
* src/include/foreign/foreign.h
*
* -------------------------------------------------------------------------
*/
#ifndef FOREIGN_H
#define FOREIGN_H
#include "access/obs/obs_am.h"
#include "commands/defrem.h"
#include "nodes/parsenodes.h"
#include "nodes/relation.h"
#ifndef OBS_SERVER
#define OBS_SERVER "obs"
#endif
#ifndef HDFS_SERVER
#define HDFS_SERVER "hdfs"
#endif
#define OBS_BUCKET_URL_FORMAT_FLAG ".obs."
#define OBS_PREFIX "obs://"
#define OBS_PREfIX_LEN strlen(OBS_PREFIX)
#define OPTION_NAME_LOCATION "location"
#define OPTION_NAME_FORMAT "format"
#define OPTION_NAME_HEADER "header"
#define OPTION_NAME_DELIMITER "delimiter"
#define OPTION_NAME_QUOTE "quote"
#define OPTION_NAME_ESCAPE "escape"
#define OPTION_NAME_NULL "null"
#define OPTION_NAME_NOESCAPING "noescaping"
#define OPTION_NAME_ENCODING "encoding"
#define OPTION_NAME_FILL_MISSING_FIELDS "fill_missing_fields"
#define OPTION_NAME_IGNORE_EXTRA_DATA "ignore_extra_data"
#define OPTION_NAME_DATE_FORMAT "date_format"
#define OPTION_NAME_TIME_FORMAT "time_format"
#define OPTION_NAME_TIMESTAMP_FORMAT "timestamp_format"
#define OPTION_NAME_SMALLDATETIME_FORMAT "smalldatetime_format"
#define OPTION_NAME_CHUNK_SIZE "chunksize"
#define OPTION_NAME_FILENAMES "filenames"
#define OPTION_NAME_FOLDERNAME "foldername"
#define OPTION_NAME_CHECK_ENCODING "checkencoding"
#define OPTION_NAME_TOTALROWS "totalrows"
#define OPTION_NAME_REGION "region"
#define OPTION_NAME_ADDRESS "address"
#define OPTION_NAME_CFGPATH "hdfscfgpath"
#define OPTION_NAME_SERVER_ENCRYPT "encrypt"
#define OPTION_NAME_SERVER_AK "access_key"
#define OPTION_NAME_SERVER_SAK "secret_access_key"
#define OPTION_NAME_SERVER_TYPE "type"
#define OPTION_NAME_DBNAME "dbname"
#define OPTION_NAME_REMOTESERVERNAME "remoteservername"
#define OPTION_NAME_OBSKEY "obskey"
#define MAX_TOTALROWS LONG_MAX
#define MIN_TOTALROWS 1
#define MappingUserName(userid) (OidIsValid(userid) ? GetUserNameFromId(userid) : "public")
#define DFS_FORMAT_TEXT "text"
#define DFS_FORMAT_CSV "csv"
#define DFS_FORMAT_ORC "orc"
#define DFS_FORMAT_PARQUET "parquet"
#define DFS_FORMAT_CARBONDATA "carbondata"
typedef enum DFSFileType {
DFS_INVALID = -1,
DFS_ORC = 0,
DFS_PARQUET = 1,
DFS_TEXT = 2,
DFS_CSV = 3,
DFS_CARBONDATA = 4
} DFSFileType;
* Generic option types for validation.
* NB! Thes are treated as flags, so use only powers of two here.
*/
typedef enum {
ServerOpt = 1,
UserMappingOpt = 2,
FdwOpt = 4
} GenericOptionFlags;
typedef struct ForeignDataWrapper {
Oid fdwid;
Oid owner;
char* fdwname;
Oid fdwhandler;
Oid fdwvalidator;
List* options;
} ForeignDataWrapper;
typedef struct ForeignServer {
Oid serverid;
Oid fdwid;
Oid owner;
char* servername;
char* servertype;
char* serverversion;
List* options;
} ForeignServer;
typedef struct UserMapping {
Oid userid;
Oid serverid;
List* options;
} UserMapping;
typedef struct ForeignTable {
Oid relid;
Oid serverid;
List* options;
bool write_only;
} ForeignTable;
*HdfsServerAddress keeps foreign server ip and port
*/
typedef struct HdfsServerAddress {
char* HdfsIp;
char* HdfsPort;
} HdfsServerAddress;
typedef enum ServerTypeOption {
T_INVALID = 0,
T_OBS_SERVER,
T_HDFS_SERVER,
T_MOT_SERVER,
T_DUMMY_SERVER,
T_TXT_CSV_OBS_SERVER,
is dist_fdw. */
T_PGFDW_SERVER
} ServerTypeOption;
* This struct store the foreign table options for computing pool.
*/
typedef struct ForeignOptions {
NodeTag type;
ServerTypeOption stype;
List* fOptions;
} ForeignOptions;
* HdfsFdwOptions holds the option values to be used when reading and parsing
* the orc file. To resolve these values, we first check foreign table's
* options, and if not present, we then fall back to the default values
* specified above.
*/
typedef struct HdfsFdwOptions {
char* foldername;
char* filename;
char* address;
int port;
char* location;
} HdfsFdwOptions;
typedef struct HdfsOptions {
char* servername;
char* format;
} HdfsOptions;
extern int find_Nth(const char* str, unsigned N, const char* find);
extern ForeignServer* GetForeignServer(Oid serverid);
extern ForeignServer* GetForeignServerByName(const char* name, bool missing_ok);
extern UserMapping* GetUserMapping(Oid userid, Oid serverid);
extern ForeignDataWrapper* GetForeignDataWrapper(Oid fdwid);
extern ForeignDataWrapper* GetForeignDataWrapperByName(const char* name, bool missing_ok);
extern ForeignTable* GetForeignTable(Oid relid);
extern List* GetForeignColumnOptions(Oid relid, AttrNumber attnum);
extern Oid get_foreign_data_wrapper_oid(const char* fdwname, bool missing_ok);
extern Oid get_foreign_server_oid(const char* servername, bool missing_ok);
extern DefElem* GetForeignTableOptionByName(Oid reloid, const char* optname);
extern bool IsSpecifiedFDW(const char* ServerName, const char* SepcifiedType);
extern char* getServerOptionValue(Oid srvOid, const char* optionName);
DefElem* HdfsGetOptionDefElem(Oid foreignTableId, const char* optionName);
extern char* getFTOptionValue(List* option_list, const char* option_name);
extern DefElemAction getFTAlterAction(List* option_list, const char* option_name);
extern DefElem* getFTOptionDefElemFromList(List* optionList, const char* optionName);
extern double convertFTOptionValue(const char* s);
extern char* GetForeignServerName(Oid serverid);
extern ColumnDef* makeColumnDef(const char* colname, char* coltype);
* @Description: Jude whether type of the foreign table equal to the specified type or not.
* @in relId: The foreign table Oid.
* @in SepcifiedType: The given type of foreign table.
* @return If the relation type equal to the given type of foreign table, return true,
* otherwise return false.
*/
extern bool IsSpecifiedFDWFromRelid(Oid relId, const char* SepcifiedType);
* @Description: Jude whether type of the foreign table support SELECT/INSERT/UPDATE/DELETE/COPY
* @in relId: The foreign table Oid.
* @return Rreturn true if the foreign table support those DML.
*/
extern bool CheckSupportedFDWType(Oid oid, bool byServerId = false);
* @Description: Get the all options for the OBS foreign table.
* we store the option into ObsOptions.
* @in foreignTable, the foreign table oid.
* @return return all options.
*/
extern ObsOptions* getObsOptions(Oid foreignTableId);
bool isSpecifiedSrvTypeFromRelId(Oid relId, const char* SepcifiedType);
bool isSpecifiedSrvTypeFromSrvName(const char* srvName, const char* SepcifiedType);
* @Description: Currently, two OBS location format support in database.
* one format is "gsobs:://obsdomain/bucket/prefix", another is "gsobs:://bucket.obsdomain/prefix".
* we adjust second format to the first format, we only deal with the first format in parse phase.
* @in optionsList, if the list include location option, we will adjust format.
* @return return new optionsList.
*/
List* regularizeObsLocationInfo(List* optionsList);
char* rebuildAllLocationOptions(char* regionCode, char* location);
* @Description: If using the region option, we must to reset location option
* with region string, eg. obs://bucket/prefix ->obs://URL/prefix/bucket.
* @in option List tobe given.
* @return return the modified option.
*/
List* adaptOBSURL(List* list);
* @Description: Currently, two OBS location format support in database.
* one format is "gsobs:://obsdomain/bucket/prefix", another is "gsobs:://bucket.obsdomain/prefix".
* we adjust second format to the first format, we only deal with the first format in parse phase.
* @in sourceStr, if the list include location option, we will adjust format.
* @return return new location string.
*/
char* adjustObsLocationInfoOrder(char* sourceStr);
* brief: Get the value of the given option name by traversing
* foreign table and foreign server options. Return the
* value of the given option, if found. Otherwise, return NULL;
* input param @foreignTableId: Oid of the foreign tableId;
* input param @optionName: name of the option.
*/
char* HdfsGetOptionValue(Oid foreignTableId, const char* optionName);
ServerTypeOption getServerType(Oid foreignTableId);
List* getFdwOptions(Oid foreignTableId);
int getSpecialCharCnt(const char* path, const char specialChar);
ObsOptions* setObsSrvOptions(ForeignOptions* fOptions);
* brief: Check foldername, filenames, hdfscfgpath format. The rules are the followings:
* 1. The space do not allow appear in the entrie OptStr, but '\ ' is needed
* 2. The comma do not appera in beignning and ending of OptStr
* 3. The comma as a separator exists if OptStr have many filenames path
* 4. Only a foldername path exists for foldername option and hdfscfgpath
* 5. The OptStr do not be empty
* input param @OptStr: the foldername path or file names or hdfscfgpath string
* input param @OptType: a foldername, a filenames or a hdfscfgpath type
*/
void CheckFoldernameOrFilenamesOrCfgPtah(const char *OptStr, char *OptType);
* brief: Check or get port and ip of foreign server(Only support ipv4 format),
* the rules are the followings:
* 1. The space do not allow appear in the entrie Address
* 2. The comma do not appera in beignning and ending of Address
* 3. The comma as a separator exists if OptStr have many address
* 4. The Address do not be empty
* input param @Address: address option of foreign server
* output param @AddrList: return List included port and ip
* input param @IsCheck: if IsCheck is true, only check, else get port and ip
*/
void CheckGetServerIpAndPort(const char *Address, List **AddrList, bool IsCheck, int real_addr_max);
bool isWriteOnlyFt(Oid relid);
* state for explain foreign remote sql
*/
typedef struct ExplainFRSqlState {
struct ExplainState* parent;
int node_num;
StringInfo str;
} ExplainFRSqlState;
typedef struct SPJPathExtraData {
List *targetList;
} SPJPathExtraData;
* Struct for extra information passed to subroutines of create_grouping_paths
*
* flags indicating what kinds of grouping are possible.
* partial_costs_set is true if the agg_partial_costs and agg_final_costs
* have been initialized.
* agg_partial_costs gives partial aggregation costs.
* agg_final_costs gives finalization costs.
* target_parallel_safe is true if target is parallel safe.
* havingQual gives list of quals to be applied after aggregation.
* targetList gives list of columns to be projected.
* patype is the type of partitionwise aggregation that is being performed.
*/
typedef struct GroupPathExtraData {
int flags;
bool partial_costs_set;
AggClauseCosts agg_partial_costs;
AggClauseCosts agg_final_costs;
Node *havingQual;
List *targetList;
} GroupPathExtraData;
typedef double Cardinality;
typedef struct OrderPathExtraData {
List *targetList;
List *irel_tel;
} OrderPathExtraData;
* Struct for extra information passed to subroutines of grouping_planner
*
* limit_needed is true if we actually need a Limit plan node.
* limit_tuples is an estimated bound on the number of output tuples,
* or -1 if no LIMIT or couldn't estimate.
* count_est and offset_est are the estimated values of the LIMIT and OFFSET
* expressions computed by preprocess_limit() (see comments for
* preprocess_limit() for more information).
*/
typedef struct FinalPathExtraData {
bool limit_needed;
Cardinality limit_tuples;
int64 count_est;
int64 offset_est;
List* targetList;
} FinalPathExtraData;
typedef enum FDWUpperRelState {
FDW_UPPER_REL_INIT,
FDW_UPPER_REL_TRY,
FDW_UPPER_REL_END
} FDWUpperRelState;
typedef struct FDWUpperRelCxt {
FDWUpperRelState state;
PlannerInfo* root;
RelOptInfo* currentRel;
RelOptInfo* upperRels[UPPERREL_FINAL + 1];
SPJPathExtraData* spjExtra;
GroupPathExtraData* groupExtra;
OrderPathExtraData* orderExtra;
FinalPathExtraData* finalExtra;
Plan* resultPlan;
List* resultPathKeys;
} FDWUpperRelCxt;
#define FDWUpperPlanContinue(cxt) ((cxt) != NULL && (cxt)->stage != FDW_UPPER_REL_END)
extern FDWUpperRelCxt* InitFDWUpperPlan(PlannerInfo* root, RelOptInfo* baseRel, Plan* localPlan);
extern void AdvanceFDWUpperPlan(FDWUpperRelCxt* ufdwCxt, UpperRelationKind stage, Plan* localPlan);
#define isObsOrHdfsTableFormTblOid(relId) \
(OidIsValid(relId) && (isSpecifiedSrvTypeFromRelId(relId, HDFS) || isSpecifiedSrvTypeFromRelId(relId, OBS)))
#define isMOTFromTblOid(relId) \
(OidIsValid(relId) && IsSpecifiedFDWFromRelid(relId, MOT_FDW))
#define isObsOrHdfsTableFormSrvName(srvName) \
(isSpecifiedSrvTypeFromSrvName(srvName, HDFS) || isSpecifiedSrvTypeFromSrvName(srvName, OBS))
#define isMOTTableFromSrvName(srvName) \
(IsSpecifiedFDW(srvName, MOT_FDW))
#define isPostgresFDWFromSrvName(srvName) \
(IsSpecifiedFDW(srvName, POSTGRES_FDW))
#define isMysqlFDWFromTblOid(relId) \
(OidIsValid(relId) && IsSpecifiedFDWFromRelid(relId, MYSQL_FDW))
#define isOracleFDWFromTblOid(relId) \
(OidIsValid(relId) && IsSpecifiedFDWFromRelid(relId, ORACLE_FDW))
#define isPostgresFDWFromTblOid(relId) \
(OidIsValid(relId) && IsSpecifiedFDWFromRelid(relId, POSTGRES_FDW))
#define IS_OBS_CSV_TXT_FOREIGN_TABLE(relId) \
(OidIsValid(relId) && \
IsSpecifiedFDWFromRelid(relId, DIST_FDW) && \
(is_obs_protocol(HdfsGetOptionValue(relId, optLocation))))
#define CAN_BUILD_INFORMATIONAL_CONSTRAINT_BY_RELID(relId) \
(isObsOrHdfsTableFormTblOid(relId) || IS_OBS_CSV_TXT_FOREIGN_TABLE(relId))
#define CAN_BUILD_INFORMATIONAL_CONSTRAINT_BY_STMT(stmt) \
(isObsOrHdfsTableFormSrvName(stmt->servername) || \
(NULL == getFTOptionValue(stmt->options, optLocation) \
? false \
: is_obs_protocol(getFTOptionValue(stmt->options, optLocation))))
#define IS_LOGFDW_FOREIGN_TABLE(relId) (OidIsValid(relId) && IsSpecifiedFDWFromRelid(relId, LOG_FDW))
#define IS_POSTGRESFDW_FOREIGN_TABLE(relId) (OidIsValid(relId) && IsSpecifiedFDWFromRelid(relId, GC_FDW))
#define ENCRYPT_STR_PREFIX "encryptstr"
#define MIN_ENCRYPTED_PASSWORD_LENGTH 54
#define isEncryptedPassword(passwd) \
(strncmp(passwd, ENCRYPT_STR_PREFIX, strlen(ENCRYPT_STR_PREFIX)) == 0 && \
strlen(passwd) >= MIN_ENCRYPTED_PASSWORD_LENGTH)
#ifdef USE_SPQ
bool rel_is_external_table(Oid relid);
#endif
#endif