Skip to content

Commit

Permalink
Rename public functions and bug fix (#1)
Browse files Browse the repository at this point in the history
* [add] MATCH AGAINST pushdown
* [fix] rename is_foreign_expr to mysql_xxx
* [fix] MATCH_AGAINST return true always
* [add] target list pushdown
* [fix] boolean to integer
* [fix] typo
* porting mysql_fdw to be compatible with PGSpider 12
* update to pass mysql_fdw original test on PGSpider12
  • Loading branch information
lamduongngoc authored Jun 2, 2020
1 parent 5974209 commit 319d41b
Show file tree
Hide file tree
Showing 5 changed files with 194 additions and 52 deletions.
160 changes: 130 additions & 30 deletions deparse.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ static void mysql_print_remote_placeholder(Oid paramtype, int32 paramtypmod,
deparse_expr_cxt *context);
static void mysql_deparse_relation(StringInfo buf, Relation rel);
static void mysql_deparse_target_list(StringInfo buf, PlannerInfo *root, Index rtindex, Relation rel,
Bitmapset *attrs_used, List **retrieved_attrs);
Bitmapset *attrs_used, List **retrieved_attrs, List *tlist, RelOptInfo *baserel);
static void mysql_deparse_column_ref(StringInfo buf, int varno, int varattno, PlannerInfo *root);

/*
Expand Down Expand Up @@ -194,7 +194,9 @@ mysql_deparse_select(StringInfo buf,
PlannerInfo *root,
RelOptInfo *baserel,
Bitmapset *attrs_used,
char *svr_table, List **retrieved_attrs)
char *svr_table,
List **retrieved_attrs,
List *tlist)
{
RangeTblEntry *rte = planner_rt_fetch(baserel->relid, root);
Relation rel;
Expand All @@ -206,7 +208,8 @@ mysql_deparse_select(StringInfo buf,
rel = heap_open(rte->relid, NoLock);

appendStringInfoString(buf, "SELECT ");
mysql_deparse_target_list(buf, root, baserel->relid, rel, attrs_used, retrieved_attrs);
mysql_deparse_target_list(buf, root, baserel->relid, rel, attrs_used,
retrieved_attrs, tlist, baserel);

/*
* Construct FROM clause
Expand Down Expand Up @@ -290,41 +293,68 @@ mysql_deparse_target_list(StringInfo buf,
Index rtindex,
Relation rel,
Bitmapset *attrs_used,
List **retrieved_attrs)
List **retrieved_attrs,
List *tlist,
RelOptInfo *baserel)
{
TupleDesc tupdesc = RelationGetDescr(rel);
bool have_wholerow;
bool first;
int i;

ListCell *cell;
/* If there's a whole-row reference, we'll need all the columns. */
have_wholerow = bms_is_member(0 - FirstLowInvalidHeapAttributeNumber,
attrs_used);

first = true;

*retrieved_attrs = NIL;
for (i = 1; i <= tupdesc->natts; i++)
if (retrieved_attrs)
{
Form_pg_attribute attr = TupleDescAttr(tupdesc, i - 1);
/* Not pushdown target list */
*retrieved_attrs = NIL;
for (i = 1; i <= tupdesc->natts; i++)
{
Form_pg_attribute attr = TupleDescAttr(tupdesc, i - 1);

/* Ignore dropped attributes. */
if (attr->attisdropped)
continue;
/* Ignore dropped attributes. */
if (attr->attisdropped)
continue;

if (have_wholerow ||
bms_is_member(i - FirstLowInvalidHeapAttributeNumber,
attrs_used))
if (have_wholerow ||
bms_is_member(i - FirstLowInvalidHeapAttributeNumber,
attrs_used))
{
if (!first)
appendStringInfoString(buf, ", ");
first = false;

mysql_deparse_column_ref(buf, rtindex, i, root);
*retrieved_attrs = lappend_int(*retrieved_attrs, i);
}
}
}
else
{
/* Pushdown target list */

/* Set up context struct for recursion */
deparse_expr_cxt context;
context.root = root;
context.foreignrel = baserel;
context.buf = buf;
context.params_list = NULL;
foreach (cell, tlist)
{
Expr *expr = ((TargetEntry *)lfirst(cell))->expr;

if (!first)
appendStringInfoString(buf, ", ");
first = false;

mysql_deparse_column_ref(buf, rtindex, i, root);
*retrieved_attrs = lappend_int(*retrieved_attrs, i);
/* Deparse target list for push down */
deparseExpr(expr, &context);
}
}

/* Don't generate bad syntax if no undropped columns */
if (first)
appendStringInfoString(buf, "NULL");
Expand Down Expand Up @@ -917,19 +947,78 @@ mysql_deparse_func_expr(FuncExpr *node, deparse_expr_cxt *context)
/* Translate PostgreSQL function into mysql function */
proname = mysql_replace_function(NameStr(procform->proname));

/* Deparse the function name ... */
appendStringInfo(buf, "%s(", proname);

/* ... and all the arguments */
first = true;
foreach(arg, node->args)
if(strcmp(proname,"match_against")==0)
{
if (!first)
appendStringInfoString(buf, ", ");
deparseExpr((Expr *) lfirst(arg), context);
first = false;
/* ... and all the arguments */
first = true;
foreach(arg, node->args)
{
Expr *node;
ListCell *lc;
ArrayExpr *anode;
bool swt_arg;
node = lfirst(arg);
Assert(nodeTag(node)==T_ArrayExpr);
anode = (ArrayExpr *)node;
appendStringInfoString(buf, "MATCH (");
swt_arg = true;
foreach(lc, anode->elements)
{
Expr *node;
node=lfirst(lc);
if(nodeTag(node)==T_Var){
if (!first)
appendStringInfoString(buf, ", ");
mysql_deparse_var((Var *)node,context);
}
else if(nodeTag(node)==T_Const){
Const *cnode = (Const *)node;
if(swt_arg == true){
appendStringInfoString(buf, ") AGAINST ( ");
swt_arg = false;
first = true;
mysql_deparse_const(cnode,context);
appendStringInfoString(buf, " ");
}
else{
Oid typoutput;
const char *valptr;
char *extval;
bool typIsVarlena;
getTypeOutputInfo(cnode->consttype,
&typoutput, &typIsVarlena);

extval = OidOutputFunctionCall(typoutput, cnode->constvalue);
for (valptr = extval; *valptr; valptr++)
{
char ch = *valptr;
if (SQL_STR_DOUBLE(ch, true))
appendStringInfoChar(buf, ch);
appendStringInfoChar(buf, ch);
}
}
}
first = false;
}
appendStringInfoChar(buf, ')');
}
}
appendStringInfoChar(buf, ')');
else
{
/* Deparse the function name ... */
appendStringInfo(buf, "%s(", proname);
/* ... and all the arguments */
first = true;
foreach(arg, node->args)
{
if (!first)
appendStringInfoString(buf, ", ");
deparseExpr((Expr *) lfirst(arg), context);
first = false;
}
appendStringInfoChar(buf, ')');
}

ReleaseSysCache(proctup);
}

Expand Down Expand Up @@ -1297,6 +1386,7 @@ foreign_expr_walker(Node *node,
foreign_loc_cxt inner_cxt;
Oid collation;
FDWCollateState state;
HeapTuple tuple;

/* Need do nothing for empty subexpressions */
if (node == NULL)
Expand Down Expand Up @@ -1418,13 +1508,23 @@ foreign_expr_walker(Node *node,
case T_FuncExpr:
{
FuncExpr *fe = (FuncExpr *) node;
char *opername = NULL;

/*
* If function used by the expression is not built-in, it
* can't be sent to remote because it might have incompatible
* semantics on remote side.
*/
if (!is_builtin(fe->funcid))
tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(fe->funcid));
if (!HeapTupleIsValid(tuple))
{
elog(ERROR, "cache lookup failed for function %u", fe->funcid);
}
opername = pstrdup(((Form_pg_proc) GETSTRUCT(tuple))->proname.data);
ReleaseSysCache(tuple);

/* pushed down to mysql */
if (!is_builtin(fe->funcid) && strcmp(opername, "match_against") != 0)
return false;

/*
Expand Down Expand Up @@ -1710,7 +1810,7 @@ foreign_expr_walker(Node *node,
* Returns true if given expr is safe to evaluate on the foreign server.
*/
bool
is_foreign_expr(PlannerInfo *root,
mysql_is_foreign_expr(PlannerInfo *root,
RelOptInfo *baserel,
Expr *expr)
{
Expand Down
7 changes: 7 additions & 0 deletions mysql_fdw--1.0.sql
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,13 @@ RETURNS void
AS 'MODULE_PATHNAME'
LANGUAGE C STRICT;

CREATE FUNCTION MATCH_AGAINST(varidiadic text[]) RETURNS INT AS $$
BEGIN
RETURN 1;
END
$$ LANGUAGE plpgsql IMMUTABLE;

CREATE FOREIGN DATA WRAPPER mysql_fdw
HANDLER mysql_fdw_handler
VALIDATOR mysql_fdw_validator;

7 changes: 7 additions & 0 deletions mysql_fdw--1.1.sql
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ CREATE FOREIGN DATA WRAPPER mysql_fdw
HANDLER mysql_fdw_handler
VALIDATOR mysql_fdw_validator;

CREATE FUNCTION MATCH_AGAINST(varidiadic text[]) RETURNS INT AS $$
BEGIN
RETURN 1;
END
$$ LANGUAGE plpgsql IMMUTABLE;

CREATE OR REPLACE FUNCTION mysql_fdw_version()
RETURNS pg_catalog.int4 STRICT
AS 'MODULE_PATHNAME' LANGUAGE C;

Loading

0 comments on commit 319d41b

Please sign in to comment.