forked from huawei/openGauss-server
1221 lines
45 KiB
C++
Executable File
1221 lines
45 KiB
C++
Executable File
/*
|
|
* Copyright (c) 2020 Huawei Technologies Co.,Ltd.
|
|
*
|
|
* openGauss is licensed under Mulan PSL v2.
|
|
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
|
* You may obtain a copy of Mulan PSL v2 at:
|
|
*
|
|
* http://license.coscl.org.cn/MulanPSL2
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
|
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
|
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
|
* See the Mulan PSL v2 for more details.
|
|
* ---------------------------------------------------------------------------------------
|
|
*
|
|
* dfs_query.h
|
|
*
|
|
*
|
|
*
|
|
* IDENTIFICATION
|
|
* src/include/access/dfs/dfs_query.h
|
|
*
|
|
* ---------------------------------------------------------------------------------------
|
|
*/
|
|
|
|
#ifndef DFS_QUERY_H_
|
|
#define DFS_QUERY_H_
|
|
|
|
#include "orc/Exceptions.hh"
|
|
#include "access/dfs/dfs_am.h"
|
|
#include "catalog/pg_collation.h"
|
|
#include "nodes/execnodes.h"
|
|
#include "nodes/pg_list.h"
|
|
#include "optimizer/clauses.h"
|
|
#include "optimizer/subselect.h"
|
|
#include "utils/biginteger.h"
|
|
#include "utils/builtins.h"
|
|
#include "utils/date.h"
|
|
#include "utils/dfs_vector.h"
|
|
#include "utils/numeric.h"
|
|
#include "utils/numeric_gs.h"
|
|
#include "utils/lsyscache.h"
|
|
|
|
#ifndef MIN
|
|
#define MIN(A, B) ((B) < (A) ? (B) : (A))
|
|
#endif
|
|
|
|
#define DFS_PRIVATE_ITEM "DfsPrivateItem"
|
|
#define DFS_NUMERIC64_MAX_PRECISION 18
|
|
|
|
/* MACROS which help to catch and print the exception. */
|
|
#define DFS_TRY() \
|
|
bool saveStatus = t_thrd.int_cxt.ImmediateInterruptOK; \
|
|
t_thrd.int_cxt.ImmediateInterruptOK = false; \
|
|
bool errOccur = false; \
|
|
int errNo = ERRCODE_SYSTEM_ERROR; \
|
|
StringInfo errMsg = makeStringInfo(); \
|
|
StringInfo errDetail = makeStringInfo(); \
|
|
try
|
|
#define DFS_CATCH() \
|
|
catch (abi::__forced_unwind &) \
|
|
{ \
|
|
throw; \
|
|
} \
|
|
catch (orc::OrcException & ex) \
|
|
{ \
|
|
errOccur = true; \
|
|
errNo = ex.getErrNo(); \
|
|
try { \
|
|
appendStringInfo(errMsg, "%s", ex.what()); \
|
|
appendStringInfo(errDetail, "%s", ex.msg().c_str()); \
|
|
} catch (abi::__forced_unwind &) { \
|
|
throw; \
|
|
} catch (...) { \
|
|
} \
|
|
} \
|
|
catch (std::exception & ex) \
|
|
{ \
|
|
errOccur = true; \
|
|
try { \
|
|
appendStringInfo(errMsg, "%s", ex.what()); \
|
|
} catch (abi::__forced_unwind &) { \
|
|
throw; \
|
|
} catch (...) { \
|
|
} \
|
|
} \
|
|
catch (...) \
|
|
{ \
|
|
errOccur = true; \
|
|
} \
|
|
t_thrd.int_cxt.ImmediateInterruptOK = saveStatus; \
|
|
saveStatus = InterruptPending; \
|
|
InterruptPending = false; \
|
|
if (errOccur && errDetail->len > 0) { \
|
|
ereport(LOG, (errmodule(MOD_DFS), errmsg("Caught exceptiion for: %s.", errDetail->data))); \
|
|
} \
|
|
InterruptPending = saveStatus; \
|
|
pfree_ext(errDetail->data); \
|
|
pfree_ext(errDetail);
|
|
|
|
#define DFS_ERRREPORT(msg, module) \
|
|
if (errOccur) { \
|
|
destroy(); \
|
|
ereport(ERROR, (errcode(errNo), errmodule(module), \
|
|
errmsg(msg, errMsg->data, g_instance.attr.attr_common.PGXCNodeName))); \
|
|
} \
|
|
pfree_ext(errMsg->data); \
|
|
pfree_ext(errMsg);
|
|
|
|
#define DFS_ERRREPORT_WITHARGS(msg, module, ...) \
|
|
if (errOccur) { \
|
|
ereport(ERROR, (errcode(errNo), errmodule(module), \
|
|
errmsg(msg, __VA_ARGS__, errMsg->data, g_instance.attr.attr_common.PGXCNodeName))); \
|
|
} \
|
|
pfree_ext(errMsg->data); \
|
|
pfree_ext(errMsg);
|
|
|
|
#define DFS_ERRREPORT_WITHOUTARGS(msg, module) \
|
|
if (errOccur) { \
|
|
ereport(ERROR, (errcode(errNo), errmodule(module), \
|
|
errmsg(msg, errMsg->data, g_instance.attr.attr_common.PGXCNodeName))); \
|
|
} \
|
|
pfree_ext(errMsg->data); \
|
|
pfree_ext(errMsg);
|
|
|
|
#ifdef ENABLE_LLVM_COMPILE
|
|
extern bool CodeGenThreadObjectReady();
|
|
extern bool ForeignScanExprCodeGen(Expr *expr, PlanState *parent, void **jittedFunc);
|
|
|
|
/*
|
|
* Declare the function pointers for LLVM machine code address.
|
|
*/
|
|
typedef bool (*evaPredicateDouble)(double value);
|
|
typedef bool (*evaPredicateInt)(int64_t value);
|
|
#endif
|
|
|
|
#define DEFAULT_HIVE_NULL "__HIVE_DEFAULT_PARTITION__"
|
|
#define DEFAULT_HIVE_NULL_LENGTH 26
|
|
|
|
/*
|
|
* Check partition signature creation exception in case of the content exceeding
|
|
* max allowed partition length
|
|
*/
|
|
#define partition_err_msg \
|
|
"The length of the partition directory exceeds the current value(%d) of the option " \
|
|
"\"dfs_partition_directory_length\", change the option to the greater value."
|
|
#define CHECK_PARTITION_SIGNATURE(rc, dirname) do { \
|
|
if (rc != 0) { \
|
|
ereport(ERROR, (errcode(ERRCODE_DATA_EXCEPTION), errmodule(MOD_DFS), \
|
|
errmsg(partition_err_msg, u_sess->attr.attr_storage.dfs_max_parsig_length), \
|
|
errdetail("the path name is \"%s\".", dirname))); \
|
|
} \
|
|
securec_check(rc, "\0", "\0"); \
|
|
} while (0)
|
|
|
|
#define strpos(p, s) (strstr(p, s) != NULL ? strstr(p, s) - p : -1)
|
|
#define basename_len(p, s) (strrchr(p, s) != NULL ? strrchr(p, s) - p : -1)
|
|
|
|
#define INT_CMP_HDFS(arg1, arg2, compare) do { \
|
|
if ((arg1) < (arg2)) { \
|
|
compare = -1; \
|
|
} else if ((arg1) > (arg2)) { \
|
|
compare = 1; \
|
|
} else { \
|
|
compare = 0; \
|
|
} \
|
|
} while (0)
|
|
|
|
/*
|
|
* 1. NAN = NAN
|
|
* 2. NAN > non-NAN
|
|
* 3. non-NAN < NAN
|
|
* 4. non-NAN cmp non-NAN
|
|
* 5. arg2 will never be NAN here
|
|
*/
|
|
#define FLOAT_CMP_HDFS(arg1, arg2, compare) do { \
|
|
if (isnan(arg1)) { \
|
|
compare = 1; \
|
|
} else { \
|
|
if ((arg1) > (arg2)) { \
|
|
compare = 1; \
|
|
} else if ((arg1) < (arg2)) { \
|
|
compare = -1; \
|
|
} else { \
|
|
compare = 0; \
|
|
} \
|
|
} \
|
|
} while (0)
|
|
|
|
/*
|
|
* define the strategy numbers for hdfs foriegn scan. -1 is invalid,
|
|
* 0-6 stand for op strategy, 11-12 stand for isnull/is not null.
|
|
*/
|
|
typedef enum {
|
|
HDFS_QUERY_INVALID = -1,
|
|
|
|
/*
|
|
* 0-6 stand for OpExpr strategy,
|
|
* HDFS_QUERY_EQ: '='
|
|
* HDFS_QUERY_LT: '<'
|
|
* HDFS_QUERY_GT: '>'
|
|
* HDFS_QUERY_LTE: '<='
|
|
* HDFS_QUERY_GTE: '>='
|
|
* HDFS_QUERY_NE1: '<>'
|
|
* HDFS_QUERY_NE2: '!='
|
|
*/
|
|
HDFS_QUERY_EQ = 0,
|
|
HDFS_QUERY_LT = 1,
|
|
HDFS_QUERY_GT = 2,
|
|
HDFS_QUERY_LTE = 3,
|
|
HDFS_QUERY_GTE = 4,
|
|
HDFS_QUERY_NE1 = 5,
|
|
HDFS_QUERY_NE2 = 6,
|
|
|
|
/* 11-12 stand for isnull/is not null */
|
|
HDFS_QUERY_ISNULL = 11,
|
|
HDFS_QUERY_ISNOTNULL = 12,
|
|
} HdfsQueryOperator;
|
|
|
|
typedef enum {
|
|
NO_ENCODING_CHECK = 0,
|
|
LOW_ENCODING_CHECK = 1,
|
|
HIGH_ENCODING_CHECK = 2
|
|
} EncodingLevel;
|
|
|
|
/*
|
|
* The base template class for all the data type wrapper to inherit.
|
|
*/
|
|
template <typename T>
|
|
class HdfsCheckWrapper : public BaseObject {
|
|
public:
|
|
virtual ~HdfsCheckWrapper()
|
|
{
|
|
}
|
|
/*
|
|
* Abstract function to compare the argument and velue.
|
|
* @_in param argument: The target to be compared with the member value.
|
|
* @_in param collation: the collation of the var, it is used in function varstr_cmp.
|
|
* @return Return 1=eq, -1=lt, 1=gt.
|
|
*/
|
|
virtual int compareT(T argument, Oid collation) = 0;
|
|
|
|
/*
|
|
* Set the value in the class which is converted from datum.
|
|
* @_in param datumValue: the datum value to be set.
|
|
* @_in param datumType: the data type oid of the datum.
|
|
* @_in param typeMod: the mod of the datum type.
|
|
*/
|
|
virtual void SetValueFromDatum(Datum datumValue, Oid datumType, int32 typeMod) = 0;
|
|
|
|
/*
|
|
* A template function to check if the argument transfered in can be filtered. All the non-string
|
|
* wrapper will inherit this function for call.
|
|
*
|
|
* @_in param argument: the value transfered in to be checked
|
|
* @_in param strategy: the strategy used in the predicate.
|
|
* @_in param collation: the collation of the var, it is used in function varstr_cmp.
|
|
* @return True: match and not filtered; False: filtered and set isSelected to false.
|
|
*/
|
|
inline bool CheckPredicate(T argument, Oid collation)
|
|
{
|
|
int cmpResult = compareT(argument, collation);
|
|
return HdfsCheckCompareResult(cmpResult);
|
|
}
|
|
|
|
/*
|
|
* Get the value of the wrapper.
|
|
* @return Return the value in the class.
|
|
*/
|
|
inline const T getValue()
|
|
{
|
|
return value;
|
|
}
|
|
|
|
/*
|
|
* Get the datum of the wrapper.
|
|
* @return the datum value.
|
|
*/
|
|
inline Datum getDatum()
|
|
{
|
|
return dValue;
|
|
}
|
|
|
|
private:
|
|
/*
|
|
* Check the compare result depending on the strategy of the predicate pushed down.
|
|
*
|
|
* @_in param cmpResult: The result of comparision, (o=eq, -1=lt, 1=gt)
|
|
*
|
|
* @return True: indicates the value of the row and column match the preidcate pushed down; False:
|
|
* indicates the value does not match the predicate and need to be filtered.
|
|
*/
|
|
bool HdfsCheckCompareResult(int cmpResult);
|
|
|
|
protected:
|
|
/* Store the real value of the wrapper with type T. */
|
|
T value;
|
|
Datum dValue;
|
|
|
|
/*
|
|
* The strategy of the predicate's operator, which must between HDFS_QUERY_EQ
|
|
* and HDFS_QUERY_NE2.
|
|
*/
|
|
HdfsQueryOperator strategy;
|
|
int32 typeMod;
|
|
Oid datumType;
|
|
};
|
|
|
|
/*
|
|
* Check the result of comparation according to the strategy.
|
|
*/
|
|
template <typename T>
|
|
inline bool HdfsCheckWrapper<T>::HdfsCheckCompareResult(int cmpResult)
|
|
{
|
|
bool result = false;
|
|
switch (strategy) {
|
|
case HDFS_QUERY_LT: {
|
|
if (0 > cmpResult)
|
|
result = true;
|
|
break;
|
|
}
|
|
case HDFS_QUERY_LTE: {
|
|
if (0 >= cmpResult)
|
|
result = true;
|
|
break;
|
|
}
|
|
case HDFS_QUERY_EQ: {
|
|
if (0 == cmpResult)
|
|
result = true;
|
|
break;
|
|
}
|
|
case HDFS_QUERY_GTE: {
|
|
if (0 <= cmpResult)
|
|
result = true;
|
|
break;
|
|
}
|
|
case HDFS_QUERY_GT: {
|
|
if (0 < cmpResult)
|
|
result = true;
|
|
break;
|
|
}
|
|
case HDFS_QUERY_NE1:
|
|
case HDFS_QUERY_NE2: {
|
|
if (0 != cmpResult)
|
|
result = true;
|
|
break;
|
|
}
|
|
case HDFS_QUERY_INVALID:
|
|
default: {
|
|
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmodule(MOD_DFS),
|
|
errmsg("Find unsupported strategy %d!", strategy)));
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/*
|
|
* A wrapper class of int64 type, inherit HdfsCheckWrapper. Here we do not seperate
|
|
* int16, int 32 and int64 wrapper just because what we read from orc file directly for int16,int32 and int64
|
|
* is int64, then it will convert to int16,int32 or int64 datum. Since the predicate need to be checked before
|
|
* the conversion from basic type to datum, so we will compare the int64 value directly and needn't
|
|
* Int32Wrapper and Int16Wrapper.
|
|
*/
|
|
class Int64Wrapper : public HdfsCheckWrapper<int64> {
|
|
public:
|
|
Int64Wrapper(HdfsQueryOperator _strategy)
|
|
{
|
|
strategy = _strategy;
|
|
}
|
|
virtual ~Int64Wrapper()
|
|
{
|
|
}
|
|
inline void SetValueFromDatum(Datum datumValue, Oid datumType, int32 typeMod)
|
|
{
|
|
dValue = datumValue;
|
|
|
|
if (INT1OID == datumType) {
|
|
value = DatumGetChar(datumValue);
|
|
} else if (INT2OID == datumType) {
|
|
value = DatumGetInt16(datumValue);
|
|
} else if (INT4OID == datumType) {
|
|
value = DatumGetInt32(datumValue);
|
|
} else if (NUMERICOID == datumType) {
|
|
int dscale = (unsigned int)(typeMod - VARHDRSZ) & 0xffff;
|
|
Numeric n = DatumGetNumeric(datumValue);
|
|
if (NUMERIC_IS_BI(n)) {
|
|
Assert(dscale == NUMERIC_BI_SCALE(n));
|
|
Assert(NUMERIC_IS_BI64(n));
|
|
|
|
value = NUMERIC_64VALUE(n);
|
|
} else
|
|
value = convert_short_numeric_to_int64_byscale(n, dscale);
|
|
} else {
|
|
value = DatumGetInt64(datumValue);
|
|
}
|
|
}
|
|
|
|
private:
|
|
inline int compareT(int64 argument, Oid collation)
|
|
{
|
|
int cmp = 0;
|
|
INT_CMP_HDFS(argument, value, cmp);
|
|
return cmp;
|
|
}
|
|
};
|
|
|
|
/* just for decimal128, 18 < p <= 38 */
|
|
class Int128Wrapper : public HdfsCheckWrapper<int128> {
|
|
public:
|
|
Int128Wrapper(HdfsQueryOperator _strategy)
|
|
{
|
|
strategy = _strategy;
|
|
}
|
|
virtual ~Int128Wrapper()
|
|
{
|
|
}
|
|
inline void SetValueFromDatum(Datum datumValue, Oid datumType, int32 typeMod)
|
|
{
|
|
int dscale = (unsigned int)(typeMod - VARHDRSZ) & 0xffff;
|
|
|
|
dValue = datumValue;
|
|
Numeric n = DatumGetNumeric(datumValue);
|
|
if (NUMERIC_IS_BI(n)) {
|
|
Assert(dscale == NUMERIC_BI_SCALE(n));
|
|
|
|
if (NUMERIC_IS_BI128(n)) {
|
|
errno_t rc = EOK;
|
|
rc = memcpy_s(&value, sizeof(int128), (n)->choice.n_bi.n_data, sizeof(int128));
|
|
securec_check(rc, "\0", "\0");
|
|
} else
|
|
value = NUMERIC_64VALUE(n);
|
|
} else
|
|
convert_short_numeric_to_int128_byscale(n, dscale, value);
|
|
}
|
|
|
|
private:
|
|
inline int compareT(int128 argument, Oid collation)
|
|
{
|
|
int cmp = 0;
|
|
INT_CMP_HDFS(argument, value, cmp);
|
|
return cmp;
|
|
}
|
|
};
|
|
|
|
/*
|
|
* A wrapper class of bool type, inherit HdfsCheckWrapper. The actual value stored is a char here.
|
|
*/
|
|
class BoolWrapper : public HdfsCheckWrapper<char> {
|
|
public:
|
|
BoolWrapper(HdfsQueryOperator _strategy)
|
|
{
|
|
strategy = _strategy;
|
|
}
|
|
virtual ~BoolWrapper()
|
|
{
|
|
}
|
|
inline void SetValueFromDatum(Datum datumValue, Oid datumType, int32 typeMod)
|
|
{
|
|
dValue = datumValue;
|
|
value = DatumGetBool(datumValue);
|
|
}
|
|
|
|
private:
|
|
inline int compareT(char argument, Oid collation)
|
|
{
|
|
int cmp = 0;
|
|
INT_CMP_HDFS(argument, value, cmp);
|
|
return cmp;
|
|
}
|
|
};
|
|
|
|
/*
|
|
* A wrapper class of float8 type, inherit HdfsCheckWrapper.
|
|
*/
|
|
class Float8Wrapper : public HdfsCheckWrapper<float8> {
|
|
public:
|
|
Float8Wrapper(HdfsQueryOperator _strategy)
|
|
{
|
|
strategy = _strategy;
|
|
}
|
|
virtual ~Float8Wrapper()
|
|
{
|
|
}
|
|
inline void SetValueFromDatum(Datum datumValue, Oid _datumType, int32 typeMod)
|
|
{
|
|
datumType = _datumType;
|
|
/*
|
|
* For float4/8, there may be data convertion of the const value, so we
|
|
* need to process seperately here.
|
|
*/
|
|
if (FLOAT4OID == datumType) {
|
|
value = (float8)DatumGetFloat4(datumValue);
|
|
dValue = Float8GetDatum(value);
|
|
} else // float8
|
|
{
|
|
value = DatumGetFloat8(datumValue);
|
|
dValue = datumValue;
|
|
}
|
|
}
|
|
|
|
private:
|
|
inline int compareT(float8 argument, Oid collation)
|
|
{
|
|
int cmp = 0;
|
|
FLOAT_CMP_HDFS(argument, value, cmp);
|
|
return cmp;
|
|
}
|
|
};
|
|
|
|
/*
|
|
* A wrapper class of Timestamp type, inherit HdfsCheckWrapper. Since there is not actual Date type
|
|
* in PG, we just need the wrapper for Timestamp here, and convert the hive date to timestamp before
|
|
* the comparasion with predicate.
|
|
*/
|
|
class TimestampWrapper : public HdfsCheckWrapper<Timestamp> {
|
|
public:
|
|
TimestampWrapper(HdfsQueryOperator _strategy)
|
|
{
|
|
strategy = _strategy;
|
|
}
|
|
virtual ~TimestampWrapper()
|
|
{
|
|
}
|
|
inline void SetValueFromDatum(Datum datumValue, Oid datumType, int32 typeMod)
|
|
{
|
|
dValue = datumValue;
|
|
|
|
/*
|
|
* For different time types, we use different ways to convert to timestamp.
|
|
*/
|
|
if (DATEOID == datumType) {
|
|
value = date2timestamp(DatumGetDateADT(datumValue));
|
|
} else if (TIMESTAMPTZOID == datumType) {
|
|
Datum out = DirectFunctionCall1(timestamptz_out, datumValue);
|
|
Datum in = DirectFunctionCall3(timestamp_in, out, ObjectIdGetDatum(InvalidOid), Int32GetDatum(typeMod));
|
|
value = DatumGetTimestamp(in);
|
|
} else {
|
|
value = DatumGetTimestamp(datumValue);
|
|
}
|
|
}
|
|
|
|
private:
|
|
inline int compareT(Timestamp argument, Oid collation)
|
|
{
|
|
int cmp = 0;
|
|
#ifdef HAVE_INT64_TIMESTAMP
|
|
INT_CMP_HDFS(argument, value, cmp);
|
|
#else
|
|
FLOAT_CMP_HDFS(argument, value, cmp);
|
|
#endif
|
|
return cmp;
|
|
}
|
|
};
|
|
|
|
/*
|
|
* Since we only care about equality or not-equality, we can avoid all the
|
|
* expense of strcoll() here, and just do bitwise comparison.
|
|
* The caller must ensure that both src1 and src2 are valid strings with '\0' at end.
|
|
* return 0 if the two strings are equal.
|
|
*/
|
|
static int stringEQ(const char *src1, const char *src2)
|
|
{
|
|
int result = 0;
|
|
int len1 = strlen(src1);
|
|
int len2 = strlen(src2);
|
|
if (len1 != len2) {
|
|
result = 1;
|
|
} else {
|
|
result = memcmp(src1, src2, len1);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/*
|
|
* A wrapper class of string type includes varchar,bpchar,text because these types is actually the same for hive.
|
|
*/
|
|
class StringWrapper : public HdfsCheckWrapper<char *> {
|
|
public:
|
|
StringWrapper(HdfsQueryOperator _strategy)
|
|
{
|
|
strategy = _strategy;
|
|
}
|
|
virtual ~StringWrapper()
|
|
{
|
|
}
|
|
inline void SetValueFromDatum(Datum datumValue, Oid _datumType, int32 typeMod)
|
|
{
|
|
dValue = datumValue;
|
|
datumType = _datumType;
|
|
|
|
if (BPCHAROID == datumType) {
|
|
int varLen = 0;
|
|
char *str = TextDatumGetCString(datumValue);
|
|
int strLen = strlen(str);
|
|
|
|
/* variable length */
|
|
if (typeMod < (int32)VARHDRSZ) {
|
|
varLen = strLen;
|
|
} else /* fixed length */
|
|
{
|
|
varLen = typeMod - VARHDRSZ;
|
|
}
|
|
|
|
/*
|
|
* When the length of the var is larger than the const string's length, it needs to
|
|
* add some blanks in the tail.
|
|
*/
|
|
if (varLen >= strLen) {
|
|
Datum bpchar = DirectFunctionCall3(bpcharin, CStringGetDatum(str), ObjectIdGetDatum(InvalidOid),
|
|
Int32GetDatum(typeMod));
|
|
value = TextDatumGetCString(bpchar);
|
|
} else {
|
|
value = str;
|
|
}
|
|
} else {
|
|
value = TextDatumGetCString(datumValue);
|
|
}
|
|
}
|
|
|
|
private:
|
|
inline int compareT(char *argument, Oid collation)
|
|
{
|
|
int cmp = 0;
|
|
if (HDFS_QUERY_EQ == strategy || HDFS_QUERY_NE1 == strategy || HDFS_QUERY_NE2 == strategy) {
|
|
cmp = stringEQ(argument, value);
|
|
} else {
|
|
cmp = varstr_cmp(argument, strlen(argument), value, strlen(value), collation);
|
|
}
|
|
return cmp;
|
|
}
|
|
};
|
|
|
|
/*
|
|
* This wrapper is only used for HdfsPredicateCheckNull, and there is need to store any value here. We don't
|
|
* remove it because Null check is processed specially and keeping a special empty wrapper for null can
|
|
* make it less confused.
|
|
*/
|
|
class NullWrapper {
|
|
};
|
|
|
|
/*
|
|
* A template class which stores the info from the expression. This predicate will be pushed down to orc reader and
|
|
* check it before the conversion to datum.
|
|
*/
|
|
template <typename T, typename baseType>
|
|
class HdfsScanPredicate : public BaseObject {
|
|
public:
|
|
AttrNumber m_attno; // column no
|
|
Oid m_attType; // column data type
|
|
int32 m_varTypMod; // the var type of the value
|
|
HdfsQueryOperator m_strategy; // the number of strategy
|
|
Oid m_collation; // collation to use, if needed
|
|
bool m_keepFalse; // the check result keeps false if it is true
|
|
T *m_argument; // store value
|
|
#ifdef ENABLE_LLVM_COMPILE
|
|
char *m_predFunc; /* IR function pointer */
|
|
bool m_isPredJitted; /* whether use LLVM optimization or not. if the m_isPredJitted is true, use it */
|
|
void *m_jittedFunc; /* machine code address pointer. */
|
|
#endif
|
|
|
|
public:
|
|
/*
|
|
* Construct function of template class HdfsScanPredicate
|
|
*
|
|
* @_in param attNo: the index no of the column in the relation defination.
|
|
* @_in param attType: the data type oid of the current var.
|
|
* @_in param strategy: the HdfsQueryOperator(=,<,>,<=,>=,<>,!=,is null,is not null)
|
|
*/
|
|
HdfsScanPredicate(AttrNumber attNo, Oid attType, HdfsQueryOperator strategy, Oid collation, int32 varTypMod)
|
|
: m_attno(attNo),
|
|
m_attType(attType),
|
|
m_varTypMod(varTypMod),
|
|
m_strategy(strategy),
|
|
m_collation(collation),
|
|
m_keepFalse(false)
|
|
{
|
|
m_argument = New(CurrentMemoryContext) T(strategy);
|
|
#ifdef ENABLE_LLVM_COMPILE
|
|
m_predFunc = NULL;
|
|
m_isPredJitted = false;
|
|
m_jittedFunc = NULL;
|
|
#endif
|
|
}
|
|
|
|
~HdfsScanPredicate()
|
|
{
|
|
delete (m_argument);
|
|
m_argument = NULL;
|
|
}
|
|
|
|
/*
|
|
* Initialize the m_argument of HdfsScanPredicate by datumValue if it is a operation predicate.
|
|
*
|
|
* @_in param datumValue: Just as the name says, it is a value of datum.
|
|
* @_in param datumType: THe data type of the datum.
|
|
*/
|
|
inline void Init(Datum datumValue, Oid datumType, int32 typeMod)
|
|
{
|
|
if (m_strategy >= HDFS_QUERY_EQ && m_strategy <= HDFS_QUERY_NE2) {
|
|
m_argument->SetValueFromDatum(datumValue, datumType, typeMod);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* Set the keepFalse flag.
|
|
*
|
|
* @_in param keepFalse: flag indicates whether the check result keeps false.
|
|
*/
|
|
inline void setKeepFalse(bool keepFalse)
|
|
{
|
|
m_keepFalse = keepFalse;
|
|
}
|
|
|
|
/*
|
|
* Build HdfsScanPredicate which will be pushed down to orc_reader according to the filtered and-clauses, we
|
|
* can not push down the or-clauses now.
|
|
*
|
|
* @_in param expr: Expression which has been filtered by the optimizer.
|
|
* @_in param state: PlanState is used when the expr is extern_param or exec_param to afford information.
|
|
* @_in param scanstate: ScanState is used when init rumtime predicate.
|
|
* @_in param varNoPos: An order number of var in the hdfsScanPredicateArr.
|
|
* @_in param predicateArrPos: The parameter predicate position in *hdfsScanPredicateArr.
|
|
* @return True: has init predicate; False, do not init predicate, need init dynamicly on running time phase.
|
|
*/
|
|
bool BuildHdfsScanPredicateFromClause(Expr *expr, PlanState *ps, ScanState *scanstate, AttrNumber varNoPos,
|
|
int predicateArrPos);
|
|
|
|
/*
|
|
* Check the value by the predicate.
|
|
*
|
|
* @_in param value: The value to be checked, it is of basic type like int64 or char*.
|
|
* @return True: match and not filtered; False: filtered and set isSelected to false.
|
|
*/
|
|
inline bool HdfsPredicateCheckOne(baseType value)
|
|
{
|
|
return m_argument->CheckPredicate(value, m_collation);
|
|
}
|
|
};
|
|
|
|
#ifdef ENABLE_LLVM_COMPILE
|
|
/*
|
|
* Brief : Function to check if a value of basic type can match the clauses list pushed
|
|
* down. Here we do not check the length of scanClauses, and the caller need ensure it.
|
|
* Description :
|
|
* Input : value, The value to be checked, can not be NULL (it will handled by HdfsPredicateCheckNull).
|
|
* scanClauses, Clauses which can be pushed down to orc reader.
|
|
* Output : None.
|
|
* Return Value : True: means the value match the predicate pushed down, so we can not prunning it,
|
|
* False: means the value does not match the predicate pushed down, so skip it.
|
|
* Notes : If the predicate->m_isPredJitted is true, we choose LLVM optimization to check scanclauses.
|
|
*/
|
|
template <typename wrapper, typename baseType>
|
|
bool HdfsPredicateCheckValueIntForLlvm(baseType &value, List *&scanClauses)
|
|
{
|
|
ListCell *lc = NULL;
|
|
HdfsScanPredicate<wrapper, baseType> *predicate = NULL;
|
|
|
|
foreach (lc, scanClauses) {
|
|
predicate = (HdfsScanPredicate<wrapper, baseType> *)lfirst(lc);
|
|
|
|
if (NULL != predicate->m_jittedFunc) {
|
|
if (!((evaPredicateInt)(predicate->m_jittedFunc))(value)) {
|
|
return false;
|
|
}
|
|
|
|
} else {
|
|
if (HDFS_QUERY_ISNULL == predicate->m_strategy || true == predicate->m_keepFalse) {
|
|
return false;
|
|
} else if (HDFS_QUERY_ISNOTNULL == predicate->m_strategy) {
|
|
continue;
|
|
} else if (!predicate->HdfsPredicateCheckOne(value)) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* Brief : Function to check if a value of basic type can match the clauses list pushed
|
|
* down. Here we do not check the length of scanClauses, and the caller need ensure it.
|
|
* Description :
|
|
* Input : value, The value to be checked, can not be NULL (it will handled by HdfsPredicateCheckNull).
|
|
* scanClauses, Clauses which can be pushed down to orc reader.
|
|
* Output : None.
|
|
* Return Value : True: means the value match the predicate pushed down, so we can not prunning it,
|
|
* False: means the value does not match the predicate pushed down, so skip it.
|
|
* Notes : If the predicate->m_isPredJitted is true, we choose LLVM optimization to check scanclauses.
|
|
*/
|
|
template <typename wrapper, typename baseType>
|
|
bool HdfsPredicateCheckValueDoubleForLlvm(baseType &value, List *&scanClauses)
|
|
{
|
|
ListCell *lc = NULL;
|
|
HdfsScanPredicate<wrapper, baseType> *predicate = NULL;
|
|
|
|
foreach (lc, scanClauses) {
|
|
predicate = (HdfsScanPredicate<wrapper, baseType> *)lfirst(lc);
|
|
|
|
if (NULL != predicate->m_jittedFunc) {
|
|
if (!((evaPredicateDouble)(predicate->m_jittedFunc))((double)value)) {
|
|
return false;
|
|
}
|
|
|
|
} else {
|
|
if (HDFS_QUERY_ISNULL == predicate->m_strategy || true == predicate->m_keepFalse) {
|
|
return false;
|
|
} else if (HDFS_QUERY_ISNOTNULL == predicate->m_strategy) {
|
|
continue;
|
|
} else if (!predicate->HdfsPredicateCheckOne(value)) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
#endif
|
|
|
|
/*
|
|
* Function to check if a value of basic type can match the clauses list pushed down. Here we do not
|
|
* check the length of scanClauses, and the caller need ensure it.
|
|
*
|
|
* @_in param value: The value to be checked, can not be NULL (it will handled by HdfsPredicateCheckNull).
|
|
* @_in param scanClauses: Clauses which can be pushed down to orc reader.
|
|
*
|
|
* @return True: means the value match the predicate pushed down, so we can not prunning it,
|
|
* False: means the value does not match the predicate pushed down, so skip it.
|
|
*/
|
|
template <typename wrapper, typename baseType>
|
|
bool HdfsPredicateCheckValue(baseType &value, List *&scanClauses)
|
|
{
|
|
ListCell *lc = NULL;
|
|
HdfsScanPredicate<wrapper, baseType> *predicate = NULL;
|
|
|
|
foreach (lc, scanClauses) {
|
|
predicate = (HdfsScanPredicate<wrapper, baseType> *)lfirst(lc);
|
|
|
|
if (true == predicate->m_keepFalse) {
|
|
return false;
|
|
} else if (HDFS_QUERY_ISNULL == predicate->m_strategy) {
|
|
return false;
|
|
} else if (HDFS_QUERY_ISNOTNULL == predicate->m_strategy) {
|
|
continue;
|
|
} else if (!predicate->HdfsPredicateCheckOne(value)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
* Function to check if a null value can match the clauses list pushed down.
|
|
*
|
|
* @_in param scanClauses: Clauses which can be pushed down for the partition and orc reader.
|
|
*
|
|
* @return True: means the value match the predicate pushed down, so we can not prunning it,
|
|
* False: means the value does not match the predicate pushed down, so skip it.
|
|
*/
|
|
template <typename T>
|
|
bool HdfsPredicateCheckNull(List *scanClauses)
|
|
{
|
|
ListCell *lc = NULL;
|
|
HdfsScanPredicate<T, void *> *predicate = NULL;
|
|
|
|
if (0 == list_length(scanClauses))
|
|
return true;
|
|
|
|
foreach (lc, scanClauses) {
|
|
predicate = (HdfsScanPredicate<T, void *> *)lfirst(lc);
|
|
if (true == predicate->m_keepFalse) {
|
|
return false;
|
|
} else if (HDFS_QUERY_ISNULL == predicate->m_strategy) {
|
|
continue;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* @Description: Check the column value by predicates.
|
|
* @in isNull, Whether the column is null value.
|
|
* @in value, If the column is not null, it presents the column value.
|
|
* @in predicateList, The pushdown predicates on this column.
|
|
* @return If the column value satisfies the predicates, return true, otherwise
|
|
* return false.
|
|
*/
|
|
template <typename wrapper, typename baseType>
|
|
bool HdfsPredicateCheck(bool isNull, baseType value, List *predicateList)
|
|
{
|
|
bool filtered = false;
|
|
if (isNull) {
|
|
filtered = HdfsPredicateCheckNull<NullWrapper>(predicateList);
|
|
} else {
|
|
filtered = HdfsPredicateCheckValue<wrapper, baseType>(value, predicateList);
|
|
}
|
|
|
|
return filtered;
|
|
}
|
|
|
|
/**
|
|
* @Description: Identify the qual which could be pushed down to
|
|
* file level(e.g. ORC reader level).
|
|
* @out hdfsPushDownQual: List to store all the clauses to push down.
|
|
* @in/out primitiveQual: As a input parameter, it represents all expression
|
|
* restrictions. As a output parameter, it represents actual expression
|
|
* restrictions for bottom scan(.e.g. dfs scan, foreign scan).
|
|
* @return Return the list of the column no which maps the pushdown qual.
|
|
*/
|
|
List *fix_pushdown_qual(List **hdfsPushDownQual, List **primitiveQual, const List *part_list);
|
|
|
|
/*
|
|
* Convert a char* to Datum according to the data type oid.
|
|
*
|
|
* @_in param typeOid: The oid of the type in pg_type catalog.
|
|
* @_in param typeMod: The mod of data type.
|
|
* @_in param value: The string value which need to be converted to datum.
|
|
* @return Return the datum converted from String.
|
|
*/
|
|
Datum GetDatumFromString(Oid typeOid, int4 typeMod, char *value);
|
|
|
|
void GetStringFromDatum(Oid typeOid, int4 typeMod, Datum data, StringInfo string);
|
|
|
|
/*
|
|
* Initialize a folder split by the folder name, filename(both folder name and filename comprise the absolute file
|
|
* path), columnNo list of partition and column value list of partition.
|
|
*
|
|
* @_in param fileName: name of the file.
|
|
* @_in param partContentList: the list of value in partition column.
|
|
* @_in param objectSize: the size of the current object
|
|
* @return Return the constructed split.
|
|
*/
|
|
SplitInfo *InitFolderSplit(char *fileName, List *partContentList, int64 objectSize);
|
|
|
|
/*
|
|
* Initialize a file split by the file path, columnNo list of partition and column value list of partition. This is
|
|
* different from InitFolderSplit for it use the absolute file path as the param and has no file name which is used for
|
|
* partition only.
|
|
*
|
|
* @_in param filePath: the absolute path of the split file.
|
|
* @_in param partContentList: the list of value in partition column.
|
|
* @_in param fileSize: the size of the current object
|
|
* @return Return the constructed split.
|
|
*/
|
|
SplitInfo *InitFileSplit(char *filePath, List *partContentList, int64 fileSize);
|
|
|
|
/*
|
|
* Destroy all the structors in the split.
|
|
* @_in param split: The split need to to clean and is not used any more.
|
|
*/
|
|
void DestroySplit(SplitInfo *split);
|
|
|
|
/*
|
|
* Build a basic Operator expression.
|
|
* @_in param variable: The var according to whose type we build the base constraint.
|
|
* @return Return and OpExpression.
|
|
*/
|
|
Node *MakeBaseConstraint(Var *variable, Datum minValue, Datum maxValue, bool hasMinimum, bool hasMaximum);
|
|
|
|
Node *MakeBaseConstraintWithExpr(OpExpr *lessThanExpr, OpExpr *greaterThanExpr, Datum minValue, Datum maxValue,
|
|
bool hasMinimum, bool hasMaximum);
|
|
|
|
OpExpr *MakeOperatorExpression(Var *variable, int16 strategyNumber);
|
|
|
|
/*
|
|
* Build a new null test expr with the given type.
|
|
*
|
|
* @_in param variable: The value based on which we build a NullTest expression.
|
|
* @_in param type: is null or is not null.
|
|
* @return Return the NullTest expression we build here.
|
|
*/
|
|
Node *BuildNullTestConstraint(Var *variable, NullTestType type);
|
|
|
|
/*
|
|
* Fill the expression with the const value.
|
|
* @_in param equalExpr: the expression of the constraint.
|
|
* @_in param value: Value to be filled for the right op.
|
|
* @_in param isNull: Whether the value is null.
|
|
* @return Return the constraint.
|
|
*/
|
|
Node *BuildConstraintConst(Expr *equalExpr, Datum value, bool isNull);
|
|
|
|
/*
|
|
* Fetch the Var according to the column no from the columnList, used in partition filter.
|
|
*
|
|
* @_in param columnList: The column list from which we find the var.
|
|
* @_in param colNo: The column index by which we find the var.
|
|
* @return Return null: we don't find the var in the list with the colno; not null: we find the var and return it.
|
|
*/
|
|
Var *GetVarFromColumnList(List *columnList, int colNo);
|
|
|
|
/*
|
|
* Return the digits of a int value. like 0 return 1, 10 return 2.
|
|
*/
|
|
uint64 GetDigitOfInt(uint64 x);
|
|
|
|
/*
|
|
* Encode the uri char. Like "#" -> "%23", used in partition filter.
|
|
*
|
|
* @_in param pSrc: The uri format string to be encoded.
|
|
* @return Return the encoded string.
|
|
*/
|
|
char *UriEncode(const char *pSrc);
|
|
|
|
/*
|
|
* Decode the uri char. Like "%23" -> "#", used in partition filter.
|
|
*
|
|
* @_in param pSrc: The uri format string to be decoded.
|
|
* @return Return the decoded string.
|
|
*/
|
|
char *UriDecode(const char *pSrc);
|
|
|
|
/*
|
|
* Construct a node of DfsPrivateItem.
|
|
*/
|
|
DfsPrivateItem *MakeDfsPrivateItem(List *columnList, List *targetList, List *restrictColList, List *opExpressionList,
|
|
List *dnTask, List *hdfsQual, double *selectivity, int colNum, List *partList);
|
|
|
|
/*
|
|
* Parse the fileNames string from the split List.
|
|
* @_in_out param splitList: point to the original split List, which may contain multiple files.
|
|
* @_in param currentFileName: point to the first file.
|
|
* @return Return the split parsed from the list.
|
|
*/
|
|
SplitInfo *ParseFileSplitList(List **splitList, char **currentFileName);
|
|
|
|
/*
|
|
* @Description: find a split from the split list by file ID
|
|
* @IN splitList: the list of all splits
|
|
* @IN fileID: the file id
|
|
* @Return: the split if found, or return NULL
|
|
* @See also:
|
|
*/
|
|
SplitInfo *FindFileSplitByID(List *splitList, int fileID);
|
|
|
|
/**
|
|
* @Description: Set all the rows of current ScalarVector with the same value transfered.
|
|
* The value can be null.
|
|
* @in vec, The scalar vector to which we set the value.
|
|
* @in rowsToRead, The number of rows to set.
|
|
* @in value: The fixed value to set all the rows.
|
|
* @in isNull, Whether the column value is null.
|
|
* @return None.
|
|
*/
|
|
void SetAllValue(ScalarVector *vec, int rows, Datum value, bool isNull);
|
|
|
|
/* Brief: Acquires column information needed for this foreign table from the restriction.
|
|
* Returns them in a new list.
|
|
* input param @rel: relation information struct pointer.
|
|
*/
|
|
List *GetRestrictColumns(List *neededList, int count);
|
|
|
|
/*
|
|
* Merge two list and kick out the repeated one.
|
|
* _in_param targetList: The list of the target columns.
|
|
* _in_param restrictList: The list of the restriction columns.
|
|
* _in_param count: The length of the result list.
|
|
* @return the merged and de-duplicated list.
|
|
*/
|
|
List *MergeList(List *targetList, List *restrictList, int count);
|
|
|
|
/*
|
|
* @Description: build the columns list for dfsscan, which comes from reltargetlist
|
|
* and exclude the index columns.
|
|
* @IN reltargetlist: the primitive target list
|
|
* @IN excludedColList: the columns which should be abandoned.
|
|
* @Return: the final reader list for dfs scan
|
|
* @See also:
|
|
*/
|
|
List *build_dfs_reader_tlist(List *reltargetlist, List *excludedColList);
|
|
|
|
/*
|
|
* Calculate the predicate selectivity of each column.
|
|
*/
|
|
void CalculateWeightByColumns(PlannerInfo *root, List *hdfsQualColumn, List *hdfsQual, double *selectivity, int colNum);
|
|
|
|
/*
|
|
*brief: Check column data type for orc table.
|
|
*input param @ColType: Oid of column data type;
|
|
*input param @ColName: column name.
|
|
*/
|
|
void OrcCheckDataType(TypeName *typName, char *ColName, char *fileType = NULL);
|
|
|
|
/*
|
|
* Fill up the structure: readerState which can not be NULL.
|
|
*/
|
|
void FillReaderState(dfs::reader::ReaderState *readerState, ScanState *ss, DfsPrivateItem *item,
|
|
Snapshot snapshot = NULL);
|
|
|
|
/*
|
|
* brief: Check foldername, filenames, hdfscfgpath format. The rules are the followings:
|
|
* 1. The space do not allow appear in the entrie OptStr, but '\ ' is needed
|
|
* 2. The comma do not appera in beignning and ending of OptStr
|
|
* 3. The comma as a separator exists if OptStr have many filenames path
|
|
* 4. Only a foldername path exists for foldername option and hdfscfgpath
|
|
* 5. The OptStr do not be empty
|
|
* input param @OptStr: the foldername path or file names or hdfscfgpath string
|
|
* input param @OptType: a foldername, a filenames or a hdfscfgpath type
|
|
*/
|
|
void CheckFoldernameOrFilenamesOrCfgPtah(const char *OptStr, char *OptType);
|
|
|
|
/*
|
|
* brief: Check or get port and ip of foreign server(Only support ipv4 format),
|
|
* the rules are the followings:
|
|
* 1. The space do not allow appear in the entrie Address
|
|
* 2. The comma do not appera in beignning and ending of Address
|
|
* 3. The comma as a separator exists if OptStr have many address
|
|
* 4. The Address do not be empty
|
|
* input param @Address: address option of foreign server
|
|
* output param @AddrList: return List included port and ip
|
|
* input param @IsCheck: if IsCheck is true, only check, else get port and ip
|
|
*/
|
|
void CheckGetServerIpAndPort(const char *Address, List **AddrList, bool IsCheck, int real_addr_max);
|
|
|
|
/*
|
|
* brief: Build internal executor parameter predicate for pushdown of dfs scan
|
|
* when excute plan.
|
|
* input param @readerState: Includes all the params which are used during reading.
|
|
*/
|
|
void BuildRunTimePredicates(dfs::reader::ReaderState *readerState);
|
|
|
|
/**
|
|
* @Description: Get the int64 data according to the column type.
|
|
* @in datumValue, the datum value.
|
|
* @in colVar, The Var struct. It keeps data type. As for decimal data, the
|
|
* precision store here.
|
|
* @return return the transformed data.
|
|
*/
|
|
int64_t datumGetInt64ByVar(Datum datumValue, Var *colVar);
|
|
|
|
/**
|
|
* @Description: Get the int128 data according to the column type. Currently,
|
|
* only the decimal may be converted to int128 data.
|
|
* @in datumValue, the datum value.
|
|
* @in colVar, The Var struct. It keeps data type. As for decimal data, the
|
|
* precision store here.
|
|
* @return return the transformed data.
|
|
*/
|
|
__int128 datumGetInt128ByVar(Datum datumValue, Var *colVar);
|
|
|
|
/**
|
|
* @Description: Get the float8 data according to the column type.
|
|
* @in datumValue, the datum value.
|
|
* @in colVar, The Var struct. It keeps data type.
|
|
* @return return the transformed data.
|
|
*/
|
|
double datumGetFloat8ByVar(Datum datumValue, Var *colVar);
|
|
|
|
/**
|
|
* @Description: Get the string data according to the column type.
|
|
* @in datumValue, the datum value.
|
|
* @in colVar, The Var struct. It keeps data type.
|
|
* @return return the transformed data.
|
|
*/
|
|
char *datumGetStringByVar(Datum datumValue, Var *colVar);
|
|
|
|
/*
|
|
*
|
|
* brief: Generate column list.
|
|
* input param @attributes: information of pg_attribure;
|
|
* input param @columnCount: the count of column.
|
|
* input param @colIdx: The column idx array.
|
|
*/
|
|
List *CreateColList(Form_pg_attribute *attributes, const int columnCount, const int16 *colIdx = NULL);
|
|
|
|
/*
|
|
* @Description: remove the elements of the 'del' list in the 'src' list
|
|
*/
|
|
void list_delete_list(List **src, List *del);
|
|
|
|
/**
|
|
* @Description: Check the given file encoding.
|
|
* @in optionDef: The envoding string.
|
|
* @return None.
|
|
*/
|
|
void checkEncoding(DefElem *optionDef);
|
|
|
|
int FindLastCharPos(char seperator, const char *srcString);
|
|
|
|
bool IsVarNode(Node *node);
|
|
|
|
/**
|
|
* @Description: The default column value satisfies whether predicates.
|
|
* @in isNull, The default column whether is null.
|
|
* @in value, The default column value.
|
|
* @in colVar, The Var sturct of default column.
|
|
* @in predicateList, The default column predicates.
|
|
* @return If the default column value satisfies the default column predicates,
|
|
* return true, otherwise return false.
|
|
* @Notes: Only the column of the pushed down data type can reach here.
|
|
*/
|
|
bool defColSatisfyPredicates(bool isNull, Datum value, Var *col_var, List *predicate_list);
|
|
|
|
/**
|
|
* @Description: Convert the string according to the database encoding and original encoding.
|
|
* @in src: the input string.
|
|
* @in length: the length of the input string.
|
|
* @in encoding: the original encoding.
|
|
* @return the converted string.
|
|
*/
|
|
char *pg_to_server_withfailure(char *src, int64 length, int32 encoding, int32 checkEncodingLevel, bool &meetError);
|
|
|
|
BlockNumber getPageCountForFt(void *additionalData);
|
|
|
|
#define QUERY_NOT_SUPPORT(foreignTableId, msg) do { \
|
|
Relation relation = RelationIdGetRelation(foreignTableId); \
|
|
if (RelationIsValid(relation)) \
|
|
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmodule(MOD_DFS), \
|
|
errmsg(msg, RelationGetRelationName(relation)))); \
|
|
else \
|
|
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmodule(MOD_DFS), \
|
|
errmsg("could not open relation with OID %u", foreignTableId))); \
|
|
} while (0)
|
|
|
|
#endif /* ORC_QUERY_H_ */
|