Header And Logo

PostgreSQL
| The world's most advanced open source database.

deparse.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * deparse.c
00004  *        Query deparser for postgres_fdw
00005  *
00006  * This file includes functions that examine query WHERE clauses to see
00007  * whether they're safe to send to the remote server for execution, as
00008  * well as functions to construct the query text to be sent.  The latter
00009  * functionality is annoyingly duplicative of ruleutils.c, but there are
00010  * enough special considerations that it seems best to keep this separate.
00011  * One saving grace is that we only need deparse logic for node types that
00012  * we consider safe to send.
00013  *
00014  * We assume that the remote session's search_path is exactly "pg_catalog",
00015  * and thus we need schema-qualify all and only names outside pg_catalog.
00016  *
00017  * We do not consider that it is ever safe to send COLLATE expressions to
00018  * the remote server: it might not have the same collation names we do.
00019  * (Later we might consider it safe to send COLLATE "C", but even that would
00020  * fail on old remote servers.)  An expression is considered safe to send only
00021  * if all collations used in it are traceable to Var(s) of the foreign table.
00022  * That implies that if the remote server gets a different answer than we do,
00023  * the foreign table's columns are not marked with collations that match the
00024  * remote table's columns, which we can consider to be user error.
00025  *
00026  * Portions Copyright (c) 2012-2013, PostgreSQL Global Development Group
00027  *
00028  * IDENTIFICATION
00029  *        contrib/postgres_fdw/deparse.c
00030  *
00031  *-------------------------------------------------------------------------
00032  */
00033 #include "postgres.h"
00034 
00035 #include "postgres_fdw.h"
00036 
00037 #include "access/heapam.h"
00038 #include "access/htup_details.h"
00039 #include "access/sysattr.h"
00040 #include "access/transam.h"
00041 #include "catalog/pg_collation.h"
00042 #include "catalog/pg_namespace.h"
00043 #include "catalog/pg_operator.h"
00044 #include "catalog/pg_proc.h"
00045 #include "catalog/pg_type.h"
00046 #include "commands/defrem.h"
00047 #include "nodes/nodeFuncs.h"
00048 #include "optimizer/clauses.h"
00049 #include "optimizer/var.h"
00050 #include "parser/parsetree.h"
00051 #include "utils/builtins.h"
00052 #include "utils/lsyscache.h"
00053 #include "utils/syscache.h"
00054 
00055 
00056 /*
00057  * Global context for foreign_expr_walker's search of an expression tree.
00058  */
00059 typedef struct foreign_glob_cxt
00060 {
00061     PlannerInfo *root;          /* global planner state */
00062     RelOptInfo *foreignrel;     /* the foreign relation we are planning for */
00063 } foreign_glob_cxt;
00064 
00065 /*
00066  * Local (per-tree-level) context for foreign_expr_walker's search.
00067  * This is concerned with identifying collations used in the expression.
00068  */
00069 typedef enum
00070 {
00071     FDW_COLLATE_NONE,           /* expression is of a noncollatable type */
00072     FDW_COLLATE_SAFE,           /* collation derives from a foreign Var */
00073     FDW_COLLATE_UNSAFE          /* collation derives from something else */
00074 } FDWCollateState;
00075 
00076 typedef struct foreign_loc_cxt
00077 {
00078     Oid         collation;      /* OID of current collation, if any */
00079     FDWCollateState state;      /* state of current collation choice */
00080 } foreign_loc_cxt;
00081 
00082 /*
00083  * Context for deparseExpr
00084  */
00085 typedef struct deparse_expr_cxt
00086 {
00087     PlannerInfo *root;          /* global planner state */
00088     RelOptInfo *foreignrel;     /* the foreign relation we are planning for */
00089     StringInfo  buf;            /* output buffer to append to */
00090     List      **params_list;    /* exprs that will become remote Params */
00091 } deparse_expr_cxt;
00092 
00093 /*
00094  * Functions to determine whether an expression can be evaluated safely on
00095  * remote server.
00096  */
00097 static bool foreign_expr_walker(Node *node,
00098                     foreign_glob_cxt *glob_cxt,
00099                     foreign_loc_cxt *outer_cxt);
00100 static bool is_builtin(Oid procid);
00101 
00102 /*
00103  * Functions to construct string representation of a node tree.
00104  */
00105 static void deparseTargetList(StringInfo buf,
00106                   PlannerInfo *root,
00107                   Index rtindex,
00108                   Relation rel,
00109                   Bitmapset *attrs_used,
00110                   List **retrieved_attrs);
00111 static void deparseReturningList(StringInfo buf, PlannerInfo *root,
00112                      Index rtindex, Relation rel,
00113                      List *returningList,
00114                      List **retrieved_attrs);
00115 static void deparseColumnRef(StringInfo buf, int varno, int varattno,
00116                  PlannerInfo *root);
00117 static void deparseRelation(StringInfo buf, Relation rel);
00118 static void deparseStringLiteral(StringInfo buf, const char *val);
00119 static void deparseExpr(Expr *expr, deparse_expr_cxt *context);
00120 static void deparseVar(Var *node, deparse_expr_cxt *context);
00121 static void deparseConst(Const *node, deparse_expr_cxt *context);
00122 static void deparseParam(Param *node, deparse_expr_cxt *context);
00123 static void deparseArrayRef(ArrayRef *node, deparse_expr_cxt *context);
00124 static void deparseFuncExpr(FuncExpr *node, deparse_expr_cxt *context);
00125 static void deparseOpExpr(OpExpr *node, deparse_expr_cxt *context);
00126 static void deparseOperatorName(StringInfo buf, Form_pg_operator opform);
00127 static void deparseDistinctExpr(DistinctExpr *node, deparse_expr_cxt *context);
00128 static void deparseScalarArrayOpExpr(ScalarArrayOpExpr *node,
00129                          deparse_expr_cxt *context);
00130 static void deparseRelabelType(RelabelType *node, deparse_expr_cxt *context);
00131 static void deparseBoolExpr(BoolExpr *node, deparse_expr_cxt *context);
00132 static void deparseNullTest(NullTest *node, deparse_expr_cxt *context);
00133 static void deparseArrayExpr(ArrayExpr *node, deparse_expr_cxt *context);
00134 
00135 
00136 /*
00137  * Examine each restriction clause in baserel's baserestrictinfo list,
00138  * and classify them into two groups, which are returned as two lists:
00139  *  - remote_conds contains expressions that can be evaluated remotely
00140  *  - local_conds contains expressions that can't be evaluated remotely
00141  */
00142 void
00143 classifyConditions(PlannerInfo *root,
00144                    RelOptInfo *baserel,
00145                    List **remote_conds,
00146                    List **local_conds)
00147 {
00148     ListCell   *lc;
00149 
00150     *remote_conds = NIL;
00151     *local_conds = NIL;
00152 
00153     foreach(lc, baserel->baserestrictinfo)
00154     {
00155         RestrictInfo *ri = (RestrictInfo *) lfirst(lc);
00156 
00157         if (is_foreign_expr(root, baserel, ri->clause))
00158             *remote_conds = lappend(*remote_conds, ri);
00159         else
00160             *local_conds = lappend(*local_conds, ri);
00161     }
00162 }
00163 
00164 /*
00165  * Returns true if given expr is safe to evaluate on the foreign server.
00166  */
00167 bool
00168 is_foreign_expr(PlannerInfo *root,
00169                 RelOptInfo *baserel,
00170                 Expr *expr)
00171 {
00172     foreign_glob_cxt glob_cxt;
00173     foreign_loc_cxt loc_cxt;
00174 
00175     /*
00176      * Check that the expression consists of nodes that are safe to execute
00177      * remotely.
00178      */
00179     glob_cxt.root = root;
00180     glob_cxt.foreignrel = baserel;
00181     loc_cxt.collation = InvalidOid;
00182     loc_cxt.state = FDW_COLLATE_NONE;
00183     if (!foreign_expr_walker((Node *) expr, &glob_cxt, &loc_cxt))
00184         return false;
00185 
00186     /* Expressions examined here should be boolean, ie noncollatable */
00187     Assert(loc_cxt.collation == InvalidOid);
00188     Assert(loc_cxt.state == FDW_COLLATE_NONE);
00189 
00190     /*
00191      * An expression which includes any mutable functions can't be sent over
00192      * because its result is not stable.  For example, sending now() remote
00193      * side could cause confusion from clock offsets.  Future versions might
00194      * be able to make this choice with more granularity.  (We check this last
00195      * because it requires a lot of expensive catalog lookups.)
00196      */
00197     if (contain_mutable_functions((Node *) expr))
00198         return false;
00199 
00200     /* OK to evaluate on the remote server */
00201     return true;
00202 }
00203 
00204 /*
00205  * Check if expression is safe to execute remotely, and return true if so.
00206  *
00207  * In addition, *outer_cxt is updated with collation information.
00208  *
00209  * We must check that the expression contains only node types we can deparse,
00210  * that all types/functions/operators are safe to send (which we approximate
00211  * as being built-in), and that all collations used in the expression derive
00212  * from Vars of the foreign table.  Because of the latter, the logic is
00213  * pretty close to assign_collations_walker() in parse_collate.c, though we
00214  * can assume here that the given expression is valid.
00215  */
00216 static bool
00217 foreign_expr_walker(Node *node,
00218                     foreign_glob_cxt *glob_cxt,
00219                     foreign_loc_cxt *outer_cxt)
00220 {
00221     bool        check_type = true;
00222     foreign_loc_cxt inner_cxt;
00223     Oid         collation;
00224     FDWCollateState state;
00225 
00226     /* Need do nothing for empty subexpressions */
00227     if (node == NULL)
00228         return true;
00229 
00230     /* Set up inner_cxt for possible recursion to child nodes */
00231     inner_cxt.collation = InvalidOid;
00232     inner_cxt.state = FDW_COLLATE_NONE;
00233 
00234     switch (nodeTag(node))
00235     {
00236         case T_Var:
00237             {
00238                 Var        *var = (Var *) node;
00239 
00240                 /*
00241                  * If the Var is from the foreign table, we consider its
00242                  * collation (if any) safe to use.  If it is from another
00243                  * table, we treat its collation the same way as we would a
00244                  * Param's collation, ie it's not safe for it to have a
00245                  * non-default collation.
00246                  */
00247                 if (var->varno == glob_cxt->foreignrel->relid &&
00248                     var->varlevelsup == 0)
00249                 {
00250                     /* Var belongs to foreign table */
00251                     collation = var->varcollid;
00252                     state = OidIsValid(collation) ? FDW_COLLATE_SAFE : FDW_COLLATE_NONE;
00253                 }
00254                 else
00255                 {
00256                     /* Var belongs to some other table */
00257                     if (var->varcollid != InvalidOid &&
00258                         var->varcollid != DEFAULT_COLLATION_OID)
00259                         return false;
00260 
00261                     /* We can consider that it doesn't set collation */
00262                     collation = InvalidOid;
00263                     state = FDW_COLLATE_NONE;
00264                 }
00265             }
00266             break;
00267         case T_Const:
00268             {
00269                 Const      *c = (Const *) node;
00270 
00271                 /*
00272                  * If the constant has nondefault collation, either it's of a
00273                  * non-builtin type, or it reflects folding of a CollateExpr;
00274                  * either way, it's unsafe to send to the remote.
00275                  */
00276                 if (c->constcollid != InvalidOid &&
00277                     c->constcollid != DEFAULT_COLLATION_OID)
00278                     return false;
00279 
00280                 /* Otherwise, we can consider that it doesn't set collation */
00281                 collation = InvalidOid;
00282                 state = FDW_COLLATE_NONE;
00283             }
00284             break;
00285         case T_Param:
00286             {
00287                 Param      *p = (Param *) node;
00288 
00289                 /*
00290                  * Collation handling is same as for Consts.
00291                  */
00292                 if (p->paramcollid != InvalidOid &&
00293                     p->paramcollid != DEFAULT_COLLATION_OID)
00294                     return false;
00295 
00296                 collation = InvalidOid;
00297                 state = FDW_COLLATE_NONE;
00298             }
00299             break;
00300         case T_ArrayRef:
00301             {
00302                 ArrayRef   *ar = (ArrayRef *) node;;
00303 
00304                 /* Assignment should not be in restrictions. */
00305                 if (ar->refassgnexpr != NULL)
00306                     return false;
00307 
00308                 /*
00309                  * Recurse to remaining subexpressions.  Since the array
00310                  * subscripts must yield (noncollatable) integers, they won't
00311                  * affect the inner_cxt state.
00312                  */
00313                 if (!foreign_expr_walker((Node *) ar->refupperindexpr,
00314                                          glob_cxt, &inner_cxt))
00315                     return false;
00316                 if (!foreign_expr_walker((Node *) ar->reflowerindexpr,
00317                                          glob_cxt, &inner_cxt))
00318                     return false;
00319                 if (!foreign_expr_walker((Node *) ar->refexpr,
00320                                          glob_cxt, &inner_cxt))
00321                     return false;
00322 
00323                 /*
00324                  * Array subscripting should yield same collation as input,
00325                  * but for safety use same logic as for function nodes.
00326                  */
00327                 collation = ar->refcollid;
00328                 if (collation == InvalidOid)
00329                     state = FDW_COLLATE_NONE;
00330                 else if (inner_cxt.state == FDW_COLLATE_SAFE &&
00331                          collation == inner_cxt.collation)
00332                     state = FDW_COLLATE_SAFE;
00333                 else
00334                     state = FDW_COLLATE_UNSAFE;
00335             }
00336             break;
00337         case T_FuncExpr:
00338             {
00339                 FuncExpr   *fe = (FuncExpr *) node;
00340 
00341                 /*
00342                  * If function used by the expression is not built-in, it
00343                  * can't be sent to remote because it might have incompatible
00344                  * semantics on remote side.
00345                  */
00346                 if (!is_builtin(fe->funcid))
00347                     return false;
00348 
00349                 /*
00350                  * Recurse to input subexpressions.
00351                  */
00352                 if (!foreign_expr_walker((Node *) fe->args,
00353                                          glob_cxt, &inner_cxt))
00354                     return false;
00355 
00356                 /*
00357                  * If function's input collation is not derived from a foreign
00358                  * Var, it can't be sent to remote.
00359                  */
00360                 if (fe->inputcollid == InvalidOid)
00361                      /* OK, inputs are all noncollatable */ ;
00362                 else if (inner_cxt.state != FDW_COLLATE_SAFE ||
00363                          fe->inputcollid != inner_cxt.collation)
00364                     return false;
00365 
00366                 /*
00367                  * Detect whether node is introducing a collation not derived
00368                  * from a foreign Var.  (If so, we just mark it unsafe for now
00369                  * rather than immediately returning false, since the parent
00370                  * node might not care.)
00371                  */
00372                 collation = fe->funccollid;
00373                 if (collation == InvalidOid)
00374                     state = FDW_COLLATE_NONE;
00375                 else if (inner_cxt.state == FDW_COLLATE_SAFE &&
00376                          collation == inner_cxt.collation)
00377                     state = FDW_COLLATE_SAFE;
00378                 else
00379                     state = FDW_COLLATE_UNSAFE;
00380             }
00381             break;
00382         case T_OpExpr:
00383         case T_DistinctExpr:    /* struct-equivalent to OpExpr */
00384             {
00385                 OpExpr     *oe = (OpExpr *) node;
00386 
00387                 /*
00388                  * Similarly, only built-in operators can be sent to remote.
00389                  * (If the operator is, surely its underlying function is
00390                  * too.)
00391                  */
00392                 if (!is_builtin(oe->opno))
00393                     return false;
00394 
00395                 /*
00396                  * Recurse to input subexpressions.
00397                  */
00398                 if (!foreign_expr_walker((Node *) oe->args,
00399                                          glob_cxt, &inner_cxt))
00400                     return false;
00401 
00402                 /*
00403                  * If operator's input collation is not derived from a foreign
00404                  * Var, it can't be sent to remote.
00405                  */
00406                 if (oe->inputcollid == InvalidOid)
00407                      /* OK, inputs are all noncollatable */ ;
00408                 else if (inner_cxt.state != FDW_COLLATE_SAFE ||
00409                          oe->inputcollid != inner_cxt.collation)
00410                     return false;
00411 
00412                 /* Result-collation handling is same as for functions */
00413                 collation = oe->opcollid;
00414                 if (collation == InvalidOid)
00415                     state = FDW_COLLATE_NONE;
00416                 else if (inner_cxt.state == FDW_COLLATE_SAFE &&
00417                          collation == inner_cxt.collation)
00418                     state = FDW_COLLATE_SAFE;
00419                 else
00420                     state = FDW_COLLATE_UNSAFE;
00421             }
00422             break;
00423         case T_ScalarArrayOpExpr:
00424             {
00425                 ScalarArrayOpExpr *oe = (ScalarArrayOpExpr *) node;
00426 
00427                 /*
00428                  * Again, only built-in operators can be sent to remote.
00429                  */
00430                 if (!is_builtin(oe->opno))
00431                     return false;
00432 
00433                 /*
00434                  * Recurse to input subexpressions.
00435                  */
00436                 if (!foreign_expr_walker((Node *) oe->args,
00437                                          glob_cxt, &inner_cxt))
00438                     return false;
00439 
00440                 /*
00441                  * If operator's input collation is not derived from a foreign
00442                  * Var, it can't be sent to remote.
00443                  */
00444                 if (oe->inputcollid == InvalidOid)
00445                      /* OK, inputs are all noncollatable */ ;
00446                 else if (inner_cxt.state != FDW_COLLATE_SAFE ||
00447                          oe->inputcollid != inner_cxt.collation)
00448                     return false;
00449 
00450                 /* Output is always boolean and so noncollatable. */
00451                 collation = InvalidOid;
00452                 state = FDW_COLLATE_NONE;
00453             }
00454             break;
00455         case T_RelabelType:
00456             {
00457                 RelabelType *r = (RelabelType *) node;
00458 
00459                 /*
00460                  * Recurse to input subexpression.
00461                  */
00462                 if (!foreign_expr_walker((Node *) r->arg,
00463                                          glob_cxt, &inner_cxt))
00464                     return false;
00465 
00466                 /*
00467                  * RelabelType must not introduce a collation not derived from
00468                  * an input foreign Var.
00469                  */
00470                 collation = r->resultcollid;
00471                 if (collation == InvalidOid)
00472                     state = FDW_COLLATE_NONE;
00473                 else if (inner_cxt.state == FDW_COLLATE_SAFE &&
00474                          collation == inner_cxt.collation)
00475                     state = FDW_COLLATE_SAFE;
00476                 else
00477                     state = FDW_COLLATE_UNSAFE;
00478             }
00479             break;
00480         case T_BoolExpr:
00481             {
00482                 BoolExpr   *b = (BoolExpr *) node;
00483 
00484                 /*
00485                  * Recurse to input subexpressions.
00486                  */
00487                 if (!foreign_expr_walker((Node *) b->args,
00488                                          glob_cxt, &inner_cxt))
00489                     return false;
00490 
00491                 /* Output is always boolean and so noncollatable. */
00492                 collation = InvalidOid;
00493                 state = FDW_COLLATE_NONE;
00494             }
00495             break;
00496         case T_NullTest:
00497             {
00498                 NullTest   *nt = (NullTest *) node;
00499 
00500                 /*
00501                  * Recurse to input subexpressions.
00502                  */
00503                 if (!foreign_expr_walker((Node *) nt->arg,
00504                                          glob_cxt, &inner_cxt))
00505                     return false;
00506 
00507                 /* Output is always boolean and so noncollatable. */
00508                 collation = InvalidOid;
00509                 state = FDW_COLLATE_NONE;
00510             }
00511             break;
00512         case T_ArrayExpr:
00513             {
00514                 ArrayExpr  *a = (ArrayExpr *) node;
00515 
00516                 /*
00517                  * Recurse to input subexpressions.
00518                  */
00519                 if (!foreign_expr_walker((Node *) a->elements,
00520                                          glob_cxt, &inner_cxt))
00521                     return false;
00522 
00523                 /*
00524                  * ArrayExpr must not introduce a collation not derived from
00525                  * an input foreign Var.
00526                  */
00527                 collation = a->array_collid;
00528                 if (collation == InvalidOid)
00529                     state = FDW_COLLATE_NONE;
00530                 else if (inner_cxt.state == FDW_COLLATE_SAFE &&
00531                          collation == inner_cxt.collation)
00532                     state = FDW_COLLATE_SAFE;
00533                 else
00534                     state = FDW_COLLATE_UNSAFE;
00535             }
00536             break;
00537         case T_List:
00538             {
00539                 List       *l = (List *) node;
00540                 ListCell   *lc;
00541 
00542                 /*
00543                  * Recurse to component subexpressions.
00544                  */
00545                 foreach(lc, l)
00546                 {
00547                     if (!foreign_expr_walker((Node *) lfirst(lc),
00548                                              glob_cxt, &inner_cxt))
00549                         return false;
00550                 }
00551 
00552                 /*
00553                  * When processing a list, collation state just bubbles up
00554                  * from the list elements.
00555                  */
00556                 collation = inner_cxt.collation;
00557                 state = inner_cxt.state;
00558 
00559                 /* Don't apply exprType() to the list. */
00560                 check_type = false;
00561             }
00562             break;
00563         default:
00564 
00565             /*
00566              * If it's anything else, assume it's unsafe.  This list can be
00567              * expanded later, but don't forget to add deparse support below.
00568              */
00569             return false;
00570     }
00571 
00572     /*
00573      * If result type of given expression is not built-in, it can't be sent to
00574      * remote because it might have incompatible semantics on remote side.
00575      */
00576     if (check_type && !is_builtin(exprType(node)))
00577         return false;
00578 
00579     /*
00580      * Now, merge my collation information into my parent's state.
00581      */
00582     if (state > outer_cxt->state)
00583     {
00584         /* Override previous parent state */
00585         outer_cxt->collation = collation;
00586         outer_cxt->state = state;
00587     }
00588     else if (state == outer_cxt->state)
00589     {
00590         /* Merge, or detect error if there's a collation conflict */
00591         switch (state)
00592         {
00593             case FDW_COLLATE_NONE:
00594                 /* Nothing + nothing is still nothing */
00595                 break;
00596             case FDW_COLLATE_SAFE:
00597                 if (collation != outer_cxt->collation)
00598                 {
00599                     /*
00600                      * Non-default collation always beats default.
00601                      */
00602                     if (outer_cxt->collation == DEFAULT_COLLATION_OID)
00603                     {
00604                         /* Override previous parent state */
00605                         outer_cxt->collation = collation;
00606                     }
00607                     else if (collation != DEFAULT_COLLATION_OID)
00608                     {
00609                         /*
00610                          * Conflict; show state as indeterminate.  We don't
00611                          * want to "return false" right away, since parent
00612                          * node might not care about collation.
00613                          */
00614                         outer_cxt->state = FDW_COLLATE_UNSAFE;
00615                     }
00616                 }
00617                 break;
00618             case FDW_COLLATE_UNSAFE:
00619                 /* We're still conflicted ... */
00620                 break;
00621         }
00622     }
00623 
00624     /* It looks OK */
00625     return true;
00626 }
00627 
00628 /*
00629  * Return true if given object is one of PostgreSQL's built-in objects.
00630  *
00631  * We use FirstBootstrapObjectId as the cutoff, so that we only consider
00632  * objects with hand-assigned OIDs to be "built in", not for instance any
00633  * function or type defined in the information_schema.
00634  *
00635  * Our constraints for dealing with types are tighter than they are for
00636  * functions or operators: we want to accept only types that are in pg_catalog,
00637  * else format_type might incorrectly fail to schema-qualify their names.
00638  * (This could be fixed with some changes to format_type, but for now there's
00639  * no need.)  Thus we must exclude information_schema types.
00640  *
00641  * XXX there is a problem with this, which is that the set of built-in
00642  * objects expands over time.  Something that is built-in to us might not
00643  * be known to the remote server, if it's of an older version.  But keeping
00644  * track of that would be a huge exercise.
00645  */
00646 static bool
00647 is_builtin(Oid oid)
00648 {
00649     return (oid < FirstBootstrapObjectId);
00650 }
00651 
00652 
00653 /*
00654  * Construct a simple SELECT statement that retrieves desired columns
00655  * of the specified foreign table, and append it to "buf".  The output
00656  * contains just "SELECT ... FROM tablename".
00657  *
00658  * We also create an integer List of the columns being retrieved, which is
00659  * returned to *retrieved_attrs.
00660  */
00661 void
00662 deparseSelectSql(StringInfo buf,
00663                  PlannerInfo *root,
00664                  RelOptInfo *baserel,
00665                  Bitmapset *attrs_used,
00666                  List **retrieved_attrs)
00667 {
00668     RangeTblEntry *rte = planner_rt_fetch(baserel->relid, root);
00669     Relation    rel;
00670 
00671     /*
00672      * Core code already has some lock on each rel being planned, so we can
00673      * use NoLock here.
00674      */
00675     rel = heap_open(rte->relid, NoLock);
00676 
00677     /*
00678      * Construct SELECT list
00679      */
00680     appendStringInfoString(buf, "SELECT ");
00681     deparseTargetList(buf, root, baserel->relid, rel, attrs_used,
00682                       retrieved_attrs);
00683 
00684     /*
00685      * Construct FROM clause
00686      */
00687     appendStringInfoString(buf, " FROM ");
00688     deparseRelation(buf, rel);
00689 
00690     heap_close(rel, NoLock);
00691 }
00692 
00693 /*
00694  * Emit a target list that retrieves the columns specified in attrs_used.
00695  * This is used for both SELECT and RETURNING targetlists.
00696  *
00697  * The tlist text is appended to buf, and we also create an integer List
00698  * of the columns being retrieved, which is returned to *retrieved_attrs.
00699  */
00700 static void
00701 deparseTargetList(StringInfo buf,
00702                   PlannerInfo *root,
00703                   Index rtindex,
00704                   Relation rel,
00705                   Bitmapset *attrs_used,
00706                   List **retrieved_attrs)
00707 {
00708     TupleDesc   tupdesc = RelationGetDescr(rel);
00709     bool        have_wholerow;
00710     bool        first;
00711     int         i;
00712 
00713     *retrieved_attrs = NIL;
00714 
00715     /* If there's a whole-row reference, we'll need all the columns. */
00716     have_wholerow = bms_is_member(0 - FirstLowInvalidHeapAttributeNumber,
00717                                   attrs_used);
00718 
00719     first = true;
00720     for (i = 1; i <= tupdesc->natts; i++)
00721     {
00722         Form_pg_attribute attr = tupdesc->attrs[i - 1];
00723 
00724         /* Ignore dropped attributes. */
00725         if (attr->attisdropped)
00726             continue;
00727 
00728         if (have_wholerow ||
00729             bms_is_member(i - FirstLowInvalidHeapAttributeNumber,
00730                           attrs_used))
00731         {
00732             if (!first)
00733                 appendStringInfoString(buf, ", ");
00734             first = false;
00735 
00736             deparseColumnRef(buf, rtindex, i, root);
00737 
00738             *retrieved_attrs = lappend_int(*retrieved_attrs, i);
00739         }
00740     }
00741 
00742     /*
00743      * Add ctid if needed.  We currently don't support retrieving any other
00744      * system columns.
00745      */
00746     if (bms_is_member(SelfItemPointerAttributeNumber - FirstLowInvalidHeapAttributeNumber,
00747                       attrs_used))
00748     {
00749         if (!first)
00750             appendStringInfoString(buf, ", ");
00751         first = false;
00752 
00753         appendStringInfoString(buf, "ctid");
00754 
00755         *retrieved_attrs = lappend_int(*retrieved_attrs,
00756                                        SelfItemPointerAttributeNumber);
00757     }
00758 
00759     /* Don't generate bad syntax if no undropped columns */
00760     if (first)
00761         appendStringInfoString(buf, "NULL");
00762 }
00763 
00764 /*
00765  * Deparse WHERE clauses in given list of RestrictInfos and append them to buf.
00766  *
00767  * baserel is the foreign table we're planning for.
00768  *
00769  * If no WHERE clause already exists in the buffer, is_first should be true.
00770  *
00771  * If params is not NULL, it receives a list of Params and other-relation Vars
00772  * used in the clauses; these values must be transmitted to the remote server
00773  * as parameter values.
00774  *
00775  * If params is NULL, we're generating the query for EXPLAIN purposes,
00776  * so Params and other-relation Vars should be replaced by dummy values.
00777  */
00778 void
00779 appendWhereClause(StringInfo buf,
00780                   PlannerInfo *root,
00781                   RelOptInfo *baserel,
00782                   List *exprs,
00783                   bool is_first,
00784                   List **params)
00785 {
00786     deparse_expr_cxt context;
00787     int         nestlevel;
00788     ListCell   *lc;
00789 
00790     if (params)
00791         *params = NIL;          /* initialize result list to empty */
00792 
00793     /* Set up context struct for recursion */
00794     context.root = root;
00795     context.foreignrel = baserel;
00796     context.buf = buf;
00797     context.params_list = params;
00798 
00799     /* Make sure any constants in the exprs are printed portably */
00800     nestlevel = set_transmission_modes();
00801 
00802     foreach(lc, exprs)
00803     {
00804         RestrictInfo *ri = (RestrictInfo *) lfirst(lc);
00805 
00806         /* Connect expressions with "AND" and parenthesize each condition. */
00807         if (is_first)
00808             appendStringInfoString(buf, " WHERE ");
00809         else
00810             appendStringInfoString(buf, " AND ");
00811 
00812         appendStringInfoChar(buf, '(');
00813         deparseExpr(ri->clause, &context);
00814         appendStringInfoChar(buf, ')');
00815 
00816         is_first = false;
00817     }
00818 
00819     reset_transmission_modes(nestlevel);
00820 }
00821 
00822 /*
00823  * deparse remote INSERT statement
00824  *
00825  * The statement text is appended to buf, and we also create an integer List
00826  * of the columns being retrieved by RETURNING (if any), which is returned
00827  * to *retrieved_attrs.
00828  */
00829 void
00830 deparseInsertSql(StringInfo buf, PlannerInfo *root,
00831                  Index rtindex, Relation rel,
00832                  List *targetAttrs, List *returningList,
00833                  List **retrieved_attrs)
00834 {
00835     AttrNumber  pindex;
00836     bool        first;
00837     ListCell   *lc;
00838 
00839     appendStringInfoString(buf, "INSERT INTO ");
00840     deparseRelation(buf, rel);
00841 
00842     if (targetAttrs)
00843     {
00844         appendStringInfoString(buf, "(");
00845 
00846         first = true;
00847         foreach(lc, targetAttrs)
00848         {
00849             int         attnum = lfirst_int(lc);
00850 
00851             if (!first)
00852                 appendStringInfoString(buf, ", ");
00853             first = false;
00854 
00855             deparseColumnRef(buf, rtindex, attnum, root);
00856         }
00857 
00858         appendStringInfoString(buf, ") VALUES (");
00859 
00860         pindex = 1;
00861         first = true;
00862         foreach(lc, targetAttrs)
00863         {
00864             if (!first)
00865                 appendStringInfoString(buf, ", ");
00866             first = false;
00867 
00868             appendStringInfo(buf, "$%d", pindex);
00869             pindex++;
00870         }
00871 
00872         appendStringInfoString(buf, ")");
00873     }
00874     else
00875         appendStringInfoString(buf, " DEFAULT VALUES");
00876 
00877     if (returningList)
00878         deparseReturningList(buf, root, rtindex, rel, returningList,
00879                              retrieved_attrs);
00880     else
00881         *retrieved_attrs = NIL;
00882 }
00883 
00884 /*
00885  * deparse remote UPDATE statement
00886  *
00887  * The statement text is appended to buf, and we also create an integer List
00888  * of the columns being retrieved by RETURNING (if any), which is returned
00889  * to *retrieved_attrs.
00890  */
00891 void
00892 deparseUpdateSql(StringInfo buf, PlannerInfo *root,
00893                  Index rtindex, Relation rel,
00894                  List *targetAttrs, List *returningList,
00895                  List **retrieved_attrs)
00896 {
00897     AttrNumber  pindex;
00898     bool        first;
00899     ListCell   *lc;
00900 
00901     appendStringInfoString(buf, "UPDATE ");
00902     deparseRelation(buf, rel);
00903     appendStringInfoString(buf, " SET ");
00904 
00905     pindex = 2;                 /* ctid is always the first param */
00906     first = true;
00907     foreach(lc, targetAttrs)
00908     {
00909         int         attnum = lfirst_int(lc);
00910 
00911         if (!first)
00912             appendStringInfoString(buf, ", ");
00913         first = false;
00914 
00915         deparseColumnRef(buf, rtindex, attnum, root);
00916         appendStringInfo(buf, " = $%d", pindex);
00917         pindex++;
00918     }
00919     appendStringInfoString(buf, " WHERE ctid = $1");
00920 
00921     if (returningList)
00922         deparseReturningList(buf, root, rtindex, rel, returningList,
00923                              retrieved_attrs);
00924     else
00925         *retrieved_attrs = NIL;
00926 }
00927 
00928 /*
00929  * deparse remote DELETE statement
00930  *
00931  * The statement text is appended to buf, and we also create an integer List
00932  * of the columns being retrieved by RETURNING (if any), which is returned
00933  * to *retrieved_attrs.
00934  */
00935 void
00936 deparseDeleteSql(StringInfo buf, PlannerInfo *root,
00937                  Index rtindex, Relation rel,
00938                  List *returningList,
00939                  List **retrieved_attrs)
00940 {
00941     appendStringInfoString(buf, "DELETE FROM ");
00942     deparseRelation(buf, rel);
00943     appendStringInfoString(buf, " WHERE ctid = $1");
00944 
00945     if (returningList)
00946         deparseReturningList(buf, root, rtindex, rel, returningList,
00947                              retrieved_attrs);
00948     else
00949         *retrieved_attrs = NIL;
00950 }
00951 
00952 /*
00953  * deparse RETURNING clause of INSERT/UPDATE/DELETE
00954  */
00955 static void
00956 deparseReturningList(StringInfo buf, PlannerInfo *root,
00957                      Index rtindex, Relation rel,
00958                      List *returningList,
00959                      List **retrieved_attrs)
00960 {
00961     Bitmapset  *attrs_used;
00962 
00963     /*
00964      * We need the attrs mentioned in the query's RETURNING list.
00965      */
00966     attrs_used = NULL;
00967     pull_varattnos((Node *) returningList, rtindex,
00968                    &attrs_used);
00969 
00970     appendStringInfoString(buf, " RETURNING ");
00971     deparseTargetList(buf, root, rtindex, rel, attrs_used,
00972                       retrieved_attrs);
00973 }
00974 
00975 /*
00976  * Construct SELECT statement to acquire size in blocks of given relation.
00977  *
00978  * Note: we use local definition of block size, not remote definition.
00979  * This is perhaps debatable.
00980  *
00981  * Note: pg_relation_size() exists in 8.1 and later.
00982  */
00983 void
00984 deparseAnalyzeSizeSql(StringInfo buf, Relation rel)
00985 {
00986     StringInfoData relname;
00987 
00988     /* We'll need the remote relation name as a literal. */
00989     initStringInfo(&relname);
00990     deparseRelation(&relname, rel);
00991 
00992     appendStringInfo(buf, "SELECT pg_catalog.pg_relation_size(");
00993     deparseStringLiteral(buf, relname.data);
00994     appendStringInfo(buf, "::pg_catalog.regclass) / %d", BLCKSZ);
00995 }
00996 
00997 /*
00998  * Construct SELECT statement to acquire sample rows of given relation.
00999  *
01000  * SELECT command is appended to buf, and list of columns retrieved
01001  * is returned to *retrieved_attrs.
01002  */
01003 void
01004 deparseAnalyzeSql(StringInfo buf, Relation rel, List **retrieved_attrs)
01005 {
01006     Oid         relid = RelationGetRelid(rel);
01007     TupleDesc   tupdesc = RelationGetDescr(rel);
01008     int         i;
01009     char       *colname;
01010     List       *options;
01011     ListCell   *lc;
01012     bool        first = true;
01013 
01014     *retrieved_attrs = NIL;
01015 
01016     appendStringInfoString(buf, "SELECT ");
01017     for (i = 0; i < tupdesc->natts; i++)
01018     {
01019         /* Ignore dropped columns. */
01020         if (tupdesc->attrs[i]->attisdropped)
01021             continue;
01022 
01023         if (!first)
01024             appendStringInfoString(buf, ", ");
01025         first = false;
01026 
01027         /* Use attribute name or column_name option. */
01028         colname = NameStr(tupdesc->attrs[i]->attname);
01029         options = GetForeignColumnOptions(relid, i + 1);
01030 
01031         foreach(lc, options)
01032         {
01033             DefElem    *def = (DefElem *) lfirst(lc);
01034 
01035             if (strcmp(def->defname, "column_name") == 0)
01036             {
01037                 colname = defGetString(def);
01038                 break;
01039             }
01040         }
01041 
01042         appendStringInfoString(buf, quote_identifier(colname));
01043 
01044         *retrieved_attrs = lappend_int(*retrieved_attrs, i + 1);
01045     }
01046 
01047     /* Don't generate bad syntax for zero-column relation. */
01048     if (first)
01049         appendStringInfoString(buf, "NULL");
01050 
01051     /*
01052      * Construct FROM clause
01053      */
01054     appendStringInfoString(buf, " FROM ");
01055     deparseRelation(buf, rel);
01056 }
01057 
01058 /*
01059  * Construct name to use for given column, and emit it into buf.
01060  * If it has a column_name FDW option, use that instead of attribute name.
01061  */
01062 static void
01063 deparseColumnRef(StringInfo buf, int varno, int varattno, PlannerInfo *root)
01064 {
01065     RangeTblEntry *rte;
01066     char       *colname = NULL;
01067     List       *options;
01068     ListCell   *lc;
01069 
01070     /* varno must not be any of OUTER_VAR, INNER_VAR and INDEX_VAR. */
01071     Assert(!IS_SPECIAL_VARNO(varno));
01072 
01073     /* Get RangeTblEntry from array in PlannerInfo. */
01074     rte = planner_rt_fetch(varno, root);
01075 
01076     /*
01077      * If it's a column of a foreign table, and it has the column_name FDW
01078      * option, use that value.
01079      */
01080     options = GetForeignColumnOptions(rte->relid, varattno);
01081     foreach(lc, options)
01082     {
01083         DefElem    *def = (DefElem *) lfirst(lc);
01084 
01085         if (strcmp(def->defname, "column_name") == 0)
01086         {
01087             colname = defGetString(def);
01088             break;
01089         }
01090     }
01091 
01092     /*
01093      * If it's a column of a regular table or it doesn't have column_name FDW
01094      * option, use attribute name.
01095      */
01096     if (colname == NULL)
01097         colname = get_relid_attribute_name(rte->relid, varattno);
01098 
01099     appendStringInfoString(buf, quote_identifier(colname));
01100 }
01101 
01102 /*
01103  * Append remote name of specified foreign table to buf.
01104  * Use value of table_name FDW option (if any) instead of relation's name.
01105  * Similarly, schema_name FDW option overrides schema name.
01106  */
01107 static void
01108 deparseRelation(StringInfo buf, Relation rel)
01109 {
01110     ForeignTable *table;
01111     const char *nspname = NULL;
01112     const char *relname = NULL;
01113     ListCell   *lc;
01114 
01115     /* obtain additional catalog information. */
01116     table = GetForeignTable(RelationGetRelid(rel));
01117 
01118     /*
01119      * Use value of FDW options if any, instead of the name of object itself.
01120      */
01121     foreach(lc, table->options)
01122     {
01123         DefElem    *def = (DefElem *) lfirst(lc);
01124 
01125         if (strcmp(def->defname, "schema_name") == 0)
01126             nspname = defGetString(def);
01127         else if (strcmp(def->defname, "table_name") == 0)
01128             relname = defGetString(def);
01129     }
01130 
01131     /*
01132      * Note: we could skip printing the schema name if it's pg_catalog, but
01133      * that doesn't seem worth the trouble.
01134      */
01135     if (nspname == NULL)
01136         nspname = get_namespace_name(RelationGetNamespace(rel));
01137     if (relname == NULL)
01138         relname = RelationGetRelationName(rel);
01139 
01140     appendStringInfo(buf, "%s.%s",
01141                      quote_identifier(nspname), quote_identifier(relname));
01142 }
01143 
01144 /*
01145  * Append a SQL string literal representing "val" to buf.
01146  */
01147 static void
01148 deparseStringLiteral(StringInfo buf, const char *val)
01149 {
01150     const char *valptr;
01151 
01152     /*
01153      * Rather than making assumptions about the remote server's value of
01154      * standard_conforming_strings, always use E'foo' syntax if there are any
01155      * backslashes.  This will fail on remote servers before 8.1, but those
01156      * are long out of support.
01157      */
01158     if (strchr(val, '\\') != NULL)
01159         appendStringInfoChar(buf, ESCAPE_STRING_SYNTAX);
01160     appendStringInfoChar(buf, '\'');
01161     for (valptr = val; *valptr; valptr++)
01162     {
01163         char        ch = *valptr;
01164 
01165         if (SQL_STR_DOUBLE(ch, true))
01166             appendStringInfoChar(buf, ch);
01167         appendStringInfoChar(buf, ch);
01168     }
01169     appendStringInfoChar(buf, '\'');
01170 }
01171 
01172 /*
01173  * Deparse given expression into context->buf.
01174  *
01175  * This function must support all the same node types that foreign_expr_walker
01176  * accepts.
01177  *
01178  * Note: unlike ruleutils.c, we just use a simple hard-wired parenthesization
01179  * scheme: anything more complex than a Var, Const, function call or cast
01180  * should be self-parenthesized.
01181  */
01182 static void
01183 deparseExpr(Expr *node, deparse_expr_cxt *context)
01184 {
01185     if (node == NULL)
01186         return;
01187 
01188     switch (nodeTag(node))
01189     {
01190         case T_Var:
01191             deparseVar((Var *) node, context);
01192             break;
01193         case T_Const:
01194             deparseConst((Const *) node, context);
01195             break;
01196         case T_Param:
01197             deparseParam((Param *) node, context);
01198             break;
01199         case T_ArrayRef:
01200             deparseArrayRef((ArrayRef *) node, context);
01201             break;
01202         case T_FuncExpr:
01203             deparseFuncExpr((FuncExpr *) node, context);
01204             break;
01205         case T_OpExpr:
01206             deparseOpExpr((OpExpr *) node, context);
01207             break;
01208         case T_DistinctExpr:
01209             deparseDistinctExpr((DistinctExpr *) node, context);
01210             break;
01211         case T_ScalarArrayOpExpr:
01212             deparseScalarArrayOpExpr((ScalarArrayOpExpr *) node, context);
01213             break;
01214         case T_RelabelType:
01215             deparseRelabelType((RelabelType *) node, context);
01216             break;
01217         case T_BoolExpr:
01218             deparseBoolExpr((BoolExpr *) node, context);
01219             break;
01220         case T_NullTest:
01221             deparseNullTest((NullTest *) node, context);
01222             break;
01223         case T_ArrayExpr:
01224             deparseArrayExpr((ArrayExpr *) node, context);
01225             break;
01226         default:
01227             elog(ERROR, "unsupported expression type for deparse: %d",
01228                  (int) nodeTag(node));
01229             break;
01230     }
01231 }
01232 
01233 /*
01234  * Deparse given Var node into context->buf.
01235  *
01236  * If the Var belongs to the foreign relation, just print its remote name.
01237  * Otherwise, it's effectively a Param (and will in fact be a Param at
01238  * run time).  Handle it the same way we handle plain Params --- see
01239  * deparseParam for comments.
01240  */
01241 static void
01242 deparseVar(Var *node, deparse_expr_cxt *context)
01243 {
01244     StringInfo  buf = context->buf;
01245 
01246     if (node->varno == context->foreignrel->relid &&
01247         node->varlevelsup == 0)
01248     {
01249         /* Var belongs to foreign table */
01250         deparseColumnRef(buf, node->varno, node->varattno, context->root);
01251     }
01252     else
01253     {
01254         /* Treat like a Param */
01255         if (context->params_list)
01256         {
01257             int         pindex = 0;
01258             ListCell   *lc;
01259 
01260             /* find its index in params_list */
01261             foreach(lc, *context->params_list)
01262             {
01263                 pindex++;
01264                 if (equal(node, (Node *) lfirst(lc)))
01265                     break;
01266             }
01267             if (lc == NULL)
01268             {
01269                 /* not in list, so add it */
01270                 pindex++;
01271                 *context->params_list = lappend(*context->params_list, node);
01272             }
01273 
01274             appendStringInfo(buf, "$%d", pindex);
01275             appendStringInfo(buf, "::%s",
01276                              format_type_with_typemod(node->vartype,
01277                                                       node->vartypmod));
01278         }
01279         else
01280         {
01281             appendStringInfo(buf, "(SELECT null::%s)",
01282                              format_type_with_typemod(node->vartype,
01283                                                       node->vartypmod));
01284         }
01285     }
01286 }
01287 
01288 /*
01289  * Deparse given constant value into context->buf.
01290  *
01291  * This function has to be kept in sync with ruleutils.c's get_const_expr.
01292  */
01293 static void
01294 deparseConst(Const *node, deparse_expr_cxt *context)
01295 {
01296     StringInfo  buf = context->buf;
01297     Oid         typoutput;
01298     bool        typIsVarlena;
01299     char       *extval;
01300     bool        isfloat = false;
01301     bool        needlabel;
01302 
01303     if (node->constisnull)
01304     {
01305         appendStringInfo(buf, "NULL");
01306         appendStringInfo(buf, "::%s",
01307                          format_type_with_typemod(node->consttype,
01308                                                   node->consttypmod));
01309         return;
01310     }
01311 
01312     getTypeOutputInfo(node->consttype,
01313                       &typoutput, &typIsVarlena);
01314     extval = OidOutputFunctionCall(typoutput, node->constvalue);
01315 
01316     switch (node->consttype)
01317     {
01318         case INT2OID:
01319         case INT4OID:
01320         case INT8OID:
01321         case OIDOID:
01322         case FLOAT4OID:
01323         case FLOAT8OID:
01324         case NUMERICOID:
01325             {
01326                 /*
01327                  * No need to quote unless it's a special value such as 'NaN'.
01328                  * See comments in get_const_expr().
01329                  */
01330                 if (strspn(extval, "0123456789+-eE.") == strlen(extval))
01331                 {
01332                     if (extval[0] == '+' || extval[0] == '-')
01333                         appendStringInfo(buf, "(%s)", extval);
01334                     else
01335                         appendStringInfoString(buf, extval);
01336                     if (strcspn(extval, "eE.") != strlen(extval))
01337                         isfloat = true; /* it looks like a float */
01338                 }
01339                 else
01340                     appendStringInfo(buf, "'%s'", extval);
01341             }
01342             break;
01343         case BITOID:
01344         case VARBITOID:
01345             appendStringInfo(buf, "B'%s'", extval);
01346             break;
01347         case BOOLOID:
01348             if (strcmp(extval, "t") == 0)
01349                 appendStringInfoString(buf, "true");
01350             else
01351                 appendStringInfoString(buf, "false");
01352             break;
01353         default:
01354             deparseStringLiteral(buf, extval);
01355             break;
01356     }
01357 
01358     /*
01359      * Append ::typename unless the constant will be implicitly typed as the
01360      * right type when it is read in.
01361      *
01362      * XXX this code has to be kept in sync with the behavior of the parser,
01363      * especially make_const.
01364      */
01365     switch (node->consttype)
01366     {
01367         case BOOLOID:
01368         case INT4OID:
01369         case UNKNOWNOID:
01370             needlabel = false;
01371             break;
01372         case NUMERICOID:
01373             needlabel = !isfloat || (node->consttypmod >= 0);
01374             break;
01375         default:
01376             needlabel = true;
01377             break;
01378     }
01379     if (needlabel)
01380         appendStringInfo(buf, "::%s",
01381                          format_type_with_typemod(node->consttype,
01382                                                   node->consttypmod));
01383 }
01384 
01385 /*
01386  * Deparse given Param node.
01387  *
01388  * If we're generating the query "for real", add the Param to
01389  * context->params_list if it's not already present, and then use its index
01390  * in that list as the remote parameter number.
01391  *
01392  * If we're just generating the query for EXPLAIN, replace the Param with
01393  * a dummy expression "(SELECT null::<type>)".  In all extant versions of
01394  * Postgres, the planner will see that as an unknown constant value, which is
01395  * what we want.  (If we sent a Param, recent versions might try to use the
01396  * value supplied for the Param as an estimated or even constant value, which
01397  * we don't want.)  This might need adjustment if we ever make the planner
01398  * flatten scalar subqueries.
01399  *
01400  * Note: we label the Param's type explicitly rather than relying on
01401  * transmitting a numeric type OID in PQexecParams().  This allows us to
01402  * avoid assuming that types have the same OIDs on the remote side as they
01403  * do locally --- they need only have the same names.
01404  */
01405 static void
01406 deparseParam(Param *node, deparse_expr_cxt *context)
01407 {
01408     StringInfo  buf = context->buf;
01409 
01410     if (context->params_list)
01411     {
01412         int         pindex = 0;
01413         ListCell   *lc;
01414 
01415         /* find its index in params_list */
01416         foreach(lc, *context->params_list)
01417         {
01418             pindex++;
01419             if (equal(node, (Node *) lfirst(lc)))
01420                 break;
01421         }
01422         if (lc == NULL)
01423         {
01424             /* not in list, so add it */
01425             pindex++;
01426             *context->params_list = lappend(*context->params_list, node);
01427         }
01428 
01429         appendStringInfo(buf, "$%d", pindex);
01430         appendStringInfo(buf, "::%s",
01431                          format_type_with_typemod(node->paramtype,
01432                                                   node->paramtypmod));
01433     }
01434     else
01435     {
01436         appendStringInfo(buf, "(SELECT null::%s)",
01437                          format_type_with_typemod(node->paramtype,
01438                                                   node->paramtypmod));
01439     }
01440 }
01441 
01442 /*
01443  * Deparse an array subscript expression.
01444  */
01445 static void
01446 deparseArrayRef(ArrayRef *node, deparse_expr_cxt *context)
01447 {
01448     StringInfo  buf = context->buf;
01449     ListCell   *lowlist_item;
01450     ListCell   *uplist_item;
01451 
01452     /* Always parenthesize the expression. */
01453     appendStringInfoChar(buf, '(');
01454 
01455     /*
01456      * Deparse referenced array expression first.  If that expression includes
01457      * a cast, we have to parenthesize to prevent the array subscript from
01458      * being taken as typename decoration.  We can avoid that in the typical
01459      * case of subscripting a Var, but otherwise do it.
01460      */
01461     if (IsA(node->refexpr, Var))
01462         deparseExpr(node->refexpr, context);
01463     else
01464     {
01465         appendStringInfoChar(buf, '(');
01466         deparseExpr(node->refexpr, context);
01467         appendStringInfoChar(buf, ')');
01468     }
01469 
01470     /* Deparse subscript expressions. */
01471     lowlist_item = list_head(node->reflowerindexpr);    /* could be NULL */
01472     foreach(uplist_item, node->refupperindexpr)
01473     {
01474         appendStringInfoChar(buf, '[');
01475         if (lowlist_item)
01476         {
01477             deparseExpr(lfirst(lowlist_item), context);
01478             appendStringInfoChar(buf, ':');
01479             lowlist_item = lnext(lowlist_item);
01480         }
01481         deparseExpr(lfirst(uplist_item), context);
01482         appendStringInfoChar(buf, ']');
01483     }
01484 
01485     appendStringInfoChar(buf, ')');
01486 }
01487 
01488 /*
01489  * Deparse a function call.
01490  */
01491 static void
01492 deparseFuncExpr(FuncExpr *node, deparse_expr_cxt *context)
01493 {
01494     StringInfo  buf = context->buf;
01495     HeapTuple   proctup;
01496     Form_pg_proc procform;
01497     const char *proname;
01498     bool        use_variadic;
01499     bool        first;
01500     ListCell   *arg;
01501 
01502     /*
01503      * If the function call came from an implicit coercion, then just show the
01504      * first argument.
01505      */
01506     if (node->funcformat == COERCE_IMPLICIT_CAST)
01507     {
01508         deparseExpr((Expr *) linitial(node->args), context);
01509         return;
01510     }
01511 
01512     /*
01513      * If the function call came from a cast, then show the first argument
01514      * plus an explicit cast operation.
01515      */
01516     if (node->funcformat == COERCE_EXPLICIT_CAST)
01517     {
01518         Oid         rettype = node->funcresulttype;
01519         int32       coercedTypmod;
01520 
01521         /* Get the typmod if this is a length-coercion function */
01522         (void) exprIsLengthCoercion((Node *) node, &coercedTypmod);
01523 
01524         deparseExpr((Expr *) linitial(node->args), context);
01525         appendStringInfo(buf, "::%s",
01526                          format_type_with_typemod(rettype, coercedTypmod));
01527         return;
01528     }
01529 
01530     /*
01531      * Normal function: display as proname(args).
01532      */
01533     proctup = SearchSysCache1(PROCOID, ObjectIdGetDatum(node->funcid));
01534     if (!HeapTupleIsValid(proctup))
01535         elog(ERROR, "cache lookup failed for function %u", node->funcid);
01536     procform = (Form_pg_proc) GETSTRUCT(proctup);
01537 
01538     /* Check if need to print VARIADIC (cf. ruleutils.c) */
01539     if (OidIsValid(procform->provariadic))
01540     {
01541         if (procform->provariadic != ANYOID)
01542             use_variadic = true;
01543         else
01544             use_variadic = node->funcvariadic;
01545     }
01546     else
01547         use_variadic = false;
01548 
01549     /* Print schema name only if it's not pg_catalog */
01550     if (procform->pronamespace != PG_CATALOG_NAMESPACE)
01551     {
01552         const char *schemaname;
01553 
01554         schemaname = get_namespace_name(procform->pronamespace);
01555         appendStringInfo(buf, "%s.", quote_identifier(schemaname));
01556     }
01557 
01558     /* Deparse the function name ... */
01559     proname = NameStr(procform->proname);
01560     appendStringInfo(buf, "%s(", quote_identifier(proname));
01561     /* ... and all the arguments */
01562     first = true;
01563     foreach(arg, node->args)
01564     {
01565         if (!first)
01566             appendStringInfoString(buf, ", ");
01567         if (use_variadic && lnext(arg) == NULL)
01568             appendStringInfoString(buf, "VARIADIC ");
01569         deparseExpr((Expr *) lfirst(arg), context);
01570         first = false;
01571     }
01572     appendStringInfoChar(buf, ')');
01573 
01574     ReleaseSysCache(proctup);
01575 }
01576 
01577 /*
01578  * Deparse given operator expression.   To avoid problems around
01579  * priority of operations, we always parenthesize the arguments.
01580  */
01581 static void
01582 deparseOpExpr(OpExpr *node, deparse_expr_cxt *context)
01583 {
01584     StringInfo  buf = context->buf;
01585     HeapTuple   tuple;
01586     Form_pg_operator form;
01587     char        oprkind;
01588     ListCell   *arg;
01589 
01590     /* Retrieve information about the operator from system catalog. */
01591     tuple = SearchSysCache1(OPEROID, ObjectIdGetDatum(node->opno));
01592     if (!HeapTupleIsValid(tuple))
01593         elog(ERROR, "cache lookup failed for operator %u", node->opno);
01594     form = (Form_pg_operator) GETSTRUCT(tuple);
01595     oprkind = form->oprkind;
01596 
01597     /* Sanity check. */
01598     Assert((oprkind == 'r' && list_length(node->args) == 1) ||
01599            (oprkind == 'l' && list_length(node->args) == 1) ||
01600            (oprkind == 'b' && list_length(node->args) == 2));
01601 
01602     /* Always parenthesize the expression. */
01603     appendStringInfoChar(buf, '(');
01604 
01605     /* Deparse left operand. */
01606     if (oprkind == 'r' || oprkind == 'b')
01607     {
01608         arg = list_head(node->args);
01609         deparseExpr(lfirst(arg), context);
01610         appendStringInfoChar(buf, ' ');
01611     }
01612 
01613     /* Deparse operator name. */
01614     deparseOperatorName(buf, form);
01615 
01616     /* Deparse right operand. */
01617     if (oprkind == 'l' || oprkind == 'b')
01618     {
01619         arg = list_tail(node->args);
01620         appendStringInfoChar(buf, ' ');
01621         deparseExpr(lfirst(arg), context);
01622     }
01623 
01624     appendStringInfoChar(buf, ')');
01625 
01626     ReleaseSysCache(tuple);
01627 }
01628 
01629 /*
01630  * Print the name of an operator.
01631  */
01632 static void
01633 deparseOperatorName(StringInfo buf, Form_pg_operator opform)
01634 {
01635     char       *opname;
01636 
01637     /* opname is not a SQL identifier, so we should not quote it. */
01638     opname = NameStr(opform->oprname);
01639 
01640     /* Print schema name only if it's not pg_catalog */
01641     if (opform->oprnamespace != PG_CATALOG_NAMESPACE)
01642     {
01643         const char *opnspname;
01644 
01645         opnspname = get_namespace_name(opform->oprnamespace);
01646         /* Print fully qualified operator name. */
01647         appendStringInfo(buf, "OPERATOR(%s.%s)",
01648                          quote_identifier(opnspname), opname);
01649     }
01650     else
01651     {
01652         /* Just print operator name. */
01653         appendStringInfo(buf, "%s", opname);
01654     }
01655 }
01656 
01657 /*
01658  * Deparse IS DISTINCT FROM.
01659  */
01660 static void
01661 deparseDistinctExpr(DistinctExpr *node, deparse_expr_cxt *context)
01662 {
01663     StringInfo  buf = context->buf;
01664 
01665     Assert(list_length(node->args) == 2);
01666 
01667     appendStringInfoChar(buf, '(');
01668     deparseExpr(linitial(node->args), context);
01669     appendStringInfoString(buf, " IS DISTINCT FROM ");
01670     deparseExpr(lsecond(node->args), context);
01671     appendStringInfoChar(buf, ')');
01672 }
01673 
01674 /*
01675  * Deparse given ScalarArrayOpExpr expression.  To avoid problems
01676  * around priority of operations, we always parenthesize the arguments.
01677  */
01678 static void
01679 deparseScalarArrayOpExpr(ScalarArrayOpExpr *node, deparse_expr_cxt *context)
01680 {
01681     StringInfo  buf = context->buf;
01682     HeapTuple   tuple;
01683     Form_pg_operator form;
01684     Expr       *arg1;
01685     Expr       *arg2;
01686 
01687     /* Retrieve information about the operator from system catalog. */
01688     tuple = SearchSysCache1(OPEROID, ObjectIdGetDatum(node->opno));
01689     if (!HeapTupleIsValid(tuple))
01690         elog(ERROR, "cache lookup failed for operator %u", node->opno);
01691     form = (Form_pg_operator) GETSTRUCT(tuple);
01692 
01693     /* Sanity check. */
01694     Assert(list_length(node->args) == 2);
01695 
01696     /* Always parenthesize the expression. */
01697     appendStringInfoChar(buf, '(');
01698 
01699     /* Deparse left operand. */
01700     arg1 = linitial(node->args);
01701     deparseExpr(arg1, context);
01702     appendStringInfoChar(buf, ' ');
01703 
01704     /* Deparse operator name plus decoration. */
01705     deparseOperatorName(buf, form);
01706     appendStringInfo(buf, " %s (", node->useOr ? "ANY" : "ALL");
01707 
01708     /* Deparse right operand. */
01709     arg2 = lsecond(node->args);
01710     deparseExpr(arg2, context);
01711 
01712     appendStringInfoChar(buf, ')');
01713 
01714     /* Always parenthesize the expression. */
01715     appendStringInfoChar(buf, ')');
01716 
01717     ReleaseSysCache(tuple);
01718 }
01719 
01720 /*
01721  * Deparse a RelabelType (binary-compatible cast) node.
01722  */
01723 static void
01724 deparseRelabelType(RelabelType *node, deparse_expr_cxt *context)
01725 {
01726     deparseExpr(node->arg, context);
01727     if (node->relabelformat != COERCE_IMPLICIT_CAST)
01728         appendStringInfo(context->buf, "::%s",
01729                          format_type_with_typemod(node->resulttype,
01730                                                   node->resulttypmod));
01731 }
01732 
01733 /*
01734  * Deparse a BoolExpr node.
01735  *
01736  * Note: by the time we get here, AND and OR expressions have been flattened
01737  * into N-argument form, so we'd better be prepared to deal with that.
01738  */
01739 static void
01740 deparseBoolExpr(BoolExpr *node, deparse_expr_cxt *context)
01741 {
01742     StringInfo  buf = context->buf;
01743     const char *op = NULL;      /* keep compiler quiet */
01744     bool        first;
01745     ListCell   *lc;
01746 
01747     switch (node->boolop)
01748     {
01749         case AND_EXPR:
01750             op = "AND";
01751             break;
01752         case OR_EXPR:
01753             op = "OR";
01754             break;
01755         case NOT_EXPR:
01756             appendStringInfoString(buf, "(NOT ");
01757             deparseExpr(linitial(node->args), context);
01758             appendStringInfoChar(buf, ')');
01759             return;
01760     }
01761 
01762     appendStringInfoChar(buf, '(');
01763     first = true;
01764     foreach(lc, node->args)
01765     {
01766         if (!first)
01767             appendStringInfo(buf, " %s ", op);
01768         deparseExpr((Expr *) lfirst(lc), context);
01769         first = false;
01770     }
01771     appendStringInfoChar(buf, ')');
01772 }
01773 
01774 /*
01775  * Deparse IS [NOT] NULL expression.
01776  */
01777 static void
01778 deparseNullTest(NullTest *node, deparse_expr_cxt *context)
01779 {
01780     StringInfo  buf = context->buf;
01781 
01782     appendStringInfoChar(buf, '(');
01783     deparseExpr(node->arg, context);
01784     if (node->nulltesttype == IS_NULL)
01785         appendStringInfoString(buf, " IS NULL)");
01786     else
01787         appendStringInfoString(buf, " IS NOT NULL)");
01788 }
01789 
01790 /*
01791  * Deparse ARRAY[...] construct.
01792  */
01793 static void
01794 deparseArrayExpr(ArrayExpr *node, deparse_expr_cxt *context)
01795 {
01796     StringInfo  buf = context->buf;
01797     bool        first = true;
01798     ListCell   *lc;
01799 
01800     appendStringInfoString(buf, "ARRAY[");
01801     foreach(lc, node->elements)
01802     {
01803         if (!first)
01804             appendStringInfoString(buf, ", ");
01805         deparseExpr(lfirst(lc), context);
01806         first = false;
01807     }
01808     appendStringInfoChar(buf, ']');
01809 
01810     /* If the array is empty, we need an explicit cast to the array type. */
01811     if (node->elements == NIL)
01812         appendStringInfo(buf, "::%s",
01813                          format_type_with_typemod(node->array_typeid, -1));
01814 }