mirror of https://github.com/citusdata/citus.git
commit
0dfc8e6693
|
@ -26,9 +26,6 @@ configure -whitespace
|
||||||
|
|
||||||
# except these exceptions...
|
# except these exceptions...
|
||||||
src/backend/distributed/utils/citus_outfuncs.c -citus-style
|
src/backend/distributed/utils/citus_outfuncs.c -citus-style
|
||||||
src/backend/distributed/utils/citus_read.c -citus-style
|
|
||||||
src/backend/distributed/utils/citus_readfuncs_95.c -citus-style
|
|
||||||
src/backend/distributed/utils/ruleutils_95.c -citus-style
|
|
||||||
src/backend/distributed/utils/ruleutils_96.c -citus-style
|
src/backend/distributed/utils/ruleutils_96.c -citus-style
|
||||||
src/backend/distributed/utils/ruleutils_10.c -citus-style
|
src/backend/distributed/utils/ruleutils_10.c -citus-style
|
||||||
src/include/distributed/citus_nodes.h -citus-style
|
src/include/distributed/citus_nodes.h -citus-style
|
||||||
|
|
|
@ -14,7 +14,6 @@ env:
|
||||||
# During pull request builds (not push builds), use custom-built PostgreSQL
|
# During pull request builds (not push builds), use custom-built PostgreSQL
|
||||||
- USE_CUSTOM_PG="${TRAVIS_PULL_REQUEST_SHA}"
|
- USE_CUSTOM_PG="${TRAVIS_PULL_REQUEST_SHA}"
|
||||||
matrix:
|
matrix:
|
||||||
- PGVERSION=9.5
|
|
||||||
- PGVERSION=9.6
|
- PGVERSION=9.6
|
||||||
- PGVERSION=10
|
- PGVERSION=10
|
||||||
before_install:
|
before_install:
|
||||||
|
|
|
@ -47,7 +47,7 @@ why we ask this as well as instructions for how to proceed, see the
|
||||||
sudo apt-key add -
|
sudo apt-key add -
|
||||||
sudo apt-get update
|
sudo apt-get update
|
||||||
|
|
||||||
sudo apt-get install -y postgresql-server-dev-9.5 postgresql-9.5 \
|
sudo apt-get install -y postgresql-server-dev-9.6 postgresql-9.6 \
|
||||||
libedit-dev libselinux1-dev libxslt-dev \
|
libedit-dev libselinux1-dev libxslt-dev \
|
||||||
libpam0g-dev git flex make
|
libpam0g-dev git flex make
|
||||||
```
|
```
|
||||||
|
@ -66,7 +66,7 @@ why we ask this as well as instructions for how to proceed, see the
|
||||||
|
|
||||||
#### Red Hat-based Linux (RHEL, CentOS, Fedora)
|
#### Red Hat-based Linux (RHEL, CentOS, Fedora)
|
||||||
|
|
||||||
1. Find the PostgreSQL 9.5 RPM URL for your repo at [yum.postgresql.org](http://yum.postgresql.org/repopackages.php#pg95)
|
1. Find the PostgreSQL 9.6 RPM URL for your repo at [yum.postgresql.org](http://yum.postgresql.org/repopackages.php#pg96)
|
||||||
2. Register its contents with Yum:
|
2. Register its contents with Yum:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
@ -78,13 +78,13 @@ why we ask this as well as instructions for how to proceed, see the
|
||||||
```bash
|
```bash
|
||||||
sudo yum update -y
|
sudo yum update -y
|
||||||
sudo yum groupinstall -y 'Development Tools'
|
sudo yum groupinstall -y 'Development Tools'
|
||||||
sudo yum install -y postgresql95-devel postgresql95-server \
|
sudo yum install -y postgresql96-devel postgresql96-server \
|
||||||
libxml2-devel libxslt-devel openssl-devel \
|
libxml2-devel libxslt-devel openssl-devel \
|
||||||
pam-devel readline-devel git
|
pam-devel readline-devel git
|
||||||
|
|
||||||
git clone https://github.com/citusdata/citus.git
|
git clone https://github.com/citusdata/citus.git
|
||||||
cd citus
|
cd citus
|
||||||
PG_CONFIG=/usr/pgsql-9.5/bin/pg_config ./configure
|
PG_CONFIG=/usr/pgsql-9.6/bin/pg_config ./configure
|
||||||
make
|
make
|
||||||
sudo make install
|
sudo make install
|
||||||
cd src/test/regress
|
cd src/test/regress
|
||||||
|
|
|
@ -2005,7 +2005,7 @@ if test -z "$version_num"; then
|
||||||
as_fn_error $? "Could not detect PostgreSQL version from pg_config." "$LINENO" 5
|
as_fn_error $? "Could not detect PostgreSQL version from pg_config." "$LINENO" 5
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if test "$version_num" != '9.5' -a "$version_num" != '9.6' -a "$version_num" != '10'; then
|
if test "$version_num" != '9.6' -a "$version_num" != '10'; then
|
||||||
as_fn_error $? "Citus is not compatible with the detected PostgreSQL version ${version_num}." "$LINENO" 5
|
as_fn_error $? "Citus is not compatible with the detected PostgreSQL version ${version_num}." "$LINENO" 5
|
||||||
else
|
else
|
||||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: building against PostgreSQL $version_num" >&5
|
{ $as_echo "$as_me:${as_lineno-$LINENO}: building against PostgreSQL $version_num" >&5
|
||||||
|
|
|
@ -59,7 +59,7 @@ if test -z "$version_num"; then
|
||||||
AC_MSG_ERROR([Could not detect PostgreSQL version from pg_config.])
|
AC_MSG_ERROR([Could not detect PostgreSQL version from pg_config.])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if test "$version_num" != '9.5' -a "$version_num" != '9.6' -a "$version_num" != '10'; then
|
if test "$version_num" != '9.6' -a "$version_num" != '10'; then
|
||||||
AC_MSG_ERROR([Citus is not compatible with the detected PostgreSQL version ${version_num}.])
|
AC_MSG_ERROR([Citus is not compatible with the detected PostgreSQL version ${version_num}.])
|
||||||
else
|
else
|
||||||
AC_MSG_NOTICE([building against PostgreSQL $version_num])
|
AC_MSG_NOTICE([building against PostgreSQL $version_num])
|
||||||
|
|
|
@ -21,9 +21,7 @@
|
||||||
#include "catalog/dependency.h"
|
#include "catalog/dependency.h"
|
||||||
#include "catalog/index.h"
|
#include "catalog/index.h"
|
||||||
#include "catalog/pg_am.h"
|
#include "catalog/pg_am.h"
|
||||||
#if (PG_VERSION_NUM >= 90600)
|
|
||||||
#include "catalog/pg_constraint_fn.h"
|
#include "catalog/pg_constraint_fn.h"
|
||||||
#endif
|
|
||||||
#include "catalog/pg_enum.h"
|
#include "catalog/pg_enum.h"
|
||||||
#include "catalog/pg_extension.h"
|
#include "catalog/pg_extension.h"
|
||||||
#include "catalog/pg_opclass.h"
|
#include "catalog/pg_opclass.h"
|
||||||
|
|
|
@ -132,13 +132,8 @@ static inline void CopyFlushOutput(CopyOutState outputState, char *start, char *
|
||||||
/* CitusCopyDestReceiver functions */
|
/* CitusCopyDestReceiver functions */
|
||||||
static void CitusCopyDestReceiverStartup(DestReceiver *copyDest, int operation,
|
static void CitusCopyDestReceiverStartup(DestReceiver *copyDest, int operation,
|
||||||
TupleDesc inputTupleDesc);
|
TupleDesc inputTupleDesc);
|
||||||
#if PG_VERSION_NUM >= 90600
|
|
||||||
static bool CitusCopyDestReceiverReceive(TupleTableSlot *slot,
|
static bool CitusCopyDestReceiverReceive(TupleTableSlot *slot,
|
||||||
DestReceiver *copyDest);
|
DestReceiver *copyDest);
|
||||||
#else
|
|
||||||
static void CitusCopyDestReceiverReceive(TupleTableSlot *slot,
|
|
||||||
DestReceiver *copyDest);
|
|
||||||
#endif
|
|
||||||
static void CitusCopyDestReceiverShutdown(DestReceiver *destReceiver);
|
static void CitusCopyDestReceiverShutdown(DestReceiver *destReceiver);
|
||||||
static void CitusCopyDestReceiverDestroy(DestReceiver *destReceiver);
|
static void CitusCopyDestReceiverDestroy(DestReceiver *destReceiver);
|
||||||
|
|
||||||
|
@ -1837,11 +1832,7 @@ CitusCopyDestReceiverStartup(DestReceiver *dest, int operation,
|
||||||
* CitusCopyDestReceiver. It takes a TupleTableSlot and sends the contents to
|
* CitusCopyDestReceiver. It takes a TupleTableSlot and sends the contents to
|
||||||
* the appropriate shard placement(s).
|
* the appropriate shard placement(s).
|
||||||
*/
|
*/
|
||||||
#if PG_VERSION_NUM >= 90600
|
|
||||||
static bool
|
static bool
|
||||||
#else
|
|
||||||
static void
|
|
||||||
#endif
|
|
||||||
CitusCopyDestReceiverReceive(TupleTableSlot *slot, DestReceiver *dest)
|
CitusCopyDestReceiverReceive(TupleTableSlot *slot, DestReceiver *dest)
|
||||||
{
|
{
|
||||||
CitusCopyDestReceiver *copyDest = (CitusCopyDestReceiver *) dest;
|
CitusCopyDestReceiver *copyDest = (CitusCopyDestReceiver *) dest;
|
||||||
|
@ -1949,9 +1940,7 @@ CitusCopyDestReceiverReceive(TupleTableSlot *slot, DestReceiver *dest)
|
||||||
|
|
||||||
copyDest->tuplesSent++;
|
copyDest->tuplesSent++;
|
||||||
|
|
||||||
#if PG_VERSION_NUM >= 90600
|
|
||||||
return true;
|
return true;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -137,9 +137,7 @@ ExecuteIntoDestReceiver(Query *query, ParamListInfo params, DestReceiver *dest)
|
||||||
/* don't display the portal in pg_cursors, it is for internal use only */
|
/* don't display the portal in pg_cursors, it is for internal use only */
|
||||||
portal->visible = false;
|
portal->visible = false;
|
||||||
|
|
||||||
#if (PG_VERSION_NUM >= 90600)
|
|
||||||
cursorOptions = CURSOR_OPT_PARALLEL_OK;
|
cursorOptions = CURSOR_OPT_PARALLEL_OK;
|
||||||
#endif
|
|
||||||
|
|
||||||
/* plan the subquery, this may be another distributed query */
|
/* plan the subquery, this may be another distributed query */
|
||||||
queryPlan = pg_plan_query(query, cursorOptions, params);
|
queryPlan = pg_plan_query(query, cursorOptions, params);
|
||||||
|
|
|
@ -775,12 +775,6 @@ ExecuteSingleModifyTask(CitusScanState *scanState, Task *task, bool expectResult
|
||||||
taskPlacement->nodeName, taskPlacement->nodePort)));
|
taskPlacement->nodeName, taskPlacement->nodePort)));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (PG_VERSION_NUM < 90600)
|
|
||||||
|
|
||||||
/* before 9.6, PostgreSQL used a uint32 for this field, so check */
|
|
||||||
Assert(currentAffectedTupleCount <= 0xFFFFFFFF);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
resultsOK = true;
|
resultsOK = true;
|
||||||
gotResults = true;
|
gotResults = true;
|
||||||
}
|
}
|
||||||
|
@ -1487,11 +1481,6 @@ ConsumeQueryResult(MultiConnection *connection, bool failOnError, int64 *rows)
|
||||||
Assert(currentAffectedTupleCount >= 0);
|
Assert(currentAffectedTupleCount >= 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (PG_VERSION_NUM < 90600)
|
|
||||||
|
|
||||||
/* before 9.6, PostgreSQL used a uint32 for this field, so check */
|
|
||||||
Assert(currentAffectedTupleCount <= 0xFFFFFFFF);
|
|
||||||
#endif
|
|
||||||
*rows += currentAffectedTupleCount;
|
*rows += currentAffectedTupleCount;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -1383,9 +1383,7 @@ DeparseVacuumStmtPrefix(VacuumStmt *vacuumStmt)
|
||||||
int vacuumFlags = vacuumStmt->options;
|
int vacuumFlags = vacuumStmt->options;
|
||||||
const int unsupportedFlags PG_USED_FOR_ASSERTS_ONLY = ~(
|
const int unsupportedFlags PG_USED_FOR_ASSERTS_ONLY = ~(
|
||||||
VACOPT_ANALYZE |
|
VACOPT_ANALYZE |
|
||||||
#if (PG_VERSION_NUM >= 90600)
|
|
||||||
VACOPT_DISABLE_PAGE_SKIPPING |
|
VACOPT_DISABLE_PAGE_SKIPPING |
|
||||||
#endif
|
|
||||||
VACOPT_FREEZE |
|
VACOPT_FREEZE |
|
||||||
VACOPT_FULL
|
VACOPT_FULL
|
||||||
);
|
);
|
||||||
|
@ -1419,12 +1417,10 @@ DeparseVacuumStmtPrefix(VacuumStmt *vacuumStmt)
|
||||||
appendStringInfoString(vacuumPrefix, "ANALYZE,");
|
appendStringInfoString(vacuumPrefix, "ANALYZE,");
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (PG_VERSION_NUM >= 90600)
|
|
||||||
if (vacuumFlags & VACOPT_DISABLE_PAGE_SKIPPING)
|
if (vacuumFlags & VACOPT_DISABLE_PAGE_SKIPPING)
|
||||||
{
|
{
|
||||||
appendStringInfoString(vacuumPrefix, "DISABLE_PAGE_SKIPPING,");
|
appendStringInfoString(vacuumPrefix, "DISABLE_PAGE_SKIPPING,");
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
if (vacuumFlags & VACOPT_FREEZE)
|
if (vacuumFlags & VACOPT_FREEZE)
|
||||||
{
|
{
|
||||||
|
|
|
@ -33,9 +33,7 @@
|
||||||
#include "catalog/namespace.h"
|
#include "catalog/namespace.h"
|
||||||
#include "catalog/pg_class.h"
|
#include "catalog/pg_class.h"
|
||||||
#include "catalog/pg_constraint.h"
|
#include "catalog/pg_constraint.h"
|
||||||
#if (PG_VERSION_NUM >= 90600)
|
|
||||||
#include "catalog/pg_constraint_fn.h"
|
#include "catalog/pg_constraint_fn.h"
|
||||||
#endif
|
|
||||||
#include "catalog/pg_index.h"
|
#include "catalog/pg_index.h"
|
||||||
#include "catalog/pg_type.h"
|
#include "catalog/pg_type.h"
|
||||||
#include "catalog/pg_namespace.h"
|
#include "catalog/pg_namespace.h"
|
||||||
|
|
|
@ -618,10 +618,8 @@ ExplainOneQuery(Query *query, IntoClause *into, ExplainState *es,
|
||||||
/* plan the query */
|
/* plan the query */
|
||||||
#if (PG_VERSION_NUM >= 100000)
|
#if (PG_VERSION_NUM >= 100000)
|
||||||
plan = pg_plan_query(query, cursorOptions, params);
|
plan = pg_plan_query(query, cursorOptions, params);
|
||||||
#elif (PG_VERSION_NUM >= 90600)
|
|
||||||
plan = pg_plan_query(query, into ? 0 : CURSOR_OPT_PARALLEL_OK, params);
|
|
||||||
#else
|
#else
|
||||||
plan = pg_plan_query(query, 0, params);
|
plan = pg_plan_query(query, into ? 0 : CURSOR_OPT_PARALLEL_OK, params);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
INSTR_TIME_SET_CURRENT(planduration);
|
INSTR_TIME_SET_CURRENT(planduration);
|
||||||
|
|
|
@ -1450,11 +1450,9 @@ MasterAggregateExpression(Aggref *originalAggregate,
|
||||||
unionAggregate->args = list_make1(hllTargetEntry);
|
unionAggregate->args = list_make1(hllTargetEntry);
|
||||||
unionAggregate->aggkind = AGGKIND_NORMAL;
|
unionAggregate->aggkind = AGGKIND_NORMAL;
|
||||||
unionAggregate->aggfilter = NULL;
|
unionAggregate->aggfilter = NULL;
|
||||||
#if (PG_VERSION_NUM >= 90600)
|
|
||||||
unionAggregate->aggtranstype = InvalidOid;
|
unionAggregate->aggtranstype = InvalidOid;
|
||||||
unionAggregate->aggargtypes = list_make1_oid(unionAggregate->aggtype);
|
unionAggregate->aggargtypes = list_make1_oid(unionAggregate->aggtype);
|
||||||
unionAggregate->aggsplit = AGGSPLIT_SIMPLE;
|
unionAggregate->aggsplit = AGGSPLIT_SIMPLE;
|
||||||
#endif
|
|
||||||
|
|
||||||
cardinalityExpression = makeNode(FuncExpr);
|
cardinalityExpression = makeNode(FuncExpr);
|
||||||
cardinalityExpression->funcid = cardinalityFunctionId;
|
cardinalityExpression->funcid = cardinalityFunctionId;
|
||||||
|
@ -1515,11 +1513,9 @@ MasterAggregateExpression(Aggref *originalAggregate,
|
||||||
newMasterAggregate->aggfnoid = sumFunctionId;
|
newMasterAggregate->aggfnoid = sumFunctionId;
|
||||||
newMasterAggregate->aggtype = masterReturnType;
|
newMasterAggregate->aggtype = masterReturnType;
|
||||||
newMasterAggregate->aggfilter = NULL;
|
newMasterAggregate->aggfilter = NULL;
|
||||||
#if (PG_VERSION_NUM >= 90600)
|
|
||||||
newMasterAggregate->aggtranstype = InvalidOid;
|
newMasterAggregate->aggtranstype = InvalidOid;
|
||||||
newMasterAggregate->aggargtypes = list_make1_oid(newMasterAggregate->aggtype);
|
newMasterAggregate->aggargtypes = list_make1_oid(newMasterAggregate->aggtype);
|
||||||
newMasterAggregate->aggsplit = AGGSPLIT_SIMPLE;
|
newMasterAggregate->aggsplit = AGGSPLIT_SIMPLE;
|
||||||
#endif
|
|
||||||
|
|
||||||
column = makeVar(masterTableId, walkerContext->columnId, workerReturnType,
|
column = makeVar(masterTableId, walkerContext->columnId, workerReturnType,
|
||||||
workerReturnTypeMod, workerCollationId, columnLevelsUp);
|
workerReturnTypeMod, workerCollationId, columnLevelsUp);
|
||||||
|
@ -1585,11 +1581,9 @@ MasterAggregateExpression(Aggref *originalAggregate,
|
||||||
newMasterAggregate->aggfnoid = aggregateFunctionId;
|
newMasterAggregate->aggfnoid = aggregateFunctionId;
|
||||||
newMasterAggregate->args = list_make1(arrayCatAggArgument);
|
newMasterAggregate->args = list_make1(arrayCatAggArgument);
|
||||||
newMasterAggregate->aggfilter = NULL;
|
newMasterAggregate->aggfilter = NULL;
|
||||||
#if (PG_VERSION_NUM >= 90600)
|
|
||||||
newMasterAggregate->aggtranstype = InvalidOid;
|
newMasterAggregate->aggtranstype = InvalidOid;
|
||||||
newMasterAggregate->aggargtypes = list_make1_oid(ANYARRAYOID);
|
newMasterAggregate->aggargtypes = list_make1_oid(ANYARRAYOID);
|
||||||
newMasterAggregate->aggsplit = AGGSPLIT_SIMPLE;
|
newMasterAggregate->aggsplit = AGGSPLIT_SIMPLE;
|
||||||
#endif
|
|
||||||
|
|
||||||
newMasterExpression = (Expr *) newMasterAggregate;
|
newMasterExpression = (Expr *) newMasterAggregate;
|
||||||
}
|
}
|
||||||
|
@ -1644,12 +1638,8 @@ MasterAggregateExpression(Aggref *originalAggregate,
|
||||||
/* Run AggRefs through cost machinery to mark required fields sanely */
|
/* Run AggRefs through cost machinery to mark required fields sanely */
|
||||||
memset(&aggregateCosts, 0, sizeof(aggregateCosts));
|
memset(&aggregateCosts, 0, sizeof(aggregateCosts));
|
||||||
|
|
||||||
#if PG_VERSION_NUM >= 90600
|
|
||||||
get_agg_clause_costs(NULL, (Node *) newMasterExpression, AGGSPLIT_SIMPLE,
|
get_agg_clause_costs(NULL, (Node *) newMasterExpression, AGGSPLIT_SIMPLE,
|
||||||
&aggregateCosts);
|
&aggregateCosts);
|
||||||
#else
|
|
||||||
count_agg_clauses(NULL, (Node *) newMasterExpression, &aggregateCosts);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return newMasterExpression;
|
return newMasterExpression;
|
||||||
}
|
}
|
||||||
|
@ -1693,11 +1683,9 @@ MasterAverageExpression(Oid sumAggregateType, Oid countAggregateType,
|
||||||
firstSum->aggtype = get_func_rettype(firstSum->aggfnoid);
|
firstSum->aggtype = get_func_rettype(firstSum->aggfnoid);
|
||||||
firstSum->args = list_make1(firstTargetEntry);
|
firstSum->args = list_make1(firstTargetEntry);
|
||||||
firstSum->aggkind = AGGKIND_NORMAL;
|
firstSum->aggkind = AGGKIND_NORMAL;
|
||||||
#if (PG_VERSION_NUM >= 90600)
|
|
||||||
firstSum->aggtranstype = InvalidOid;
|
firstSum->aggtranstype = InvalidOid;
|
||||||
firstSum->aggargtypes = list_make1_oid(firstSum->aggtype);
|
firstSum->aggargtypes = list_make1_oid(firstSum->aggtype);
|
||||||
firstSum->aggsplit = AGGSPLIT_SIMPLE;
|
firstSum->aggsplit = AGGSPLIT_SIMPLE;
|
||||||
#endif
|
|
||||||
|
|
||||||
/* create the second argument for sum(column2) */
|
/* create the second argument for sum(column2) */
|
||||||
secondColumn = makeVar(masterTableId, (*columnId), countAggregateType,
|
secondColumn = makeVar(masterTableId, (*columnId), countAggregateType,
|
||||||
|
@ -1710,11 +1698,9 @@ MasterAverageExpression(Oid sumAggregateType, Oid countAggregateType,
|
||||||
secondSum->aggtype = get_func_rettype(secondSum->aggfnoid);
|
secondSum->aggtype = get_func_rettype(secondSum->aggfnoid);
|
||||||
secondSum->args = list_make1(secondTargetEntry);
|
secondSum->args = list_make1(secondTargetEntry);
|
||||||
secondSum->aggkind = AGGKIND_NORMAL;
|
secondSum->aggkind = AGGKIND_NORMAL;
|
||||||
#if (PG_VERSION_NUM >= 90600)
|
|
||||||
secondSum->aggtranstype = InvalidOid;
|
secondSum->aggtranstype = InvalidOid;
|
||||||
secondSum->aggargtypes = list_make1_oid(firstSum->aggtype);
|
secondSum->aggargtypes = list_make1_oid(firstSum->aggtype);
|
||||||
secondSum->aggsplit = AGGSPLIT_SIMPLE;
|
secondSum->aggsplit = AGGSPLIT_SIMPLE;
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Build the division operator between these two aggregates. This function
|
* Build the division operator between these two aggregates. This function
|
||||||
|
@ -2090,20 +2076,16 @@ WorkerAggregateExpressionList(Aggref *originalAggregate,
|
||||||
sumAggregate->aggfnoid = AggregateFunctionOid(sumAggregateName, argumentType);
|
sumAggregate->aggfnoid = AggregateFunctionOid(sumAggregateName, argumentType);
|
||||||
sumAggregate->aggtype = get_func_rettype(sumAggregate->aggfnoid);
|
sumAggregate->aggtype = get_func_rettype(sumAggregate->aggfnoid);
|
||||||
|
|
||||||
#if (PG_VERSION_NUM >= 90600)
|
|
||||||
sumAggregate->aggtranstype = InvalidOid;
|
sumAggregate->aggtranstype = InvalidOid;
|
||||||
sumAggregate->aggargtypes = list_make1_oid(argumentType);
|
sumAggregate->aggargtypes = list_make1_oid(argumentType);
|
||||||
sumAggregate->aggsplit = AGGSPLIT_SIMPLE;
|
sumAggregate->aggsplit = AGGSPLIT_SIMPLE;
|
||||||
#endif
|
|
||||||
|
|
||||||
/* count has any input type */
|
/* count has any input type */
|
||||||
countAggregate->aggfnoid = AggregateFunctionOid(countAggregateName, ANYOID);
|
countAggregate->aggfnoid = AggregateFunctionOid(countAggregateName, ANYOID);
|
||||||
countAggregate->aggtype = get_func_rettype(countAggregate->aggfnoid);
|
countAggregate->aggtype = get_func_rettype(countAggregate->aggfnoid);
|
||||||
#if (PG_VERSION_NUM >= 90600)
|
|
||||||
countAggregate->aggtranstype = InvalidOid;
|
countAggregate->aggtranstype = InvalidOid;
|
||||||
countAggregate->aggargtypes = list_make1_oid(argumentType);
|
countAggregate->aggargtypes = list_make1_oid(argumentType);
|
||||||
countAggregate->aggsplit = AGGSPLIT_SIMPLE;
|
countAggregate->aggsplit = AGGSPLIT_SIMPLE;
|
||||||
#endif
|
|
||||||
|
|
||||||
workerAggregateList = lappend(workerAggregateList, sumAggregate);
|
workerAggregateList = lappend(workerAggregateList, sumAggregate);
|
||||||
workerAggregateList = lappend(workerAggregateList, countAggregate);
|
workerAggregateList = lappend(workerAggregateList, countAggregate);
|
||||||
|
@ -2122,12 +2104,8 @@ WorkerAggregateExpressionList(Aggref *originalAggregate,
|
||||||
/* Run AggRefs through cost machinery to mark required fields sanely */
|
/* Run AggRefs through cost machinery to mark required fields sanely */
|
||||||
memset(&aggregateCosts, 0, sizeof(aggregateCosts));
|
memset(&aggregateCosts, 0, sizeof(aggregateCosts));
|
||||||
|
|
||||||
#if PG_VERSION_NUM >= 90600
|
|
||||||
get_agg_clause_costs(NULL, (Node *) workerAggregateList, AGGSPLIT_SIMPLE,
|
get_agg_clause_costs(NULL, (Node *) workerAggregateList, AGGSPLIT_SIMPLE,
|
||||||
&aggregateCosts);
|
&aggregateCosts);
|
||||||
#else
|
|
||||||
count_agg_clauses(NULL, (Node *) workerAggregateList, &aggregateCosts);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return workerAggregateList;
|
return workerAggregateList;
|
||||||
}
|
}
|
||||||
|
@ -2418,17 +2396,11 @@ ErrorIfContainsUnsupportedAggregate(MultiNode *logicalPlanNode)
|
||||||
|
|
||||||
List *targetList = extendedOpNode->targetList;
|
List *targetList = extendedOpNode->targetList;
|
||||||
|
|
||||||
#if (PG_VERSION_NUM >= 90600)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* PVC_REJECT_PLACEHOLDERS is now implicit if PVC_INCLUDE_PLACEHOLDERS
|
* PVC_REJECT_PLACEHOLDERS is implicit if PVC_INCLUDE_PLACEHOLDERS isn't
|
||||||
* isn't specified.
|
* specified.
|
||||||
*/
|
*/
|
||||||
List *expressionList = pull_var_clause((Node *) targetList, PVC_INCLUDE_AGGREGATES);
|
List *expressionList = pull_var_clause((Node *) targetList, PVC_INCLUDE_AGGREGATES);
|
||||||
#else
|
|
||||||
List *expressionList = pull_var_clause((Node *) targetList, PVC_INCLUDE_AGGREGATES,
|
|
||||||
PVC_REJECT_PLACEHOLDERS);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ListCell *expressionCell = NULL;
|
ListCell *expressionCell = NULL;
|
||||||
foreach(expressionCell, expressionList)
|
foreach(expressionCell, expressionList)
|
||||||
|
|
|
@ -2769,17 +2769,11 @@ ExtractRangeTableEntryWalker(Node *node, List **rangeTableList)
|
||||||
List *
|
List *
|
||||||
pull_var_clause_default(Node *node)
|
pull_var_clause_default(Node *node)
|
||||||
{
|
{
|
||||||
#if (PG_VERSION_NUM >= 90600)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* PVC_REJECT_PLACEHOLDERS is now implicit if PVC_INCLUDE_PLACEHOLDERS
|
* PVC_REJECT_PLACEHOLDERS is implicit if PVC_INCLUDE_PLACEHOLDERS
|
||||||
* isn't specified.
|
* isn't specified.
|
||||||
*/
|
*/
|
||||||
List *columnList = pull_var_clause(node, PVC_RECURSE_AGGREGATES);
|
List *columnList = pull_var_clause(node, PVC_RECURSE_AGGREGATES);
|
||||||
#else
|
|
||||||
List *columnList = pull_var_clause(node, PVC_RECURSE_AGGREGATES,
|
|
||||||
PVC_REJECT_PLACEHOLDERS);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return columnList;
|
return columnList;
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,14 +99,9 @@ BuildAggregatePlan(Query *masterQuery, Plan *subPlan)
|
||||||
|
|
||||||
/* estimate aggregate execution costs */
|
/* estimate aggregate execution costs */
|
||||||
memset(&aggregateCosts, 0, sizeof(AggClauseCosts));
|
memset(&aggregateCosts, 0, sizeof(AggClauseCosts));
|
||||||
#if (PG_VERSION_NUM >= 90600)
|
|
||||||
get_agg_clause_costs(NULL, (Node *) aggregateTargetList, AGGSPLIT_SIMPLE,
|
get_agg_clause_costs(NULL, (Node *) aggregateTargetList, AGGSPLIT_SIMPLE,
|
||||||
&aggregateCosts);
|
&aggregateCosts);
|
||||||
get_agg_clause_costs(NULL, (Node *) havingQual, AGGSPLIT_SIMPLE, &aggregateCosts);
|
get_agg_clause_costs(NULL, (Node *) havingQual, AGGSPLIT_SIMPLE, &aggregateCosts);
|
||||||
#else
|
|
||||||
count_agg_clauses(NULL, (Node *) aggregateTargetList, &aggregateCosts);
|
|
||||||
count_agg_clauses(NULL, (Node *) havingQual, &aggregateCosts);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* For upper level plans above the sequential scan, the planner expects the
|
* For upper level plans above the sequential scan, the planner expects the
|
||||||
|
@ -142,17 +137,10 @@ BuildAggregatePlan(Query *masterQuery, Plan *subPlan)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* finally create the plan */
|
/* finally create the plan */
|
||||||
#if (PG_VERSION_NUM >= 90600)
|
|
||||||
aggregatePlan = make_agg(aggregateTargetList, (List *) havingQual, aggregateStrategy,
|
aggregatePlan = make_agg(aggregateTargetList, (List *) havingQual, aggregateStrategy,
|
||||||
AGGSPLIT_SIMPLE, groupColumnCount, groupColumnIdArray,
|
AGGSPLIT_SIMPLE, groupColumnCount, groupColumnIdArray,
|
||||||
groupColumnOpArray, NIL, NIL,
|
groupColumnOpArray, NIL, NIL,
|
||||||
rowEstimate, subPlan);
|
rowEstimate, subPlan);
|
||||||
#else
|
|
||||||
aggregatePlan = make_agg(NULL, aggregateTargetList, (List *) havingQual,
|
|
||||||
aggregateStrategy,
|
|
||||||
&aggregateCosts, groupColumnCount, groupColumnIdArray,
|
|
||||||
groupColumnOpArray, NIL, rowEstimate, subPlan);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* just for reproducible costs between different PostgreSQL versions */
|
/* just for reproducible costs between different PostgreSQL versions */
|
||||||
aggregatePlan->plan.startup_cost = 0;
|
aggregatePlan->plan.startup_cost = 0;
|
||||||
|
@ -219,11 +207,7 @@ BuildSelectStatement(Query *masterQuery, List *masterTargetList, CustomScan *rem
|
||||||
if (masterQuery->sortClause)
|
if (masterQuery->sortClause)
|
||||||
{
|
{
|
||||||
List *sortClauseList = masterQuery->sortClause;
|
List *sortClauseList = masterQuery->sortClause;
|
||||||
#if (PG_VERSION_NUM >= 90600)
|
|
||||||
Sort *sortPlan = make_sort_from_sortclauses(sortClauseList, topLevelPlan);
|
Sort *sortPlan = make_sort_from_sortclauses(sortClauseList, topLevelPlan);
|
||||||
#else
|
|
||||||
Sort *sortPlan = make_sort_from_sortclauses(NULL, sortClauseList, topLevelPlan);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* just for reproducible costs between different PostgreSQL versions */
|
/* just for reproducible costs between different PostgreSQL versions */
|
||||||
sortPlan->plan.startup_cost = 0;
|
sortPlan->plan.startup_cost = 0;
|
||||||
|
@ -238,15 +222,7 @@ BuildSelectStatement(Query *masterQuery, List *masterTargetList, CustomScan *rem
|
||||||
{
|
{
|
||||||
Node *limitCount = masterQuery->limitCount;
|
Node *limitCount = masterQuery->limitCount;
|
||||||
Node *limitOffset = masterQuery->limitOffset;
|
Node *limitOffset = masterQuery->limitOffset;
|
||||||
#if (PG_VERSION_NUM >= 90600)
|
|
||||||
Limit *limitPlan = make_limit(topLevelPlan, limitOffset, limitCount);
|
Limit *limitPlan = make_limit(topLevelPlan, limitOffset, limitCount);
|
||||||
#else
|
|
||||||
int64 offsetEstimate = 0;
|
|
||||||
int64 countEstimate = 0;
|
|
||||||
|
|
||||||
Limit *limitPlan = make_limit(topLevelPlan, limitOffset, limitCount,
|
|
||||||
offsetEstimate, countEstimate);
|
|
||||||
#endif
|
|
||||||
topLevelPlan = (Plan *) limitPlan;
|
topLevelPlan = (Plan *) limitPlan;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -444,7 +444,7 @@ SerializeMultiPlan(MultiPlan *multiPlan)
|
||||||
char *serializedMultiPlan = NULL;
|
char *serializedMultiPlan = NULL;
|
||||||
Const *multiPlanData = NULL;
|
Const *multiPlanData = NULL;
|
||||||
|
|
||||||
serializedMultiPlan = CitusNodeToString(multiPlan);
|
serializedMultiPlan = nodeToString(multiPlan);
|
||||||
|
|
||||||
multiPlanData = makeNode(Const);
|
multiPlanData = makeNode(Const);
|
||||||
multiPlanData->consttype = CSTRINGOID;
|
multiPlanData->consttype = CSTRINGOID;
|
||||||
|
@ -472,7 +472,7 @@ DeserializeMultiPlan(Node *node)
|
||||||
multiPlanData = (Const *) node;
|
multiPlanData = (Const *) node;
|
||||||
serializedMultiPlan = DatumGetCString(multiPlanData->constvalue);
|
serializedMultiPlan = DatumGetCString(multiPlanData->constvalue);
|
||||||
|
|
||||||
multiPlan = (MultiPlan *) CitusStringToNode(serializedMultiPlan);
|
multiPlan = (MultiPlan *) stringToNode(serializedMultiPlan);
|
||||||
Assert(CitusIsA(multiPlan, MultiPlan));
|
Assert(CitusIsA(multiPlan, MultiPlan));
|
||||||
|
|
||||||
return multiPlan;
|
return multiPlan;
|
||||||
|
@ -661,14 +661,14 @@ RemoteScanRangeTableEntry(List *columnNameList)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* CheckNodeIsDumpable checks that the passed node can be dumped using
|
* CheckNodeIsDumpable checks that the passed node can be dumped using
|
||||||
* CitusNodeToString(). As this checks is expensive, it's only active when
|
* nodeToString(). As this checks is expensive, it's only active when
|
||||||
* assertions are enabled.
|
* assertions are enabled.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
CheckNodeIsDumpable(Node *node)
|
CheckNodeIsDumpable(Node *node)
|
||||||
{
|
{
|
||||||
#ifdef USE_ASSERT_CHECKING
|
#ifdef USE_ASSERT_CHECKING
|
||||||
char *out = CitusNodeToString(node);
|
char *out = nodeToString(node);
|
||||||
pfree(out);
|
pfree(out);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -2804,14 +2804,8 @@ ReorderInsertSelectTargetLists(Query *originalQuery, RangeTblEntry *insertRte,
|
||||||
* It is safe to pull Var clause and ignore the coercions since that
|
* It is safe to pull Var clause and ignore the coercions since that
|
||||||
* are already going to be added on the workers implicitly.
|
* are already going to be added on the workers implicitly.
|
||||||
*/
|
*/
|
||||||
#if (PG_VERSION_NUM >= 90600)
|
|
||||||
targetVarList = pull_var_clause((Node *) oldInsertTargetEntry->expr,
|
targetVarList = pull_var_clause((Node *) oldInsertTargetEntry->expr,
|
||||||
PVC_RECURSE_AGGREGATES);
|
PVC_RECURSE_AGGREGATES);
|
||||||
#else
|
|
||||||
targetVarList = pull_var_clause((Node *) oldInsertTargetEntry->expr,
|
|
||||||
PVC_RECURSE_AGGREGATES,
|
|
||||||
PVC_RECURSE_PLACEHOLDERS);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
targetVarCount = list_length(targetVarList);
|
targetVarCount = list_length(targetVarList);
|
||||||
|
|
||||||
|
|
|
@ -89,15 +89,9 @@ FakeGetForeignPaths(PlannerInfo *root, RelOptInfo *baserel, Oid foreigntableid)
|
||||||
Cost startup_cost = 0;
|
Cost startup_cost = 0;
|
||||||
Cost total_cost = startup_cost + baserel->rows;
|
Cost total_cost = startup_cost + baserel->rows;
|
||||||
|
|
||||||
#if (PG_VERSION_NUM >= 90600)
|
|
||||||
add_path(baserel, (Path *) create_foreignscan_path(root, baserel, NULL, baserel->rows,
|
add_path(baserel, (Path *) create_foreignscan_path(root, baserel, NULL, baserel->rows,
|
||||||
startup_cost, total_cost, NIL,
|
startup_cost, total_cost, NIL,
|
||||||
NULL, NULL, NIL));
|
NULL, NULL, NIL));
|
||||||
#else
|
|
||||||
add_path(baserel, (Path *) create_foreignscan_path(root, baserel, baserel->rows,
|
|
||||||
startup_cost, total_cost, NIL,
|
|
||||||
NULL, NULL, NIL));
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -339,8 +339,6 @@ citus_extradata_container(PG_FUNCTION_ARGS)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if (PG_VERSION_NUM >= 90600)
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
CopyUnsupportedCitusNode(struct ExtensibleNode *newnode,
|
CopyUnsupportedCitusNode(struct ExtensibleNode *newnode,
|
||||||
const struct ExtensibleNode *oldnode)
|
const struct ExtensibleNode *oldnode)
|
||||||
|
@ -403,12 +401,10 @@ const ExtensibleNodeMethods nodeMethods[] =
|
||||||
DEFINE_NODE_METHODS_NO_READ(MultiCartesianProduct),
|
DEFINE_NODE_METHODS_NO_READ(MultiCartesianProduct),
|
||||||
DEFINE_NODE_METHODS_NO_READ(MultiExtendedOp)
|
DEFINE_NODE_METHODS_NO_READ(MultiExtendedOp)
|
||||||
};
|
};
|
||||||
#endif
|
|
||||||
|
|
||||||
void
|
void
|
||||||
RegisterNodes(void)
|
RegisterNodes(void)
|
||||||
{
|
{
|
||||||
#if (PG_VERSION_NUM >= 90600)
|
|
||||||
int off;
|
int off;
|
||||||
|
|
||||||
StaticAssertExpr(lengthof(nodeMethods) == lengthof(CitusNodeTagNamesD),
|
StaticAssertExpr(lengthof(nodeMethods) == lengthof(CitusNodeTagNamesD),
|
||||||
|
@ -418,5 +414,4 @@ RegisterNodes(void)
|
||||||
{
|
{
|
||||||
RegisterExtensibleNodeMethods(&nodeMethods[off]);
|
RegisterExtensibleNodeMethods(&nodeMethods[off]);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,16 +45,9 @@
|
||||||
const nodeTypeName *node = (const nodeTypeName *) raw_node
|
const nodeTypeName *node = (const nodeTypeName *) raw_node
|
||||||
|
|
||||||
/* Write the label for the node type */
|
/* Write the label for the node type */
|
||||||
#if (PG_VERSION_NUM >= 90600)
|
|
||||||
#define WRITE_NODE_TYPE(nodelabel) \
|
#define WRITE_NODE_TYPE(nodelabel) \
|
||||||
(void) 0
|
(void) 0
|
||||||
|
|
||||||
#else
|
|
||||||
#define WRITE_NODE_TYPE(nodelabel) \
|
|
||||||
appendStringInfoString(str, nodelabel)
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Write an integer field (anything written as ":fldname %d") */
|
/* Write an integer field (anything written as ":fldname %d") */
|
||||||
#define WRITE_INT_FIELD(fldname) \
|
#define WRITE_INT_FIELD(fldname) \
|
||||||
appendStringInfo(str, " :" CppAsString(fldname) " %d", node->fldname)
|
appendStringInfo(str, " :" CppAsString(fldname) " %d", node->fldname)
|
||||||
|
@ -115,123 +108,6 @@
|
||||||
|
|
||||||
#define booltostr(x) ((x) ? "true" : "false")
|
#define booltostr(x) ((x) ? "true" : "false")
|
||||||
|
|
||||||
#if (PG_VERSION_NUM < 90600)
|
|
||||||
static void outNode(StringInfo str, const void *obj);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* outToken
|
|
||||||
* Convert an ordinary string (eg, an identifier) into a form that
|
|
||||||
* will be decoded back to a plain token by read.c's functions.
|
|
||||||
*
|
|
||||||
* If a null or empty string is given, it is encoded as "<>".
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
outToken(StringInfo str, const char *s)
|
|
||||||
{
|
|
||||||
if (s == NULL || *s == '\0')
|
|
||||||
{
|
|
||||||
appendStringInfoString(str, "<>");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Look for characters or patterns that are treated specially by read.c
|
|
||||||
* (either in pg_strtok() or in nodeRead()), and therefore need a
|
|
||||||
* protective backslash.
|
|
||||||
*/
|
|
||||||
/* These characters only need to be quoted at the start of the string */
|
|
||||||
if (*s == '<' ||
|
|
||||||
*s == '\"' ||
|
|
||||||
isdigit((unsigned char) *s) ||
|
|
||||||
((*s == '+' || *s == '-') &&
|
|
||||||
(isdigit((unsigned char) s[1]) || s[1] == '.')))
|
|
||||||
appendStringInfoChar(str, '\\');
|
|
||||||
while (*s)
|
|
||||||
{
|
|
||||||
/* These chars must be backslashed anywhere in the string */
|
|
||||||
if (*s == ' ' || *s == '\n' || *s == '\t' ||
|
|
||||||
*s == '(' || *s == ')' || *s == '{' || *s == '}' ||
|
|
||||||
*s == '\\')
|
|
||||||
appendStringInfoChar(str, '\\');
|
|
||||||
appendStringInfoChar(str, *s++);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
|
||||||
_outList(StringInfo str, const List *node)
|
|
||||||
{
|
|
||||||
const ListCell *lc;
|
|
||||||
|
|
||||||
appendStringInfoChar(str, '(');
|
|
||||||
|
|
||||||
if (IsA(node, IntList))
|
|
||||||
appendStringInfoChar(str, 'i');
|
|
||||||
else if (IsA(node, OidList))
|
|
||||||
appendStringInfoChar(str, 'o');
|
|
||||||
|
|
||||||
foreach(lc, node)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* For the sake of backward compatibility, we emit a slightly
|
|
||||||
* different whitespace format for lists of nodes vs. other types of
|
|
||||||
* lists. XXX: is this necessary?
|
|
||||||
*/
|
|
||||||
if (IsA(node, List))
|
|
||||||
{
|
|
||||||
outNode(str, lfirst(lc));
|
|
||||||
if (lnext(lc))
|
|
||||||
appendStringInfoChar(str, ' ');
|
|
||||||
}
|
|
||||||
else if (IsA(node, IntList))
|
|
||||||
appendStringInfo(str, " %d", lfirst_int(lc));
|
|
||||||
else if (IsA(node, OidList))
|
|
||||||
appendStringInfo(str, " %u", lfirst_oid(lc));
|
|
||||||
else
|
|
||||||
elog(ERROR, "unrecognized list node type: %d",
|
|
||||||
(int) node->type);
|
|
||||||
}
|
|
||||||
|
|
||||||
appendStringInfoChar(str, ')');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Print the value of a Datum given its type.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
outDatum(StringInfo str, Datum value, int typlen, bool typbyval)
|
|
||||||
{
|
|
||||||
Size length,
|
|
||||||
i;
|
|
||||||
char *s;
|
|
||||||
|
|
||||||
length = datumGetSize(value, typbyval, typlen);
|
|
||||||
|
|
||||||
if (typbyval)
|
|
||||||
{
|
|
||||||
s = (char *) (&value);
|
|
||||||
appendStringInfo(str, "%u [ ", (unsigned int) length);
|
|
||||||
for (i = 0; i < (Size) sizeof(Datum); i++)
|
|
||||||
appendStringInfo(str, "%d ", (int) (s[i]));
|
|
||||||
appendStringInfoChar(str, ']');
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
s = (char *) DatumGetPointer(value);
|
|
||||||
if (!PointerIsValid(s))
|
|
||||||
appendStringInfoString(str, "0 [ ]");
|
|
||||||
else
|
|
||||||
{
|
|
||||||
appendStringInfo(str, "%u [ ", (unsigned int) length);
|
|
||||||
for (i = 0; i < length; i++)
|
|
||||||
appendStringInfo(str, "%d ", (int) (s[i]));
|
|
||||||
appendStringInfoChar(str, ']');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
* Output routines for Citus node types
|
* Output routines for Citus node types
|
||||||
|
@ -540,156 +416,3 @@ OutDeferredErrorMessage(OUTFUNC_ARGS)
|
||||||
WRITE_INT_FIELD(linenumber);
|
WRITE_INT_FIELD(linenumber);
|
||||||
WRITE_STRING_FIELD(functionname);
|
WRITE_STRING_FIELD(functionname);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if (PG_VERSION_NUM < 90600)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* outNode -
|
|
||||||
* converts a Node into ascii string and append it to 'str'
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
outNode(StringInfo str, const void *obj)
|
|
||||||
{
|
|
||||||
if (obj == NULL)
|
|
||||||
{
|
|
||||||
appendStringInfoString(str, "<>");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
switch (CitusNodeTag(obj))
|
|
||||||
{
|
|
||||||
case T_List:
|
|
||||||
case T_IntList:
|
|
||||||
case T_OidList:
|
|
||||||
_outList(str, obj);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case T_MultiTreeRoot:
|
|
||||||
appendStringInfoChar(str, '{');
|
|
||||||
OutMultiTreeRoot(str, obj);
|
|
||||||
appendStringInfoChar(str, '}');
|
|
||||||
break;
|
|
||||||
|
|
||||||
case T_MultiProject:
|
|
||||||
appendStringInfoChar(str, '{');
|
|
||||||
OutMultiProject(str, obj);
|
|
||||||
appendStringInfoChar(str, '}');
|
|
||||||
break;
|
|
||||||
|
|
||||||
case T_MultiCollect:
|
|
||||||
appendStringInfoChar(str, '{');
|
|
||||||
OutMultiCollect(str, obj);
|
|
||||||
appendStringInfoChar(str, '}');
|
|
||||||
break;
|
|
||||||
|
|
||||||
case T_MultiSelect:
|
|
||||||
appendStringInfoChar(str, '{');
|
|
||||||
OutMultiSelect(str, obj);
|
|
||||||
appendStringInfoChar(str, '}');
|
|
||||||
break;
|
|
||||||
|
|
||||||
case T_MultiTable:
|
|
||||||
appendStringInfoChar(str, '{');
|
|
||||||
OutMultiTable(str, obj);
|
|
||||||
appendStringInfoChar(str, '}');
|
|
||||||
break;
|
|
||||||
|
|
||||||
case T_MultiJoin:
|
|
||||||
appendStringInfoChar(str, '{');
|
|
||||||
OutMultiJoin(str, obj);
|
|
||||||
appendStringInfoChar(str, '}');
|
|
||||||
break;
|
|
||||||
|
|
||||||
case T_MultiPartition:
|
|
||||||
appendStringInfoChar(str, '{');
|
|
||||||
OutMultiPartition(str, obj);
|
|
||||||
appendStringInfoChar(str, '}');
|
|
||||||
break;
|
|
||||||
|
|
||||||
case T_MultiCartesianProduct:
|
|
||||||
appendStringInfoChar(str, '{');
|
|
||||||
OutMultiCartesianProduct(str, obj);
|
|
||||||
appendStringInfoChar(str, '}');
|
|
||||||
break;
|
|
||||||
|
|
||||||
case T_MultiExtendedOp:
|
|
||||||
appendStringInfoChar(str, '{');
|
|
||||||
OutMultiExtendedOp(str, obj);
|
|
||||||
appendStringInfoChar(str, '}');
|
|
||||||
break;
|
|
||||||
|
|
||||||
case T_Job:
|
|
||||||
appendStringInfoChar(str, '{');
|
|
||||||
OutJob(str, obj);
|
|
||||||
appendStringInfoChar(str, '}');
|
|
||||||
break;
|
|
||||||
|
|
||||||
case T_MapMergeJob:
|
|
||||||
appendStringInfoChar(str, '{');
|
|
||||||
OutMapMergeJob(str, obj);
|
|
||||||
appendStringInfoChar(str, '}');
|
|
||||||
break;
|
|
||||||
|
|
||||||
case T_MultiPlan:
|
|
||||||
appendStringInfoChar(str, '{');
|
|
||||||
OutMultiPlan(str, obj);
|
|
||||||
appendStringInfoChar(str, '}');
|
|
||||||
break;
|
|
||||||
|
|
||||||
case T_Task:
|
|
||||||
appendStringInfoChar(str, '{');
|
|
||||||
OutTask(str, obj);
|
|
||||||
appendStringInfoChar(str, '}');
|
|
||||||
break;
|
|
||||||
|
|
||||||
case T_ShardInterval:
|
|
||||||
appendStringInfoChar(str, '{');
|
|
||||||
OutShardInterval(str, obj);
|
|
||||||
appendStringInfoChar(str, '}');
|
|
||||||
break;
|
|
||||||
|
|
||||||
case T_ShardPlacement:
|
|
||||||
appendStringInfoChar(str, '{');
|
|
||||||
OutShardPlacement(str, obj);
|
|
||||||
appendStringInfoChar(str, '}');
|
|
||||||
break;
|
|
||||||
|
|
||||||
case T_RelationShard:
|
|
||||||
appendStringInfoChar(str, '{');
|
|
||||||
OutRelationShard(str, obj);
|
|
||||||
appendStringInfoChar(str, '}');
|
|
||||||
break;
|
|
||||||
|
|
||||||
case T_DeferredErrorMessage:
|
|
||||||
appendStringInfoChar(str, '{');
|
|
||||||
OutDeferredErrorMessage(str, obj);
|
|
||||||
appendStringInfoChar(str, '}');
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
/* fall back into postgres' normal nodeToString machinery */
|
|
||||||
appendStringInfoString(str, nodeToString(obj));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
* CitusNodeToString -
|
|
||||||
* returns the ascii representation of the Node as a palloc'd string
|
|
||||||
*/
|
|
||||||
char *
|
|
||||||
CitusNodeToString(const void *obj)
|
|
||||||
{
|
|
||||||
#if (PG_VERSION_NUM >= 90600)
|
|
||||||
return nodeToString(obj);
|
|
||||||
#else
|
|
||||||
StringInfoData str;
|
|
||||||
|
|
||||||
initStringInfo(&str);
|
|
||||||
outNode(&str, obj);
|
|
||||||
return str.data;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,379 +0,0 @@
|
||||||
/*-------------------------------------------------------------------------
|
|
||||||
*
|
|
||||||
* citus_read.c
|
|
||||||
* Citus version of postgres' read.c, using a different state variable for
|
|
||||||
* citus_pg_strtok.
|
|
||||||
*
|
|
||||||
* Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
|
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
|
||||||
* Portions Copyright (c) 2012-2016, Citus Data, Inc.
|
|
||||||
*
|
|
||||||
* NOTES
|
|
||||||
* Unfortunately we have to copy this file as the state variable for
|
|
||||||
* pg_strtok is not externally accessible. That prevents creating a a
|
|
||||||
* version of stringToNode() that calls CitusNodeRead() instead of
|
|
||||||
* nodeRead(). Luckily these functions seldomly change.
|
|
||||||
*
|
|
||||||
* Keep as closely aligned with the upstream version as possible.
|
|
||||||
*
|
|
||||||
*-------------------------------------------------------------------------
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "postgres.h"
|
|
||||||
|
|
||||||
#include <ctype.h>
|
|
||||||
|
|
||||||
#include "nodes/pg_list.h"
|
|
||||||
#include "nodes/readfuncs.h"
|
|
||||||
#include "distributed/citus_nodefuncs.h"
|
|
||||||
#include "nodes/value.h"
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* For 9.6 onwards, we use 9.6's extensible node system, thus there's no need
|
|
||||||
* to copy various routines anymore. In that case, replace these functions
|
|
||||||
* with plain wrappers.
|
|
||||||
*/
|
|
||||||
#if (PG_VERSION_NUM >= 90600)
|
|
||||||
|
|
||||||
void *
|
|
||||||
CitusStringToNode(char *str)
|
|
||||||
{
|
|
||||||
return stringToNode(str);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
char *
|
|
||||||
citus_pg_strtok(int *length)
|
|
||||||
{
|
|
||||||
return pg_strtok(length);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void *
|
|
||||||
CitusNodeRead(char *token, int tok_len)
|
|
||||||
{
|
|
||||||
return nodeRead(token, tok_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
/* Static state for citus_pg_strtok */
|
|
||||||
static char *citus_pg_strtok_ptr = NULL;
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* CitusStringToNode -
|
|
||||||
* returns a Node with a given legal ASCII representation
|
|
||||||
*/
|
|
||||||
void *
|
|
||||||
CitusStringToNode(char *str)
|
|
||||||
{
|
|
||||||
char *save_strtok;
|
|
||||||
void *retval;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* We save and restore the pre-existing state of citus_pg_strtok. This makes the
|
|
||||||
* world safe for re-entrant invocation of stringToNode, without incurring
|
|
||||||
* a lot of notational overhead by having to pass the next-character
|
|
||||||
* pointer around through all the readfuncs.c code.
|
|
||||||
*/
|
|
||||||
save_strtok = citus_pg_strtok_ptr;
|
|
||||||
|
|
||||||
citus_pg_strtok_ptr = str; /* point citus_pg_strtok at the string to read */
|
|
||||||
|
|
||||||
retval = CitusNodeRead(NULL, 0); /* do the reading */
|
|
||||||
|
|
||||||
citus_pg_strtok_ptr = save_strtok;
|
|
||||||
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* citus_pg_strtok is a copy of postgres' pg_strtok routine, referencing
|
|
||||||
* citus_pg_strtok_ptr instead of pg_strtok_ptr as state.
|
|
||||||
*/
|
|
||||||
char *
|
|
||||||
citus_pg_strtok(int *length)
|
|
||||||
{
|
|
||||||
char *local_str; /* working pointer to string */
|
|
||||||
char *ret_str; /* start of token to return */
|
|
||||||
|
|
||||||
local_str = citus_pg_strtok_ptr;
|
|
||||||
|
|
||||||
while (*local_str == ' ' || *local_str == '\n' || *local_str == '\t')
|
|
||||||
local_str++;
|
|
||||||
|
|
||||||
if (*local_str == '\0')
|
|
||||||
{
|
|
||||||
*length = 0;
|
|
||||||
citus_pg_strtok_ptr = local_str;
|
|
||||||
return NULL; /* no more tokens */
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Now pointing at start of next token.
|
|
||||||
*/
|
|
||||||
ret_str = local_str;
|
|
||||||
|
|
||||||
if (*local_str == '(' || *local_str == ')' ||
|
|
||||||
*local_str == '{' || *local_str == '}')
|
|
||||||
{
|
|
||||||
/* special 1-character token */
|
|
||||||
local_str++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* Normal token, possibly containing backslashes */
|
|
||||||
while (*local_str != '\0' &&
|
|
||||||
*local_str != ' ' && *local_str != '\n' &&
|
|
||||||
*local_str != '\t' &&
|
|
||||||
*local_str != '(' && *local_str != ')' &&
|
|
||||||
*local_str != '{' && *local_str != '}')
|
|
||||||
{
|
|
||||||
if (*local_str == '\\' && local_str[1] != '\0')
|
|
||||||
local_str += 2;
|
|
||||||
else
|
|
||||||
local_str++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*length = local_str - ret_str;
|
|
||||||
|
|
||||||
/* Recognize special case for "empty" token */
|
|
||||||
if (*length == 2 && ret_str[0] == '<' && ret_str[1] == '>')
|
|
||||||
*length = 0;
|
|
||||||
|
|
||||||
citus_pg_strtok_ptr = local_str;
|
|
||||||
|
|
||||||
return ret_str;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define RIGHT_PAREN (1000000 + 1)
|
|
||||||
#define LEFT_PAREN (1000000 + 2)
|
|
||||||
#define LEFT_BRACE (1000000 + 3)
|
|
||||||
#define OTHER_TOKEN (1000000 + 4)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* nodeTokenType -
|
|
||||||
* returns the type of the node token contained in token.
|
|
||||||
* It returns one of the following valid NodeTags:
|
|
||||||
* T_Integer, T_Float, T_String, T_BitString
|
|
||||||
* and some of its own:
|
|
||||||
* RIGHT_PAREN, LEFT_PAREN, LEFT_BRACE, OTHER_TOKEN
|
|
||||||
*
|
|
||||||
* Assumption: the ascii representation is legal
|
|
||||||
*/
|
|
||||||
static NodeTag
|
|
||||||
nodeTokenType(char *token, int length)
|
|
||||||
{
|
|
||||||
NodeTag retval;
|
|
||||||
char *numptr;
|
|
||||||
int numlen;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check if the token is a number
|
|
||||||
*/
|
|
||||||
numptr = token;
|
|
||||||
numlen = length;
|
|
||||||
if (*numptr == '+' || *numptr == '-')
|
|
||||||
numptr++, numlen--;
|
|
||||||
if ((numlen > 0 && isdigit((unsigned char) *numptr)) ||
|
|
||||||
(numlen > 1 && *numptr == '.' && isdigit((unsigned char) numptr[1])))
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Yes. Figure out whether it is integral or float; this requires
|
|
||||||
* both a syntax check and a range check. strtol() can do both for us.
|
|
||||||
* We know the token will end at a character that strtol will stop at,
|
|
||||||
* so we do not need to modify the string.
|
|
||||||
*/
|
|
||||||
long val;
|
|
||||||
char *endptr;
|
|
||||||
|
|
||||||
errno = 0;
|
|
||||||
val = strtol(token, &endptr, 10);
|
|
||||||
(void) val; /* avoid compiler warning if unused */
|
|
||||||
if (endptr != token + length || errno == ERANGE
|
|
||||||
#ifdef HAVE_LONG_INT_64
|
|
||||||
/* if long > 32 bits, check for overflow of int4 */
|
|
||||||
|| val != (long) ((int32) val)
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
return T_Float;
|
|
||||||
return T_Integer;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* these three cases do not need length checks, since citus_pg_strtok() will
|
|
||||||
* always treat them as single-byte tokens
|
|
||||||
*/
|
|
||||||
else if (*token == '(')
|
|
||||||
retval = LEFT_PAREN;
|
|
||||||
else if (*token == ')')
|
|
||||||
retval = RIGHT_PAREN;
|
|
||||||
else if (*token == '{')
|
|
||||||
retval = LEFT_BRACE;
|
|
||||||
else if (*token == '\"' && length > 1 && token[length - 1] == '\"')
|
|
||||||
retval = T_String;
|
|
||||||
else if (*token == 'b')
|
|
||||||
retval = T_BitString;
|
|
||||||
else
|
|
||||||
retval = OTHER_TOKEN;
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* CitusNodeRead is an adapted copy of postgres' nodeRead routine, using
|
|
||||||
* citus_pg_strtok_ptr instead of pg_strtok_ptr.
|
|
||||||
*/
|
|
||||||
void *
|
|
||||||
CitusNodeRead(char *token, int tok_len)
|
|
||||||
{
|
|
||||||
Node *result;
|
|
||||||
NodeTag type;
|
|
||||||
|
|
||||||
if (token == NULL) /* need to read a token? */
|
|
||||||
{
|
|
||||||
token = citus_pg_strtok(&tok_len);
|
|
||||||
|
|
||||||
if (token == NULL) /* end of input */
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
type = nodeTokenType(token, tok_len);
|
|
||||||
|
|
||||||
switch ((int) type)
|
|
||||||
{
|
|
||||||
case LEFT_BRACE:
|
|
||||||
result = CitusParseNodeString();
|
|
||||||
token = citus_pg_strtok(&tok_len);
|
|
||||||
if (token == NULL || token[0] != '}')
|
|
||||||
elog(ERROR, "did not find '}' at end of input node");
|
|
||||||
break;
|
|
||||||
case LEFT_PAREN:
|
|
||||||
{
|
|
||||||
List *l = NIL;
|
|
||||||
|
|
||||||
/*----------
|
|
||||||
* Could be an integer list: (i int int ...)
|
|
||||||
* or an OID list: (o int int ...)
|
|
||||||
* or a list of nodes/values: (node node ...)
|
|
||||||
*----------
|
|
||||||
*/
|
|
||||||
token = citus_pg_strtok(&tok_len);
|
|
||||||
if (token == NULL)
|
|
||||||
elog(ERROR, "unterminated List structure");
|
|
||||||
if (tok_len == 1 && token[0] == 'i')
|
|
||||||
{
|
|
||||||
/* List of integers */
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
int val;
|
|
||||||
char *endptr;
|
|
||||||
|
|
||||||
token = citus_pg_strtok(&tok_len);
|
|
||||||
if (token == NULL)
|
|
||||||
elog(ERROR, "unterminated List structure");
|
|
||||||
if (token[0] == ')')
|
|
||||||
break;
|
|
||||||
val = (int) strtol(token, &endptr, 10);
|
|
||||||
if (endptr != token + tok_len)
|
|
||||||
elog(ERROR, "unrecognized integer: \"%.*s\"",
|
|
||||||
tok_len, token);
|
|
||||||
l = lappend_int(l, val);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (tok_len == 1 && token[0] == 'o')
|
|
||||||
{
|
|
||||||
/* List of OIDs */
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
Oid val;
|
|
||||||
char *endptr;
|
|
||||||
|
|
||||||
token = citus_pg_strtok(&tok_len);
|
|
||||||
if (token == NULL)
|
|
||||||
elog(ERROR, "unterminated List structure");
|
|
||||||
if (token[0] == ')')
|
|
||||||
break;
|
|
||||||
val = (Oid) strtoul(token, &endptr, 10);
|
|
||||||
if (endptr != token + tok_len)
|
|
||||||
elog(ERROR, "unrecognized OID: \"%.*s\"",
|
|
||||||
tok_len, token);
|
|
||||||
l = lappend_oid(l, val);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* List of other node types */
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
/* We have already scanned next token... */
|
|
||||||
if (token[0] == ')')
|
|
||||||
break;
|
|
||||||
l = lappend(l, CitusNodeRead(token, tok_len));
|
|
||||||
token = citus_pg_strtok(&tok_len);
|
|
||||||
if (token == NULL)
|
|
||||||
elog(ERROR, "unterminated List structure");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result = (Node *) l;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case RIGHT_PAREN:
|
|
||||||
elog(ERROR, "unexpected right parenthesis");
|
|
||||||
result = NULL; /* keep compiler happy */
|
|
||||||
break;
|
|
||||||
case OTHER_TOKEN:
|
|
||||||
if (tok_len == 0)
|
|
||||||
{
|
|
||||||
/* must be "<>" --- represents a null pointer */
|
|
||||||
result = NULL;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
elog(ERROR, "unrecognized token: \"%.*s\"", tok_len, token);
|
|
||||||
result = NULL; /* keep compiler happy */
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case T_Integer:
|
|
||||||
|
|
||||||
/*
|
|
||||||
* we know that the token terminates on a char atol will stop at
|
|
||||||
*/
|
|
||||||
result = (Node *) makeInteger(atol(token));
|
|
||||||
break;
|
|
||||||
case T_Float:
|
|
||||||
{
|
|
||||||
char *fval = (char *) palloc(tok_len + 1);
|
|
||||||
|
|
||||||
memcpy(fval, token, tok_len);
|
|
||||||
fval[tok_len] = '\0';
|
|
||||||
result = (Node *) makeFloat(fval);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case T_String:
|
|
||||||
/* need to remove leading and trailing quotes, and backslashes */
|
|
||||||
result = (Node *) makeString(debackslash(token + 1, tok_len - 2));
|
|
||||||
break;
|
|
||||||
case T_BitString:
|
|
||||||
{
|
|
||||||
char *val = palloc(tok_len);
|
|
||||||
|
|
||||||
/* skip leading 'b' */
|
|
||||||
memcpy(val, token + 1, tok_len - 1);
|
|
||||||
val[tok_len - 1] = '\0';
|
|
||||||
result = (Node *) makeBitString(val);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
elog(ERROR, "unrecognized node type: %d", (int) type);
|
|
||||||
result = NULL; /* keep compiler happy */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (void *) result;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* (PG_VERSION_NUM < 90600) */
|
|
|
@ -29,7 +29,6 @@
|
||||||
|
|
||||||
/* Macros for declaring appropriate local variables */
|
/* Macros for declaring appropriate local variables */
|
||||||
/* A few guys need only local_node */
|
/* A few guys need only local_node */
|
||||||
#if (PG_VERSION_NUM >= 90600)
|
|
||||||
static inline Node *
|
static inline Node *
|
||||||
CitusSetTag(Node *node, int tag)
|
CitusSetTag(Node *node, int tag)
|
||||||
{
|
{
|
||||||
|
@ -42,12 +41,8 @@ CitusSetTag(Node *node, int tag)
|
||||||
/* *INDENT-OFF* */
|
/* *INDENT-OFF* */
|
||||||
#define READ_LOCALS_NO_FIELDS(nodeTypeName) \
|
#define READ_LOCALS_NO_FIELDS(nodeTypeName) \
|
||||||
nodeTypeName *local_node = (nodeTypeName *) CitusSetTag((Node *) node, T_##nodeTypeName)
|
nodeTypeName *local_node = (nodeTypeName *) CitusSetTag((Node *) node, T_##nodeTypeName)
|
||||||
#else
|
|
||||||
#define READ_LOCALS_NO_FIELDS(nodeTypeName) \
|
|
||||||
nodeTypeName *local_node = CitusMakeNode(nodeTypeName)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* And a few guys need only the citus_pg_strtok support fields */
|
/* And a few guys need only the pg_strtok support fields */
|
||||||
#define READ_TEMP_LOCALS() \
|
#define READ_TEMP_LOCALS() \
|
||||||
char *token; \
|
char *token; \
|
||||||
int length
|
int length
|
||||||
|
@ -59,80 +54,74 @@ CitusSetTag(Node *node, int tag)
|
||||||
|
|
||||||
/* Read an integer field (anything written as ":fldname %d") */
|
/* Read an integer field (anything written as ":fldname %d") */
|
||||||
#define READ_INT_FIELD(fldname) \
|
#define READ_INT_FIELD(fldname) \
|
||||||
token = citus_pg_strtok(&length); /* skip :fldname */ \
|
token = pg_strtok(&length); /* skip :fldname */ \
|
||||||
token = citus_pg_strtok(&length); /* get field value */ \
|
token = pg_strtok(&length); /* get field value */ \
|
||||||
local_node->fldname = atoi(token)
|
local_node->fldname = atoi(token)
|
||||||
|
|
||||||
/* Read an unsigned integer field (anything written as ":fldname %u") */
|
/* Read an unsigned integer field (anything written as ":fldname %u") */
|
||||||
#define READ_UINT_FIELD(fldname) \
|
#define READ_UINT_FIELD(fldname) \
|
||||||
token = citus_pg_strtok(&length); /* skip :fldname */ \
|
token = pg_strtok(&length); /* skip :fldname */ \
|
||||||
token = citus_pg_strtok(&length); /* get field value */ \
|
token = pg_strtok(&length); /* get field value */ \
|
||||||
local_node->fldname = atoui(token)
|
local_node->fldname = atoui(token)
|
||||||
|
|
||||||
/* XXX: CITUS Read an uint64 field (anything written as ":fldname %u") */
|
/* XXX: CITUS Read an uint64 field (anything written as ":fldname %u") */
|
||||||
#define READ_UINT64_FIELD(fldname) \
|
#define READ_UINT64_FIELD(fldname) \
|
||||||
token = citus_pg_strtok(&length); /* skip :fldname */ \
|
token = pg_strtok(&length); /* skip :fldname */ \
|
||||||
token = citus_pg_strtok(&length); /* get field value */ \
|
token = pg_strtok(&length); /* get field value */ \
|
||||||
local_node->fldname = atoull(token)
|
local_node->fldname = atoull(token)
|
||||||
|
|
||||||
/* Read an OID field (don't hard-wire assumption that OID is same as uint) */
|
/* Read an OID field (don't hard-wire assumption that OID is same as uint) */
|
||||||
#define READ_OID_FIELD(fldname) \
|
#define READ_OID_FIELD(fldname) \
|
||||||
token = citus_pg_strtok(&length); /* skip :fldname */ \
|
token = pg_strtok(&length); /* skip :fldname */ \
|
||||||
token = citus_pg_strtok(&length); /* get field value */ \
|
token = pg_strtok(&length); /* get field value */ \
|
||||||
local_node->fldname = atooid(token)
|
local_node->fldname = atooid(token)
|
||||||
|
|
||||||
/* Read a char field (ie, one ascii character) */
|
/* Read a char field (ie, one ascii character) */
|
||||||
#define READ_CHAR_FIELD(fldname) \
|
#define READ_CHAR_FIELD(fldname) \
|
||||||
token = citus_pg_strtok(&length); /* skip :fldname */ \
|
token = pg_strtok(&length); /* skip :fldname */ \
|
||||||
token = citus_pg_strtok(&length); /* get field value */ \
|
token = pg_strtok(&length); /* get field value */ \
|
||||||
local_node->fldname = token[0]
|
local_node->fldname = token[0]
|
||||||
|
|
||||||
/* Read an enumerated-type field that was written as an integer code */
|
/* Read an enumerated-type field that was written as an integer code */
|
||||||
#define READ_ENUM_FIELD(fldname, enumtype) \
|
#define READ_ENUM_FIELD(fldname, enumtype) \
|
||||||
token = citus_pg_strtok(&length); /* skip :fldname */ \
|
token = pg_strtok(&length); /* skip :fldname */ \
|
||||||
token = citus_pg_strtok(&length); /* get field value */ \
|
token = pg_strtok(&length); /* get field value */ \
|
||||||
local_node->fldname = (enumtype) atoi(token)
|
local_node->fldname = (enumtype) atoi(token)
|
||||||
|
|
||||||
/* Read a float field */
|
/* Read a float field */
|
||||||
#define READ_FLOAT_FIELD(fldname) \
|
#define READ_FLOAT_FIELD(fldname) \
|
||||||
token = citus_pg_strtok(&length); /* skip :fldname */ \
|
token = pg_strtok(&length); /* skip :fldname */ \
|
||||||
token = citus_pg_strtok(&length); /* get field value */ \
|
token = pg_strtok(&length); /* get field value */ \
|
||||||
local_node->fldname = atof(token)
|
local_node->fldname = atof(token)
|
||||||
|
|
||||||
/* Read a boolean field */
|
/* Read a boolean field */
|
||||||
#define READ_BOOL_FIELD(fldname) \
|
#define READ_BOOL_FIELD(fldname) \
|
||||||
token = citus_pg_strtok(&length); /* skip :fldname */ \
|
token = pg_strtok(&length); /* skip :fldname */ \
|
||||||
token = citus_pg_strtok(&length); /* get field value */ \
|
token = pg_strtok(&length); /* get field value */ \
|
||||||
local_node->fldname = strtobool(token)
|
local_node->fldname = strtobool(token)
|
||||||
|
|
||||||
/* Read a character-string field */
|
/* Read a character-string field */
|
||||||
#define READ_STRING_FIELD(fldname) \
|
#define READ_STRING_FIELD(fldname) \
|
||||||
token = citus_pg_strtok(&length); /* skip :fldname */ \
|
token = pg_strtok(&length); /* skip :fldname */ \
|
||||||
token = citus_pg_strtok(&length); /* get field value */ \
|
token = pg_strtok(&length); /* get field value */ \
|
||||||
local_node->fldname = nullable_string(token, length)
|
local_node->fldname = nullable_string(token, length)
|
||||||
|
|
||||||
/* Read a parse location field (and throw away the value, per notes above) */
|
/* Read a parse location field (and throw away the value, per notes above) */
|
||||||
#define READ_LOCATION_FIELD(fldname) \
|
#define READ_LOCATION_FIELD(fldname) \
|
||||||
token = citus_pg_strtok(&length); /* skip :fldname */ \
|
token = pg_strtok(&length); /* skip :fldname */ \
|
||||||
token = citus_pg_strtok(&length); /* get field value */ \
|
token = pg_strtok(&length); /* get field value */ \
|
||||||
(void) token; /* in case not used elsewhere */ \
|
(void) token; /* in case not used elsewhere */ \
|
||||||
local_node->fldname = -1 /* set field to "unknown" */
|
local_node->fldname = -1 /* set field to "unknown" */
|
||||||
|
|
||||||
/* Read a Node field XXX: Citus: replaced call to nodeRead with CitusNodeRead */
|
/* Read a Node field */
|
||||||
#define READ_NODE_FIELD(fldname) \
|
#define READ_NODE_FIELD(fldname) \
|
||||||
token = citus_pg_strtok(&length); /* skip :fldname */ \
|
token = pg_strtok(&length); /* skip :fldname */ \
|
||||||
(void) token; /* in case not used elsewhere */ \
|
(void) token; /* in case not used elsewhere */ \
|
||||||
local_node->fldname = CitusNodeRead(NULL, 0)
|
local_node->fldname = nodeRead(NULL, 0)
|
||||||
|
|
||||||
/* Routine exit */
|
/* Routine exit */
|
||||||
#if (PG_VERSION_NUM >= 90600)
|
|
||||||
#define READ_DONE() \
|
#define READ_DONE() \
|
||||||
return;
|
return;
|
||||||
#else
|
|
||||||
#define READ_DONE() \
|
|
||||||
return (Node *) local_node
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NOTE: use atoi() to read values written with %d, or atoui() to read
|
* NOTE: use atoi() to read values written with %d, or atoui() to read
|
||||||
|
@ -214,15 +203,15 @@ ReadShardInterval(READFUNC_ARGS)
|
||||||
READ_BOOL_FIELD(minValueExists);
|
READ_BOOL_FIELD(minValueExists);
|
||||||
READ_BOOL_FIELD(maxValueExists);
|
READ_BOOL_FIELD(maxValueExists);
|
||||||
|
|
||||||
token = citus_pg_strtok(&length); /* skip :minValue */
|
token = pg_strtok(&length); /* skip :minValue */
|
||||||
if (!local_node->minValueExists)
|
if (!local_node->minValueExists)
|
||||||
token = citus_pg_strtok(&length); /* skip "<>" */
|
token = pg_strtok(&length); /* skip "<>" */
|
||||||
else
|
else
|
||||||
local_node->minValue = readDatum(local_node->valueByVal);
|
local_node->minValue = readDatum(local_node->valueByVal);
|
||||||
|
|
||||||
token = citus_pg_strtok(&length); /* skip :maxValue */
|
token = pg_strtok(&length); /* skip :maxValue */
|
||||||
if (!local_node->minValueExists)
|
if (!local_node->minValueExists)
|
||||||
token = citus_pg_strtok(&length); /* skip "<>" */
|
token = pg_strtok(&length); /* skip "<>" */
|
||||||
else
|
else
|
||||||
local_node->maxValue = readDatum(local_node->valueByVal);
|
local_node->maxValue = readDatum(local_node->valueByVal);
|
||||||
|
|
||||||
|
@ -257,7 +246,7 @@ ReadMapMergeJob(READFUNC_ARGS)
|
||||||
for (i = 0; i < arrayLength; ++i)
|
for (i = 0; i < arrayLength; ++i)
|
||||||
{
|
{
|
||||||
/* can't use READ_NODE_FIELD, no field names */
|
/* can't use READ_NODE_FIELD, no field names */
|
||||||
local_node->sortedShardIntervalArray[i] = CitusNodeRead(NULL, 0);
|
local_node->sortedShardIntervalArray[i] = nodeRead(NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
READ_NODE_FIELD(mapTaskList);
|
READ_NODE_FIELD(mapTaskList);
|
||||||
|
@ -347,86 +336,3 @@ ReadUnsupportedCitusNode(READFUNC_ARGS)
|
||||||
{
|
{
|
||||||
ereport(ERROR, (errmsg("not implemented")));
|
ereport(ERROR, (errmsg("not implemented")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if (PG_VERSION_NUM < 90600)
|
|
||||||
|
|
||||||
/*
|
|
||||||
* readDatum
|
|
||||||
*
|
|
||||||
* Given a string representation of a constant, recreate the appropriate
|
|
||||||
* Datum. The string representation embeds length info, but not byValue,
|
|
||||||
* so we must be told that.
|
|
||||||
*/
|
|
||||||
Datum
|
|
||||||
readDatum(bool typbyval)
|
|
||||||
{
|
|
||||||
Size length,
|
|
||||||
i;
|
|
||||||
int tokenLength;
|
|
||||||
char *token;
|
|
||||||
Datum res;
|
|
||||||
char *s;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* read the actual length of the value
|
|
||||||
*/
|
|
||||||
token = citus_pg_strtok(&tokenLength);
|
|
||||||
length = atoui(token);
|
|
||||||
|
|
||||||
token = citus_pg_strtok(&tokenLength); /* read the '[' */
|
|
||||||
if (token == NULL || token[0] != '[')
|
|
||||||
elog(ERROR, "expected \"[\" to start datum, but got \"%s\"; length = %zu",
|
|
||||||
token ? (const char *) token : "[NULL]", length);
|
|
||||||
|
|
||||||
if (typbyval)
|
|
||||||
{
|
|
||||||
if (length > (Size) sizeof(Datum))
|
|
||||||
elog(ERROR, "byval datum but length = %zu", length);
|
|
||||||
res = (Datum) 0;
|
|
||||||
s = (char *) (&res);
|
|
||||||
for (i = 0; i < (Size) sizeof(Datum); i++)
|
|
||||||
{
|
|
||||||
token = citus_pg_strtok(&tokenLength);
|
|
||||||
s[i] = (char) atoi(token);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (length <= 0)
|
|
||||||
res = (Datum) NULL;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
s = (char *) palloc(length);
|
|
||||||
for (i = 0; i < length; i++)
|
|
||||||
{
|
|
||||||
token = citus_pg_strtok(&tokenLength);
|
|
||||||
s[i] = (char) atoi(token);
|
|
||||||
}
|
|
||||||
res = PointerGetDatum(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
token = citus_pg_strtok(&tokenLength); /* read the ']' */
|
|
||||||
if (token == NULL || token[0] != ']')
|
|
||||||
elog(ERROR, "expected \"]\" to end datum, but got \"%s\"; length = %zu",
|
|
||||||
token ? (const char *) token : "[NULL]", length);
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
#if (PG_VERSION_NUM >= 90600)
|
|
||||||
|
|
||||||
/* *INDENT-ON* */
|
|
||||||
|
|
||||||
/*
|
|
||||||
* For 9.6+ we can just use the, now extensible, parseNodeString(). Before
|
|
||||||
* that citus_readfuncs_$ver.c has a version specific implementation.
|
|
||||||
*/
|
|
||||||
Node *
|
|
||||||
CitusParseNodeString(void)
|
|
||||||
{
|
|
||||||
return parseNodeString();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -14,11 +14,7 @@
|
||||||
#include "access/htup.h"
|
#include "access/htup.h"
|
||||||
#include "access/htup_details.h"
|
#include "access/htup_details.h"
|
||||||
#include "access/skey.h"
|
#include "access/skey.h"
|
||||||
#if (PG_VERSION_NUM >= 90500 && PG_VERSION_NUM < 90600)
|
|
||||||
#include "access/stratnum.h"
|
|
||||||
#else
|
|
||||||
#include "access/skey.h"
|
#include "access/skey.h"
|
||||||
#endif
|
|
||||||
#include "access/tupmacs.h"
|
#include "access/tupmacs.h"
|
||||||
#include "access/xact.h"
|
#include "access/xact.h"
|
||||||
#include "catalog/indexing.h"
|
#include "catalog/indexing.h"
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -27,18 +27,6 @@ extern void ExtractRangeTblExtraData(RangeTblEntry *rte, CitusRTEKind *rteKind,
|
||||||
List **tableIdList);
|
List **tableIdList);
|
||||||
extern CitusRTEKind GetRangeTblKind(RangeTblEntry *rte);
|
extern CitusRTEKind GetRangeTblKind(RangeTblEntry *rte);
|
||||||
|
|
||||||
/* citus_outfuncs.c */
|
|
||||||
extern char * CitusNodeToString(const void *obj);
|
|
||||||
|
|
||||||
/* citus_read.c */
|
|
||||||
extern void * CitusStringToNode(char *str);
|
|
||||||
extern char * citus_pg_strtok(int *length);
|
|
||||||
extern void * CitusNodeRead(char *token, int tok_len);
|
|
||||||
|
|
||||||
/* citus_readfuncs.c */
|
|
||||||
extern Node * CitusParseNodeString(void);
|
|
||||||
extern Datum readDatum(bool typbyval);
|
|
||||||
|
|
||||||
extern void RegisterNodes(void);
|
extern void RegisterNodes(void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -47,19 +35,10 @@ extern void RegisterNodes(void);
|
||||||
* different from before.
|
* different from before.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if (PG_VERSION_NUM >= 90600)
|
|
||||||
#define READFUNC_ARGS struct ExtensibleNode *node
|
#define READFUNC_ARGS struct ExtensibleNode *node
|
||||||
#define READFUNC_RET void
|
#define READFUNC_RET void
|
||||||
#else
|
|
||||||
#define READFUNC_ARGS void
|
|
||||||
#define READFUNC_RET Node *
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (PG_VERSION_NUM >= 90600)
|
|
||||||
#define OUTFUNC_ARGS StringInfo str, const struct ExtensibleNode *raw_node
|
#define OUTFUNC_ARGS StringInfo str, const struct ExtensibleNode *raw_node
|
||||||
#else
|
|
||||||
#define OUTFUNC_ARGS StringInfo str, const Node *raw_node
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern READFUNC_RET ReadJob(READFUNC_ARGS);
|
extern READFUNC_RET ReadJob(READFUNC_ARGS);
|
||||||
extern READFUNC_RET ReadMultiPlan(READFUNC_ARGS);
|
extern READFUNC_RET ReadMultiPlan(READFUNC_ARGS);
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#ifndef CITUS_NODES_H
|
#ifndef CITUS_NODES_H
|
||||||
#define CITUS_NODES_H
|
#define CITUS_NODES_H
|
||||||
|
|
||||||
|
#include "nodes/extensible.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Citus Node Tags
|
* Citus Node Tags
|
||||||
|
@ -63,9 +64,6 @@ typedef enum CitusNodeTag
|
||||||
|
|
||||||
const char** CitusNodeTagNames;
|
const char** CitusNodeTagNames;
|
||||||
|
|
||||||
#if (PG_VERSION_NUM >= 90600)
|
|
||||||
|
|
||||||
#include "nodes/extensible.h"
|
|
||||||
|
|
||||||
typedef struct CitusNode
|
typedef struct CitusNode
|
||||||
{
|
{
|
||||||
|
@ -98,30 +96,6 @@ CitusNodeTagI(Node *node)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
#include "nodes/nodes.h"
|
|
||||||
|
|
||||||
typedef CitusNodeTag CitusNode;
|
|
||||||
/*
|
|
||||||
* nodeTag equivalent that returns the node tag for both citus and postgres
|
|
||||||
* node tag types. Needs to return int as there's no type that covers both
|
|
||||||
* postgres and citus node values.
|
|
||||||
*/
|
|
||||||
#define CitusNodeTag(nodeptr) (*((const int*)(nodeptr)))
|
|
||||||
|
|
||||||
|
|
||||||
/* Citus variant of newNode(), don't use directly. */
|
|
||||||
#define CitusNewNode(size, tag) \
|
|
||||||
({ Node *_result; \
|
|
||||||
AssertMacro((size) >= sizeof(Node)); /* need the tag, at least */ \
|
|
||||||
_result = (Node *) palloc0fast(size); \
|
|
||||||
_result->type = (int) (tag); \
|
|
||||||
_result; \
|
|
||||||
})
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* IsA equivalent that compares node tags, including Citus-specific nodes.
|
* IsA equivalent that compares node tags, including Citus-specific nodes.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -18,13 +18,6 @@
|
||||||
#include "distributed/multi_server_executor.h"
|
#include "distributed/multi_server_executor.h"
|
||||||
|
|
||||||
|
|
||||||
#if (PG_VERSION_NUM >= 90600)
|
|
||||||
#define tuplecount_t uint64
|
|
||||||
#else
|
|
||||||
#define tuplecount_t long
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct CitusScanState
|
typedef struct CitusScanState
|
||||||
{
|
{
|
||||||
CustomScanState customScanState; /* underlying custom scan node */
|
CustomScanState customScanState; /* underlying custom scan node */
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -2,13 +2,6 @@
|
||||||
-- MULTI_JOIN_ORDER_ADDITIONAL
|
-- MULTI_JOIN_ORDER_ADDITIONAL
|
||||||
--
|
--
|
||||||
ALTER SEQUENCE pg_catalog.pg_dist_shardid_seq RESTART 650000;
|
ALTER SEQUENCE pg_catalog.pg_dist_shardid_seq RESTART 650000;
|
||||||
-- print whether we're running on 9.5 to make version-specific tests clear
|
|
||||||
SELECT substring(version(), '\d+(?:\.\d+)?') = '9.5' AS is_95;
|
|
||||||
is_95
|
|
||||||
-------
|
|
||||||
f
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- Set configuration to print table join order and pruned shards
|
-- Set configuration to print table join order and pruned shards
|
||||||
SET citus.explain_distributed_queries TO off;
|
SET citus.explain_distributed_queries TO off;
|
||||||
SET citus.log_multi_join_order TO TRUE;
|
SET citus.log_multi_join_order TO TRUE;
|
||||||
|
|
|
@ -1,260 +0,0 @@
|
||||||
--
|
|
||||||
-- MULTI_JOIN_ORDER_ADDITIONAL
|
|
||||||
--
|
|
||||||
ALTER SEQUENCE pg_catalog.pg_dist_shardid_seq RESTART 650000;
|
|
||||||
-- print whether we're running on 9.5 to make version-specific tests clear
|
|
||||||
SELECT substring(version(), '\d+(?:\.\d+)?') = '9.5' AS is_95;
|
|
||||||
is_95
|
|
||||||
-------
|
|
||||||
t
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- Set configuration to print table join order and pruned shards
|
|
||||||
SET citus.explain_distributed_queries TO off;
|
|
||||||
SET citus.log_multi_join_order TO TRUE;
|
|
||||||
SET citus.task_executor_type = 'task-tracker'; -- can't explain all queries otherwise
|
|
||||||
SET client_min_messages TO DEBUG2;
|
|
||||||
-- Create new table definitions for use in testing in distributed planning and
|
|
||||||
-- execution functionality. Also create indexes to boost performance.
|
|
||||||
CREATE TABLE lineitem_hash (
|
|
||||||
l_orderkey bigint not null,
|
|
||||||
l_partkey integer not null,
|
|
||||||
l_suppkey integer not null,
|
|
||||||
l_linenumber integer not null,
|
|
||||||
l_quantity decimal(15, 2) not null,
|
|
||||||
l_extendedprice decimal(15, 2) not null,
|
|
||||||
l_discount decimal(15, 2) not null,
|
|
||||||
l_tax decimal(15, 2) not null,
|
|
||||||
l_returnflag char(1) not null,
|
|
||||||
l_linestatus char(1) not null,
|
|
||||||
l_shipdate date not null,
|
|
||||||
l_commitdate date not null,
|
|
||||||
l_receiptdate date not null,
|
|
||||||
l_shipinstruct char(25) not null,
|
|
||||||
l_shipmode char(10) not null,
|
|
||||||
l_comment varchar(44) not null,
|
|
||||||
PRIMARY KEY(l_orderkey, l_linenumber) );
|
|
||||||
DEBUG: CREATE TABLE / PRIMARY KEY will create implicit index "lineitem_hash_pkey" for table "lineitem_hash"
|
|
||||||
DEBUG: building index "lineitem_hash_pkey" on table "lineitem_hash"
|
|
||||||
DEBUG: creating and filling new WAL file
|
|
||||||
DEBUG: done creating and filling new WAL file
|
|
||||||
SELECT master_create_distributed_table('lineitem_hash', 'l_orderkey', 'hash');
|
|
||||||
master_create_distributed_table
|
|
||||||
---------------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT master_create_worker_shards('lineitem_hash', 2, 1);
|
|
||||||
master_create_worker_shards
|
|
||||||
-----------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
CREATE INDEX lineitem_hash_time_index ON lineitem_hash (l_shipdate);
|
|
||||||
DEBUG: building index "lineitem_hash_time_index" on table "lineitem_hash"
|
|
||||||
NOTICE: using one-phase commit for distributed DDL commands
|
|
||||||
HINT: You can enable two-phase commit for extra safety with: SET citus.multi_shard_commit_protocol TO '2pc'
|
|
||||||
CREATE TABLE orders_hash (
|
|
||||||
o_orderkey bigint not null,
|
|
||||||
o_custkey integer not null,
|
|
||||||
o_orderstatus char(1) not null,
|
|
||||||
o_totalprice decimal(15,2) not null,
|
|
||||||
o_orderdate date not null,
|
|
||||||
o_orderpriority char(15) not null,
|
|
||||||
o_clerk char(15) not null,
|
|
||||||
o_shippriority integer not null,
|
|
||||||
o_comment varchar(79) not null,
|
|
||||||
PRIMARY KEY(o_orderkey) );
|
|
||||||
DEBUG: CREATE TABLE / PRIMARY KEY will create implicit index "orders_hash_pkey" for table "orders_hash"
|
|
||||||
DEBUG: building index "orders_hash_pkey" on table "orders_hash"
|
|
||||||
SELECT master_create_distributed_table('orders_hash', 'o_orderkey', 'hash');
|
|
||||||
master_create_distributed_table
|
|
||||||
---------------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT master_create_worker_shards('orders_hash', 2, 1);
|
|
||||||
master_create_worker_shards
|
|
||||||
-----------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
CREATE TABLE customer_hash (
|
|
||||||
c_custkey integer not null,
|
|
||||||
c_name varchar(25) not null,
|
|
||||||
c_address varchar(40) not null,
|
|
||||||
c_nationkey integer not null,
|
|
||||||
c_phone char(15) not null,
|
|
||||||
c_acctbal decimal(15,2) not null,
|
|
||||||
c_mktsegment char(10) not null,
|
|
||||||
c_comment varchar(117) not null);
|
|
||||||
SELECT master_create_distributed_table('customer_hash', 'c_custkey', 'hash');
|
|
||||||
master_create_distributed_table
|
|
||||||
---------------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
SELECT master_create_worker_shards('customer_hash', 2, 1);
|
|
||||||
master_create_worker_shards
|
|
||||||
-----------------------------
|
|
||||||
|
|
||||||
(1 row)
|
|
||||||
|
|
||||||
-- The following query checks that we can correctly handle self-joins
|
|
||||||
EXPLAIN SELECT l1.l_quantity FROM lineitem l1, lineitem l2
|
|
||||||
WHERE l1.l_orderkey = l2.l_orderkey AND l1.l_quantity > 5;
|
|
||||||
LOG: join order: [ "lineitem" ][ local partition join "lineitem" ]
|
|
||||||
DEBUG: join prunable for intervals [1,1509] and [2951,4455]
|
|
||||||
DEBUG: join prunable for intervals [1,1509] and [4480,5986]
|
|
||||||
DEBUG: join prunable for intervals [1,1509] and [8997,10560]
|
|
||||||
DEBUG: join prunable for intervals [1,1509] and [10560,12036]
|
|
||||||
DEBUG: join prunable for intervals [1,1509] and [12036,13473]
|
|
||||||
DEBUG: join prunable for intervals [1,1509] and [13473,14947]
|
|
||||||
DEBUG: join prunable for intervals [1509,4964] and [8997,10560]
|
|
||||||
DEBUG: join prunable for intervals [1509,4964] and [10560,12036]
|
|
||||||
DEBUG: join prunable for intervals [1509,4964] and [12036,13473]
|
|
||||||
DEBUG: join prunable for intervals [1509,4964] and [13473,14947]
|
|
||||||
DEBUG: join prunable for intervals [2951,4455] and [1,1509]
|
|
||||||
DEBUG: join prunable for intervals [2951,4455] and [4480,5986]
|
|
||||||
DEBUG: join prunable for intervals [2951,4455] and [8997,10560]
|
|
||||||
DEBUG: join prunable for intervals [2951,4455] and [10560,12036]
|
|
||||||
DEBUG: join prunable for intervals [2951,4455] and [12036,13473]
|
|
||||||
DEBUG: join prunable for intervals [2951,4455] and [13473,14947]
|
|
||||||
DEBUG: join prunable for intervals [4480,5986] and [1,1509]
|
|
||||||
DEBUG: join prunable for intervals [4480,5986] and [2951,4455]
|
|
||||||
DEBUG: join prunable for intervals [4480,5986] and [8997,10560]
|
|
||||||
DEBUG: join prunable for intervals [4480,5986] and [10560,12036]
|
|
||||||
DEBUG: join prunable for intervals [4480,5986] and [12036,13473]
|
|
||||||
DEBUG: join prunable for intervals [4480,5986] and [13473,14947]
|
|
||||||
DEBUG: join prunable for intervals [8997,10560] and [1,1509]
|
|
||||||
DEBUG: join prunable for intervals [8997,10560] and [1509,4964]
|
|
||||||
DEBUG: join prunable for intervals [8997,10560] and [2951,4455]
|
|
||||||
DEBUG: join prunable for intervals [8997,10560] and [4480,5986]
|
|
||||||
DEBUG: join prunable for intervals [8997,10560] and [12036,13473]
|
|
||||||
DEBUG: join prunable for intervals [8997,10560] and [13473,14947]
|
|
||||||
DEBUG: join prunable for intervals [10560,12036] and [1,1509]
|
|
||||||
DEBUG: join prunable for intervals [10560,12036] and [1509,4964]
|
|
||||||
DEBUG: join prunable for intervals [10560,12036] and [2951,4455]
|
|
||||||
DEBUG: join prunable for intervals [10560,12036] and [4480,5986]
|
|
||||||
DEBUG: join prunable for intervals [10560,12036] and [13473,14947]
|
|
||||||
DEBUG: join prunable for intervals [12036,13473] and [1,1509]
|
|
||||||
DEBUG: join prunable for intervals [12036,13473] and [1509,4964]
|
|
||||||
DEBUG: join prunable for intervals [12036,13473] and [2951,4455]
|
|
||||||
DEBUG: join prunable for intervals [12036,13473] and [4480,5986]
|
|
||||||
DEBUG: join prunable for intervals [12036,13473] and [8997,10560]
|
|
||||||
DEBUG: join prunable for intervals [13473,14947] and [1,1509]
|
|
||||||
DEBUG: join prunable for intervals [13473,14947] and [1509,4964]
|
|
||||||
DEBUG: join prunable for intervals [13473,14947] and [2951,4455]
|
|
||||||
DEBUG: join prunable for intervals [13473,14947] and [4480,5986]
|
|
||||||
DEBUG: join prunable for intervals [13473,14947] and [8997,10560]
|
|
||||||
DEBUG: join prunable for intervals [13473,14947] and [10560,12036]
|
|
||||||
QUERY PLAN
|
|
||||||
--------------------------------------------------------------------
|
|
||||||
Custom Scan (Citus Task-Tracker) (cost=0.00..0.00 rows=0 width=0)
|
|
||||||
explain statements for distributed queries are not enabled
|
|
||||||
(2 rows)
|
|
||||||
|
|
||||||
-- Update configuration to treat lineitem and orders tables as large
|
|
||||||
SET citus.large_table_shard_count TO 2;
|
|
||||||
SET client_min_messages TO LOG;
|
|
||||||
-- The following queries check that we correctly handle joins and OR clauses. In
|
|
||||||
-- particular, these queries check that we factorize out OR clauses if possible,
|
|
||||||
-- and that we default to a cartesian product otherwise.
|
|
||||||
EXPLAIN SELECT count(*) FROM lineitem, orders
|
|
||||||
WHERE (l_orderkey = o_orderkey AND l_quantity > 5)
|
|
||||||
OR (l_orderkey = o_orderkey AND l_quantity < 10);
|
|
||||||
LOG: join order: [ "lineitem" ][ local partition join "orders" ]
|
|
||||||
QUERY PLAN
|
|
||||||
--------------------------------------------------------------------------
|
|
||||||
Aggregate (cost=0.00..0.00 rows=0 width=0)
|
|
||||||
-> Custom Scan (Citus Task-Tracker) (cost=0.00..0.00 rows=0 width=0)
|
|
||||||
explain statements for distributed queries are not enabled
|
|
||||||
(3 rows)
|
|
||||||
|
|
||||||
EXPLAIN SELECT l_quantity FROM lineitem, orders
|
|
||||||
WHERE (l_orderkey = o_orderkey OR l_quantity > 5);
|
|
||||||
LOG: join order: [ "lineitem" ][ cartesian product "orders" ]
|
|
||||||
ERROR: cannot perform distributed planning on this query
|
|
||||||
DETAIL: Cartesian products are currently unsupported
|
|
||||||
-- The below queries modify the partition method in pg_dist_partition. We thus
|
|
||||||
-- begin a transaction here so the changes don't impact any other parallel
|
|
||||||
-- running tests.
|
|
||||||
BEGIN;
|
|
||||||
-- Validate that we take into account the partition method when building the
|
|
||||||
-- join-order plan.
|
|
||||||
EXPLAIN SELECT count(*) FROM orders, lineitem_hash
|
|
||||||
WHERE o_orderkey = l_orderkey;
|
|
||||||
LOG: join order: [ "orders" ][ single partition join "lineitem_hash" ]
|
|
||||||
QUERY PLAN
|
|
||||||
--------------------------------------------------------------------------
|
|
||||||
Aggregate (cost=0.00..0.00 rows=0 width=0)
|
|
||||||
-> Custom Scan (Citus Task-Tracker) (cost=0.00..0.00 rows=0 width=0)
|
|
||||||
explain statements for distributed queries are not enabled
|
|
||||||
(3 rows)
|
|
||||||
|
|
||||||
-- Verify we handle local joins between two hash-partitioned tables.
|
|
||||||
EXPLAIN SELECT count(*) FROM orders_hash, lineitem_hash
|
|
||||||
WHERE o_orderkey = l_orderkey;
|
|
||||||
LOG: join order: [ "orders_hash" ][ local partition join "lineitem_hash" ]
|
|
||||||
QUERY PLAN
|
|
||||||
--------------------------------------------------------------------------
|
|
||||||
Aggregate (cost=0.00..0.00 rows=0 width=0)
|
|
||||||
-> Custom Scan (Citus Task-Tracker) (cost=0.00..0.00 rows=0 width=0)
|
|
||||||
explain statements for distributed queries are not enabled
|
|
||||||
(3 rows)
|
|
||||||
|
|
||||||
-- Validate that we can handle broadcast joins with hash-partitioned tables.
|
|
||||||
EXPLAIN SELECT count(*) FROM customer_hash, nation
|
|
||||||
WHERE c_nationkey = n_nationkey;
|
|
||||||
LOG: join order: [ "customer_hash" ][ broadcast join "nation" ]
|
|
||||||
QUERY PLAN
|
|
||||||
--------------------------------------------------------------------------
|
|
||||||
Aggregate (cost=0.00..0.00 rows=0 width=0)
|
|
||||||
-> Custom Scan (Citus Task-Tracker) (cost=0.00..0.00 rows=0 width=0)
|
|
||||||
explain statements for distributed queries are not enabled
|
|
||||||
(3 rows)
|
|
||||||
|
|
||||||
-- Update the large table shard count for all the following tests.
|
|
||||||
SET citus.large_table_shard_count TO 1;
|
|
||||||
-- Validate that we don't use a single-partition join method for a hash
|
|
||||||
-- re-partitioned table, thus preventing a partition of just the customer table.
|
|
||||||
EXPLAIN SELECT count(*) FROM orders, lineitem, customer
|
|
||||||
WHERE o_custkey = l_partkey AND o_custkey = c_nationkey;
|
|
||||||
LOG: join order: [ "orders" ][ dual partition join "lineitem" ][ dual partition join "customer" ]
|
|
||||||
QUERY PLAN
|
|
||||||
--------------------------------------------------------------------------
|
|
||||||
Aggregate (cost=0.00..0.00 rows=0 width=0)
|
|
||||||
-> Custom Scan (Citus Task-Tracker) (cost=0.00..0.00 rows=0 width=0)
|
|
||||||
explain statements for distributed queries are not enabled
|
|
||||||
(3 rows)
|
|
||||||
|
|
||||||
-- Validate that we don't chose a single-partition join method with a
|
|
||||||
-- hash-partitioned base table
|
|
||||||
EXPLAIN SELECT count(*) FROM orders, customer_hash
|
|
||||||
WHERE c_custkey = o_custkey;
|
|
||||||
LOG: join order: [ "orders" ][ dual partition join "customer_hash" ]
|
|
||||||
QUERY PLAN
|
|
||||||
--------------------------------------------------------------------------
|
|
||||||
Aggregate (cost=0.00..0.00 rows=0 width=0)
|
|
||||||
-> Custom Scan (Citus Task-Tracker) (cost=0.00..0.00 rows=0 width=0)
|
|
||||||
explain statements for distributed queries are not enabled
|
|
||||||
(3 rows)
|
|
||||||
|
|
||||||
-- Validate that we can re-partition a hash partitioned table to join with a
|
|
||||||
-- range partitioned one.
|
|
||||||
EXPLAIN SELECT count(*) FROM orders_hash, customer
|
|
||||||
WHERE c_custkey = o_custkey;
|
|
||||||
LOG: join order: [ "orders_hash" ][ single partition join "customer" ]
|
|
||||||
QUERY PLAN
|
|
||||||
--------------------------------------------------------------------------
|
|
||||||
Aggregate (cost=0.00..0.00 rows=0 width=0)
|
|
||||||
-> Custom Scan (Citus Task-Tracker) (cost=0.00..0.00 rows=0 width=0)
|
|
||||||
explain statements for distributed queries are not enabled
|
|
||||||
(3 rows)
|
|
||||||
|
|
||||||
COMMIT;
|
|
||||||
-- Reset client logging level to its previous value
|
|
||||||
SET client_min_messages TO NOTICE;
|
|
||||||
DROP TABLE lineitem_hash;
|
|
||||||
DROP TABLE orders_hash;
|
|
||||||
DROP TABLE customer_hash;
|
|
|
@ -7,7 +7,7 @@
|
||||||
#
|
#
|
||||||
# Note that we use variant comparison files to test version dependent regression
|
# Note that we use variant comparison files to test version dependent regression
|
||||||
# test results. For more information:
|
# test results. For more information:
|
||||||
# http://www.postgresql.org/docs/9.5/static/regress-variant.html
|
# http://www.postgresql.org/docs/current/static/regress-variant.html
|
||||||
# ----------
|
# ----------
|
||||||
|
|
||||||
# ---
|
# ---
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
#
|
#
|
||||||
# Note that we use variant comparison files to test version dependent regression
|
# Note that we use variant comparison files to test version dependent regression
|
||||||
# test results. For more information:
|
# test results. For more information:
|
||||||
# http://www.postgresql.org/docs/9.5/static/regress-variant.html
|
# http://www.postgresql.org/docs/current/static/regress-variant.html
|
||||||
# ----------
|
# ----------
|
||||||
|
|
||||||
# ---
|
# ---
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
#
|
#
|
||||||
# Note that we use variant comparison files to test version dependent regression
|
# Note that we use variant comparison files to test version dependent regression
|
||||||
# test results. For more information:
|
# test results. For more information:
|
||||||
# http://www.postgresql.org/docs/9.5/static/regress-variant.html
|
# http://www.postgresql.org/docs/current/static/regress-variant.html
|
||||||
# ----------
|
# ----------
|
||||||
|
|
||||||
# ---
|
# ---
|
||||||
|
|
|
@ -436,18 +436,10 @@ for my $port (@workerPorts)
|
||||||
my @arguments = (
|
my @arguments = (
|
||||||
"--host", $host,
|
"--host", $host,
|
||||||
'--port', $masterPort,
|
'--port', $masterPort,
|
||||||
'--user', $user
|
'--user', $user,
|
||||||
|
'--bindir', "tmp_check/tmp-bin"
|
||||||
);
|
);
|
||||||
|
|
||||||
if ($majorversion eq '9.5' || $majorversion eq '9.6' || $majorversion eq '10')
|
|
||||||
{
|
|
||||||
push(@arguments, '--bindir', "tmp_check/tmp-bin");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
die "Citus is not compatible with the detected PostgreSQL version $majorversion";
|
|
||||||
}
|
|
||||||
|
|
||||||
# Add load extension parameters to the argument list
|
# Add load extension parameters to the argument list
|
||||||
for my $extension (@extensions)
|
for my $extension (@extensions)
|
||||||
{
|
{
|
||||||
|
|
|
@ -5,9 +5,6 @@
|
||||||
|
|
||||||
ALTER SEQUENCE pg_catalog.pg_dist_shardid_seq RESTART 650000;
|
ALTER SEQUENCE pg_catalog.pg_dist_shardid_seq RESTART 650000;
|
||||||
|
|
||||||
-- print whether we're running on 9.5 to make version-specific tests clear
|
|
||||||
SELECT substring(version(), '\d+(?:\.\d+)?') = '9.5' AS is_95;
|
|
||||||
|
|
||||||
-- Set configuration to print table join order and pruned shards
|
-- Set configuration to print table join order and pruned shards
|
||||||
|
|
||||||
SET citus.explain_distributed_queries TO off;
|
SET citus.explain_distributed_queries TO off;
|
||||||
|
|
Loading…
Reference in New Issue