blob: 6b0bd8bffb264968b2320a05547c4bf5dad40931 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
#include <stdarg.h>
#include <stddef.h>
#include <setjmp.h>
#include "cmockery.h"
#include "c.h"
#include "../pxffilters.c"
void run__scalar_const_to_str(Const* input, StringInfo result, char* expected);
void run__scalar_const_to_str__negative(Const* input, StringInfo result, char* value);
void run__list_const_to_str(Const* input, StringInfo result, char* expected);
void run__list_const_to_str__negative(Const* input, StringInfo result, int len, Datum *dats);
/* date_eq(date, date) => bool */
#define DateEqualFuncId 1086
void
test__supported_filter_type(void **state)
{
Oid oids[] =
{
INT2OID,
INT4OID,
INT8OID,
FLOAT4OID,
FLOAT8OID,
NUMERICOID,
TEXTOID,
VARCHAROID,
BPCHAROID,
CHAROID,
BOOLOID,
DATEOID,
CIRCLEOID /* unsupported type */
};
int array_size = sizeof(oids) / sizeof(oids[0]);
bool result = false;
int i = 0;
/* supported types */
for (; i < array_size-1; ++i)
{
result = supported_filter_type(oids[i]);
assert_true(result);
}
/* unsupported type */
result = supported_filter_type(oids[i]);
assert_false(result);
/* go over pxf_supported_types array */
int nargs = sizeof(pxf_supported_types) / sizeof(Oid);
assert_int_equal(nargs, 18);
for (i = 0; i < nargs; ++i)
{
assert_true(supported_filter_type(pxf_supported_types[i]));
}
}
void
test__supported_operator_type_op_expr(void **state)
{
Oid operator_oids[13][2] = {
{ Int2EqualOperator, PXFOP_EQ },
{ 95, PXFOP_LT },
{ 520, PXFOP_GT },
{ 522, PXFOP_LE },
{ 524, PXFOP_GE },
{ 519, PXFOP_NE },
{ Int4EqualOperator, PXFOP_EQ },
{ 97, PXFOP_LT },
{ 521, PXFOP_GT },
{ 523, PXFOP_LE },
{ 525, PXFOP_GE },
{ 518, PXFOP_NE },
{ InvalidOid, InvalidOid }
};
PxfFilterDesc *filter = (PxfFilterDesc*) palloc0(sizeof(PxfFilterDesc));
int array_size = sizeof(operator_oids) / sizeof(operator_oids[0]);
bool result = false;
int i = 0;
/* supported types */
for (; i < array_size-1; ++i)
{
result = supported_operator_type_op_expr(operator_oids[i][0], filter);
assert_true(result);
assert_true(operator_oids[i][1] == filter->op);
}
/* unsupported type */
result = supported_operator_type_op_expr(operator_oids[i][0], filter);
assert_false(result);
/* go over pxf_supported_opr_op_expr array */
int nargs = sizeof(pxf_supported_opr_op_expr) / sizeof(dbop_pxfop_map);
assert_int_equal(nargs, 91);
for (i = 0; i < nargs; ++i)
{
assert_true(supported_operator_type_op_expr(pxf_supported_opr_op_expr[i].dbop, filter));
assert_true(pxf_supported_opr_op_expr[i].pxfop == filter->op);
}
}
void
test__supported_operator_type_scalar_array_op_expr(void **state)
{
Oid operator_oids[15][2] = {
{Int2EqualOperator, PXFOP_IN},
{Int4EqualOperator, PXFOP_IN},
{Int8EqualOperator, PXFOP_IN},
{TextEqualOperator, PXFOP_IN},
{Int24EqualOperator, PXFOP_IN},
{Int42EqualOperator, PXFOP_IN},
{Int84EqualOperator, PXFOP_IN},
{Int48EqualOperator, PXFOP_IN},
{Int28EqualOperator, PXFOP_IN},
{Int82EqualOperator, PXFOP_IN},
{DateEqualOperator, PXFOP_IN},
{Float8EqualOperator, PXFOP_IN},
{1120 , PXFOP_IN},
{BPCharEqualOperator, PXFOP_IN},
{BooleanEqualOperator, PXFOP_IN},
};
PxfFilterDesc *filter = (PxfFilterDesc*) palloc0(sizeof(PxfFilterDesc));
int array_size = sizeof(operator_oids) / sizeof(operator_oids[0]);
bool result = false;
int i = 0;
/* supported types */
for (; i < array_size-1; ++i)
{
result = supported_operator_type_scalar_array_op_expr(operator_oids[i][0], filter, true);
assert_true(result);
assert_true(operator_oids[i][1] == filter->op);
}
/* unsupported type */
result = supported_operator_type_op_expr(InvalidOid, filter);
assert_false(result);
/* go over pxf_supported_opr_scalar_array_op_expr array */
int nargs = sizeof(pxf_supported_opr_scalar_array_op_expr) / sizeof(dbop_pxfop_array_map);
assert_int_equal(nargs, 15);
for (i = 0; i < nargs; ++i)
{
assert_true(supported_operator_type_scalar_array_op_expr(pxf_supported_opr_op_expr[i].dbop, filter, pxf_supported_opr_scalar_array_op_expr[i].useOr));
assert_true(pxf_supported_opr_scalar_array_op_expr[i].pxfop == filter->op);
}
}
/*
* const_value must be palloc'ed, it will be freed by scalar_const_to_str
*/
void
mock__scalar_const_to_str(Oid const_type, char* const_value)
{
expect_value(getTypeOutputInfo, type, const_type);
expect_any(getTypeOutputInfo, typOutput);
expect_any(getTypeOutputInfo, typIsVarlena);
will_return(getTypeOutputInfo, NULL);
expect_any(OidOutputFunctionCall, functionId);
expect_any(OidOutputFunctionCall, val);
will_return(OidOutputFunctionCall, const_value);
}
/*
* const_value must be palloc'ed, it will be freed by list_const_to_str
*/
void
mock__list_const_to_str(Oid const_type, int len, Datum *dats) {
expect_any(pg_detoast_datum, datum);
will_return(pg_detoast_datum, NULL);
expect_any(deconstruct_array, array);
expect_any(deconstruct_array, elmtype);
expect_any(deconstruct_array, elmlen);
expect_any(deconstruct_array, elmbyval);
expect_any(deconstruct_array, elmalign);
expect_any(deconstruct_array, elemsp);
expect_any(deconstruct_array, nullsp);
expect_any(deconstruct_array, nelemsp);
will_return(deconstruct_array, NULL);
will_assign_value(deconstruct_array, nelemsp, len);
will_assign_value(deconstruct_array, elemsp, dats);
if (const_type == TEXTARRAYOID)
{
for (int i = 0; i < len; i++)
{
expect_any(DirectFunctionCall1, func);
expect_any(DirectFunctionCall1, arg1);
will_return(DirectFunctionCall1, dats[i]);
}
}
}
void
verify__scalar_const_to_str(bool is_null, char* const_value, Oid const_type, char* expected)
{
StringInfo result = makeStringInfo();
char* value = NULL;
Const* input = (Const*) palloc0(sizeof(Const));
input->constisnull = is_null;
input->consttype = const_type;
/* need to prepare inner functions */
if (!is_null)
{
value = strdup(const_value); /* will be free'd by scalar_const_to_str */
mock__scalar_const_to_str(const_type, value);
}
/* no expected value means it's a negative test */
if (expected)
{
run__scalar_const_to_str(input, result, expected);
}
else
{
run__scalar_const_to_str__negative(input, result, value);
pfree(value); /* value was not freed by scalar_const_to_str b/c of failure */
}
pfree(result->data);
pfree(result);
pfree(input);
}
void
verify__list_const_to_str(Oid const_type, char* expected, int len, Datum *dats)
{
StringInfo result = makeStringInfo();
Const* input = (Const*) palloc0(sizeof(Const));
input->constisnull = false;
input->consttype = const_type;
/* need to prepare inner functions */
mock__list_const_to_str(const_type, len, dats);
/* no expected value means it's a negative test */
if (expected)
{
run__list_const_to_str(input, result, expected);
}
else
{
run__list_const_to_str__negative(input, result, len, dats);
}
pfree(result->data);
pfree(result);
pfree(input);
}
void
test__list_const_to_str__int(void **state) {
Datum dats8[3] = {Int8GetDatum(1), Int8GetDatum(2), Int8GetDatum(3)};
verify__list_const_to_str(INT2ARRAYOID, "s1d1s1d2s1d3", 3, dats8);
Datum dats16[1] = {Int16GetDatum(42)};
verify__list_const_to_str(INT4ARRAYOID, "s2d42", 1, dats16);
Datum dats32[2] = {Int32GetDatum(11), Int32GetDatum(22)};
verify__list_const_to_str(INT4ARRAYOID, "s2d11s2d22", 2, dats32);
}
void
test__list_const_to_str__boolean(void **state)
{
Datum dats1[2] = {BoolGetDatum(true), BoolGetDatum(false)};
verify__list_const_to_str(BOOLARRAYOID, "s4dtrues5dfalse", 2, dats1);
Datum dats2[2] = {BoolGetDatum(false), BoolGetDatum(true)};
verify__list_const_to_str(BOOLARRAYOID, "s5dfalses4dtrue", 2, dats2);
Datum dats3[1] = {BoolGetDatum(true)};
verify__list_const_to_str(BOOLARRAYOID, "s4dtrue", 1, dats3);
Datum dats4[1] = {BoolGetDatum(false)};
verify__list_const_to_str(BOOLARRAYOID, "s5dfalse", 1, dats4);
}
void
test__list_const_to_str__text(void **state)
{
Datum dats1[2] = {CStringGetDatum("row1"), CStringGetDatum("row2")};
verify__list_const_to_str(TEXTARRAYOID, "s4drow1s4drow2", 2, dats1);
Datum dats2[3] = {CStringGetDatum("r,o,w,1"), CStringGetDatum("r'o'w2"), CStringGetDatum("r\"o\"w3")};
verify__list_const_to_str(TEXTARRAYOID, "s7dr,o,w,1s6dr'o'w2s6dr\"o\"w3", 3, dats2);
}
void run__scalar_const_to_str(Const* input, StringInfo result, char* expected)
{
scalar_const_to_str(input, result);
assert_string_equal(result->data, expected);
}
void run__scalar_const_to_str__negative(Const* input, StringInfo result, char* value)
{
StringInfo err_msg = makeStringInfo();
appendStringInfo(err_msg,
"internal error in pxffilters.c:scalar_const_to_str. "
"Using unsupported data type (%d) (value %s)", input->consttype, value);
/* Setting the test -- code omitted -- */
PG_TRY();
{
/* This will throw a ereport(ERROR).*/
scalar_const_to_str(input, result);
}
PG_CATCH();
{
CurrentMemoryContext = 1;
ErrorData *edata = CopyErrorData();
/* Validate the type of expected error */
assert_true(edata->sqlerrcode == ERRCODE_INTERNAL_ERROR);
assert_true(edata->elevel == ERROR);
assert_string_equal(edata->message, err_msg->data);
pfree(err_msg->data);
pfree(err_msg);
return;
}
PG_END_TRY();
assert_true(false);
}
void run__list_const_to_str(Const* input, StringInfo result, char* expected)
{
list_const_to_str(input, result);
assert_string_equal(result->data, expected);
}
void run__list_const_to_str__negative(Const* input, StringInfo result, int len, Datum *dats)
{
StringInfo err_msg = makeStringInfo();
appendStringInfo(err_msg,
"internal error in pxffilters.c:list_const_to_str. "
"Using unsupported data type (%d) (len %d)", input->consttype, len);
/* Setting the test -- code omitted -- */
PG_TRY();
{
/* This will throw a ereport(ERROR).*/
list_const_to_str(input, result);
}
PG_CATCH();
{
CurrentMemoryContext = 1;
ErrorData *edata = CopyErrorData();
/* Validate the type of expected error */
assert_true(edata->sqlerrcode == ERRCODE_INTERNAL_ERROR);
assert_true(edata->elevel == ERROR);
assert_string_equal(edata->message, err_msg->data);
pfree(err_msg->data);
pfree(err_msg);
return;
}
PG_END_TRY();
assert_true(false);
}
void
test__scalar_const_to_str__null(void **state)
{
verify__scalar_const_to_str(true, NULL, 1, NullConstValue);
}
void
test__scalar_const_to_str__int(void **state)
{
verify__scalar_const_to_str(false, "1234", INT2OID, "1234");
verify__scalar_const_to_str(false, "1234", INT4OID, "1234");
verify__scalar_const_to_str(false, "1234", INT8OID, "1234");
verify__scalar_const_to_str(false, "1.234", FLOAT4OID, "1.234");
verify__scalar_const_to_str(false, "1.234", FLOAT8OID, "1.234");
verify__scalar_const_to_str(false, "1234", NUMERICOID, "1234");
}
void
test__scalar_const_to_str__text(void **state)
{
verify__scalar_const_to_str(false, "that", TEXTOID, "that");
verify__scalar_const_to_str(false, "joke", VARCHAROID, "joke");
verify__scalar_const_to_str(false, "isn't", BPCHAROID, "isn't");
verify__scalar_const_to_str(false, "funny", CHAROID, "funny");
verify__scalar_const_to_str(false, "anymore", BYTEAOID, "anymore");
verify__scalar_const_to_str(false, "iamdate", DATEOID, "iamdate");
}
void
test__scalar_const_to_str__boolean(void **state)
{
verify__scalar_const_to_str(false, "t", BOOLOID, "true");
verify__scalar_const_to_str(false, "f", BOOLOID, "false");
}
void
test__scalar_const_to_str__NegativeCircle(void **state)
{
verify__scalar_const_to_str(false, "<3,3,9>", CIRCLEOID, NULL);
}
void
test__opexpr_to_pxffilter__null(void **state)
{
PxfFilterDesc *filter = (PxfFilterDesc*) palloc0(sizeof(PxfFilterDesc));
OpExpr *expr = (OpExpr*) palloc0(sizeof(OpExpr));
assert_false(opexpr_to_pxffilter(NULL, NULL));
assert_false(opexpr_to_pxffilter(NULL, filter));
assert_false(opexpr_to_pxffilter(expr, NULL));
expr->args = NIL;
assert_false(opexpr_to_pxffilter(expr, filter));
pfree(filter);
pfree(expr);
}
void
test__opexpr_to_pxffilter__unary_expr(void **state)
{
PxfFilterDesc *filter = (PxfFilterDesc*) palloc0(sizeof(PxfFilterDesc));
OpExpr *expr = (OpExpr*) palloc0(sizeof(OpExpr));
Var *arg = (Var*) palloc0(sizeof(Var));
arg->xpr.type = T_Var;
assert_false(opexpr_to_pxffilter(NULL, NULL));
assert_false(opexpr_to_pxffilter(NULL, filter));
assert_false(opexpr_to_pxffilter(expr, NULL));
expr->args = NIL;
expr->args = lappend(expr->args, arg);
assert_false(opexpr_to_pxffilter(expr, filter));
pfree(arg);
pfree(filter);
pfree(expr);
}
void
compare_filters(PxfFilterDesc* result, PxfFilterDesc* expected)
{
assert_int_equal(result->l.opcode, expected->l.opcode);
assert_int_equal(result->l.attnum, expected->l.attnum);
if (expected->l.conststr)
assert_string_equal(result->l.conststr->data, expected->l.conststr->data);
else
assert_true(result->l.conststr == NULL);
assert_true(result->r.opcode == expected->r.opcode);
assert_int_equal(result->r.attnum, expected->r.attnum);
if (expected->r.conststr)
assert_string_equal(result->r.conststr->data, expected->r.conststr->data);
else
assert_true(result->r.conststr == NULL);
assert_int_equal(result->op, expected->op);
}
PxfFilterDesc* build_filter(char lopcode, int lattnum, char* lconststr,
char ropcode, int rattnum, char* rconststr,
PxfOperatorCode op)
{
PxfFilterDesc *filter = (PxfFilterDesc*) palloc0(sizeof(PxfFilterDesc));
filter->l.opcode = lopcode;
filter->l.attnum = lattnum;
if (lconststr)
{
filter->l.conststr = makeStringInfo();
appendStringInfoString(filter->l.conststr, lconststr);
}
filter->r.opcode = ropcode;
filter->r.attnum = rattnum;
if (rconststr)
{
filter->r.conststr = makeStringInfo();
appendStringInfoString(filter->r.conststr, rconststr);
}
filter->op = op;
return filter;
}
Var* build_var(Oid oid, int attno) {
Var *arg_var = (Var*) palloc0(sizeof(Var));
arg_var->xpr.type = T_Var;
arg_var->vartype = oid;
arg_var->varattno = attno;
return arg_var;
}
Const* build_const(Oid oid, char* value, bool expectToBeRead)
{
Const* arg_const = (Const*) palloc0(sizeof(Const));
arg_const->xpr.type = T_Const;
arg_const->constisnull = (value == NULL);
arg_const->consttype = oid;
if (value != NULL && expectToBeRead)
{
mock__scalar_const_to_str(oid, value);
}
return arg_const;
}
OpExpr* build_op_expr(void* left, void* right, int op)
{
OpExpr *expr = (OpExpr*) palloc0(sizeof(OpExpr));
expr->args = NIL;
expr->args = lappend(expr->args, left);
expr->args = lappend(expr->args, right);
expr->opno = op;
expr->xpr.type = T_OpExpr;
return expr;
}
NullTest* build_null_expr(Expr* arg, NullTestType nullType)
{
NullTest *expr = (NullTest*) palloc0(sizeof(NullTest));
expr->nulltesttype = nullType;
expr->arg = arg;
expr->xpr.type = T_NullTest;
return expr;
}
ExpressionItem* build_null_expression_item(int attnum, Oid attrtype, NullTestType nullType)
{
ExpressionItem *expressionItem = (ExpressionItem*) palloc0(sizeof(ExpressionItem));
Var *vararg = build_var(attrtype, attnum);
OpExpr *operationExpression = build_null_expr(vararg, nullType);
expressionItem->node = operationExpression;
expressionItem->processed = false;
expressionItem->parent = NULL;
return expressionItem;
}
ExpressionItem* build_expression_item(int lattnum, Oid lattrtype, char* rconststr, Oid rattrtype, int op)
{
ExpressionItem *expressionItem = (ExpressionItem*) palloc0(sizeof(ExpressionItem));
Var *leftop = build_var(lattrtype, lattnum);
Const *rightop = build_const(rattrtype, strdup(rconststr), true);
OpExpr *operationExpression = build_op_expr(leftop, rightop, op);
expressionItem->node = operationExpression;
expressionItem->processed = false;
expressionItem->parent = NULL;
return expressionItem;
}
FuncExpr* build_func_expr_operand(List *args, CoercionForm funcformat) {
FuncExpr* operand = palloc0(sizeof(FuncExpr));
((Node*) operand)->type = T_FuncExpr;
operand->args = args;
operand->funcformat = funcformat;
return operand;
}
/**
* builds FuncExpr for a following expression: function(column1, column2,...,columnk)
* columnOids - oids of column1, column2, ... types
*
* Typical representation of a functions we support:
* COERCE_EXPLICIT_CAST->COERCE_EXPLICIT_CALL->COERCE_IMPLICIT_CAST->T_Var,
* where Var holds actual arguments - column1, column2,...,columnk
*/
FuncExpr* build_nested_func_expr_operand(List *columnsOids, List *attrsIndices) {
assert_int_equal(columnsOids->length, attrsIndices->length);
ListCell *columnOidLc = NULL, *attrIndexLc = NULL;
Var *var = NULL;
List* args = NIL;
forboth(columnOidLc, columnsOids, attrIndexLc, attrsIndices) {
var = build_var(lfirst(columnOidLc), lfirst(attrIndexLc));
args = lappend(args, var);
}
FuncExpr* operandImplicitCast = build_func_expr_operand(args, COERCE_IMPLICIT_CAST);
FuncExpr* operandExplicitCall = build_func_expr_operand(list_make1(operandImplicitCast), COERCE_EXPLICIT_CALL);
FuncExpr* operandExplicitCast = build_func_expr_operand(list_make1(operandExplicitCall), COERCE_EXPLICIT_CALL);
return operandExplicitCast;
}
void run__opexpr_to_pxffilter__positive(Oid dbop, PxfOperatorCode expectedPxfOp)
{
PxfFilterDesc *filter = (PxfFilterDesc*) palloc0(sizeof(PxfFilterDesc));
Var *arg_var = build_var(INT2OID, 1);
char* const_value = strdup("1984"); /* will be free'd by const_to_str */
Const* arg_const = build_const(INT2OID, const_value, true);
OpExpr *expr = build_op_expr(arg_var, arg_const, dbop);
PxfFilterDesc* expected = build_filter(
PXF_ATTR_CODE, 1, NULL,
PXF_SCALAR_CONST_CODE, 0, "1984",
expectedPxfOp);
/* run test */
assert_true(opexpr_to_pxffilter(expr, filter));
compare_filters(filter, expected);
pxf_free_filter(expected);
pxf_free_filter(filter);
list_free_deep(expr->args); /* free all args */
pfree(expr);
}
void
test__opexpr_to_pxffilter__intGT(void **state)
{
run__opexpr_to_pxffilter__positive(520 /* int2gt */, PXFOP_GT);
}
void
test__opexpr_to_pxffilter__allSupportedTypes(void **state)
{
int nargs = sizeof(pxf_supported_opr_op_expr) / sizeof(dbop_pxfop_map);
PxfOperatorCode pxfop = 0;
Oid dbop = InvalidOid;
for (int i = 0; i < nargs; ++i)
{
dbop = pxf_supported_opr_op_expr[i].dbop;
pxfop = pxf_supported_opr_op_expr[i].pxfop;
run__opexpr_to_pxffilter__positive(dbop, pxfop);
}
}
/* NOTE: this test is not a use case - when the query includes
* 'is null' or 'is not null' the qualifier code is T_NullTest and not T_OpExpr */
void
test__opexpr_to_pxffilter__attributeEqualsNull(void **state)
{
PxfFilterDesc *filter = (PxfFilterDesc*) palloc0(sizeof(PxfFilterDesc));
Var *arg_var = build_var(INT2OID, 1);
Const* arg_const = build_const(INT2OID, NULL, true
);
OpExpr *expr = build_op_expr(arg_var, arg_const, 94 /* int2eq */);
PxfFilterDesc* expected = build_filter(
PXF_ATTR_CODE, 1, NULL,
PXF_SCALAR_CONST_CODE, 0, NullConstValue,
PXFOP_EQ);
/* run test */
assert_true(opexpr_to_pxffilter(expr, filter));
compare_filters(filter, expected);
pxf_free_filter(filter);
pxf_free_filter(expected);
list_free_deep(expr->args); /* free all args */
pfree(expr);
}
void
test__opexpr_to_pxffilter__attributeIsNull(void **state)
{
PxfFilterDesc *filter = (PxfFilterDesc*) palloc0(sizeof(PxfFilterDesc));
Var *arg_var = build_var(INT2OID, 1);
NullTest *expr = build_null_expr(arg_var, IS_NULL);
free(expr->arg);
pfree(expr);
}
/*
* Test for a query with different types.
* Types pairing are not checked, it is covered by the
* supported operations which are type specific.
*/
void
test__opexpr_to_pxffilter__differentTypes(void **state)
{
PxfFilterDesc *filter = (PxfFilterDesc*) palloc0(sizeof(PxfFilterDesc));
Var *arg_var = build_var(INT2OID, 3);
char* const_value = strdup("13"); /* will be free'd by const_to_str */
Const *arg_const = build_const(INT8OID, const_value, true);
OpExpr *expr = build_op_expr(arg_const, arg_var, 1864 /* int28lt */);
/* run test */
assert_true(opexpr_to_pxffilter(expr, filter));
PxfFilterDesc *expected = build_filter(
PXF_SCALAR_CONST_CODE, 0, "13",
PXF_ATTR_CODE, 3, NULL,
PXFOP_LT);
compare_filters(filter, expected);
pxf_free_filter(filter);
list_free_deep(expr->args); /* free all args */
pfree(expr);
}
void
test__opexpr_to_pxffilter__unsupportedTypeCircle(void **state)
{
PxfFilterDesc *filter = (PxfFilterDesc*) palloc0(sizeof(PxfFilterDesc));
Var *arg_var = build_var(CIRCLEOID, 8);
Const *arg_const = build_const(CIRCLEOID, NULL, true);
OpExpr *expr = build_op_expr(arg_const, arg_var, 0 /* whatever */);
/* run test */
assert_false(opexpr_to_pxffilter(expr, filter));
pxf_free_filter(filter);
list_free_deep(expr->args); /* free all args */
pfree(expr);
}
void
test__opexpr_to_pxffilter__twoVars(void **state)
{
PxfFilterDesc *filter = (PxfFilterDesc*) palloc0(sizeof(PxfFilterDesc));
Var *arg_var_left = build_var(INT4OID, 8);
Var *arg_var_right = build_var(INT4OID, 9);
OpExpr *expr = build_op_expr(arg_var_left, arg_var_right, 0 /* whatever */);
/* run test */
assert_false(opexpr_to_pxffilter(expr, filter));
pxf_free_filter(filter);
list_free_deep(expr->args); /* free all args */
pfree(expr);
}
void
test__opexpr_to_pxffilter__unsupportedOpNot(void **state)
{
PxfFilterDesc *filter = (PxfFilterDesc*) palloc0(sizeof(PxfFilterDesc));
Var *arg_var = build_var(INT2OID, 3);
Const *arg_const = build_const(INT2OID, NULL, true);
OpExpr *expr = build_op_expr(arg_const, arg_var, 1877 /* int2not */);
/* run test */
assert_false(opexpr_to_pxffilter(expr, filter));
pxf_free_filter(filter);
list_free_deep(expr->args); /* free all args */
pfree(expr);
}
void test__pxf_serialize_filter_list__oneFilter(void **state)
{
List* expressionItems = NIL;
ExpressionItem* filterExpressionItem = build_expression_item(1, TEXTOID, "1984", TEXTOID, TextEqualOperator);
expressionItems = lappend(expressionItems, filterExpressionItem);
char* result = pxf_serialize_filter_list(expressionItems);
assert_string_equal(result, "a0c25s4d1984o5");
pxf_free_expression_items_list(expressionItems);
expressionItems = NIL;
pfree(result);
}
void test__pxf_serialize_fillter_list__nullFilter(void **state)
{
List* expressionItems = NIL;
ExpressionItem* filterExpressionItem = build_null_expression_item(1, TEXTOID, IS_NULL);
expressionItems = lappend(expressionItems, filterExpressionItem);
char* result = pxf_serialize_filter_list(expressionItems);
assert_string_equal(result, "a0o8");
pxf_free_expression_items_list(expressionItems);
expressionItems = NIL;
pfree(result);
}
void
test__pxf_serialize_filter_list__manyFilters(void **state)
{
char* result = NULL;
List* expressionItems = NIL;
ExpressionItem* expressionItem1 = build_expression_item(1, TEXTOID, "1984", TEXTOID, TextEqualOperator);
ExpressionItem* expressionItem2 = build_expression_item(2, TEXTOID, "George Orwell", TEXTOID, TextEqualOperator);
ExpressionItem* expressionItem3 = build_expression_item(3, TEXTOID, "Winston", TEXTOID, TextEqualOperator);
ExpressionItem* expressionItem4 = build_expression_item(4, TEXTOID, "Eric-%", TEXTOID, 1209);
ExpressionItem* expressionItem5 = build_expression_item(5, TEXTOID, "\"Ugly\" string with quotes", TEXTOID, TextEqualOperator);
ExpressionItem* expressionItem6 = build_expression_item(6, TEXTOID, "", TEXTOID, TextEqualOperator);
ExpressionItem* expressionItem7 = build_null_expression_item(7, TEXTOID, IS_NOT_NULL);
expressionItems = lappend(expressionItems, expressionItem1);
expressionItems = lappend(expressionItems, expressionItem2);
expressionItems = lappend(expressionItems, expressionItem3);
expressionItems = lappend(expressionItems, expressionItem4);
expressionItems = lappend(expressionItems, expressionItem5);
expressionItems = lappend(expressionItems, expressionItem6);
expressionItems = lappend(expressionItems, expressionItem7);
result = pxf_serialize_filter_list(expressionItems);
assert_string_equal(result, "a0c25s4d1984o5a1c25s13dGeorge Orwello5a2c25s7dWinstono5a3c25s6dEric-%o7a4c25s25d\"Ugly\" string with quoteso5a5c25s0do5a6o9");
pfree(result);
int trivialExpressionItems = expressionItems->length;
add_extra_and_expression_items(expressionItems, trivialExpressionItems - 1);
assert_int_equal(expressionItems->length, 2 * trivialExpressionItems - 1);
pxf_free_expression_items_list(expressionItems);
expressionItems = NIL;
}
void
test__extractPxfAttributes_empty_quals(void **state)
{
bool qualsAreSupported;
qualsAreSupported = true;
List* quals = NIL;
extractPxfAttributes(quals, &qualsAreSupported);
assert_true(qualsAreSupported);
}
/**
* covers queries like:
* SELECT a,b,c
* FROM tab1
* WHERE d = function(e) = const
*
* d is a column number 5 of int4 datatype
* e is a column number 7 of date datatype
* const is a int4 datatype
*
*/
void
test__extractPxfAttributes_supported_function_one_arg(void **state) {
int argumentColumnIndex = 6; // index starts from 0
bool qualsAreSupported;
qualsAreSupported = true;
List* columnsOids = list_make1(DATEOID);
List* attrsIndices = list_make1(argumentColumnIndex);
// Create operands FuncExpr, Const
FuncExpr* leftop = build_nested_func_expr_operand(columnsOids, attrsIndices);
// extractPxfAttributes just extracts columns, doesn't read values of constants
Node* rightop = build_const(INT4OID, strdup("42"), false);
OpExpr* opExpr = build_op_expr(leftop, rightop, Int4EqualOperator);
List* quals = list_make1(opExpr);
// Extract columns(attributes) from WHERE clause
List* attrs = extractPxfAttributes(quals, &qualsAreSupported);
// Make sure we extracted one attribute, column e
assert_int_equal(1, attrs->length);
// Make sure it's supported
assert_true(qualsAreSupported);
ListCell* lc = NULL;
int attnum;
foreach(lc, attrs)
{
attnum = lfirst_int(lc);
// Index of attnum starts from 0
assert_int_equal(attnum + 1, argumentColumnIndex);
}
}
int
main(int argc, char* argv[])
{
cmockery_parse_arguments(argc, argv);
const UnitTest tests[] = {
unit_test(test__supported_filter_type),
unit_test(test__supported_operator_type_op_expr),
unit_test(test__scalar_const_to_str__null),
unit_test(test__scalar_const_to_str__int),
unit_test(test__scalar_const_to_str__text),
unit_test(test__scalar_const_to_str__boolean),
unit_test(test__scalar_const_to_str__NegativeCircle),
unit_test(test__list_const_to_str__int),
unit_test(test__list_const_to_str__boolean),
unit_test(test__list_const_to_str__text),
unit_test(test__opexpr_to_pxffilter__null),
unit_test(test__opexpr_to_pxffilter__unary_expr),
unit_test(test__opexpr_to_pxffilter__intGT),
unit_test(test__opexpr_to_pxffilter__allSupportedTypes),
unit_test(test__opexpr_to_pxffilter__attributeEqualsNull),
unit_test(test__opexpr_to_pxffilter__differentTypes),
unit_test(test__opexpr_to_pxffilter__unsupportedTypeCircle),
unit_test(test__opexpr_to_pxffilter__twoVars),
unit_test(test__opexpr_to_pxffilter__unsupportedOpNot),
unit_test(test__opexpr_to_pxffilter__attributeIsNull),
unit_test(test__pxf_serialize_filter_list__oneFilter),
unit_test(test__pxf_serialize_fillter_list__nullFilter),
unit_test(test__pxf_serialize_filter_list__manyFilters),
unit_test(test__extractPxfAttributes_empty_quals),
unit_test(test__extractPxfAttributes_supported_function_one_arg)
};
return run_tests(tests);
}