From e57aa3f2a789dd7cfbf024908c511ee65ed9aa97 Mon Sep 17 00:00:00 2001 From: velioglu Date: Thu, 4 May 2017 19:31:24 +0300 Subject: [PATCH] Check whether binary output function is defined for type of each column. --- src/backend/distributed/commands/multi_copy.c | 57 +++++++++++++++---- src/test/regress/input/multi_copy.source | 16 ++++++ src/test/regress/output/multi_copy.source | 19 +++++++ 3 files changed, 82 insertions(+), 10 deletions(-) diff --git a/src/backend/distributed/commands/multi_copy.c b/src/backend/distributed/commands/multi_copy.c index bfc73c676..ec198e778 100644 --- a/src/backend/distributed/commands/multi_copy.c +++ b/src/backend/distributed/commands/multi_copy.c @@ -92,8 +92,8 @@ static void OpenCopyConnections(CopyStmt *copyStatement, ShardConnections *shardConnections, bool stopOnFailure, bool useBinaryCopyFormat); -static bool CanUseBinaryCopyFormat(TupleDesc tupleDescription, - CopyOutState rowOutputState); +static bool CanUseBinaryCopyFormat(TupleDesc tupleDescription); +static bool BinaryOutputFunctionDefined(Oid typeId); static List * MasterShardPlacementList(uint64 shardId); static List * RemoteFinalizedShardPlacementList(uint64 shardId); @@ -397,7 +397,7 @@ CopyToExistingShards(CopyStmt *copyStatement, char *completionTag) copyOutState->delim = (char *) delimiterCharacter; copyOutState->null_print = (char *) nullPrintCharacter; copyOutState->null_print_client = (char *) nullPrintCharacter; - copyOutState->binary = CanUseBinaryCopyFormat(tupleDescriptor, copyOutState); + copyOutState->binary = CanUseBinaryCopyFormat(tupleDescriptor); copyOutState->fe_msgbuf = makeStringInfo(); copyOutState->rowcontext = executorTupleContext; @@ -593,7 +593,7 @@ CopyToNewShards(CopyStmt *copyStatement, char *completionTag, Oid relationId) copyOutState->delim = (char *) delimiterCharacter; copyOutState->null_print = (char *) nullPrintCharacter; copyOutState->null_print_client = (char *) nullPrintCharacter; - copyOutState->binary = CanUseBinaryCopyFormat(tupleDescriptor, copyOutState); + copyOutState->binary = CanUseBinaryCopyFormat(tupleDescriptor); copyOutState->fe_msgbuf = makeStringInfo(); copyOutState->rowcontext = executorTupleContext; @@ -931,14 +931,15 @@ OpenCopyConnections(CopyStmt *copyStatement, ShardConnections *shardConnections, /* - * CanUseBinaryCopyFormat iterates over columns of the relation given in rowOutputState - * and looks for a column whose type is array of user-defined type or composite type. - * If it finds such column, that means we cannot use binary format for COPY, because - * binary format sends Oid of the types, which are generally not same in master and - * worker nodes for user-defined types. + * CanUseBinaryCopyFormat iterates over columns of the relation and looks for a + * column whose type is array of user-defined type or composite type. If it finds + * such column, that means we cannot use binary format for COPY, because binary + * format sends Oid of the types, which are generally not same in master and + * worker nodes for user-defined types. If the function can not detect a binary + * output function for any of the column, it returns false. */ static bool -CanUseBinaryCopyFormat(TupleDesc tupleDescription, CopyOutState rowOutputState) +CanUseBinaryCopyFormat(TupleDesc tupleDescription) { bool useBinaryCopyFormat = true; int totalColumnCount = tupleDescription->natts; @@ -950,6 +951,7 @@ CanUseBinaryCopyFormat(TupleDesc tupleDescription, CopyOutState rowOutputState) Oid typeId = InvalidOid; char typeCategory = '\0'; bool typePreferred = false; + bool binaryOutputFunctionDefined = false; if (currentColumn->attisdropped) { @@ -957,6 +959,15 @@ CanUseBinaryCopyFormat(TupleDesc tupleDescription, CopyOutState rowOutputState) } typeId = currentColumn->atttypid; + + /* built-in types may also don't have binary output function */ + binaryOutputFunctionDefined = BinaryOutputFunctionDefined(typeId); + if (!binaryOutputFunctionDefined) + { + useBinaryCopyFormat = false; + break; + } + if (typeId >= FirstNormalObjectId) { get_type_category_preferred(typeId, &typeCategory, &typePreferred); @@ -973,6 +984,32 @@ CanUseBinaryCopyFormat(TupleDesc tupleDescription, CopyOutState rowOutputState) } +/* + * BinaryOutputFunctionDefined checks whether binary output function is defined + * for the given type. + */ +static bool +BinaryOutputFunctionDefined(Oid typeId) +{ + Oid typeFunctionId = InvalidOid; + Oid typeIoParam = InvalidOid; + int16 typeLength = 0; + bool typeByVal = false; + char typeAlign = 0; + char typeDelim = 0; + + get_type_io_data(typeId, IOFunc_send, &typeLength, &typeByVal, + &typeAlign, &typeDelim, &typeIoParam, &typeFunctionId); + + if (OidIsValid(typeFunctionId)) + { + return true; + } + + return false; +} + + /* * MasterShardPlacementList dispatches the finalized shard placements call * between local or remote master node according to the master connection state. diff --git a/src/test/regress/input/multi_copy.source b/src/test/regress/input/multi_copy.source index 16703c580..80fa16f82 100644 --- a/src/test/regress/input/multi_copy.source +++ b/src/test/regress/input/multi_copy.source @@ -749,3 +749,19 @@ SELECT shardid, shardstate, nodename, nodeport DROP TABLE numbers_hash; SELECT * FROM run_command_on_workers('DROP USER test_user'); DROP USER test_user; + +-- Test copy with built-in type without binary output function +CREATE TABLE test_smgr ( +col1 smgr NOT NULL, +col2 character varying(255) NOT NULL +); + +SELECT create_reference_table('test_smgr'); + +\COPY test_smgr FROM STDIN WITH (format CSV) +magnetic disk, test +\. + +SELECT * FROM test_smgr; + +DROP TABLE test_smgr; diff --git a/src/test/regress/output/multi_copy.source b/src/test/regress/output/multi_copy.source index 9b02124f6..a9a058032 100644 --- a/src/test/regress/output/multi_copy.source +++ b/src/test/regress/output/multi_copy.source @@ -1015,3 +1015,22 @@ SELECT * FROM run_command_on_workers('DROP USER test_user'); (2 rows) DROP USER test_user; +-- Test copy with built-in type without binary output function +CREATE TABLE test_smgr ( +col1 smgr NOT NULL, +col2 character varying(255) NOT NULL +); +SELECT create_reference_table('test_smgr'); + create_reference_table +------------------------ + +(1 row) + +\COPY test_smgr FROM STDIN WITH (format CSV) +SELECT * FROM test_smgr; + col1 | col2 +---------------+------- + magnetic disk | test +(1 row) + +DROP TABLE test_smgr;