提交 cc799db4 编写于 作者: K khannaekta 提交者: Bhuvnesh

Fix Relcache Translator to send CoercePath info (#2842)

Fix Relcache Translator to send CoercePath info

Currently ORCA crashes while executing following query:
```
CREATE TABLE FOO(a integer NOT NULL, b double precision[]);
SELECT b FROM foo
UNION ALL
SELECT ARRAY[90, 90] as Cont_features;
```

In the query, we are appending an integer array (ARRAY[90, 90]) to a double
precision array (foo.b) and hence we need to apply a cast on ARRAY[90, 90] to
generate ARRAY[90, 90]::double precision[].
In gpdb5 there is not direct function available that can cast array of any type
to array of any other type.
So in relcache to dxl translator we look into the array elements and get their type
and try to find a cast function for them.  For this query, source type is 23 i.e.
integer and destination type is 701 i.e. double precision and we try to find if
we have a conversion function for 23 -> 701. Since that is available we send
that function to ORCA as follows:
```
<dxl:MDCast Mdid="3.1007.1.0;1022.1.0"
Name="float8" BinaryCoercible="false" SourceTypeId="0.1007.1.0"
DestinationTypeId="0.1022.1.0" CastFuncId="0.316.1.0"/>
```
Here we are misinforming ORCA by specifying that function with id 316 is available
to convert type 1007 i.e. integer array to 1022 i.e. double precision array.
However Function id 316 is simple int4 to float8 conversion function and it CAN NOT
convert an array of int4 to array of double precision. ORCA generates a plan
using this function but executor crashes while executing this function because
this function can not handle arrays.

This commit fixes this issue by passing a ArrayCoercePath info to ORCA.
In Relcache Translator, The appropriate cast function is retrieved in `gpdb::FCastFunc()`
which relies on `find_coercion_pathway()` to provide the cast function oid given the src
and dest types.

`find_coercion_pathway()` does not just determines the cast function to be used but
also determines the coercion path; however we ignored the coercision path
and generate a simple Cast Metadata Object.

With this commit, we now pass the pathtype to relcache translator and
generate ArrayCoerceCast Metadata object depending on the coercion path.

In ORCA, when the dxl is translated to expression, we check the path type along with
the cast function and generate `CScalarArrayCoerceExpr` if the path type is
array coerce path; otherwise we generate simple `CScalaraCast`.

Please check the corresponding ORCA PR.

Bump ORCA version to 2.40
Signed-off-by: NBhuvnesh Chaudhary <bchaudhary@pivotal.io>
上级 e4cd1422
......@@ -53,10 +53,10 @@ AC_RUN_IFELSE([AC_LANG_PROGRAM([[
#include <string.h>
]],
[
return strncmp("2.39.", GPORCA_VERSION_STRING, 5);
return strncmp("2.40.", GPORCA_VERSION_STRING, 5);
])],
[AC_MSG_RESULT([[ok]])],
[AC_MSG_ERROR([Your ORCA version is expected to be 2.39.XXX])]
[AC_MSG_ERROR([Your ORCA version is expected to be 2.40.XXX])]
)
AC_LANG_POP([C++])
])# PGAC_CHECK_ORCA_VERSION
......
......@@ -12540,7 +12540,7 @@ int
main ()
{
return strncmp("2.39.", GPORCA_VERSION_STRING, 5);
return strncmp("2.40.", GPORCA_VERSION_STRING, 5);
;
return 0;
......@@ -12550,7 +12550,7 @@ if ac_fn_cxx_try_run "$LINENO"; then :
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5
$as_echo "ok" >&6; }
else
as_fn_error $? "Your ORCA version is expected to be 2.39.XXX" "$LINENO" 5
as_fn_error $? "Your ORCA version is expected to be 2.40.XXX" "$LINENO" 5
fi
rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
......
......@@ -120,7 +120,7 @@ sync_tools: opt_write_test /opt/releng/apache-ant
-Divyrepo.user=$(IVYREPO_USER) -Divyrepo.passwd="$(IVYREPO_PASSWD)" resolve);
@echo "Resolve finished";
LD_LIBRARY_PATH='' wget -O - https://github.com/greenplum-db/gporca/releases/download/v2.39.2/bin_orca_centos5_release.tar.gz | tar zxf - -C $(BLD_TOP)/ext/$(BLD_ARCH)
LD_LIBRARY_PATH='' wget -O - https://github.com/greenplum-db/gporca/releases/download/v2.40.0/bin_orca_centos5_release.tar.gz | tar zxf - -C $(BLD_TOP)/ext/$(BLD_ARCH)
clean_tools: opt_write_test
@cd releng/make/dependencies; \
......
......@@ -1055,13 +1055,14 @@ gpdb::FCastFunc
Oid oidSrc,
Oid oidDest,
bool *is_binary_coercible,
Oid *oidCastFunc
Oid *oidCastFunc,
CoercionPathType *pathtype
)
{
GP_WRAP_START;
{
/* catalog tables: pg_cast */
return get_cast_func(oidSrc, oidDest, is_binary_coercible, oidCastFunc);
return get_cast_func(oidSrc, oidDest, is_binary_coercible, oidCastFunc, pathtype);
}
GP_WRAP_END;
return false;
......
......@@ -38,6 +38,7 @@
#include "naucrates/dxl/gpdb_types.h"
#include "naucrates/md/CMDCastGPDB.h"
#include "naucrates/md/CMDArrayCoerceCastGPDB.h"
#include "naucrates/md/CMDScCmpGPDB.h"
#include "gpopt/translate/CTranslatorUtils.h"
......@@ -2588,14 +2589,16 @@ CTranslatorRelcacheToDXL::PimdobjCast
CMDIdCast *pmdidCast = CMDIdCast::PmdidConvert(pmdid);
IMDId *pmdidSrc = pmdidCast->PmdidSrc();
IMDId *pmdidDest = pmdidCast->PmdidDest();
IMDCast::EmdCoercepathType coercePathType;
OID oidSrc = CMDIdGPDB::PmdidConvert(pmdidSrc)->OidObjectId();
OID oidDest = CMDIdGPDB::PmdidConvert(pmdidDest)->OidObjectId();
CoercionPathType pathtype;
OID oidCastFunc = 0;
BOOL fBinaryCoercible = false;
BOOL fCastExists = gpdb::FCastFunc(oidSrc, oidDest, &fBinaryCoercible, &oidCastFunc);
BOOL fCastExists = gpdb::FCastFunc(oidSrc, oidDest, &fBinaryCoercible, &oidCastFunc, &pathtype);
if (!fCastExists)
{
......@@ -2624,6 +2627,21 @@ CTranslatorRelcacheToDXL::PimdobjCast
CMDName *pmdname = CDXLUtils::PmdnameFromSz(pmp, szFuncName);
switch (pathtype) {
case COERCION_PATH_ARRAYCOERCE:
{
coercePathType = IMDCast::EmdtArrayCoerce;
return GPOS_NEW(pmp) CMDArrayCoerceCastGPDB(pmp, pmdid, pmdname, pmdidSrc, pmdidDest, fBinaryCoercible, GPOS_NEW(pmp) CMDIdGPDB(oidCastFunc), IMDCast::EmdtArrayCoerce, -1, false, EdxlcfImplicitCast, -1);
}
break;
case COERCION_PATH_FUNC:
return GPOS_NEW(pmp) CMDCastGPDB(pmp, pmdid, pmdname, pmdidSrc, pmdidDest, fBinaryCoercible, GPOS_NEW(pmp) CMDIdGPDB(oidCastFunc), IMDCast::EmdtFunc);
break;
default:
break;
}
// fall back for none path types
return GPOS_NEW(pmp) CMDCastGPDB(pmp, pmdid, pmdname, pmdidSrc, pmdidDest, fBinaryCoercible, GPOS_NEW(pmp) CMDIdGPDB(oidCastFunc));
}
......
......@@ -3709,9 +3709,8 @@ get_check_constraint_expr_tree(Oid oidCheckconstraint)
* Returns true if a cast exists, false otherwise.
*/
bool
get_cast_func(Oid oidSrc, Oid oidDest, bool *is_binary_coercible, Oid *oidCastFunc)
get_cast_func(Oid oidSrc, Oid oidDest, bool *is_binary_coercible, Oid *oidCastFunc, CoercionPathType *pathtype)
{
CoercionPathType pathtype;
if (IsBinaryCoercible(oidSrc, oidDest))
{
*is_binary_coercible = true;
......@@ -3721,8 +3720,8 @@ get_cast_func(Oid oidSrc, Oid oidDest, bool *is_binary_coercible, Oid *oidCastFu
*is_binary_coercible = false;
pathtype = find_coercion_pathway(oidDest, oidSrc, COERCION_IMPLICIT, oidCastFunc);
if (pathtype != COERCION_PATH_NONE)
*pathtype = find_coercion_pathway(oidDest, oidSrc, COERCION_IMPLICIT, oidCastFunc);
if (*pathtype != COERCION_PATH_NONE)
return true;
return false;
}
......
......@@ -18,6 +18,7 @@
#include "postgres.h"
#include "access/attnum.h"
#include "utils/faultinjector.h"
#include "parser/parse_coerce.h"
// fwd declarations
typedef struct SysScanDescData *SysScanDesc;
......@@ -242,7 +243,7 @@ namespace gpdb {
Node *PnodePartConstraintRel(Oid oidRel, List **pplDefaultLevels);
// get the cast function for the specified source and destination types
bool FCastFunc(Oid oidSrc, Oid oidDest, bool *is_binary_coercible, Oid *oidCastFunc);
bool FCastFunc(Oid oidSrc, Oid oidDest, bool *is_binary_coercible, Oid *oidCastFunc, CoercionPathType *pathtype);
// get type of operator
unsigned int UlCmpt(Oid oidOp, Oid oidLeft, Oid oidRight);
......
......@@ -18,6 +18,7 @@
#include "catalog/gp_policy.h"
#include "nodes/pg_list.h"
#include "utils/relcache.h"
#include "parser/parse_coerce.h"
/* I/O function selector for get_type_io_data */
typedef enum IOFuncSelector
......@@ -190,7 +191,7 @@ extern GpPolicy *relation_policy(Relation rel);
extern bool child_distribution_mismatch(Relation rel);
extern bool child_triggers(Oid relationId, int32 triggerType);
extern bool get_cast_func(Oid oidSrc, Oid oidDest, bool *is_binary_coercible, Oid *oidCastFunc);
extern bool get_cast_func(Oid oidSrc, Oid oidDest, bool *is_binary_coercible, Oid *oidCastFunc, CoercionPathType *pathtype);
extern Oid get_comparison_operator(Oid oidLeft, Oid oidRight, CmpType cmpt);
extern CmpType get_comparison_type(Oid oidOp, Oid oidLeft, Oid oidRight);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册