-
Notifications
You must be signed in to change notification settings - Fork 68
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature issue#16 #73
Feature issue#16 #73
Changes from 9 commits
e17fbbd
20b17d6
b62f9f8
952b980
abbd49b
9621c5b
941a0e3
c469f82
cffe56e
ea5154f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,6 +21,7 @@ | |
#include "create_shards.h" | ||
#include "ddl_commands.h" | ||
#include "distribution_metadata.h" | ||
#include "prune_shard_list.h" | ||
|
||
#include <ctype.h> | ||
#include <limits.h> | ||
|
@@ -29,8 +30,13 @@ | |
#include <string.h> | ||
|
||
#include "access/attnum.h" | ||
#include "access/hash.h" | ||
#include "access/nbtree.h" | ||
#include "access/skey.h" | ||
#include "catalog/namespace.h" | ||
#include "catalog/pg_class.h" | ||
#include "catalog/pg_am.h" | ||
#include "commands/defrem.h" | ||
#include "lib/stringinfo.h" | ||
#include "nodes/pg_list.h" | ||
#include "nodes/primnodes.h" | ||
|
@@ -50,6 +56,8 @@ static List * ParseWorkerNodeFile(char *workerNodeFilename); | |
static int CompareWorkerNodes(const void *leftElement, const void *rightElement); | ||
static bool ExecuteRemoteCommand(PGconn *connection, const char *sqlCommand); | ||
static text * IntegerToText(int32 value); | ||
static Oid SupportFunctionForColumn(Var* partitionColumn, Oid accessMethodId, | ||
int16 supportFunctionNumber); | ||
|
||
|
||
/* declarations for dynamic loading */ | ||
|
@@ -70,9 +78,9 @@ master_create_distributed_table(PG_FUNCTION_ARGS) | |
char partitionMethod = PG_GETARG_CHAR(2); | ||
Oid distributedTableId = ResolveRelationId(tableNameText); | ||
char relationKind = '\0'; | ||
AttrNumber partitionColumnId = InvalidAttrNumber; | ||
char *partitionColumnName = text_to_cstring(partitionColumnText); | ||
char *tableName = text_to_cstring(tableNameText); | ||
Var *partitionColumnVar = NULL; | ||
|
||
/* verify target relation is either regular or foreign table */ | ||
relationKind = get_rel_relkind(distributedTableId); | ||
|
@@ -84,17 +92,53 @@ master_create_distributed_table(PG_FUNCTION_ARGS) | |
"foreign tables."))); | ||
} | ||
|
||
/* verify column exists in given table */ | ||
partitionColumnId = get_attnum(distributedTableId, partitionColumnName); | ||
if (partitionColumnId == InvalidAttrNumber) | ||
/* ColumnNameToColumn verifies column exists in given table */ | ||
partitionColumnVar = ColumnNameToColumn(distributedTableId, partitionColumnName); | ||
|
||
if (partitionMethod != HASH_PARTITION_TYPE) | ||
{ | ||
ereport(ERROR, (errmsg("could not find column: %s", partitionColumnName))); | ||
/* we only support hash partitioning right now */ | ||
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), | ||
errmsg("pg_shard only supports hash partitioning"))); | ||
} | ||
|
||
/* we only support hash partitioning method for now */ | ||
if (partitionMethod != HASH_PARTITION_TYPE) | ||
/* depending on the partition type, check for the existence of support function */ | ||
if (partitionMethod == HASH_PARTITION_TYPE) | ||
{ | ||
ereport(ERROR, (errmsg("unsupported partition method: %c", partitionMethod))); | ||
Oid hashSupportFunction = SupportFunctionForColumn(partitionColumnVar, | ||
HASH_AM_OID, HASHPROC); | ||
if (hashSupportFunction == InvalidOid) | ||
{ | ||
Oid partitionColumnTypeId = partitionColumnVar->vartype; | ||
|
||
ereport(ERROR, (errcode(ERRCODE_UNDEFINED_FUNCTION), | ||
errmsg("could not identify a hash function for type %s", | ||
format_type_be(partitionColumnTypeId)), | ||
errdetail("Partition column types must have a hash function " | ||
"defined to use hash partitioning."))); | ||
} | ||
} | ||
else if (partitionMethod == RANGE_PARTITION_TYPE) | ||
{ | ||
/* | ||
* Currently we do not support RANGE_PARTITION_TYPE. However, for the | ||
* completeness of the code, we also check operators for range partitioning. | ||
* TODO: Add regression tests for this check when RANGE_PARTITION_TYPE is | ||
* supported. | ||
*/ | ||
Oid btreeSupportFunction = SupportFunctionForColumn(partitionColumnVar, | ||
BTREE_AM_OID, BTORDER_PROC); | ||
if (btreeSupportFunction == InvalidOid) | ||
{ | ||
Oid partitionColumnTypeId = partitionColumnVar->vartype; | ||
|
||
ereport(ERROR, | ||
(errcode(ERRCODE_UNDEFINED_FUNCTION), | ||
errmsg("could not identify a comparison function for type %s", | ||
format_type_be(partitionColumnTypeId)), | ||
errdetail("Partition column types must have a comparison function " | ||
"defined to use range partitioning."))); | ||
} | ||
} | ||
|
||
/* insert row into the partition metadata table */ | ||
|
@@ -534,3 +578,40 @@ IntegerToText(int32 value) | |
|
||
return valueText; | ||
} | ||
|
||
|
||
/* | ||
* SupportFunctionForColumn helps to find the support function given a column, an access | ||
* method and id of a support function. This function returns InvalidOid if there is no | ||
* support function associated with the data type of the column. Also, this function | ||
* errors-out if there is no default operator class for the data type of the column. | ||
*/ | ||
Oid | ||
SupportFunctionForColumn(Var *partitionColumn, Oid accessMethodId, | ||
int16 supportFunctionNumber) | ||
{ | ||
Oid operatorFamilyId = InvalidOid; | ||
Oid supportFunctionOid = InvalidOid; | ||
Oid columnOid = partitionColumn->vartype; | ||
Oid operatorClassId = GetDefaultOpClass(columnOid, accessMethodId); | ||
|
||
/* | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This comment is actually incorrect, I think… This documentation section shows that an index can be defined using a customer operator class rather than the default. So it's possible we could support types without default operator classes, so long as the user specified which custom operator class to use at the time of distribution. I'll update this comment to clarify that we just don't support anything other than using a default operator class at the moment. |
||
* If data type of the partition column does not have a default operator class, | ||
* we should not continue to get support function. A type with no default op | ||
* class cannot have any support functions. | ||
*/ | ||
if (operatorClassId == InvalidOid) | ||
{ | ||
ereport(ERROR, (errcode(ERRCODE_UNDEFINED_OBJECT), | ||
errmsg("data type %s has no default operator class for specified" | ||
" partition method", format_type_be(columnOid)), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Slight alignment issue here. I'll fix before merge. |
||
errdetail("Partition column types must have a default operator" | ||
" class defined."))); | ||
} | ||
|
||
operatorFamilyId = get_opclass_family(operatorClassId); | ||
supportFunctionOid = get_opfamily_proc(operatorFamilyId, columnOid, columnOid, | ||
supportFunctionNumber); | ||
|
||
return supportFunctionOid; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -52,7 +52,6 @@ static List *OperatorIdCache = NIL; | |
|
||
/* local function forward declarations */ | ||
static Oid LookupOperatorByType(Oid typeId, Oid accessMethodId, int16 strategyNumber); | ||
static Oid GetOperatorByType(Oid typeId, Oid accessMethodId, int16 strategyNumber); | ||
static bool SimpleOpExpression(Expr *clause); | ||
static Node * HashableClauseMutator(Node *originalNode, Var *partitionColumn); | ||
static bool OpExpressionContainsColumn(OpExpr *operatorExpression, Var *partitionColumn); | ||
|
@@ -305,7 +304,7 @@ LookupOperatorByType(Oid typeId, Oid accessMethodId, int16 strategyNumber) | |
* GetOperatorByType returns the operator oid for the given type, access | ||
* method, and strategy number. | ||
*/ | ||
static Oid | ||
Oid | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we're starting to see we might want to move some of these common functions out into their own file. |
||
GetOperatorByType(Oid typeId, Oid accessMethodId, int16 strategyNumber) | ||
{ | ||
/* Get default operator class from pg_opclass */ | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see the point in this variable existing, so I'm going to remove it before merging (it's only referenced once).