提交 cbb8ea18 编写于 作者: H Heikki Linnakangas

Share external URL-mapping code between planner and ORCA.

Planner and ORCA translator both implemented the same logic, to assign
external table URIs to segments. But I spotted one case where the logic
differed:

CREATE EXTERNAL TABLE exttab_with_on_master( i int, j text )
LOCATION ('file://@hostname@@abs_srcdir@/data/exttab_few_errors.data') ON MASTER FORMAT 'TEXT' (DELIMITER '|');

SELECT * FROM exttab_with_on_master;
ERROR:  'ON MASTER' is not supported by this protocol yet.

With ORCA you got a less user-friendly error:

set optimizer=on;
set optimizer_enable_master_only_queries = on;
postgres=# explain SELECT * FROM exttab_with_on_master;
ERROR:  External scan error: Could not assign a segment database for external file (CTranslatorDXLToPlStmt.cpp:472)

The immediate cause of that was that commit fcf82234 didn't remember to
modify the ORCA translator's copy of the same logic. But really, it's silly
and error-prone to duplicate the code, so modify ORCA to use the same code
that the planner does.
上级 5a7563cc
......@@ -2463,6 +2463,21 @@ gpdb::Pexttable
return NULL;
}
List *
gpdb::PlExternalScanUriList
(
ExtTableEntry *ext,
bool *ismasteronlyp
)
{
GP_WRAP_START;
{
return create_external_scan_uri_list(ext, ismasteronlyp);
}
GP_WRAP_END;
return NULL;
}
TargetEntry *
gpdb::PteMember
(
......
......@@ -409,613 +409,6 @@ CTranslatorDXLToPlStmt::SetParamIds(Plan* pplan)
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToPlStmt::MapLocationsFile
//
// @doc:
// Segment mapping for tables with LOCATION http:// or file://
// These two protocols are very similar in that they enforce a 1-URI:1-segdb
// relationship. The only difference between them is that file:// URI must
// be assigned to a segdb on a host that is local to that URI.
//
//---------------------------------------------------------------------------
void
CTranslatorDXLToPlStmt::MapLocationsFile
(
OID oidRel,
char **rgszSegFileMap,
CdbComponentDatabases *pcdbCompDB
)
{
// extract file path and name from URI strings and assign them a primary segdb
ExtTableEntry *extentry = gpdb::Pexttable(oidRel);
ListCell *plcLocation = NULL;
ForEach (plcLocation, extentry->urilocations)
{
Value* pvLocation = (Value *)lfirst(plcLocation);
CHAR *szUri = pvLocation->val.str;
Uri *pUri = gpdb::PuriParseExternalTable(szUri);
BOOL fCandidateFound = false;
BOOL fMatchFound = false;
// try to find a segment database that can handle this uri
for (int i = 0; i < pcdbCompDB->total_segment_dbs && !fMatchFound; i++)
{
CdbComponentDatabaseInfo *pcdbCompDBInfo = &pcdbCompDB->segment_db_info[i];
INT iSegInd = pcdbCompDBInfo->segindex;
if (SEGMENT_IS_ACTIVE_PRIMARY(pcdbCompDBInfo))
{
if (URI_FILE == pUri->protocol &&
0 != gpdb::IStrCmpIgnoreCase(pUri->hostname, pcdbCompDBInfo->hostname) &&
0 != gpdb::IStrCmpIgnoreCase(pUri->hostname, pcdbCompDBInfo->address))
{
continue;
}
fCandidateFound = true;
if (NULL == rgszSegFileMap[iSegInd])
{
rgszSegFileMap[iSegInd] = PStrDup(szUri);
fMatchFound = true;
}
}
}
if (!fMatchFound)
{
GPOS_RAISE(gpdxl::ExmaDXL, gpdxl::ExmiDXL2PlStmtExternalScanError,
GPOS_WSZ_LIT("Could not assign a segment database for external file"));
}
}
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToPlStmt::MapLocationsFdist
//
// @doc:
// Segment mapping for tables with LOCATION gpfdist(s):// or custom protocol
// The user supplied gpfdist(s):// URIs are duplicated so that there is one
// available to every segdb. However, in some cases (as determined by
// gp_external_max_segs GUC) we don't want to use *all* segdbs but instead
// figure out how many and pick them randomly (for better performance)
//
//---------------------------------------------------------------------------
void
CTranslatorDXLToPlStmt::MapLocationsFdist
(
OID oidRel,
char **rgszSegFileMap,
CdbComponentDatabases *pcdbCompDB,
Uri *pUri,
const ULONG ulTotalPrimaries
)
{
ULONG ulParticipatingSegments = ulTotalPrimaries;
ULONG ulMaxParticipants = ulParticipatingSegments;
ExtTableEntry *extentry = gpdb::Pexttable(oidRel);
const ULONG ulLocations = gpdb::UlListLength(extentry->urilocations);
if (URI_GPFDIST == pUri->protocol || URI_GPFDISTS == pUri->protocol)
{
ulMaxParticipants = ulLocations * gp_external_max_segs;
}
ULONG ulSkip = 0;
BOOL fSkipRandomly = false;
if (ulParticipatingSegments > ulMaxParticipants)
{
ulSkip = ulParticipatingSegments - ulMaxParticipants;
ulParticipatingSegments = ulMaxParticipants;
fSkipRandomly = true;
}
if (ulLocations > ulParticipatingSegments)
{
// This should match the same error in createplan.c
char msgbuf[200];
snprintf(msgbuf, sizeof(msgbuf),
"There are more external files (URLs) than primary segments that can read them. Found %d URLs and %d primary segments.",
ulLocations, ulParticipatingSegments);
GpdbEreport(ERRCODE_INVALID_TABLE_DEFINITION, // errcode
ERROR,
msgbuf, // errmsg
NULL); // errhint
}
BOOL fDone = false;
List *plModifiedLocations = NIL;
ULONG ulModifiedLocations = 0;
while (!fDone)
{
ListCell *plcLocation = NULL;
ForEach (plcLocation, extentry->urilocations)
{
Value* pvLocation = (Value *)lfirst(plcLocation);
CHAR *szUri = pvLocation->val.str;
plModifiedLocations = gpdb::PlAppendElement(plModifiedLocations, gpdb::PvalMakeString(szUri));
ulModifiedLocations ++;
if (ulModifiedLocations == ulParticipatingSegments)
{
fDone = true;
break;
}
if (ulModifiedLocations > ulParticipatingSegments)
{
GPOS_RAISE(gpdxl::ExmaDXL, gpdxl::ExmiDXL2PlStmtExternalScanError,
GPOS_WSZ_LIT("External scan location list failed building distribution"));
}
}
}
BOOL *rgfSkipMap = NULL;
if (fSkipRandomly)
{
rgfSkipMap = gpdb::RgfRandomSegMap(ulTotalPrimaries, ulSkip);
}
// assign each URI from the new location list a primary segdb
ListCell *plc = NULL;
ForEach (plc, plModifiedLocations)
{
const CHAR *szUri = (CHAR *) strVal(lfirst(plc));
BOOL fCandidateFound = false;
BOOL fMatchFound = false;
for (int i = 0; i < pcdbCompDB->total_segment_dbs && !fMatchFound; i++)
{
CdbComponentDatabaseInfo *pcdbCompDBInfo = &pcdbCompDB->segment_db_info[i];
INT iSegInd = pcdbCompDBInfo->segindex;
if (SEGMENT_IS_ACTIVE_PRIMARY(pcdbCompDBInfo))
{
if (fSkipRandomly)
{
GPOS_ASSERT(iSegInd < (INT) ulTotalPrimaries);
if (rgfSkipMap[iSegInd])
{
continue;
}
}
fCandidateFound = true;
if (NULL == rgszSegFileMap[iSegInd])
{
rgszSegFileMap[iSegInd] = PStrDup(szUri);
fMatchFound = true;
}
}
}
if (!fMatchFound)
{
GPOS_RAISE(gpdxl::ExmaDXL, gpdxl::ExmiDXL2PlStmtExternalScanError,
GPOS_WSZ_LIT("Unable to assign segments for gpfdist(s)"));
}
}
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToPlStmt::MapLocationsExecute
//
// @doc:
// Segment mapping for tables with EXECUTE 'cmd' ON.
// In here we don't have URI's. We have a single command string and a
// specification of the segdb granularity it should get executed on (the
// ON clause). Depending on the ON clause specification we could go many
// different ways, for example: assign the command to all segdb, or one
// command per host, or assign to 5 random segments, etc...
//
//---------------------------------------------------------------------------
void
CTranslatorDXLToPlStmt::MapLocationsExecute
(
OID oidRel,
char **rgszSegFileMap,
CdbComponentDatabases *pcdbCompDB,
const ULONG ulTotalPrimaries
)
{
ExtTableEntry *extentry = gpdb::Pexttable(oidRel);
CHAR *szCommand = extentry->command;
const CHAR *szPrefix = "execute:";
StringInfo si = gpdb::SiMakeStringInfo();
gpdb::AppendStringInfo(si, szPrefix, szCommand);
CHAR *szPrefixedCommand = PStrDup(si->data);
gpdb::GPDBFree(si->data);
gpdb::GPDBFree(si);
si = NULL;
// get the ON clause (execute location) information
Value *pvOnClause = (Value *) gpdb::PvListNth(extentry->execlocations, 0);
CHAR *szOnClause = pvOnClause->val.str;
if (0 == gpos::clib::IStrCmp(szOnClause, "ALL_SEGMENTS"))
{
MapLocationsExecuteAllSegments(szPrefixedCommand, rgszSegFileMap, pcdbCompDB);
}
else if (0 == gpos::clib::IStrCmp(szOnClause, "PER_HOST"))
{
MapLocationsExecutePerHost(szPrefixedCommand, rgszSegFileMap, pcdbCompDB);
}
else if (0 == gpos::clib::IStrNCmp(szOnClause, "HOST:", gpos::clib::UlStrLen("HOST:")))
{
CHAR *szHostName = szOnClause + gpos::clib::UlStrLen("HOST:");
MapLocationsExecuteOneHost(szHostName, szPrefixedCommand, rgszSegFileMap, pcdbCompDB);
}
else if (0 == gpos::clib::IStrNCmp(szOnClause, "SEGMENT_ID:", gpos::clib::UlStrLen("SEGMENT_ID:")))
{
CHAR *pcEnd = NULL;
INT iTargetSegInd = (INT) gpos::clib::LStrToL(szOnClause + gpos::clib::UlStrLen("SEGMENT_ID:"), &pcEnd, 10);
MapLocationsExecuteOneSegment(iTargetSegInd, szPrefixedCommand, rgszSegFileMap, pcdbCompDB);
}
else if (0 == gpos::clib::IStrNCmp(szOnClause, "TOTAL_SEGS:", gpos::clib::UlStrLen("TOTAL_SEGS:")))
{
// total n segments selected randomly
CHAR *pcEnd = NULL;
ULONG ulSegsToUse = gpos::clib::LStrToL(szOnClause + gpos::clib::UlStrLen("TOTAL_SEGS:"), &pcEnd, 10);
MapLocationsExecuteRandomSegments(ulSegsToUse, ulTotalPrimaries, szPrefixedCommand, rgszSegFileMap, pcdbCompDB);
}
else if (0 == gpos::clib::IStrCmp(szOnClause, "MASTER_ONLY"))
{
rgszSegFileMap[0] = PStrDup(szPrefixedCommand);
}
else
{
GPOS_RAISE(gpdxl::ExmaDXL, gpdxl::ExmiDXL2PlStmtExternalScanError,
GPOS_WSZ_LIT("Invalid ON clause"));
}
gpdb::GPDBFree(szPrefixedCommand);
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToPlStmt::MapLocationsExecuteAllSegments
//
// @doc:
// Segment mapping for tables with EXECUTE 'cmd' on all segments
//
//---------------------------------------------------------------------------
void
CTranslatorDXLToPlStmt::MapLocationsExecuteAllSegments
(
CHAR *szPrefixedCommand,
char **rgszSegFileMap,
CdbComponentDatabases *pcdbCompDB
)
{
for (int i = 0; i < pcdbCompDB->total_segment_dbs; i++)
{
CdbComponentDatabaseInfo *pcdbCompDBInfo = &pcdbCompDB->segment_db_info[i];
INT iSegInd = pcdbCompDBInfo->segindex;
if (SEGMENT_IS_ACTIVE_PRIMARY(pcdbCompDBInfo))
{
rgszSegFileMap[iSegInd] = PStrDup(szPrefixedCommand);
}
}
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToPlStmt::MapLocationsExecutePerHost
//
// @doc:
// Segment mapping for tables with EXECUTE 'cmd' per host
//
//---------------------------------------------------------------------------
void
CTranslatorDXLToPlStmt::MapLocationsExecutePerHost
(
CHAR *szPrefixedCommand,
char **rgszSegFileMap,
CdbComponentDatabases *pcdbCompDB
)
{
List *plVisitedHosts = NIL;
for (int i = 0; i < pcdbCompDB->total_segment_dbs; i++)
{
CdbComponentDatabaseInfo *pcdbCompDBInfo = &pcdbCompDB->segment_db_info[i];
INT iSegInd = pcdbCompDBInfo->segindex;
if (SEGMENT_IS_ACTIVE_PRIMARY(pcdbCompDBInfo))
{
BOOL fHostTaken = false;
ListCell *plc = NULL;
ForEach (plc, plVisitedHosts)
{
const CHAR *szHostName = (CHAR *) strVal(lfirst(plc));
if (0 == gpdb::IStrCmpIgnoreCase(szHostName, pcdbCompDBInfo->hostname))
{
fHostTaken = true;
break;
}
}
if (!fHostTaken)
{
rgszSegFileMap[iSegInd] = PStrDup(szPrefixedCommand);
plVisitedHosts = gpdb::PlAppendElement
(
plVisitedHosts,
gpdb::PvalMakeString(PStrDup(pcdbCompDBInfo->hostname))
);
}
}
}
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToPlStmt::MapLocationsExecuteOneHost
//
// @doc:
// Segment mapping for tables with EXECUTE 'cmd' on a given host
//
//---------------------------------------------------------------------------
void
CTranslatorDXLToPlStmt::MapLocationsExecuteOneHost
(
CHAR *szHostName,
CHAR *szPrefixedCommand,
char **rgszSegFileMap,
CdbComponentDatabases *pcdbCompDB
)
{
BOOL fMatchFound = false;
for (int i = 0; i < pcdbCompDB->total_segment_dbs; i++)
{
CdbComponentDatabaseInfo *pcdbCompDBInfo = &pcdbCompDB->segment_db_info[i];
INT iSegInd = pcdbCompDBInfo->segindex;
if (SEGMENT_IS_ACTIVE_PRIMARY(pcdbCompDBInfo) &&
0 == gpdb::IStrCmpIgnoreCase(szHostName, pcdbCompDBInfo->hostname))
{
rgszSegFileMap[iSegInd] = PStrDup(szPrefixedCommand);
fMatchFound = true;
}
}
if (!fMatchFound)
{
GPOS_RAISE(gpdxl::ExmaDXL, gpdxl::ExmiDXL2PlStmtExternalScanError,
GPOS_WSZ_LIT("Could not assign a segment database for given command. No valid primary segment was found in the requested host name."));
}
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToPlStmt::MapLocationsExecuteOneSegment
//
// @doc:
// Segment mapping for tables with EXECUTE 'cmd' on a given segment
//
//---------------------------------------------------------------------------
void
CTranslatorDXLToPlStmt::MapLocationsExecuteOneSegment
(
INT iTargetSegInd,
CHAR *szPrefixedCommand,
char **rgszSegFileMap,
CdbComponentDatabases *pcdbCompDB
)
{
BOOL fMatchFound = false;
for (int i = 0; i < pcdbCompDB->total_segment_dbs; i++)
{
CdbComponentDatabaseInfo *pcdbCompDBInfo = &pcdbCompDB->segment_db_info[i];
INT iSegInd = pcdbCompDBInfo->segindex;
if (SEGMENT_IS_ACTIVE_PRIMARY(pcdbCompDBInfo) && iSegInd == iTargetSegInd)
{
rgszSegFileMap[iSegInd] = PStrDup(szPrefixedCommand);
fMatchFound = true;
}
}
if(!fMatchFound)
{
GPOS_RAISE(gpdxl::ExmaDXL, gpdxl::ExmiDXL2PlStmtExternalScanError,
GPOS_WSZ_LIT("Could not assign a segment database for given command. The requested segment id is not a valid primary segment."));
}
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToPlStmt::MapLocationsExecuteRandomSegments
//
// @doc:
// Segment mapping for tables with EXECUTE 'cmd' on N random segments
//
//---------------------------------------------------------------------------
void
CTranslatorDXLToPlStmt::MapLocationsExecuteRandomSegments
(
ULONG ulSegments,
const ULONG ulTotalPrimaries,
CHAR *szPrefixedCommand,
char **rgszSegFileMap,
CdbComponentDatabases *pcdbCompDB
)
{
if (ulSegments > ulTotalPrimaries)
{
GPOS_RAISE(gpdxl::ExmaDXL, gpdxl::ExmiDXL2PlStmtExternalScanError,
GPOS_WSZ_LIT("More segments in table definition than valid primary segments in the database."));
}
ULONG ulSkip = ulTotalPrimaries - ulSegments;
BOOL *rgfSkipMap = gpdb::RgfRandomSegMap(ulTotalPrimaries, ulSkip);
for (int i = 0; i < pcdbCompDB->total_segment_dbs; i++)
{
CdbComponentDatabaseInfo *pcdbCompDBInfo = &pcdbCompDB->segment_db_info[i];
INT iSegInd = pcdbCompDBInfo->segindex;
if (SEGMENT_IS_ACTIVE_PRIMARY(pcdbCompDBInfo))
{
GPOS_ASSERT(iSegInd < (INT) ulTotalPrimaries);
if (rgfSkipMap[iSegInd])
{
continue;
}
rgszSegFileMap[iSegInd] = PStrDup(szPrefixedCommand);
}
}
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToPlStmt::MapLocationsHdfs
//
// @doc:
// Segment mapping for tables with LOCATION gphdfs://
// The file chuck division and assignment will be done in the external
// Java program. We simply assign the location to all the segdbs.
//
//---------------------------------------------------------------------------
void
CTranslatorDXLToPlStmt::MapLocationsHdfs
(
char **rgszSegFileMap,
CdbComponentDatabases *pcdbCompDB,
CHAR *szFirstUri
)
{
for (int i = 0; i < pcdbCompDB->total_segment_dbs; i++)
{
CdbComponentDatabaseInfo *pcdbCompDBInfo = &pcdbCompDB->segment_db_info[i];
rgszSegFileMap[pcdbCompDBInfo->segindex] = PStrDup(szFirstUri);
}
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToPlStmt::PlExternalScanUriList
//
// @doc:
// List of URIs for external scan
//
//---------------------------------------------------------------------------
List*
CTranslatorDXLToPlStmt::PlExternalScanUriList
(
OID oidRel
)
{
ExtTableEntry *extentry = gpdb::Pexttable(oidRel);
if (extentry->iswritable)
{
// This should match the same error in createplan.c
GpdbEreport(ERRCODE_WRONG_OBJECT_TYPE, // errcode
ERROR,
"cannot read from a WRITABLE external table", // errmsg
"Create the table as READABLE instead."); // errhint
}
//get the total valid primary segdb count
CdbComponentDatabases *pcdbCompDB = gpdb::PcdbComponentDatabases();
ULONG ulTotalPrimaries = 0;
for (int i = 0; i < pcdbCompDB->total_segment_dbs; i++)
{
CdbComponentDatabaseInfo *pcdbCompDBInfo = &pcdbCompDB->segment_db_info[i];
if (SEGMENT_IS_ACTIVE_PRIMARY(pcdbCompDBInfo))
{
ulTotalPrimaries++;
}
}
char **rgszSegFileMap = NULL;
rgszSegFileMap = (char **) gpdb::GPDBAlloc(ulTotalPrimaries * sizeof(char *));
gpos::clib::PvMemSet(rgszSegFileMap, 0, ulTotalPrimaries * sizeof(char *));
// is this an EXECUTE table or a LOCATION (URI) table
BOOL fUsingExecute = false;
BOOL fUsingLocation = false;
const CHAR *szCommand = extentry->command;
if (NULL != szCommand)
{
if (!gp_external_enable_exec)
{
// This should match the same error in createplan.c
GpdbEreport(ERRCODE_GP_FEATURE_NOT_CONFIGURED, // errcode
ERROR,
"Using external tables with OS level commands (EXECUTE clause) is disabled", // errmsg
"To enable set gp_external_enable_exec=on"); // errhint
}
fUsingExecute = true;
}
else
{
fUsingLocation = true;
}
GPOS_ASSERT(0 < gpdb::UlListLength(extentry->urilocations));
CHAR *szFirstUri = NULL;
Uri *pUri = NULL;
if (!fUsingExecute)
{
szFirstUri = ((Value *) gpdb::PvListNth(extentry->urilocations, 0))->val.str;
pUri = gpdb::PuriParseExternalTable(szFirstUri);
}
if (fUsingLocation && (URI_FILE == pUri->protocol || URI_HTTP == pUri->protocol))
{
MapLocationsFile(oidRel, rgszSegFileMap, pcdbCompDB);
}
else if (fUsingLocation && (URI_GPFDIST == pUri->protocol || URI_GPFDISTS == pUri->protocol || URI_CUSTOM == pUri->protocol))
{
MapLocationsFdist(oidRel, rgszSegFileMap, pcdbCompDB, pUri, ulTotalPrimaries);
}
else if (fUsingExecute)
{
MapLocationsExecute(oidRel, rgszSegFileMap, pcdbCompDB, ulTotalPrimaries);
}
else if (fUsingLocation && URI_GPHDFS == pUri->protocol)
{
MapLocationsHdfs(rgszSegFileMap, pcdbCompDB, szFirstUri);
}
else
{
GPOS_RAISE(gpdxl::ExmaDXL, gpdxl::ExmiDXL2PlStmtExternalScanError, GPOS_WSZ_LIT("Unsupported protocol and/or file location"));
}
// convert array map to a list so it can be serialized as part of the plan
List *plFileNames = NIL;
for (ULONG ul = 0; ul < ulTotalPrimaries; ul++)
{
Value *pval = NULL;
if (NULL != rgszSegFileMap[ul])
{
pval = gpdb::PvalMakeString(rgszSegFileMap[ul]);
}
else
{
// no file for this segdb. add a null entry
pval = MakeNode(Value);
pval->type = T_Null;
}
plFileNames = gpdb::PlAppendElement(plFileNames, pval);
}
return plFileNames;
}
//---------------------------------------------------------------------------
// @function:
// CTranslatorDXLToPlStmt::PtsFromDXLTblScan
......@@ -1055,15 +448,17 @@ CTranslatorDXLToPlStmt::PtsFromDXLTblScan
const IMDRelationExternal *pmdrelext = dynamic_cast<const IMDRelationExternal*>(pmdrel);
OID oidRel = CMDIdGPDB::PmdidConvert(pmdrel->Pmdid())->OidObjectId();
ExtTableEntry *pextentry = gpdb::Pexttable(oidRel);
bool isMasterOnly;
// create external scan node
ExternalScan *pes = MakeNode(ExternalScan);
pes->scan.scanrelid = iRel;
pes->uriList = PlExternalScanUriList(oidRel);
pes->uriList = gpdb::PlExternalScanUriList(pextentry, &isMasterOnly);
Value *pval = gpdb::PvalMakeString(pextentry->fmtopts);
pes->fmtOpts = ListMake1(pval);
pes->fmtType = pextentry->fmtcode;
pes->isMasterOnly = (IMDRelation::EreldistrMasterOnly == pmdrelext->Ereldistribution());
pes->isMasterOnly = isMasterOnly;
GPOS_ASSERT((IMDRelation::EreldistrMasterOnly == pmdrelext->Ereldistribution()) == isMasterOnly);
pes->rejLimit = pmdrelext->IRejectLimit();
pes->rejLimitInRows = pmdrelext->FRejLimitInRows();
......
......@@ -2044,16 +2044,7 @@ _outRelOptInfo(StringInfo str, RelOptInfo *node)
WRITE_UINT_FIELD(pages);
WRITE_FLOAT_FIELD(tuples, "%.0f");
WRITE_NODE_FIELD(subplan);
WRITE_NODE_FIELD(urilocationlist);
WRITE_NODE_FIELD(execlocationlist);
WRITE_STRING_FIELD(execcommand);
WRITE_CHAR_FIELD(fmttype);
WRITE_STRING_FIELD(fmtopts);
WRITE_INT_FIELD(rejectlimit);
WRITE_CHAR_FIELD(rejectlimittype);
WRITE_OID_FIELD(fmterrtbl);
WRITE_INT_FIELD(ext_encoding);
WRITE_BOOL_FIELD(writable);
/* no output function for ExtTableEntry */
WRITE_NODE_FIELD(subrtable);
WRITE_NODE_FIELD(baserestrictinfo);
WRITE_NODE_FIELD(joininfo);
......
......@@ -375,8 +375,6 @@ get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent,
static void
get_external_relation_info(Relation relation, RelOptInfo *rel)
{
ExtTableEntry *extentry;
/*
* Get partitioning key info for distributed relation.
*/
......@@ -385,18 +383,7 @@ get_external_relation_info(Relation relation, RelOptInfo *rel)
/*
* Get the pg_exttable fields for this table
*/
extentry = GetExtTableEntry(RelationGetRelid(relation));
rel->urilocationlist = extentry->urilocations;
rel->execlocationlist = extentry->execlocations;
rel->execcommand = extentry->command;
rel->fmttype = extentry->fmtcode;
rel->fmtopts = extentry->fmtopts;
rel->rejectlimit = extentry->rejectlimit;
rel->rejectlimittype = extentry->rejectlimittype;
rel->fmterrtbl = extentry->fmterrtbl;
rel->ext_encoding = extentry->encoding;
rel->writable = extentry->iswritable;
rel->extEntry = GetExtTableEntry(RelationGetRelid(relation));
}
/*
......
......@@ -92,16 +92,7 @@ build_simple_rel(PlannerInfo *root, int relid, RelOptKind reloptkind)
rel->tuples = 0;
rel->subplan = NULL;
rel->subrtable = NIL;
rel->urilocationlist = NIL;
rel->execlocationlist = NIL;
rel->execcommand = NULL;
rel->fmttype = '\0';
rel->fmtopts = NULL;
rel->rejectlimit = -1;
rel->rejectlimittype = '\0';
rel->fmterrtbl = InvalidOid;
rel->ext_encoding = -1;
rel->writable = false;
rel->extEntry = NULL;
rel->baserestrictinfo = NIL;
rel->baserestrictcost.startup = 0;
rel->baserestrictcost.per_tuple = 0;
......
......@@ -535,6 +535,9 @@ namespace gpdb {
// get external table entry with given oid
ExtTableEntry *Pexttable(Oid relationId);
// get external table entry with given oid
List *PlExternalScanUriList(ExtTableEntry *ext, bool *isMasterOnlyP);
// return the first member of the given targetlist whose expression is
// equal to the given expression, or NULL if no such member exists
TargetEntry *PteMember(Node *node, List *targetlist);
......
......@@ -160,88 +160,6 @@ namespace gpdxl
// private copy ctor
CTranslatorDXLToPlStmt(const CTranslatorDXLToPlStmt&);
// segment mapping for tables with LOCATION http:// or file://
void MapLocationsFile
(
OID oidRel,
char **rgszSegFileMap,
CdbComponentDatabases *pcdbCompDB
);
// segment mapping for tables with LOCATION gpfdist(s):// or custom protocol
void MapLocationsFdist
(
OID oidRel,
char **rgszSegFileMap,
CdbComponentDatabases *pcdbCompDB,
Uri *pUri,
const ULONG ulTotalPrimaries
);
// segment mapping for tables with EXECUTE 'cmd' ON.
void MapLocationsExecute
(
OID oidRel,
char **rgszSegFileMap,
CdbComponentDatabases *pcdbCompDB,
const ULONG ulTotalPrimaries
);
// segment mapping for tables with EXECUTE 'cmd' on all segments
void MapLocationsExecuteAllSegments
(
CHAR *szPrefixedCommand,
char **rgszSegFileMap,
CdbComponentDatabases *pcdbCompDB
);
// segment mapping for tables with EXECUTE 'cmd' per host
void MapLocationsExecutePerHost
(
CHAR *szPrefixedCommand,
char **rgszSegFileMap,
CdbComponentDatabases *pcdbCompDB
);
// segment mapping for tables with EXECUTE 'cmd' on a given host
void MapLocationsExecuteOneHost
(
CHAR *szHostName,
CHAR *szPrefixedCommand,
char **rgszSegFileMap,
CdbComponentDatabases *pcdbCompDB
);
//segment mapping for tables with EXECUTE 'cmd' on N random segments
void MapLocationsExecuteRandomSegments
(
ULONG ulSegments,
const ULONG ulTotalPrimaries,
CHAR *szPrefixedCommand,
char **rgszSegFileMap,
CdbComponentDatabases *pcdbCompDB
);
// segment mapping for tables with EXECUTE 'cmd' on a given segment
void MapLocationsExecuteOneSegment
(
INT iTargetSegInd,
CHAR *szPrefixedCommand,
char **rgszSegFileMap,
CdbComponentDatabases *pcdbCompDB
);
// segment mapping for tables with LOCATION gphdfs://
void MapLocationsHdfs
(
char **rgszSegFileMap,
CdbComponentDatabases *pcdbCompDB,
CHAR *szFirstUri
);
// list of URIs for external scan
List* PlExternalScanUriList(OID oidRel);
// walker to set index var attno's
static
BOOL FSetIndexVarAttno(Node *pnode, SContextIndexVarAttno *pctxtidxvarattno);
......
......@@ -51,6 +51,7 @@ extern "C" {
#include "utils/typcache.h"
#include "utils/numeric.h"
#include "optimizer/tlist.h"
#include "optimizer/planmain.h"
#include "nodes/makefuncs.h"
#include "catalog/pg_operator.h"
#include "lib/stringinfo.h"
......
......@@ -492,16 +492,7 @@ typedef struct RelOptInfo
List *subrtable; /* if subquery */
/* used by external scan */
List *urilocationlist;
List *execlocationlist;
char *execcommand;
char fmttype;
char *fmtopts;
int32 rejectlimit;
char rejectlimittype;
Oid fmterrtbl;
int32 ext_encoding;
bool writable; /* true for writable, false for readable ext tables*/
struct ExtTableEntry *extEntry;
/* used by various scans and joins: */
List *baserestrictinfo; /* RestrictInfo structures (if base
......
......@@ -19,6 +19,7 @@
#include "nodes/plannodes.h"
#include "nodes/relation.h"
#include "optimizer/clauses.h" /* AggClauseCounts */
#include "utils/uri.h"
/* GUC parameters */
#define DEFAULT_CURSOR_TUPLE_FRACTION 1.0 /* assume all rows will be fetched */
......@@ -209,6 +210,8 @@ extern Plan *add_agg_cost(PlannerInfo *root, Plan *plan,
int numAggs, int transSpace);
extern Plan *plan_pushdown_tlist(PlannerInfo *root, Plan *plan, List *tlist); /*CDB*/
extern List *create_external_scan_uri_list(struct ExtTableEntry *extEntry, bool *ismasteronly);
/*
* prototypes for plan/initsplan.c
*/
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册