Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
tree: 2be6f02d06
Fetching contributors…

Cannot retrieve contributors at this time

8911 lines (7677 sloc) 261.065 kB
/*-------------------------------------------------------------------------
*
* outfuncs.c
* Output functions for Postgres tree nodes.
*
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/dblink/nodes/outfuncs.c,v 1.261.2.1 2005/11/14 23:54:34 tgl Exp $
*
* NOTES
* Every node type that can appear in stored rules' parsetrees *must*
* have an output function defined here (as well as an input function
* in readfuncs.c). For use in debugging, we also provide output
* functions for nodes that appear in raw parsetrees, path, and plan trees.
* These nodes however need not have input functions.
*
*-------------------------------------------------------------------------
*/
#include <string.h>
#include <limits.h>
#include "pool.h"
#include "parser/parser.h"
#include "parser/pool_string.h"
#include "parser/pg_list.h"
#include "parser/parsenodes.h"
#include "pool_rewrite_query.h"
#define booltostr(x) ((x) ? "true" : "false")
extern void _outNode(String *str, void *obj);
static void _rewriteNode(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, void *obj);
static void _rewriteList(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, List *node);
static void _rewriteIdList(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, List *node);
static void _rewriteAlias(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, Alias *node);
static void _rewriteRangeVar(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, RangeVar *node);
static void _rewriteVar(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, Var *node);
static void _rewriteConst(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, Const *node);
static void _rewriteParam(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, Param *node);
static void _rewriteAggref(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, Aggref *node);
static void _rewriteArrayRef(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, ArrayRef *node);
static void _rewriteFuncExpr(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, FuncExpr *node);
static void _rewriteOpExpr(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, OpExpr *node);
static void _rewriteDistinctExpr(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, DistinctExpr *node);
static void _rewriteScalarArrayOpExpr(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, ScalarArrayOpExpr *node);
static void _rewriteBoolExpr(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, BoolExpr *node);
static void _rewriteSubLink(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, SubLink *node);
static void _rewriteSubPlan(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, SubPlan *node);
static void _rewriteFieldSelect(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, FieldSelect *node);
static void _rewriteFieldStore(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, FieldStore *node);
static void _rewriteRelabelType(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, RelabelType *node);
static void _rewriteConvertRowtypeExpr(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, ConvertRowtypeExpr *node);
static void _rewriteCaseExpr(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, CaseExpr *node);
static void _rewriteCaseWhen(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, CaseWhen *node);
static void _rewriteCaseTestExpr(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, CaseTestExpr *node);
static void _rewriteArrayExpr(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, ArrayExpr *node);
static void _rewriteRowExpr(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, RowExpr *node);
static void _rewriteCoalesceExpr(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, CoalesceExpr *node);
static void _rewriteMinMaxExpr(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, MinMaxExpr *node);
static void _rewriteNullIfExpr(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, NullIfExpr *node);
static void _rewriteNullTest(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, NullTest *node);
static void _rewriteBooleanTest(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, BooleanTest *node);
static void _rewriteCoerceToDomain(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, CoerceToDomain *node);
static void _rewriteCoerceToDomainValue(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, CoerceToDomainValue *node);
static void _rewriteSetToDefault(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, SetToDefault *node);
static void _rewriteTargetEntry(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, TargetEntry *node);
static void _rewriteRangeTblRef(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, RangeTblRef *node);
static void _rewriteJoinExpr(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, JoinExpr *node);
static void _rewriteFromExpr(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, FromExpr *node);
static void _rewriteCreateStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, CreateStmt *node);
static void _rewriteIndexStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, IndexStmt *node);
static void _rewriteNotifyStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, NotifyStmt *node);
static void _rewriteDeclareCursorStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, DeclareCursorStmt *node);
static void _rewriteSelectStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, SelectStmt *node);
static void _rewriteFuncCall(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, FuncCall *node);
static void _rewriteDefElem(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, DefElem *node);
static void _rewriteLockingClause(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, LockingClause *node);
static void _rewriteColumnDef(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, ColumnDef *node);
static void _rewriteTypeName(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, TypeName *node);
static void _rewriteTypeCast(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, TypeCast *node);
static void _rewriteIndexElem(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, IndexElem *node);
static void _rewriteSortGroupClause(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, SortGroupClause *node);
static void _rewriteWindowClause(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, WindowClause *node);
static void _rewriteSetOperationStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, SetOperationStmt *node);
static void _rewriteAExpr(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, A_Expr *node);
static void _rewriteValue(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, Value *value);
static void _rewriteColumnRef(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, ColumnRef *node);
static void _rewriteParamRef(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, ParamRef *node);
static void _rewriteAConst(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, A_Const *node);
static void _rewriteA_Indices(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, A_Indices *node);
static void _rewriteA_Indirection(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, A_Indirection *node);
static void _rewriteResTarget(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, ResTarget *node);
static void _rewriteConstraint(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, Constraint *node);
static void _rewriteFkConstraint(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, FkConstraint *node);
static void _rewriteSortBy(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, SortBy *node);
static void _rewriteInsertStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, InsertStmt *node);
static void _rewriteUpdateStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, UpdateStmt *node);
static void _rewriteDeleteStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, DeleteStmt *node);
static void _rewriteTransactionStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, TransactionStmt *node);
static void _rewriteTruncateStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, TruncateStmt *node);
static void _rewriteVacuumStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, VacuumStmt *node);
static void _rewriteExplainStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, ExplainStmt *node);
static void _rewriteClusterStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, ClusterStmt *node);
static void _rewriteCheckPointStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, CheckPointStmt *node);
static void _rewriteClosePortalStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, ClosePortalStmt *node);
static void _rewriteListenStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, ListenStmt *node);
static void _rewriteUnlistenStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, UnlistenStmt *node);
static void _rewriteLoadStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, LoadStmt *node);
static void _rewriteCopyStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, CopyStmt *node);
static void _rewriteDeallocateStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, DeallocateStmt *node);
static void _rewriteRenameStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, RenameStmt *node);
static void _rewriteCreateRoleStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, CreateRoleStmt *node);
static void _rewriteAlterRoleStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, AlterRoleStmt *node);
static void _rewriteDropRoleStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, DropRoleStmt *node);
static void _rewriteCreateSchemaStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, CreateSchemaStmt *node);
static void _rewriteVariableSetStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, VariableSetStmt *node);
static void _rewriteVariableShowStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, VariableShowStmt *node);
static void _rewriteConstraintsSetStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, ConstraintsSetStmt *node);
static void _rewriteAlterTableStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, AlterTableStmt *node);
static void _rewriteCreateSeqStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, CreateSeqStmt *node);
static void _rewriteAlterSeqStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, AlterSeqStmt *node);
static void _rewriteCreatePLangStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, CreatePLangStmt *node);
static void _rewriteDropPLangStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, DropPLangStmt *node);
static void _rewriteCreateTableSpaceStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, CreateTableSpaceStmt *node);
static void _rewriteDropTableSpaceStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, DropTableSpaceStmt *node);
static void _rewriteCreateTrigStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, CreateTrigStmt *node);
static void _rewriteDropPropertyStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, DropPropertyStmt *node);
static void _rewriteDefineStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, DefineStmt *node);
static void _rewriteCreateOpClassStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, CreateOpClassStmt *node);
static void _rewriteRemoveOpClassStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, RemoveOpClassStmt *node);
static void _rewriteDropStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, DropStmt *node);
static void _rewriteFetchStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, FetchStmt *node);
static void _rewriteGrantStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, GrantStmt *node);
static void _rewriteGrantRoleStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, GrantRoleStmt *node);
static void _rewriteCreateFunctionStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, CreateFunctionStmt *node);
static void _rewriteAlterFunctionStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, AlterFunctionStmt *node);
static void _rewriteRemoveFuncStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, RemoveFuncStmt *node);
static void _rewriteCreateCastStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, CreateCastStmt *node);
static void _rewriteDropCastStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, DropCastStmt *node);
static void _rewriteReindexStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, ReindexStmt *node);
static void _rewriteRuleStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, RuleStmt *node);
static void _rewriteViewStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, ViewStmt *node);
static void _rewriteCreatedbStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, CreatedbStmt *node);
static void _rewriteAlterDatabaseStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, AlterDatabaseStmt *node);
static void _rewriteAlterDatabaseSetStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, AlterDatabaseSetStmt *node);
static void _rewriteDropdbStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, DropdbStmt *node);
static void _rewriteCreateDomainStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, CreateDomainStmt *node);
static void _rewriteAlterDomainStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, AlterDomainStmt *node);
static void _rewriteCreateConversionStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, CreateConversionStmt *node);
static void _rewritePrepareStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, PrepareStmt *node);
static void _rewriteExecuteStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, ExecuteStmt *node);
static void _rewriteLockStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, LockStmt *node);
static void _rewriteCommentStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, CommentStmt *node);
static void _rewriteFuncName(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, List *func_name);
static void _rewriteSetRest(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, VariableSetStmt *node);
static void _rewriteSetTransactionModeList(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, List *list);
static void _rewriteAlterTableCmd(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, AlterTableCmd *node);
static void _rewriteOptSeqList(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, List *options);
static void _rewritePrivGrantee(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, PrivGrantee *node);
static void _rewriteFuncWithArgs(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, FuncWithArgs *node);
static void _rewriteFunctionParameter(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, FunctionParameter *node);
static void _rewritePrivilegeList(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, List *list);
static void _rewriteFuncOptList(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, List *list);
static void _rewriteCreatedbOptList(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, List *options);
static void _rewriteOperatorArgTypes(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, List *args);
static void _rewriteRangeFunction(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, RangeFunction *node);
static void _rewriteWithDefinition(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, List *def_list);
/* analyze */
static void KeepRewriteQueryCode(RewriteQuery *message, int current_select);
static void KeepMessages(RewriteQuery *message,int current_select,int part);
static int CheckWhereCaluse(Node *BaseSelect,RewriteQuery *message,ConInfoTodblink *dblink,String *str,int true_count);
static int _writewhereClause(A_Expr *expr,RewriteQuery *message,ConInfoTodblink *dblink, String *str,int true_count);
static char *escape_string(char *str);
static void delay_string_append_char(RewriteQuery *message,String *str, char *parts);
static void build_range_info(RewriteQuery *message,DistDefInfo *info,RepliDefInfo *info2,SelectDefInfo *info3,char *alias,int select_num,int i_num);
static void AnalyzeReturnRecord(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, List *list);
static void build_virtual_table(RewriteQuery *message,void *obj, int next);
static char *search_type_from_virtual(VirtualTable *virtual,char *table,char *col);
static int _checkVirtualColumn(ColumnRef *col,RewriteQuery *message);
static void SeekColumnName(Aggexpr *agg,ColumnRef *node,int state);
/* rewirte */
static void writeSelectHeader(RewriteQuery *message,ConInfoTodblink *dblink, String *str,int parallel,int state);
static void writeSelectFooter(RewriteQuery *message,String *str,AnalyzeSelect *analyze,int state);
static void KeepRewriteQueryReturnCode(RewriteQuery *message, int r_code);
static void writeRangeHeader(RewriteQuery *message,ConInfoTodblink *dblink, String *str,DistDefInfo *info, RepliDefInfo *info2,char *alias);
static void writeRangeFooter(RewriteQuery *message,ConInfoTodblink *dblink, String *str,DistDefInfo *info, RepliDefInfo *info2,char *alias);
static bool CheckAggOpt(RewriteQuery *message);
static char *GetNameFromColumnRef(ColumnRef *node,bool state);
static void AvgFuncCall(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, FuncCall *node);
/* under define is used in _rewritejoinExpr */
#define JDEFAULT 0
#define JNORMAL 1
#define JNATURAL_INNER 2
#define JNATURAL_LEFT 3
#define JNATURAL_RIGHT 4
#define JNATURAL_FULL 5
#define JINNER 6
#define JLEFT 7
#define JRIGHT 8
#define JFULL 9
#define JUSING 10
#define LOADBALANCE false
#define PARALLEL true
#define SELECT_START -1
#define SELECT_FROMCLAUSE 0
#define SELECT_TARGETLIST 1
#define SELECT_WHERECLAUSE 2
#define SELECT_GROUPBYCLAUSE 3
#define SELECT_HAVINGCLAUSE 4
#define SELECT_SORTCLAUSE 5
#define SELECT_OFFSETCLAUSE 6
#define SELECT_LIMITCLAUSE 7
#define SELECT_OTHER 8
static char *escape_string(char *str)
{
int len = strlen(str), i, j;
char *es = palloc0(len * 2 + 1);
if (es == NULL)
{
return NULL;
}
for (i = 0, j = 0; i < len; i++, j++)
{
if (str[i] == '\'')
{
es[j++] = '\'';
}
else if (str[i] == '\\')
{
es[j++] = '\\';
}
es[j] = str[i];
}
return es;
}
static void
delay_string_append_char(RewriteQuery *message,String *str, char *parts)
{
if(message->r_code == SELECT_DEFAULT && message->ignore_rewrite == -1)
{
if(parts)
{
string_append_char( str, parts);
#ifdef DEBUG
pool_debug("debug Rewrite Query %s", str->data);
#endif
}
else
message->r_code = SELECT_RELATION_ERROR;
}
}
/*
* Is this column member of table (message->table_relname) ?
* return 1 -- member
* return 0 or -1 -- not mmeber
*/
static int
_checkVirtualColumn(ColumnRef *col,RewriteQuery *message)
{
ListCell *c;
List *list;
VirtualTable *virtual = NULL;
AnalyzeSelect *analyze = NULL;
char first = 0;
char *tmp_table = NULL;
char *colname = NULL;
char *table = NULL;
int check_col = 0;
int no = message->current_select;
int v_colnum;
int i;
list = col->fields;
analyze = message->analyze[no];
if(list->length > 2 || list->length == 0)
{
/* send error message */
return -1;
}
foreach (c, col->fields)
{
Node *n = (Node *) lfirst(c);
if (IsA(n, String))
{
Value *v = (Value *) lfirst(c);
if(list->length == 2 && first == 0)
{
first = 1;
tmp_table = v->val.str;
}
else
colname = v->val.str;
}
}
if(analyze->partstate[SELECT_FROMCLAUSE] == 'S')
{
if (message->table_relname)
{
if(tmp_table && strcmp(message->table_relname,tmp_table) != 0)
{
return check_col;
}
table = message->table_relname;
}
else
{
return check_col;
}
virtual = analyze->virtual;
v_colnum = virtual->col_num;
for(i = 0; i < v_colnum; i++)
{
if(!strcmp(virtual->table_list[i],table) &&
!strcmp(virtual->col_list[i],colname))
{
check_col = 1;
break;
}
}
} else {
virtual = analyze->virtual;
v_colnum = virtual->col_num;
for(i = 0; i < v_colnum; i++)
{
if(tmp_table)
{
if(!strcmp(virtual->table_list[i],tmp_table) &&
!strcmp(virtual->col_list[i],colname))
{
check_col = 1;
break;
}
}
else
{
if(!strcmp(virtual->col_list[i],colname))
{
check_col = 1;
break;
}
}
}
}
return check_col;
}
static void KeepMessages(RewriteQuery *message,int current_select,int part)
{
message->current_select = current_select;
message->part = part;
}
static void KeepRewriteQueryCode(RewriteQuery *message, int current_select)
{
message->current_select = current_select;
}
static void KeepRewriteQueryReturnCode(RewriteQuery *message, int r_code)
{
if((message->r_code != SELECT_RELATION_ERROR)
&& (message->r_code != SELECT_PGCATALOG))
message->r_code = r_code;
}
/*
* A_Expr check
* if A_Expr-tree use subquery,function,or other table member
* rewrite expression as "TRUE"
*
* return value is counter of rewriting query.
*/
static int
_writewhereClause(A_Expr *expr,RewriteQuery *message,ConInfoTodblink *dblink, String *str,int true_count)
{
int message_r_code = message->r_code;
switch (expr->kind)
{
case AEXPR_OP:
if (list_length(expr->name) == 1)
{
KeepRewriteQueryReturnCode(message, SELECT_AEXPR);
_rewriteNode(NULL, message, dblink, str, expr->lexpr);
if(message->r_code == SELECT_AEXPR)
{
_rewriteNode(NULL, message, dblink, str, expr->rexpr);
if(message->r_code == SELECT_AEXPR)
{
Value *op = (Value *) lfirst(list_head(expr->name));
KeepRewriteQueryReturnCode(message, message_r_code);
_rewriteNode(NULL, message, dblink, str, expr->lexpr);
delay_string_append_char(message, str, op->val.str);
_rewriteNode(NULL, message, dblink, str, expr->rexpr);
KeepRewriteQueryReturnCode(message, message_r_code);
} else {
KeepRewriteQueryReturnCode(message, message_r_code);
delay_string_append_char(message, str,"TRUE");
true_count++;
break;
}
} else {
KeepRewriteQueryReturnCode(message, message_r_code);
delay_string_append_char(message, str,"TRUE");
true_count++;
}
break;
}
else
{
delay_string_append_char(message, str,"TRUE");
true_count++;
}
break;
case AEXPR_AND:
delay_string_append_char(message, str, " (");
true_count = true_count + CheckWhereCaluse(expr->lexpr,message,dblink,str,true_count);
delay_string_append_char(message, str, " AND ");
true_count = true_count + CheckWhereCaluse(expr->rexpr,message,dblink,str,true_count);
delay_string_append_char(message, str, ")");
break;
case AEXPR_OR:
delay_string_append_char(message, str, " (");
true_count = true_count + CheckWhereCaluse(expr->lexpr,message,dblink,str,true_count);
delay_string_append_char(message, str, " OR ");
true_count = true_count + CheckWhereCaluse(expr->rexpr,message,dblink,str,true_count);
delay_string_append_char(message, str, ")");
break;
case AEXPR_OP_ANY:
/* not implemented yet */
break;
case AEXPR_OP_ALL:
/* not implemented yet */
break;
#if 0
case AEXPR_NOT:
delay_string_append_char(message, str, " (NOT ");
CheckWhereCaluse(expr->rexpr,str,tablename,dbname, schemaname,aliasname);
delay_string_append_char(message, str, ")");
break;
case AEXPR_DISTINCT:
delay_string_append_char(message, str, " (");
_rewriteNode(BaseSelect, message, dblink, str, node->lexpr);
delay_string_append_char(message, str, " IS DISTINCT FROM ");
_rewriteNode(BaseSelect, message, dblink, str, node->rexpr);
delay_string_append_char(message, str, ")");
break;
case AEXPR_NULLIF:
delay_string_append_char(message, str, " NULLIF(");
_rewriteNode(BaseSelect, message, dblink, str, node->lexpr);
delay_string_append_char(message, str, ", ");
_rewriteNode(BaseSelect, message, dblink, str, node->rexpr);
delay_string_append_char(message, str, ")");
break;
case AEXPR_OF:
_rewriteNode(BaseSelect, message, dblink, str, node->lexpr);
if (*(char *)lfirst(list_head(node->name)) == '!')
delay_string_append_char(message, str, " IS NOT OF (");
else
delay_string_append_char(message, str, " IS OF (");
_rewriteNode(BaseSelect, message, dblink, str, node->rexpr);
delay_string_append_char(message, str, ")");
break;
#endif
default:
delay_string_append_char(message, str,"TRUE");
true_count++;
break;
}
return true_count;
}
/*
* Start whereClasue check
* call _writewherelause();
*
* if messgae->r_code is SELECT DEFAULT,
* write down whereClause
* else
* check whereClause
*
* return value is counter of rewriting query
* if return value is zero, all whereclause can insert dblink function.
*/
static int
CheckWhereCaluse(Node *BaseSelect,RewriteQuery *message,ConInfoTodblink *dblink,String *str,int true_count)
{
A_Expr *expr = NULL;
if(!IsA(BaseSelect, A_Expr))
{
delay_string_append_char(message, str, "TRUE");
true_count++;
return true_count;
}
expr = (A_Expr *) BaseSelect;
if(expr->kind == AEXPR_NOT)
{
delay_string_append_char(message, str, "TRUE");
true_count++;
return true_count;
}
true_count = _writewhereClause(expr,message,dblink,str,true_count);
return true_count;
}
static void _rewriteIdList(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, List *node)
{
ListCell *lc;
char first = 0;
foreach(lc, node)
{
Value *v = lfirst(lc);
if (first == 0)
first = 1;
else
delay_string_append_char(message, str, ", ");
delay_string_append_char(message, str, "\"");
delay_string_append_char(message, str, v->val.str);
delay_string_append_char(message, str, "\"");
}
}
static void _rewriteList(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, List *node)
{
ListCell *lc;
char first = 0;
char state = (char)0;
int loop = 0;
bool from;
int current_select = message->current_select;
int next = -1;
bool lock = false;
AnalyzeSelect *analyze;
analyze = message->analyze[current_select];
if(message->r_code == SELECT_DEFAULT && message->ignore_rewrite == -1 &&
analyze->part == SELECT_TARGETLIST)
{
if(analyze->retlock == false)
{
lock = true;
analyze->retlock = true;
}
}
foreach(lc, node)
{
next = message->analyze_num;
if (first == 0)
{
first = 1;
}
else
{
if(lfirst(lc) && !IsA(lfirst(lc),A_Indices))
delay_string_append_char(message, str, ",");
}
/* init JoinTable */
if(message->r_code == SELECT_ANALYZE && message->fromClause)
{
if(lfirst(lc) && IsA(lfirst(lc),JoinExpr))
{
if(!analyze->join)
{
analyze->join = (JoinTable *) palloc(sizeof(JoinTable));
}
analyze->join->col_num = 0;
analyze->join->col_list = NULL;
analyze->join->type_list = NULL;
analyze->join->table_list = NULL;
analyze->join->using_list = NULL;
analyze->join->using_length = 0;
analyze->join->state = (char)0;
}
}
from = message->fromClause;
_rewriteNode(BaseSelect, message, dblink, str, lfirst(lc));
message->current_select = current_select;
message->fromClause = from;
if(message->r_code == SELECT_ANALYZE && message->fromClause)
{
if(lfirst(lc))
{
#if 0
/* 2009/07/27 */
if(IsA(lfirst(lc),JoinExpr) || IsA(lfirst(lc),RangeVar) || IsA(lfirst(lc),RangeSubselect))
build_virtual_table(message,lfirst(lc),next);
#endif
if(IsA(lfirst(lc),RangeVar) || IsA(lfirst(lc),RangeSubselect))
build_virtual_table(message,lfirst(lc),next);
if(IsA(lfirst(lc),JoinExpr))
{
JoinExpr *join = lfirst(lc);
if (join->quals)
{
_rewriteNode(BaseSelect, message, dblink, str, join->quals);
}
}
}
if(loop == 0)
{
state = message->table_state;
}
else
{
if(state =='L' && message->table_state == 'L')
{
message->table_state = 'L';
}
else if (state == 'L' && message->table_state == 'P')
{
message->table_state = 'P';
}
else if (state == 'P' && message->table_state == 'L')
{
message->table_state = 'P';
}
else
{
state = 'S';
message->table_state = 'S';
}
}
}
loop++;
if(message->r_code == SELECT_DEFAULT && message->ignore_rewrite == -1 &&
analyze->part == SELECT_TARGETLIST)
{
pool_debug("_rewriteList select=%d,count=%d", current_select,message->analyze[current_select]->ret_count);
if(lock)
message->analyze[current_select]->ret_count++;
}
}
if(message->r_code == SELECT_DEFAULT && message->ignore_rewrite == -1 &&
analyze->part == SELECT_TARGETLIST)
{
if(analyze->retlock && lock)
{
analyze->retlock = false;
}
}
}
/*****************************************************************************
*
* Stuff from primnodes.h.
*
*****************************************************************************/
static void
_rewriteAlias(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, Alias *node)
{
delay_string_append_char(message, str, " AS ");
delay_string_append_char(message, str, node->aliasname);
delay_string_append_char(message, str, " ");
if (node->colnames)
{
delay_string_append_char(message, str, "(");
_rewriteNode(BaseSelect, message, dblink, str, node->colnames);
delay_string_append_char(message, str, ")");
}
}
static void
append_all_virtual(AnalyzeSelect *analyze,char *table)
{
VirtualTable *virtual;
SelectDefInfo *select_ret;
int num;
int test_num;
int base;
int i;
int counter = 0;
virtual = analyze->virtual;
test_num = virtual->col_num;
select_ret = analyze->select_ret;
base = select_ret->col_num;
if(!table)
{
num = test_num;
}
else
{
num = 0;
for(i = 0; i< test_num; i++)
{
if(!strcmp(virtual->table_list[i],table))
num++;
}
}
if(base == 0)
{
select_ret->col_list = (char **) palloc(num * sizeof(char *));
select_ret->type_list = (char **) palloc(num * sizeof(char *));
select_ret->return_list = (int *) palloc(num * sizeof(int));
}
else
{
select_ret->col_list = (char **) repalloc(select_ret->col_list,(base + num) * sizeof(char *));
select_ret->type_list = (char **) repalloc(select_ret->type_list,(base + num) * sizeof(char *));
select_ret->return_list = (int *) repalloc(select_ret->return_list,(base + num) * sizeof(int));
}
for(i = 0; i< test_num;i++)
{
if(table && strcmp(virtual->table_list[i],table))
{
continue;
}
select_ret->col_list[base + counter] = virtual->col_list[i];
select_ret->type_list[base + counter] = virtual->type_list[i];
select_ret->return_list[base + counter] = -1;
pool_debug("append_select_def_info: col=%s,type=%s", select_ret->col_list[base + counter],select_ret->type_list[base + counter]);
counter++;
}
select_ret->col_num = base + num;
}
static void
append_select_def_info(SelectDefInfo *select_ret,char *col,char *type)
{
int base;
base = select_ret->col_num;
pool_debug("append_select_def_info: base=%d",base);
if(!type)
{
type = (char *)palloc(sizeof(char) * strlen("text") + 1);
strcpy(type,"text");
}
if(base == 0)
{
select_ret->col_list = (char **) palloc(sizeof(char *));
select_ret->type_list = (char **) palloc(sizeof(char *));
select_ret->return_list = (int *) palloc(sizeof(int));
}
else
{
select_ret->col_list = (char **) repalloc(select_ret->col_list,(base + 1) * sizeof(char *));
select_ret->type_list = (char **) repalloc(select_ret->type_list,(base + 1) * sizeof(char *));
select_ret->return_list = (int *) repalloc(select_ret->return_list,(base + 1) * sizeof(int));
}
select_ret->col_list[base] = col;
select_ret->type_list[base] = type;
select_ret->return_list[base] = -1;
select_ret->col_num++;
pool_debug("append_select_def_info: col=%s,type=%s base=%d",select_ret->col_list[base],select_ret->type_list[base],select_ret->col_num);
}
static char *search_type_from_virtual(VirtualTable *virtual,char *table,char *col)
{
int num = virtual->col_num;
int i;
for(i = 0; i < num; i++)
{
if(table)
{
if(!strcmp(virtual->table_list[i],table)
&& !strcmp(virtual->col_list[i],col))
return virtual->type_list[i];
}
else
{
if(!strcmp(virtual->col_list[i],col))
return virtual->type_list[i];
}
}
return NULL;
}
static void
AnalyzeReturnRecord(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, List *list)
{
int select_num;
int range_num;
AnalyzeSelect *analyze;
RangeInfo **range;
VirtualTable *virtual;
ListCell *lc;
int n_sublink = 0;
int c_sublink = 0;
select_num = message->current_select;
analyze=message->analyze[select_num];
virtual = analyze->virtual;
/* get range table info */
range_num = analyze->rangeinfo_num;
/* "range = 0" means that this select stmt have no table */
range = analyze->range;
analyze->select_ret = (SelectDefInfo *) palloc(sizeof(SelectDefInfo));
analyze->select_ret->valid = false;
analyze->select_ret->col_num = 0;
pool_debug("AnalyzeReturnRecord: current_select=%d",select_num);
foreach(lc, list)
{
ResTarget *target = NULL;
Node *n = lfirst(lc);
void *obj;
char *alias = NULL;
char *typecast = NULL;
char *colname = NULL;
char *table_name = NULL;
char *gettype = NULL;
target = (ResTarget *) n;
/* alias name */
if(target->name)
alias = target->name;
/* type name */
if(IsA(target->val, TypeCast))
{
TypeCast *type = (TypeCast *) target->val;
TypeName *typename = (TypeName *)type->typename;
obj = type->arg;
typecast = strVal(lfirst(list_head(typename->names)));
} else {
obj = target->val;
}
if(typecast && alias)
{
append_select_def_info(analyze->select_ret,alias,typecast);
continue;
}
/* column name */
if (obj && (IsA(obj, ColumnRef)))
{
int first = 0;
ListCell *c;
ColumnRef *col = NULL;
col = (ColumnRef *) obj;
foreach (c, col->fields)
{
Node *n = (Node *) lfirst(c);
if (IsA(n, String))
{
Value *v = (Value *) lfirst(c);
if(col->fields->length == 2 && first == 0)
{
first = 1;
table_name = v->val.str;
}
else
colname = v->val.str;
}
}
}
else if(obj && (IsA(obj, A_Expr)))
{
if(alias)
append_select_def_info(analyze->select_ret,alias,typecast);
else
{
char *colname;
colname = (char *)palloc(sizeof(char) * strlen("\"?column?\"") + 1);
strcpy(colname,"\"?column?\"");
append_select_def_info(analyze->select_ret,colname,typecast);
}
continue;
}
else if(obj && (IsA(obj, FuncCall)))
{
if(alias)
{
append_select_def_info(analyze->select_ret,alias,typecast);
}
else
{
FuncCall *func = NULL;
char *funcname;
func = (FuncCall *) obj;
funcname = strVal(lfirst(list_head(func->funcname)));
append_select_def_info(analyze->select_ret,funcname,typecast);
}
continue;
}
else if (obj && (IsA(obj,SubLink)))
{
int i;
int max = message->analyze_num;
AnalyzeSelect *sublink = NULL;
for(i = select_num + 1; i < max;i++)
{
sublink = message->analyze[i];
if(sublink->last_select == select_num
&& sublink->part == 1 && c_sublink == n_sublink)
break;
}
n_sublink++;
if(sublink && (sublink->select_ret->col_num == 1))
{
if(alias)
{
append_select_def_info(analyze->select_ret,alias,sublink->select_ret->type_list[0]);
continue;
}
else
{
char *column;
column = (char *)palloc(sizeof(char) * strlen("\"?column?\"") + 1);
strcpy(column,"\"?column?\"");
append_select_def_info(analyze->select_ret,column,sublink->select_ret->type_list[0]);
continue;
}
}
}
else if(obj && (IsA(obj,A_Const)))
{
char *column = NULL;
if(!alias)
{
column = (char *)palloc(sizeof(char) * strlen("\"?column?\"") + 1);
strcpy(column,"\"?column?\"");
alias = column;
}
append_select_def_info(analyze->select_ret,alias,typecast);
continue;
}
if(colname && !strcmp(colname,"*"))
{
append_all_virtual(analyze,table_name);
continue;
}
if(colname)
gettype = search_type_from_virtual(virtual,table_name,colname);
else
{
char *column = NULL;
column = (char *)palloc(sizeof(char) * strlen("\"?column?\"") + 1);
strcpy(column,"\"?column?\"");
append_select_def_info(analyze->select_ret,column,NULL);
continue;
}
if(gettype)
{
char *t_n;
char *t_t;
if(alias)
t_n = alias;
else
t_n = colname;
if(typecast)
t_t = typecast;
else
t_t = gettype;
append_select_def_info(analyze->select_ret,t_n,t_t);
}
}
}
static void
append_virtual_table(RewriteQuery *message,VirtualTable *virtual,char **col_list,char **type_list,int col_num,char *table_name,char state,int next)
{
int base;
int i;
if(virtual->col_num == 0)
{
base = 0;
virtual->col_list = (char**) palloc(sizeof(char*) * col_num);
virtual->type_list = (char**) palloc(sizeof(char*) * col_num);
virtual->table_list = (char**) palloc(sizeof(char*) * col_num);
virtual->state_list = (char*) palloc(sizeof(char) * col_num);
virtual->column_no = (int*) palloc(sizeof(int) * col_num);
virtual->valid = (int*) palloc(sizeof(int) * col_num);
}
else
{
base = virtual->col_num;
virtual->col_list = (char**) repalloc(virtual->col_list,sizeof(char*) * (base + col_num));
virtual->type_list = (char**) repalloc(virtual->type_list,sizeof(char*) * (base + col_num));
virtual->table_list = (char**) repalloc(virtual->table_list,sizeof(char*)* (base + col_num));
virtual->state_list = (char*) repalloc(virtual->state_list,sizeof(char) * (base + col_num));
virtual->column_no = (int*) repalloc(virtual->column_no,sizeof(int) * (base + col_num));
virtual->valid = (int*) repalloc(virtual->valid,sizeof(int) * (base + col_num));
}
for(i = 0; i< col_num; i++)
{
int j = base + i;
virtual->col_list[j] = col_list[i];
virtual->type_list[j] = type_list[i];
virtual->table_list[j] = table_name;
virtual->state_list[j] = state;
/* (next > 0) means this function call from RangeSubselect */
if(next > 0)
{
AnalyzeSelect *analyze = message->analyze[next];
SelectDefInfo *select_ret;
select_ret = analyze->select_ret;
select_ret->return_list[i] = message->column;
pool_debug("append_virtual_table return_list[%d]=%d,next=%d",i,message->column,next);
}
virtual->column_no[j] = message->column;
message->column++;
virtual->valid[j] = -1;
pool_debug("append_virtual_table select=%d, no=%d,col=%s,type=%s,table=%s,state=%c,valid=%d",
message->current_select,
virtual->column_no[j],virtual->col_list[j],virtual->type_list[j]
,virtual->table_list[j],virtual->state_list[j],virtual->valid[j]);
}
virtual->col_num = base + col_num;
}
static void append_join_using(AnalyzeSelect *analyze,char **col_list,char **type_list,int col_num,char *table_name)
{
int num,i,j,k;
int same[analyze->join->col_num];
int lvalid[analyze->join->col_num];
int rvalid[col_num];
char **using;
int lc = 0;
int rc = 0;
int sc = 0;
int total;
JoinTable *join = analyze->join;
JoinTable *new = (JoinTable *) palloc(sizeof(JoinTable));
using = join->using_list;
num = join->using_length;
for(i = 0; i < join->col_num; i++)
{
char *colname = join->col_list[i];
for(j = 0; j < num; j++)
{
if(!strcmp(colname, using[j]))
{
same[sc] = i;
sc++;
} else {
lvalid[lc] = i;
lc++;
}
}
}
for(i = 0; i < col_num; i++)
{
char *colname = col_list[i];
for(j = 0; j < num; j++)
{
if(strcmp(colname, using[j]))
{
rvalid[rc] = i;
rc++;
}
}
}
total= sc + lc + rc;
new->col_num = total;
new->col_list = (char**) palloc(sizeof(char*) * (total));
new->type_list = (char**) palloc(sizeof(char*) * (total));
new->table_list = (char**) palloc(sizeof(char*) * (total));
for(k = 0; k < sc; k++)
{
new->col_list[k] = join->col_list[same[k]];
new->type_list[k] = join->type_list[same[k]];
new->table_list[k] = join->table_list[same[k]];
}
for(k = sc; k < sc + lc; k++)
{
new->col_list[k] = join->col_list[lvalid[k - sc]];
new->type_list[k] = join->type_list[lvalid[k - sc]];
new->table_list[k] = join->table_list[lvalid[k - sc]];
}
for(k = sc + lc; k < sc + lc + rc; k++)
{
new->col_list[k] = col_list[rvalid[k - lc - sc]];
new->type_list[k] = type_list[rvalid[k - lc - sc]];
if(table_name)
{
new->table_list[k] = table_name;
}
else
new->table_list[k] = NULL;
}
analyze->join = new;
for(i = 0; i< analyze->join->col_num; i++)
{
pool_debug("append_join_using no = %d ,col=%s,type=%s,table=%s",
i,new->col_list[i],new->type_list[i],new->table_list[i]);
}
}
static void append_join_natural(AnalyzeSelect *analyze,char **col_list,char **type_list,int base,int col_num,char *table_name)
{
int same[base + 1];
int rvalid[base + 1];
int linvalid[col_num + 1];
int lvalid[col_num +1];
int i,j,k;
int sc = 0;
int vc = 0;
int ic = 0;
int total = 0;
int count;
JoinTable *join = analyze->join;
JoinTable *new = (JoinTable *) palloc(sizeof(JoinTable));
for(i = 0; i < base; i++)
{
char *colname = join->col_list[i];
int match = 0;
int array = -1;
for(j = 0; j < col_num; j++)
{
if(!strcmp(colname, col_list[j]))
{
match++;
array = j;
}
}
if(match == 0)
{
rvalid[vc] = i;
vc++;
}
else if(match == 1)
{
same[sc] = i;
linvalid[ic] = array;
sc++;
ic++;
}
else
{
/* XXX */
}
}
total=sc + vc + (col_num - ic);
new->col_num = total;
new->col_list = (char**) palloc(sizeof(char*) * (total));
new->type_list = (char**) palloc(sizeof(char*) * (total));
new->table_list = (char**) palloc(sizeof(char*) * (total));
for(k = 0; k < sc; k++)
{
new->col_list[k] = join->col_list[same[k]];
new->type_list[k] = join->type_list[same[k]];
if(table_name)
{
new->table_list[k] = table_name;
}
else
new->table_list[k] = join->table_list[same[k]];
}
for(k = sc; k < sc + vc; k++)
{
new->col_list[k] = join->col_list[rvalid[k - sc]];
new->type_list[k] = join->type_list[rvalid[k - sc]];
if(table_name)
{
new->table_list[k] = table_name;
}
else
new->table_list[k] = join->table_list[rvalid[k - sc]];
}
count = 0;
for(k = 0; k <col_num ; k++)
{
int l = 0;
bool test = true;
for(l = 0; l< ic; l++)
{
if(k == linvalid[l])
test = false;
}
if(test)
{
lvalid[count] = k;
count++;
}
}
for(k = sc + vc; k < sc + vc + count; k++)
{
new->col_list[k] = col_list[lvalid[k - sc - vc]];
new->type_list[k] = type_list[lvalid[k - sc - vc]];
if(table_name)
{
new->table_list[k] = table_name;
}
else
new->table_list[k] = NULL;
}
analyze->join = new;
for(i = 0; i< analyze->join->col_num; i++)
{
pool_debug("append_join_natural no = %d ,col=%s,type=%s,table=%s",
i,new->col_list[i],new->type_list[i],new->table_list[i]);
}
}
static void append_join_simple(JoinTable *join,char **col_list,char **type_list,int col_num,char *table_name)
{
int base;
int i;
pool_debug("append_join_table start");
if(join->col_num == 0)
{
base = 0;
join->col_list = (char**) palloc(sizeof(char*) * col_num);
join->type_list = (char**) palloc(sizeof(char*) * col_num);
join->table_list = (char**) palloc(sizeof(char*) * col_num);
}
else
{
base = join->col_num;
join->col_list = (char**) repalloc(join->col_list,sizeof(char*) * (base + col_num));
join->type_list = (char**) repalloc(join->type_list,sizeof(char*) * (base + col_num));
join->table_list = (char**) repalloc(join->table_list,sizeof(char*) * (base + col_num));
}
for(i = 0; i< col_num; i++)
{
join->col_list[base + i] = col_list[i];
join->type_list[base + i] = type_list[i];
join->table_list[base + i] = table_name;
pool_debug("append_join_table no = %d ,col=%s,type=%s,table=%s",
base + i,join->col_list[base + i],join->type_list[base + i],join->table_list[base + i]);
}
join->col_num = base + col_num;
}
static void build_join_table(RewriteQuery *message,char *alias, int type)
{
char *table_name = NULL;
char state;
char lstate;
int left_num,right_num,range_num,select_num;
DistDefInfo *distinfo = NULL;
RepliDefInfo *repliinfo = NULL;
SelectDefInfo *selectinfo = NULL;
JoinTable *join;
RangeInfo *range;
AnalyzeSelect *analyze;
select_num = message->current_select;
analyze=message->analyze[select_num];
join = analyze->join;
left_num = join->col_num;
range_num = analyze->rangeinfo_num;
range = analyze->range[range_num - 1];
state = range->state;
lstate = join->state;
right_num = 0;
distinfo = range->distinfo;
repliinfo = range->repliinfo;
selectinfo = range->selectinfo;
if(alias)
table_name = alias;
else if(!alias && range->alias)
table_name = range->alias;
if(distinfo && !repliinfo && !selectinfo)
{
right_num = distinfo->col_num;
if(!table_name)
table_name = distinfo->table_name;
pool_debug("inside build_join_info dist state=%c %s",range->state,table_name);
if(type == JNATURAL_INNER || type == JNATURAL_RIGHT
|| type == JNATURAL_LEFT || type == JNATURAL_FULL)
append_join_natural(analyze,distinfo->col_list,distinfo->type_list,join->col_num,distinfo->col_num,table_name);
else
append_join_simple(join,distinfo->col_list,distinfo->type_list,distinfo->col_num,table_name);
}
else if (repliinfo && !distinfo && !selectinfo)
{
right_num = repliinfo->col_num;
if(!table_name)
table_name = repliinfo->table_name;
pool_debug("inside build_join_info dist state=%c %s",range->state,table_name);
if(type == JNATURAL_INNER || type == JNATURAL_RIGHT
|| type == JNATURAL_LEFT || type == JNATURAL_FULL)
append_join_natural(analyze,repliinfo->col_list,repliinfo->type_list,join->col_num,repliinfo->col_num,table_name);
else if(join->using_length != 0)
append_join_using(analyze,repliinfo->col_list,repliinfo->type_list,repliinfo->col_num,table_name);
else
append_join_simple(join,repliinfo->col_list,repliinfo->type_list,repliinfo->col_num,table_name);
}
else if (selectinfo && !repliinfo && !distinfo)
{
pool_debug("inside build_join_info dist state=%c %s",range->state,table_name);
right_num = selectinfo->col_num;
if(type == JNATURAL_INNER || type == JNATURAL_RIGHT
|| type == JNATURAL_LEFT || type == JNATURAL_FULL)
append_join_natural(analyze,selectinfo->col_list,selectinfo->type_list,join->col_num,selectinfo->col_num,table_name);
else if(join->using_length != 0)
append_join_using(analyze,selectinfo->col_list,selectinfo->type_list,selectinfo->col_num,table_name);
else
append_join_simple(join,selectinfo->col_list,selectinfo->type_list,selectinfo->col_num,table_name);
}
if(type == JDEFAULT)
{
join->state = state;
return;
}
join =analyze->join;
if(lstate =='E' || state == 'E')
{
join->state = 'E';
return;
}
if(lstate =='L' && state =='L')
{
join->state = 'L';
return;
}
if(lstate =='L' && state =='P')
{
int total = left_num + right_num;
if(type == JRIGHT || type == JNORMAL || type == JINNER || type == JNATURAL_INNER)
join->state = 'P';
else if((join->col_num <= total) && (type == JNATURAL_RIGHT))
join->state = 'P';
else if((join->col_num == total) && (type == JNATURAL_LEFT))
join->state = 'P';
else
join->state = 'S';
}
else if(lstate =='P' && state == 'L')
{
int total = left_num + right_num;
if(type == JLEFT || type == JNORMAL || type == JINNER || type == JNATURAL_INNER)
join->state ='P';
else if((join->col_num <= total) && (type == JNATURAL_LEFT))
join->state = 'P';
else if((join->col_num == total) && (type == JNATURAL_RIGHT))
join->state = 'P';
else
join->state ='S';
}
else
join->state = 'S';
}
static void change_analyze_state(AnalyzeSelect *analyze,char state)
{
if(state == 'E' || analyze->state == 'E')
return;
if(!analyze->state)
{
analyze->state = state;
}
else if(analyze->state == 'P' && state =='L')
{
analyze->state = 'P';
}
else if(analyze->state == 'L' && state =='P')
{
analyze->state = 'P';
}
else if(analyze->state == 'L' && state =='L')
{
return;
}
else
analyze->state = 'S';
}
static void build_virtual_table(RewriteQuery *message,void *obj,int next)
{
int select_num;
int range_num;
char *alias = NULL;
char *table_name = NULL;
char state;
AnalyzeSelect *analyze;
VirtualTable *virtual;
RangeInfo *range;
DistDefInfo *distinfo;
RepliDefInfo *repliinfo;
SelectDefInfo *selectinfo;
JoinTable *join;
select_num = message->current_select;
analyze=message->analyze[select_num];
virtual = analyze->virtual;
/* last range */
if(IsA(obj,RangeVar) || IsA(obj,RangeSubselect))
{
range_num = analyze->rangeinfo_num;
range = analyze->range[range_num - 1];
distinfo = range->distinfo;
repliinfo = range->repliinfo;
selectinfo = range->selectinfo;
}
else
{
/* join case */
int i;
join =analyze->join;
for(i =0; i < join->col_num;i++)
{
append_virtual_table(message,virtual,join->col_list++,join->type_list++,1,join->table_list[i],join->state,-1);
}
pool_debug("build_virtual_table join join->colnum=%d",join->col_num);
analyze->state = join->state;
return;
}
if(range->alias)
alias = range->alias;
state = range->state;
if(distinfo && !repliinfo && !selectinfo)
{
if(alias)
table_name =alias;
else
table_name = distinfo->table_name;
pool_debug("inside build_virtual_info dist state=%c %s",range->state,table_name);
append_virtual_table(message,virtual,distinfo->col_list,distinfo->type_list,distinfo->col_num,table_name,state,-2);
change_analyze_state(analyze,state);
return;
}
else if (repliinfo && !distinfo && !selectinfo)
{
if(alias)
table_name =alias;
else
table_name = repliinfo->table_name;
pool_debug("inside build_virtual_info dist state=%c %s",range->state,table_name);
append_virtual_table(message,virtual,repliinfo->col_list,repliinfo->type_list,repliinfo->col_num,table_name,state,-3);
change_analyze_state(analyze,state);
return;
}
else if (selectinfo && !repliinfo && !distinfo)
{
table_name = alias;
pool_debug("inside build_virtual_info select state=%c %s",range->state,table_name);
append_virtual_table(message,virtual,selectinfo->col_list,selectinfo->type_list,selectinfo->col_num,table_name,state,next);
change_analyze_state(analyze,state);
return;
}
else if (!selectinfo && !repliinfo && !distinfo)
{
pool_debug("inside build_virtual_info dist state=%c %s",range->state,alias);
change_analyze_state(analyze,'E');
}
}
static void
build_range_info(RewriteQuery *message,DistDefInfo *info,RepliDefInfo *info2,SelectDefInfo *info3,char *alias, int select_num,int i_num)
{
int num;
AnalyzeSelect *analyze;
analyze=message->analyze[select_num];
if(analyze->range)
{
++analyze->rangeinfo_num;
num = analyze->rangeinfo_num;
analyze->range =
(RangeInfo **) repalloc(analyze->range,sizeof(RangeInfo *) * num);
analyze->range[num-1] = (RangeInfo *) palloc(sizeof(RangeInfo));
pool_debug("inside build_range_info num= %d current_select=%d",num,select_num);
}
else
{
num = 1;
analyze->range = (RangeInfo **) palloc(sizeof(RangeInfo *));
analyze->range[0] = (RangeInfo *) palloc(sizeof(RangeInfo));
analyze->rangeinfo_num = 1;
pool_debug("inside build_range_info num= %d current_select=%d",num,select_num);
}
analyze->range[num -1]->ret_num = num - 1;
analyze->range[num -1]->selectinfo = NULL;
/* set dist_def_info */
if(info && !info2 && !info3)
{
message->is_loadbalance = false;
analyze->range[num -1]->distinfo = info;
analyze->range[num -1]->repliinfo = NULL;
analyze->select_ret = NULL;
analyze->range[num -1]->alias = alias;
analyze->range[num -1]->state = 'P';
pool_debug("inside build_range_info dist %d",select_num);
}
/* set repli_def_info */
if(info2 && !info && !info3)
{
analyze->range[num -1]->distinfo = NULL;
analyze->range[num -1]->repliinfo = info2;
analyze->select_ret = NULL;
analyze->range[num -1]->alias = alias;
analyze->range[num -1]->state = 'L';
pool_debug("inside build_range_info repli %d",select_num);
return;
}
/* CALL FROM _rertiteRangeSubselect */
if(info3 && !info && !info2)
{
char state = (char)0;
analyze->range[num -1]->distinfo = NULL;
analyze->range[num -1]->repliinfo = NULL;
analyze->range[num -1]->selectinfo = info3;
analyze->range[num -1]->alias = alias;
state = message->analyze[i_num]->state;
analyze->range[num -1]->state = state;
pool_debug("inside build_range_info select %d, state = %c (%c)",select_num,state,analyze->state);
return;
}
if(info && info2)
{
/*TODO: error*/
analyze->select_ret = NULL;
pool_debug("inside build_range_info error %d",select_num);
return;
}
if(!info && !info2 && !info3)
{
/*TODO: error*/
message->is_loadbalance = true;
analyze->range[num -1]->distinfo = NULL;
analyze->range[num -1]->repliinfo = NULL;
analyze->range[num -1]->state = 'E';
analyze->select_ret = NULL;
analyze->range[num -1]->alias = alias;
pool_debug("inside build_range_info const or func %d",select_num);
}
}
static void
_rewriteRangeVar(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, RangeVar *node)
{
DistDefInfo *info = NULL;
RepliDefInfo *info2 = NULL;
if(message->r_code == SELECT_ANALYZE)
{
info = pool_get_dist_def_info(dblink->dbname, node->schemaname, node->relname);
info2 = pool_get_repli_def_info(dblink->dbname, node->schemaname, node->relname);
}
if(!(message->r_code == SELECT_DEFAULT && message->rewritelock == -1 && message->ignore_rewrite == -1))
{
if (node->catalogname)
{
delay_string_append_char(message, str, node->catalogname);
delay_string_append_char(message, str, ".");
}
if (node->schemaname)
{
delay_string_append_char(message, str, node->schemaname);
delay_string_append_char(message, str, ".");
if(strcmp(node->schemaname,"pg_catalog") == 0)
{
message->is_pg_catalog = true;
}
}
delay_string_append_char(message, str, node->relname);
if (node->alias)
{
Alias *alias = node->alias;
_rewriteNode(BaseSelect, message, dblink, str, node->alias);
if(message->r_code == SELECT_ANALYZE)
build_range_info(message,info,info2,NULL,alias->aliasname,message->current_select,-1);
}
else
{
if(message->r_code == SELECT_ANALYZE)
build_range_info(message,info,info2,NULL,node->relname,message->current_select,-1);
}
if (node->inhOpt == INH_YES)
{
delay_string_append_char(message, str, " * ");
}
}
else
{
/* rewrite query using dblink connection */
char *alias_name = NULL;
SelectStmt *select = (SelectStmt *)BaseSelect;
if(node->alias)
{
alias_name = node->alias->aliasname;
}
/*
* iff schemaname is pg_catalog, send query to
* one node not system db.
*/
if(node->schemaname &&
(strcmp(node->schemaname,"pg_catalog") == 0))
{
message->is_pg_catalog =true;
return;
}
info = pool_get_dist_def_info(dblink->dbname, node->schemaname, node->relname);
info2 = pool_get_repli_def_info(dblink->dbname, node->schemaname, node->relname);
writeRangeHeader(message,dblink,str,info,info2,alias_name);
if (node->catalogname)
{
delay_string_append_char(message, str, node->catalogname);
delay_string_append_char(message, str, ".");
}
if (node->schemaname)
{
delay_string_append_char(message, str, node->schemaname);
delay_string_append_char(message, str, ".");
message->schemaname = node->schemaname;
if(strcmp(node->schemaname,"pg_catalog") == 0)
{
message->is_pg_catalog = true;
}
}
else
message->schemaname = NULL;
delay_string_append_char(message, str, node->relname);
if (alias_name)
{
delay_string_append_char(message, str, " AS ");
delay_string_append_char(message, str, alias_name);
}
if(select->whereClause &&
!(message->r_code == SELECT_PGCATALOG))
{
char * temp = NULL;
int message_code = message->r_code;
delay_string_append_char(message, str, " WHERE ");
if(message->table_relname)
temp = message->table_relname;
if(alias_name)
message->table_relname = alias_name;
else
message->table_relname = node->relname;
message->rewritelock = message->current_select;
CheckWhereCaluse(select->whereClause, message,dblink,str,0);
message->rewritelock = -1;
message->table_relname = temp;
KeepRewriteQueryReturnCode(message, message_code);
}
writeRangeFooter(message,dblink,str,info,info2,alias_name);
if (node->inhOpt == INH_YES)
{
delay_string_append_char(message, str, " * ");
}
}
}
static void
_rewriteVar(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, Var *node)
{
}
static void
_rewriteConst(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, Const *node)
{
}
static void
_rewriteParam(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, Param *node)
{
}
static void
_rewriteAggref(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, Aggref *node)
{
}
static void
_rewriteArrayRef(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, ArrayRef *node)
{
}
static void
_rewriteFuncExpr(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, FuncExpr *node)
{
}
static void
_rewriteOpExpr(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, OpExpr *node)
{
}
static void
_rewriteDistinctExpr(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, DistinctExpr *node)
{
}
static void
_rewriteScalarArrayOpExpr(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, ScalarArrayOpExpr *node)
{
}
static void
_rewriteBoolExpr(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, BoolExpr *node)
{
}
static void
_rewriteSubLink(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, SubLink *node)
{
if(message->r_code == SELECT_AEXPR)
{
KeepRewriteQueryReturnCode(message, SELECT_AEXPR_FALSE);
return;
}
_rewriteNode(BaseSelect, message, dblink, str, node->testexpr);
if (node->operName != NIL)
{
Value *v = linitial(node->operName);
if (strcmp(v->val.str, "=") == 0)
delay_string_append_char(message, str, " IN ");
else
{
delay_string_append_char(message, str, v->val.str);
}
}
switch (node->subLinkType)
{
case EXISTS_SUBLINK:
delay_string_append_char(message, str, " EXISTS ");
break;
case ARRAY_SUBLINK:
delay_string_append_char(message, str, " ARRAY ");
break;
case ANY_SUBLINK:
if (node->operName != NIL)
{
Value *v = linitial(node->operName);
if (strcmp(v->val.str, "=") != 0)
{
delay_string_append_char(message, str, v->val.str);
delay_string_append_char(message, str, " ANY ");
}
}
break;
case ALL_SUBLINK:
delay_string_append_char(message, str, " ALL ");
break;
default:
break;
}
if (node->subselect)
{
int count = message->current_select;
int part = message->part;
delay_string_append_char(message, str, "(");
_rewriteNode(BaseSelect, message, dblink, str, node->subselect);
delay_string_append_char(message, str, ")");
KeepMessages(message,count,part);
}
}
static void
_rewriteSubPlan(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, SubPlan *node)
{
}
static void
_rewriteFieldSelect(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, FieldSelect *node)
{
}
static void
_rewriteFieldStore(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, FieldStore *node)
{
}
static void
_rewriteRelabelType(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, RelabelType *node)
{
}
static void
_rewriteConvertRowtypeExpr(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, ConvertRowtypeExpr *node)
{
}
static void
_rewriteCaseExpr(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, CaseExpr *node)
{
ListCell *lc;
delay_string_append_char(message, str, "CASE ");
if (node->arg)
_rewriteNode(BaseSelect, message, dblink, str, node->arg);
foreach (lc, node->args)
{
_rewriteNode(BaseSelect, message, dblink, str, lfirst(lc));
}
if (node->defresult)
{
delay_string_append_char(message, str, " ELSE ");
_rewriteNode(BaseSelect, message, dblink, str, node->defresult);
}
delay_string_append_char(message, str, " END");
}
static void
_rewriteCaseWhen(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, CaseWhen *node)
{
delay_string_append_char(message, str, " WHEN ");
_rewriteNode(BaseSelect, message, dblink, str, node->expr);
delay_string_append_char(message, str, " THEN ");
_rewriteNode(BaseSelect, message, dblink, str, node->result);
}
static void
_rewriteCaseTestExpr(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, CaseTestExpr *node)
{
}
static void
_rewriteArrayExpr(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, ArrayExpr *node)
{
delay_string_append_char(message, str, "[");
_rewriteNode(BaseSelect, message, dblink, str, node->elements);
delay_string_append_char(message, str, "]");
}
static void
_rewriteRowExpr(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, RowExpr *node)
{
if (node->args == NIL)
delay_string_append_char(message, str, "ROW ()");
else
{
delay_string_append_char(message, str, "ROW (");
_rewriteNode(BaseSelect, message, dblink, str, node->args);
delay_string_append_char(message, str, ")");
}
}
static void
_rewriteCoalesceExpr(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, CoalesceExpr *node)
{
delay_string_append_char(message, str, "COALESCE (");
_rewriteNode(BaseSelect, message, dblink, str, node->args);
delay_string_append_char(message, str, ")");
}
static void
_rewriteMinMaxExpr(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, MinMaxExpr *node)
{
if (node->op == IS_GREATEST)
{
delay_string_append_char(message, str, "GREATEST (");
_rewriteNode(BaseSelect, message, dblink, str, node->args);
delay_string_append_char(message, str, ")");
}
else if (node->op == IS_LEAST)
{
delay_string_append_char(message, str, "LEAST (");
_rewriteNode(BaseSelect, message, dblink, str, node->args);
delay_string_append_char(message, str, ")");
}
}
static void
_rewriteNullIfExpr(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, NullIfExpr *node)
{
}
static void
_rewriteNullTest(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, NullTest *node)
{
_rewriteNode(BaseSelect, message, dblink, str, node->arg);
if (node->nulltesttype == IS_NOT_NULL)
delay_string_append_char(message, str, " IS NOT NULL");
else
delay_string_append_char(message, str, " IS NULL");
}
static void
_rewriteBooleanTest(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, BooleanTest *node)
{
_rewriteNode(BaseSelect, message, dblink, str, node->arg);
switch (node->booltesttype)
{
case IS_TRUE:
delay_string_append_char(message, str, " IS TRUE");
break;
case IS_NOT_TRUE:
delay_string_append_char(message, str, " IS NOT TRUE");
break;
case IS_FALSE:
delay_string_append_char(message, str, " IS FALSE");
break;
case IS_NOT_FALSE:
delay_string_append_char(message, str, " IS NOT FALSE");
break;
case IS_UNKNOWN:
delay_string_append_char(message, str, " IS UNKNOWN");
break;
case IS_NOT_UNKNOWN:
delay_string_append_char(message, str, " IS NOT UNKNOWN");
break;
}
}
static void
_rewriteCoerceToDomain(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, CoerceToDomain *node)
{
}
static void
_rewriteCoerceToDomainValue(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, CoerceToDomainValue *node)
{
}
static void
_rewriteSetToDefault(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, SetToDefault *node)
{
delay_string_append_char(message, str, "DEFAULT");
}
static void
_rewriteTargetEntry(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, TargetEntry *node)
{
}
static void
_rewriteRangeTblRef(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, RangeTblRef *node)
{
}
static char *GetTableName(Node *node)
{
if(IsA(node, RangeVar))
{
RangeVar *range = (RangeVar *)node;
if(range->alias)
{
Alias *alias = range->alias;
return alias->aliasname;
} else {
return range->relname;
}
}
else if (IsA(node,RangeSubselect))
{
RangeSubselect *select = (RangeSubselect *)node;
Alias * alias = select->alias;
return alias->aliasname;
}
return NULL;
}
static int RetVirtualColumn(VirtualTable *virtual, char *tablename, char *colname)
{
int col_num = virtual->col_num;
int i;
for( i = 0; i < col_num; i++)
{
if(strcmp(virtual->col_list[i], colname) == 0
&& strcmp(virtual->table_list[i], tablename) == 0)
{
return virtual->column_no[i];
}
}
/* ERROR OR AMBIGIUS */
return -1;
}
static void
ConvertFromUsingToON(RewriteQuery *message, String *str, JoinExpr *node, int select_num)
{
char *lname;
char *rname;
char comma = 0;
ListCell *lc;
VirtualTable *virtual = message->analyze[select_num]->virtual;
lname = GetTableName(node->larg);
rname = GetTableName(node->rarg);
delay_string_append_char(message, str, " ON");
foreach (lc, node->using)
{
Value *value;
char lbuf[16];
char rbuf[16];
if (comma == 0)
comma = 1;
else
delay_string_append_char(message, str, " AND ");
value = lfirst(lc);
snprintf(lbuf, 16, "%d",RetVirtualColumn(virtual,lname,value->val.str));
snprintf(rbuf, 16, "%d",RetVirtualColumn(virtual,rname,value->val.str));
delay_string_append_char(message, str, " pool_c$");
delay_string_append_char(message, str, lbuf);
delay_string_append_char(message, str, " = ");
delay_string_append_char(message, str, " pool_c$");
delay_string_append_char(message, str, rbuf);
delay_string_append_char(message, str, " ");
}
}
static void
_rewriteJoinExpr(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, JoinExpr *node)
{
char l_state,r_state;
bool from;
int select_num;
bool natural = false;
bool inner = false;
bool cross = false;
bool full = false;
bool left = false;
bool right = false;
char *aliasname;
int using_length = 0;
char **using_list;
Alias *alias = node->alias;
if(alias)
aliasname = alias->aliasname;
else
aliasname = NULL;
from = message->fromClause;
select_num = message->current_select;
_rewriteNode(BaseSelect, message, dblink, str, node->larg);
/* reset message */
message->fromClause = from;
message->current_select = select_num;
l_state = message->table_state;
if(message->r_code == SELECT_ANALYZE &&
(IsA(node->larg, RangeVar) || IsA(node->larg,RangeSubselect)))
{
build_join_table(message,aliasname,JDEFAULT);
}
if (node->isNatural == TRUE)
{
natural = true;
delay_string_append_char(message, str, " NATURAL");
}
if (node->jointype == JOIN_INNER)
{
if (node->using == NIL && node->quals == NULL && !node->isNatural)
{
cross = true;
delay_string_append_char(message, str, " CROSS JOIN ");
}
else
{
delay_string_append_char(message, str, " JOIN ");
inner = true;
}
}
else if (node->jointype == JOIN_LEFT)
{
delay_string_append_char(message, str, " LEFT OUTER JOIN ");
left = true;
}
else if (node->jointype == JOIN_FULL)
{
delay_string_append_char(message, str, " FULL OUTER JOIN ");
full = true;
}
else if (node->jointype == JOIN_RIGHT)
{
delay_string_append_char(message, str, " RIGHT OUTER JOIN ");
right = true;
}
_rewriteNode(BaseSelect, message, dblink, str, node->rarg);
r_state = message->table_state;
message->fromClause = from;
message->current_select = select_num;
if(message->r_code == SELECT_ANALYZE)
{
if(cross && (IsA(node->rarg, RangeVar) || IsA(node->rarg,RangeSubselect)))
build_join_table(message,aliasname,JNORMAL);
if(IsA(node->rarg, RangeVar) || IsA(node->rarg,RangeSubselect))
{
if(natural && inner)
build_join_table(message,aliasname,JNATURAL_INNER);
else if(natural && left)
build_join_table(message,aliasname,JNATURAL_LEFT);
else if(natural && right)
build_join_table(message,aliasname,JNATURAL_RIGHT);
else if(natural && full)
build_join_table(message,aliasname,JNORMAL);
}
}
if (node->using != NIL && IsA(node->using, List))
{
ListCell *lc;
char comma = 0;
int count = 0;
using_length= list_length(node->using);
using_list = (char **) palloc(sizeof(char *) * using_length);
if(message->r_code == SELECT_DEFAULT && message->rewritelock == -1
&& message->analyze[select_num]->state == 'S')
{
/* Rewrite Using Cluase to On Clause */
ConvertFromUsingToON(message, str, node, select_num);
} else {
delay_string_append_char(message, str, " USING(");
foreach (lc, node->using)
{
Value *value;
if (comma == 0)
comma = 1;
else
delay_string_append_char(message, str, ",");
value = lfirst(lc);
delay_string_append_char(message, str, value->val.str);
using_list[count] = value->val.str;
count++;
}
message->analyze[select_num]->join->using_length = using_length;
message->analyze[select_num]->join->using_list = using_list;
delay_string_append_char(message, str, ")");
}
}
#if 0 /* 2009/07/24*/
if (node->quals)
{
delay_string_append_char(message, str, " ON ");
if(message->r_code != SELECT_ANALYZE)
_rewriteNode(BaseSelect, message, dblink, str, node->quals);
}
#endif
if(message->r_code == SELECT_ANALYZE)
{
if(IsA(node->rarg, RangeVar) || IsA(node->rarg,RangeSubselect))
{
if(!natural && inner)
build_join_table(message,aliasname,JINNER);
else if(!natural && left)
build_join_table(message,aliasname,JLEFT);
else if(!natural && right)
build_join_table(message,aliasname,JRIGHT);
else if(!natural && full)
build_join_table(message,aliasname,JNORMAL);
}
}
/* 2009/07/24
* move build_virtual_table from _rewriteList
*/
if(message->r_code == SELECT_ANALYZE)
build_virtual_table(message,node,message->analyze_num);
if (node->quals)
{
delay_string_append_char(message, str, " ON ");
_rewriteNode(BaseSelect, message, dblink, str, node->quals);
}
}
static void
_rewriteFromExpr(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, FromExpr *node)
{
}
/*****************************************************************************
*
* Stuff from parsenodes.h.
*
*****************************************************************************/
static void
_rewriteCreateStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, CreateStmt *node)
{
delay_string_append_char(message, str, "CREATE ");
if (node->relation->istemp)
delay_string_append_char(message, str, "TEMP ");
delay_string_append_char(message, str, "TABLE ");
_rewriteNode(BaseSelect, message, dblink, str, node->relation);
delay_string_append_char(message, str, " (");
_rewriteNode(BaseSelect, message, dblink, str, node->tableElts);
delay_string_append_char(message, str, ") ");
if (node->inhRelations != NIL)
{
delay_string_append_char(message, str, "INHERITS (");
_rewriteNode(BaseSelect, message, dblink, str, node->inhRelations);
delay_string_append_char(message, str, ")");
}
if (node->options)
_rewriteWithDefinition(BaseSelect, message, dblink, str, node->options);
switch (node->oncommit)
{
case ONCOMMIT_DROP:
delay_string_append_char(message, str, " ON COMMIT DROP");
break;
case ONCOMMIT_DELETE_ROWS:
delay_string_append_char(message, str, " ON COMMIT DELETE ROWS");
case ONCOMMIT_PRESERVE_ROWS:
delay_string_append_char(message, str, " ON COMMIT PRESERVE ROWS");
break;
default:
break;
}
if (node->tablespacename)
{
delay_string_append_char(message, str, " TABLESPACE \"");
delay_string_append_char(message, str, node->tablespacename);
delay_string_append_char(message, str, "\"");
}
}
static void
_rewriteIndexStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, IndexStmt *node)
{
delay_string_append_char(message, str, "CREATE ");
if (node->unique == TRUE)
delay_string_append_char(message, str, "UNIQUE ");
if (node->concurrent == true)
delay_string_append_char(message, str, "INDEX CONCURRENTLY \"");
else
delay_string_append_char(message, str, "INDEX \"");
delay_string_append_char(message, str, node->idxname);
delay_string_append_char(message, str, "\" ON ");
_rewriteNode(BaseSelect, message, dblink, str, node->relation);
if (strcmp(node->accessMethod, DEFAULT_INDEX_TYPE))
{
delay_string_append_char(message, str, " USING ");
delay_string_append_char(message, str, node->accessMethod);
}
delay_string_append_char(message, str, "(");
_rewriteNode(BaseSelect, message, dblink, str, node->indexParams);
delay_string_append_char(message, str, ")");
if (node->tableSpace)
{
delay_string_append_char(message, str, " TABLESPACE \"");
delay_string_append_char(message, str, node->tableSpace);
delay_string_append_char(message, str, "\"");
}
if (node->whereClause)
{
delay_string_append_char(message, str, " WHERE ");
_rewriteNode(BaseSelect, message, dblink, str, node->whereClause);
}
}
static void
_rewriteNotifyStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, NotifyStmt *node)
{
delay_string_append_char(message, str, "NOTIFY ");
delay_string_append_char(message, str, "\"");
_rewriteNode(BaseSelect, message, dblink, str, node->conditionname);
delay_string_append_char(message, str, "\"");
}
static void
_rewriteDeclareCursorStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, DeclareCursorStmt *node)
{
delay_string_append_char(message, str, "DECLARE \"");
delay_string_append_char(message, str, node->portalname);
delay_string_append_char(message, str, "\" ");
if (node->options & CURSOR_OPT_SCROLL)
delay_string_append_char(message, str, "SCROLL ");
if (node->options & CURSOR_OPT_BINARY)
delay_string_append_char(message, str, "BINARY ");
if (node->options & CURSOR_OPT_INSENSITIVE)
delay_string_append_char(message, str, "INSENSITIVE ");
delay_string_append_char(message, str, "CURSOR ");
if (node->options & CURSOR_OPT_HOLD)
delay_string_append_char(message, str, "WITH HOLD ");
delay_string_append_char(message, str, "FOR");
_rewriteNode(BaseSelect, message, dblink, str, node->query);
}
static void
initSelectStmt(RewriteQuery *message,SelectStmt *node)
{
int count;
int last;
int i;
AnalyzeSelect *analyze;
if(message->r_code != SELECT_ANALYZE && message->r_code != SELECT_DEFAULT)
return;
count = message->analyze_num++;
last = message->current_select;
message->current_select = count;
if(message->r_code == SELECT_ANALYZE)
{
if(count == 0)
{
message->analyze = (AnalyzeSelect **) palloc(sizeof(AnalyzeSelect *));
message->analyze[count]=(AnalyzeSelect *) palloc(sizeof(AnalyzeSelect));
message->part = SELECT_START;
analyze = message->analyze[count];
analyze->now_select = 0;
analyze->last_select = -1;
analyze->part = SELECT_START;
analyze->call_part = SELECT_START;
}
else
{
message->analyze = (AnalyzeSelect **) repalloc(message->analyze,sizeof(AnalyzeSelect *) * (count+1));
message->analyze[count]=(AnalyzeSelect *) palloc(sizeof(AnalyzeSelect));
analyze = message->analyze[count];
analyze->now_select = count;
analyze->last_select = last;
analyze->part = message->part;
analyze->call_part = message->analyze[last]->part;
}
analyze->range =NULL;
analyze->rangeinfo_num =-1;
analyze->virtual = NULL;
analyze->join = NULL;
analyze->state = (char) 0;
analyze->aggregate = false;
analyze->aggexpr = NULL;
analyze->table_name = NULL;
analyze->select_range = false;
analyze->rarg_count = -1;
analyze->larg_count = -1;
analyze->ret_count = 0;
analyze->retlock = false;
for(i = 0; i< 8; i++)
analyze->partstate[i] = (char)0;
if(node->larg && node->rarg)
analyze->select_union = true;
else
analyze->select_union = false;
pool_debug("initSelectStmt: ANALYZE now(%d)",message->current_select);
/* set default table_state */
/* S means that tuples was create by systemdb */
/* L means that tuples was create by one node */
/* P means that tuples was create by parallel node */
message->table_state = 'S';
}
}
static void writeRangeHeader(RewriteQuery *message,ConInfoTodblink *dblink, String *str,DistDefInfo *info, RepliDefInfo *info2,char *alias)
{
char port[8];
char *schema = NULL;
char *table = NULL;
pool_debug("writeRangeHeader select_no=%d",message->current_select);
sprintf(port,"%d",dblink->port);
delay_string_append_char(message, str, "dblink(");
delay_string_append_char(message, str, "'");
delay_string_append_char(message, str, "host=");
delay_string_append_char(message, str, dblink->hostaddr);
delay_string_append_char(message, str, " dbname=");
delay_string_append_char(message, str, dblink->dbname);
delay_string_append_char(message, str, " port=");
delay_string_append_char(message, str, port);
delay_string_append_char(message, str, " user=");
delay_string_append_char(message, str, dblink->user);
if(strlen(dblink->password))
{
delay_string_append_char(message, str, " password=");
delay_string_append_char(message, str, dblink->password);
}
delay_string_append_char(message, str, "'");
delay_string_append_char(message, str, ",");
delay_string_append_char(message, str, "'");
if(info && !info2)
{
delay_string_append_char(message, str, "SELECT pool_parallel(\"");
schema = info->schema_name;
if(alias)
table = alias;
else
table = info->table_name;
}
else if (!info && info2)
{
delay_string_append_char(message, str, "SELECT pool_loadbalance(\"");
schema = info2->schema_name;
if(alias)
table = alias;
else
table = info2->table_name;
}
{
VirtualTable *virtual = NULL;
int no = message->current_select;
int v_colnum;
int i;
int first = 0;
AnalyzeSelect *analyze = message->analyze[no];
virtual = analyze->virtual;
v_colnum = virtual->col_num;
delay_string_append_char(message, str, "SELECT ");
for(i = 0; i < v_colnum; i++)
{
if(!strcmp(virtual->table_list[i],table) && virtual->valid[i] != -1)
{
if(first == 0)
{
delay_string_append_char(message, str, virtual->table_list[i]);
delay_string_append_char(message, str, ".");
delay_string_append_char(message, str, virtual->col_list[i]);
first = 1;
}
else
{
delay_string_append_char(message, str, ", ");
delay_string_append_char(message, str, virtual->table_list[i]);
delay_string_append_char(message, str, ".");
delay_string_append_char(message, str, virtual->col_list[i]);
}
}
}
if(first == 0)
delay_string_append_char(message, str, " * ");
delay_string_append_char(message, str, " FROM ");
}
}
static void writeRangeFooter(RewriteQuery *message,ConInfoTodblink *dblink, String *str,DistDefInfo *info, RepliDefInfo *info2,char *alias)
{
int i,num;
char *schema = NULL;
char *table = NULL;
delay_string_append_char(message, str, "\"");
delay_string_append_char(message, str, ")");
delay_string_append_char(message, str, "'");
delay_string_append_char(message, str, ")");
delay_string_append_char(message, str," AS ");
if(alias)
table = alias;
else
{
if(info && !info2)
{
schema = info->schema_name;
table = info->table_name;
}
else if (!info && info2)
{
schema = info2->schema_name;
table = info2->table_name;
}
}
/* send one node */
if(!table)
{
message->r_code = SELECT_RELATION_ERROR;
}
delay_string_append_char(message, str, table);
delay_string_append_char(message, str, "(");
{
VirtualTable *virtual = NULL;
int first = 0;
int no = message->current_select;
AnalyzeSelect *analyze = message->analyze[no];
virtual = analyze->virtual;
num = virtual->col_num;
for(i = 0; i < num; i++)
{
char buf[16];
if(!strcmp(virtual->table_list[i],table) && virtual->valid[i] != -1)
{
if(first == 0)
first = 1;
else
delay_string_append_char(message, str, ",");
snprintf(buf, 16, "%d", analyze->virtual->column_no[i]);
delay_string_append_char(message, str,"pool_c$");
delay_string_append_char(message, str,buf);
delay_string_append_char(message, str, " ");
delay_string_append_char(message, str,virtual->type_list[i]);
}
}
if(first == 0)
{
for(i = 0; i < num; i++)
{
char buf[16];
if(!strcmp(virtual->table_list[i],table))
{
if(first == 0)
first = 1;
else
delay_string_append_char(message, str, ",");
snprintf(buf, 16, "%d", analyze->virtual->column_no[i]);
delay_string_append_char(message, str,"pool_c$");
delay_string_append_char(message, str,buf);
delay_string_append_char(message, str, " ");
delay_string_append_char(message, str,virtual->type_list[i]);
}
}
}
delay_string_append_char(message, str, ")");
}
}
static void writeSelectAggHeader(RewriteQuery *message,ConInfoTodblink *dblink, String *str,int state)
{
char port[8];
int count = message->current_select;
AnalyzeSelect *analyze;
Aggexpr *agg;
int i;
int ret_count = 0;
analyze = message->analyze[count];
agg = analyze->aggexpr;
ret_count = agg->t_num + agg->c_num + agg->h_num;
sprintf(port,"%d",dblink->port);
pool_debug("writeSelectAggHeader select_no=%d state=%d",message->current_select,state);
delay_string_append_char(message, str, "dblink(");
delay_string_append_char(message, str, "'");
delay_string_append_char(message, str, "host=");
delay_string_append_char(message, str, dblink->hostaddr);
delay_string_append_char(message, str, " dbname=");
delay_string_append_char(message, str, dblink->dbname);
delay_string_append_char(message, str, " port=");
delay_string_append_char(message, str, port);
delay_string_append_char(message, str, " user=");
delay_string_append_char(message, str, dblink->user);
if(strlen(dblink->password))
{
delay_string_append_char(message, str, " password=");
delay_string_append_char(message, str, dblink->password);
}
delay_string_append_char(message, str, "'");
delay_string_append_char(message, str, ",");
delay_string_append_char(message, str, "'");
delay_string_append_char(message, str, "SELECT pool_parallel(\"");
delay_string_append_char(message, str, "SELECT ");
message->rewritelock = count;
for(i = 0; i< agg->t_num; i++)
{
char *funcname = NULL;
funcname = strVal(lfirst(list_head(agg->tfunc_p[i]->funcname)));
if(strcmp(funcname,"avg"))
{
_rewriteFuncCall(NULL,message,NULL,str,agg->tfunc_p[i]);
}
else
{
AvgFuncCall(NULL,message,NULL,str,agg->tfunc_p[i]);
}
ret_count--;
if(ret_count != 0)
delay_string_append_char(message, str, ",");
}
for(i = 0; i< agg->c_num; i++)
{
_rewriteColumnRef(NULL,message,NULL,str,agg->col_p[i]);
ret_count--;
if(ret_count != 0)
delay_string_append_char(message, str, ",");
}
for(i = 0; i< agg->h_num; i++)
{
char *funcname = NULL;
funcname = strVal(lfirst(list_head(agg->hfunc_p[i]->funcname)));
if(strcmp(funcname,"avg"))
{
_rewriteFuncCall(NULL,message,NULL,str,agg->hfunc_p[i]);
}
else
{
AvgFuncCall(NULL,message,NULL,str,agg->hfunc_p[i]);
}
ret_count--;
if(ret_count != 0)
delay_string_append_char(message, str, ",");
}
delay_string_append_char(message, str, " FROM ");
}
static void writeSelectHeader(RewriteQuery *message,ConInfoTodblink *dblink, String *str,int parallel,int state)
{
char port[8];
sprintf(port,"%d",dblink->port);
pool_debug("writeSelectHeader select_no=%d state=%d",message->current_select,state);
if(state == SELECT_START)
{
delay_string_append_char(message, str, "SELECT * FROM ");
}
delay_string_append_char(message, str, "dblink(");
delay_string_append_char(message, str, "'");
delay_string_append_char(message, str, "host=");
delay_string_append_char(message, str, dblink->hostaddr);
delay_string_append_char(message, str, " dbname=");
delay_string_append_char(message, str, dblink->dbname);
delay_string_append_char(message, str, " port=");
delay_string_append_char(message, str, port);
delay_string_append_char(message, str, " user=");
delay_string_append_char(message, str, dblink->user);
if(strlen(dblink->password))
{
delay_string_append_char(message, str, " password=");
delay_string_append_char(message, str, dblink->password);
}
delay_string_append_char(message, str, "'");
delay_string_append_char(message, str, ",");
delay_string_append_char(message, str, "'");
if(parallel)
delay_string_append_char(message, str, "SELECT pool_parallel(\"");
else
delay_string_append_char(message, str, "SELECT pool_loadbalance(\"");
if(state == SELECT_FROMCLAUSE)
{
int no = message->current_select;
int v_colnum;
int i;
int first = 0;
AnalyzeSelect *analyze = message->analyze[no];
v_colnum = analyze->virtual->col_num;
delay_string_append_char(message, str, "SELECT ");
for(i = 0; i < v_colnum; i++)
{
if(analyze->virtual->valid[i] != -1)
{
char *col_name = analyze->virtual->col_list[i];
if(first == 0)
{
//delay_string_append_char(message, str, analyze->virtual->table_list[i]);
//delay_string_append_char(message, str, "ooo.");
if(strcmp(col_name,"\"?column?\""))
delay_string_append_char(message, str, col_name);
else
{
delay_string_append_char(message, str, "\"");
delay_string_append_char(message, str, col_name);
delay_string_append_char(message, str, "\"");
}
first = 1;
}
else
{
delay_string_append_char(message, str, ", ");
delay_string_append_char(message, str, analyze->virtual->table_list[i]);
delay_string_append_char(message, str, ".");
if(strcmp(col_name,"\"?column?\""))
delay_string_append_char(message, str, col_name);
else
{
delay_string_append_char(message, str, "\"");
delay_string_append_char(message, str, col_name);
delay_string_append_char(message, str, "\"");
}
}
}
}
if(first == 0)
delay_string_append_char(message, str, " * ");
delay_string_append_char(message, str, " FROM ");
}
}
static char *estimateFuncTypes(AnalyzeSelect *analyze,FuncCall *func)
{
char *funcname = NULL;
void *obj;
char *type;
obj = lfirst(list_head(func->args));
funcname = strVal(lfirst(list_head(func->funcname)));
if(!strcmp(funcname,"max") || !strcmp(funcname,"min"))
{
if (obj && (IsA(obj, ColumnRef)))
{
char *table_name = NULL;
char *column_name = NULL;
VirtualTable *virtual = analyze->virtual;
column_name = GetNameFromColumnRef((ColumnRef *) obj,true);
table_name = GetNameFromColumnRef((ColumnRef *) obj ,false);
type = search_type_from_virtual(virtual,table_name,column_name);
return type;
}
else if( obj && (IsA(obj,TypeCast)))
{
TypeCast *typecast = (TypeCast *) obj;
TypeName *typename = (TypeName *)typecast->typename;
type = strVal(lfirst(list_head(typename->names)));
return type;
}
else
{
char *numeric = "numeric";
type = (char *) palloc(sizeof(char) * strlen(numeric) +1);
strcpy(type,numeric);
return type;
}
}
else if(!strcmp(funcname,"sum"))
{
char *numeric = "numeric";
type = (char *) palloc(sizeof(char) * strlen(numeric) +1);
strcpy(type,numeric);
return type;
}
return "numeric";
}
static void writeSelectAggFooter(RewriteQuery *message,String *str,AnalyzeSelect *analyze)
{
int count = message->current_select;
Aggexpr *agg;
int i;
int ret_count = 0;
int group_count = 0;
analyze = message->analyze[count];
agg = analyze->aggexpr;
ret_count = agg->t_num + agg->c_num + agg->h_num;
group_count = agg->c_num;
if(group_count != 0)
{
delay_string_append_char(message, str, " GROUP BY ");
for(i = 0; i< agg->c_num; i++)
{
_rewriteColumnRef(NULL,message,NULL,str,agg->col_p[i]);
group_count--;
if(group_count != 0)
delay_string_append_char(message, str, ",");
}
}
delay_string_append_char(message, str, "\"");
delay_string_append_char(message, str, ")");
delay_string_append_char(message, str, "'");
delay_string_append_char(message, str, ")");
delay_string_append_char(message, str," AS ");
delay_string_append_char(message, str, analyze->table_name);
/* symbol of aggregate opt */
delay_string_append_char(message, str,"g");
delay_string_append_char(message, str, " (");
message->rewritelock = -1;
for(i = 0; i < ret_count; i++)
{
char buf[16];
snprintf(buf, 16, "%d", i);
delay_string_append_char(message, str, "pool_g$");
delay_string_append_char(message, str, buf);
delay_string_append_char(message, str, " ");
if(i < agg->t_num)
{
char *funcname = NULL;
funcname = strVal(lfirst(list_head(agg->tfunc_p[i]->funcname)));
if(!strcmp(funcname,"count"))
delay_string_append_char(message, str, "bigint ");
else if(!strcmp(funcname,"avg"))
{
delay_string_append_char(message, str, "numeric ");
delay_string_append_char(message, str, ",");
delay_string_append_char(message, str, "pool_g$");
delay_string_append_char(message, str, buf);
delay_string_append_char(message, str, "c");
delay_string_append_char(message, str, " ");
delay_string_append_char(message, str, "bigint ");
}
else
{
char *type = estimateFuncTypes(analyze,agg->tfunc_p[i]);
delay_string_append_char(message, str, type);
}
}
else if(i >= agg->t_num && i < agg->t_num + agg->c_num)
{
char *table_name = NULL;
char *column_name = NULL;
char *type = NULL;
VirtualTable *virtual = analyze->virtual;
column_name = GetNameFromColumnRef(agg->col_p[i - agg->t_num],true);
table_name = GetNameFromColumnRef(agg->col_p[i - agg->t_num],false);
type = search_type_from_virtual(virtual,table_name,column_name);
delay_string_append_char(message, str, type);
}
else if(i >= agg->t_num + agg->c_num)
{
char *funcname = NULL;
int arg = i - agg->t_num - agg->c_num;
funcname = strVal(lfirst(list_head(agg->hfunc_p[arg]->funcname)));
if(!strcmp(funcname,"count"))
delay_string_append_char(message, str, "bigint ");
else if(!strcmp(funcname,"avg"))
{
delay_string_append_char(message, str, "numeric ");
delay_string_append_char(message, str, ",");
delay_string_append_char(message, str, "pool_g$");
delay_string_append_char(message, str, buf);
delay_string_append_char(message, str, "c");
delay_string_append_char(message, str, " ");
delay_string_append_char(message, str, "bigint ");
}
else
{
char *type = estimateFuncTypes(analyze,agg->hfunc_p[arg]);
delay_string_append_char(message, str, type);
}
}
if( i + 1 != ret_count)
delay_string_append_char(message, str, ",");
}
delay_string_append_char(message, str, ") ");
}
static void writeSelectFooter(RewriteQuery *message,String *str,AnalyzeSelect *analyze,int state)
{
int i,num;
delay_string_append_char(message, str, "\"");
delay_string_append_char(message, str, ")");
delay_string_append_char(message, str, "'");
delay_string_append_char(message, str, ")");
delay_string_append_char(message, str," AS ");
delay_string_append_char(message, str, analyze->table_name);
delay_string_append_char(message, str, "(");
pool_debug("writeSelectFooter %s",analyze->table_name);
if(state != SELECT_FROMCLAUSE)
{
num = analyze->select_ret->col_num;
for(i = 0; i < num; i++)
{
delay_string_append_char(message, str, analyze->select_ret->col_list[i]);
delay_string_append_char(message, str, " ");
delay_string_append_char(message, str, analyze->select_ret->type_list[i]);
if (i != num -1)
delay_string_append_char(message, str, ",");
}
delay_string_append_char(message, str, ")");
}
else
{
int first = 0;
num = analyze->virtual->col_num;
for(i = 0; i < num; i++)
{
if(analyze->virtual->valid[i] != -1)
{
char buf[16];
if(first == 0)
{
snprintf(buf, 16, "%d", analyze->virtual->column_no[i]);
delay_string_append_char(message, str, "pool_c$");
delay_string_append_char(message, str, buf);
delay_string_append_char(message, str, " ");
delay_string_append_char(message, str, analyze->virtual->type_list[i]);
first = 1;
} else {
delay_string_append_char(message, str, ",");
snprintf(buf, 16, "%d", analyze->virtual->column_no[i]);
delay_string_append_char(message, str, "pool_c$");
delay_string_append_char(message, str, buf);
delay_string_append_char(message, str, " ");
delay_string_append_char(message, str, analyze->virtual->type_list[i]);
}
}
}
if(first == 0)
{
for(i = 0; i < num; i++)
{
if(first == 0)
{
delay_string_append_char(message, str, analyze->virtual->col_list[i]);
delay_string_append_char(message, str, " ");
delay_string_append_char(message, str, analyze->virtual->type_list[i]);
first = 1;
} else {
delay_string_append_char(message, str, ",");
delay_string_append_char(message, str, analyze->virtual->col_list[i]);
delay_string_append_char(message, str, " ");
delay_string_append_char(message, str, analyze->virtual->type_list[i]);
}
}
}
delay_string_append_char(message, str, ")");
}
}
static void
CopyFromLeftArg(RewriteQuery *message,int current_num)
{
AnalyzeSelect *l_analyze = message->analyze[current_num + 1];
AnalyzeSelect *analyze = message->analyze[current_num];
VirtualTable *virtual = message->analyze[current_num]->virtual;
int col_num;
int i;
char **col_list = NULL;
char **type_list = NULL;
char state;
char *table_name;
table_name = l_analyze->table_name;
col_list = l_analyze->select_ret->col_list;
type_list = l_analyze->select_ret->type_list;
col_num = l_analyze->select_ret->col_num;
state = l_analyze->state;
append_virtual_table(message,virtual,col_list,type_list,col_num,table_name,state,current_num + 1);
analyze->select_ret = (SelectDefInfo *) palloc(sizeof(SelectDefInfo));
analyze->select_ret->valid = false;
analyze->select_ret->col_num = 0;
for(i =0; i<col_num; i++)
{
append_select_def_info(analyze->select_ret,col_list[i],type_list[i]);
}
}
static void
ChangeStateByCluase(RewriteQuery *message,void *obj,int before, int after)
{
AnalyzeSelect *analyze;
int count = message->current_select;
if(message->r_code != SELECT_ANALYZE)
return;
analyze = message->analyze[count];
if (obj && analyze->partstate[before] == 'P')
analyze->partstate[after] = 'S';
else
analyze->partstate[after] = analyze->partstate[before];
}
static void
ChangeStateRewriteFooter(RewriteQuery *message,String *str,int defore, int after)
{
AnalyzeSelect *analyze;
int count = message->current_select;
char state;
if(message->r_code != SELECT_DEFAULT)
return;
analyze = message->analyze[count];
if(analyze->state == 'S' && message->rewritelock == count
&& message->ignore_rewrite == -1)
{
state = analyze->partstate[defore];
if(state == 'L' || state == 'P')
{
if(state != analyze->partstate[after])
{
writeSelectFooter(message,str,analyze,SELECT_FROMCLAUSE);
message->rewritelock = -1;
}
}
}
}
static bool
CheckUnionFromClause(RewriteQuery *message)
{
int check;
int count = message->current_select;
AnalyzeSelect *analyze;
analyze = message->analyze[count];
check = analyze->last_select;
pool_debug("CheckUnion select=%d last_select=%d", count,check);
if(check == -1)
return false;
else
{
if(message->analyze[check]->select_union &&
message->analyze[check]->call_part == SELECT_FROMCLAUSE)
{
pool_debug("CheckUnion true");
return true;
}
else
return false;
}
}
static void
_rewriteSelectStmt(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, SelectStmt *node)
{
BaseSelect = (Node *) node;
AnalyzeSelect *analyze;
int count;
int analyze_num = 0;
int target_analyze = 0;
int from_analyze = 0;
bool lock = false;
bool direct = false;
bool aggrewrite = false;
count = message->analyze_num;
/* Allocate Memory Space and initialize some Flags*/
initSelectStmt(message,node);
if(message->r_code == SELECT_DEFAULT)
{
if(message->current_select == 0)
pool_debug("_rewriteSelectStmt:START QueryRewrite");
}
analyze_num = message->analyze_num;
analyze = message->analyze[count];
analyze->part = SELECT_START;
if(message->r_code == SELECT_DEFAULT && message->rewritelock == -1
&& message->ignore_rewrite == -1)
{
#if 0
if(analyze->state == 'P')
{
if(analyze->call_part != SELECT_FROMCLAUSE || !CheckUnionFromClause(message))
{
writeSelectHeader(message,dblink,str,PARALLEL,analyze->part);
message->rewritelock = count;
direct = true;
}
else
lock =true;
}
#endif
if(analyze->state == 'L')
{
if(analyze->call_part != SELECT_FROMCLAUSE && !CheckUnionFromClause(message))
{
writeSelectHeader(message,dblink,str,LOADBALANCE,analyze->part);
message->rewritelock = count;
direct = true;
}
else
lock =true;
}
}
if (node->larg) /* SETOP */
{
if(message->r_code == SELECT_ANALYZE)
{
char buf[16];
char *temp = "pool_t$";
analyze->virtual = (VirtualTable *) palloc(sizeof(VirtualTable));
snprintf(buf, 16, "%d", message->virtual_num);
message->virtual_num++;
analyze->table_name = (char *) palloc(sizeof(char) * (strlen(temp) + strlen(buf) + 1));
strcpy(analyze->table_name,temp);
strcat(analyze->table_name,buf);
analyze->virtual->col_num = 0;
}
delay_string_append_char(message, str, "(");
message->part = SELECT_START;
_rewriteNode(BaseSelect, message, dblink, str, node->larg);
pool_debug("union larg select_no=%d(%d)",count,message->analyze_num);
delay_string_append_char(message, str, ")");
KeepMessages(message,count,SELECT_START);
/* COPY analyze of left arg */
if(message->r_code == SELECT_ANALYZE)
{
analyze->larg_count = count + 1;
analyze->rarg_count = message->analyze_num;
pool_debug("_rewriteSelectStmt: COUNT larg=%d, rarg=%d",analyze->larg_count, analyze->rarg_count);
}
switch (node->op)
{
case SETOP_UNION:
delay_string_append_char(message, str, " UNION ");
break;
case SETOP_INTERSECT:
delay_string_append_char(message, str, " INTERSECT ");
break;
case SETOP_EXCEPT:
delay_string_append_char(message, str, " EXCEPT ");
default:
break;
}
if (node->all)
delay_string_append_char(message, str, "ALL ");
if (node->rarg)
{
delay_string_append_char(message, str, "(");
message->part = SELECT_START;
_rewriteNode(BaseSelect, message, dblink, str, node->rarg);
delay_string_append_char(message, str, ")");
KeepMessages(message,count,SELECT_START);
if(message->r_code == SELECT_ANALYZE)
CopyFromLeftArg(message,count);
}
if(message->r_code == SELECT_ANALYZE)
{
pool_debug("_rewriteSelectStmt: STATE larg=%c, rarg=%c",message->analyze[analyze->larg_count]->state,
message->analyze[analyze->rarg_count]->state);
}
if(message->r_code == SELECT_DEFAULT)
{
pool_debug("_rewriteSelectStmt: DEFAULT COUNT larg=%d, rarg=%d",analyze->larg_count, analyze->rarg_count);
}
if(message->r_code == SELECT_ANALYZE)
{
int lcount = analyze->larg_count;
int rcount = analyze->rarg_count;
if(message->analyze[lcount]->state == 'L' &&
message->analyze[rcount]->state == 'L')
{
int j;
for(j = 0; j < SELECT_SORTCLAUSE; j++)
{
analyze->partstate[j]='L';
}
}
else
{
int j;
for(j = 0; j < SELECT_SORTCLAUSE; j++)
{
analyze->partstate[j]='S';
}
}
}
}
else
{
if (node->intoClause)
{
IntoClause *into = node->intoClause;
RangeVar *rel = (RangeVar *)into->rel;
delay_string_append_char(message, str, "CREATE ");
if (rel->istemp == true)
delay_string_append_char(message, str, "TEMP ");
delay_string_append_char(message, str, "TABLE ");
_rewriteNode(BaseSelect, message, dblink, str, into->rel);
KeepRewriteQueryReturnCode(message, SELECT_RELATION_ERROR);
if (into->colNames)
{
delay_string_append_char(message, str, " (");
_rewriteNode(BaseSelect, message, dblink, str, into->colNames);
delay_string_append_char(message, str, ") ");
KeepRewriteQueryReturnCode(message, SELECT_RELATION_ERROR);
}
if (into->options)
_rewriteWithDefinition(BaseSelect, message, dblink, str, into->options);
switch (into->onCommit)
{
case ONCOMMIT_DROP:
delay_string_append_char(message, str, " ON COMMIT DROP");
break;
case ONCOMMIT_DELETE_ROWS:
delay_string_append_char(message, str, " ON COMMIT DELETE ROWS");
break;
case ONCOMMIT_PRESERVE_ROWS:
delay_string_append_char(message, str, " ON COMMIT PRESERVE ROWS");
break;
default:
break;
}
delay_string_append_char(message, str, " AS");
}
delay_string_append_char(message, str, " SELECT ");
/*
* Check from-clause before Checking target-list
*/
if(node->fromClause)
{
message->part = SELECT_FROMCLAUSE;
analyze->part = SELECT_FROMCLAUSE;
message->fromClause = true;
if(message->r_code == SELECT_ANALYZE)
{
char buf[16];
char *temp = "pool_t$";
analyze->virtual = (VirtualTable *) palloc(sizeof(VirtualTable));
snprintf(buf, 16, "%d", message->virtual_num);
message->virtual_num++;
analyze->table_name = (char *) palloc(sizeof(char) * (strlen(temp) + strlen(buf) + 1));
strcpy(analyze->table_name,temp);
strcat(analyze->table_name,buf);
analyze->virtual->col_num = 0;
}
if(message->r_code == SELECT_DEFAULT && message->ignore_rewrite == -1)
message->ignore_rewrite = count;
/* remember analyze_num */
from_analyze = message->analyze_num;
_rewriteNode(BaseSelect, message, dblink, str, node->fromClause);
if(message->r_code == SELECT_DEFAULT && message->ignore_rewrite == count)
message->ignore_rewrite = -1;
message->fromClause = false;
if(message->r_code == SELECT_ANALYZE)
{
message->table_state = analyze->state;
analyze->partstate[SELECT_FROMCLAUSE] = analyze->state;
}
}
else
{
/* this is const or function call*/
message->part = SELECT_TARGETLIST;
if(message->r_code == SELECT_ANALYZE)
build_range_info(message,NULL,NULL,NULL,NULL,message->current_select,-1);
}
message->part = SELECT_OTHER;
analyze->part = SELECT_OTHER;
if (message->r_code == SELECT_ANALYZE && node->groupClause)
{
analyze->aggregate = true;
}
if (node->distinctClause)
{
if(message->r_code == SELECT_ANALYZE)
analyze->partstate[SELECT_TARGETLIST] = 'S';
#if 0
/* TODO
* DISTINCT optimization
*/
if(message->r_code == SELECT_ANALYZE)
analyze->aggregate = true;
#endif
delay_string_append_char(message, str, "DISTINCT ");
if (lfirst(list_head(node->distinctClause)) != NIL)
{
delay_string_append_char(message, str, "ON (");
_rewriteNode(BaseSelect, message, dblink,str, node->distinctClause);
KeepMessages(message,count,SELECT_OTHER);
delay_string_append_char(message, str, ") ");
}
}
message->part = SELECT_TARGETLIST;
analyze->part = SELECT_TARGETLIST;
if(analyze->partstate[SELECT_FROMCLAUSE] == 'P' && analyze->aggregate)
analyze->partstate[SELECT_TARGETLIST] = 'S';
/* TARGETLIST START */
_rewriteNode(BaseSelect, message, dblink, str, node->targetList);
aggrewrite = CheckAggOpt(message);
target_analyze = message->analyze_num;
if(message->r_code == SELECT_ANALYZE)
{
if (analyze->aggregate && (analyze->partstate[SELECT_FROMCLAUSE] == 'P'
|| analyze->partstate[SELECT_TARGETLIST] == 'P'))
analyze->partstate[SELECT_TARGETLIST] = 'S';
else if (!analyze->partstate[SELECT_TARGETLIST])
analyze->partstate[SELECT_TARGETLIST] = analyze->partstate[SELECT_FROMCLAUSE];
}
KeepMessages(message,count,SELECT_TARGETLIST);
if (node->fromClause && message->r_code != SELECT_ANALYZE)
{
message->analyze_num = from_analyze;
message->part = SELECT_FROMCLAUSE;
analyze->part = SELECT_FROMCLAUSE;
delay_string_append_char(message, str, " FROM ");
if(message->r_code == SELECT_DEFAULT &&
(analyze->state == 'S' || lock)
&& message->rewritelock == -1 && message->ignore_rewrite ==-1)
{
if(analyze->partstate[SELECT_FROMCLAUSE] == 'L')
{
writeSelectHeader(message,dblink,str,LOADBALANCE, message->part);
message->rewritelock = count;
}
else if(analyze->partstate[SELECT_FROMCLAUSE] == 'P')
{
if(aggrewrite)
{
writeSelectAggHeader(message,dblink,str, message->part);
}
else
{
writeSelectHeader(message,dblink,str,PARALLEL, message->part);
}
message->rewritelock = count;
}
}
message->fromClause = true;
_rewriteNode(BaseSelect, message, dblink, str, node->fromClause);
message->fromClause = false;
KeepMessages(message,count,SELECT_FROMCLAUSE);
if(message->r_code == SELECT_DEFAULT && analyze->state == 'S'
&& message->rewritelock == count && message->ignore_rewrite == -1)
{
if(analyze->partstate[SELECT_FROMCLAUSE] == 'L')
{
if(analyze->partstate[SELECT_WHERECLAUSE] != 'L')
{
if(node->whereClause)
{
int message_code = message->r_code;
delay_string_append_char(message, str, " WHERE ");
CheckWhereCaluse(node->whereClause, message,dblink,str,0);
KeepRewriteQueryReturnCode(message, message_code);
}
writeSelectFooter(message,str,analyze,SELECT_FROMCLAUSE);
message->rewritelock = -1;
}
}
else if(analyze->partstate[SELECT_FROMCLAUSE] == 'P')
{
if(analyze->partstate[SELECT_WHERECLAUSE] != 'P')
{
if(node->whereClause)
{
int message_code = message->r_code;
delay_string_append_char(message, str, " WHERE ");
CheckWhereCaluse(node->whereClause, message,dblink,str,0);
KeepRewriteQueryReturnCode(message, message_code);
}
writeSelectFooter(message,str,analyze,SELECT_FROMCLAUSE);
message->rewritelock = -1;
}
}
}
message->analyze_num = target_analyze;
}
/* WHERE CLAUSE */
message->part = SELECT_OTHER;
if (node->whereClause)
BaseSelect = NULL;
if (node->whereClause)
{
message->part = SELECT_WHERECLAUSE;
analyze->part = SELECT_WHERECLAUSE;
delay_string_append_char(message, str, " WHERE ");
_rewriteNode(BaseSelect, message, dblink, str, node->whereClause);
KeepMessages(message,count,SELECT_OTHER);
}
if(!analyze->partstate[SELECT_WHERECLAUSE] && message->r_code == SELECT_ANALYZE)
analyze->partstate[SELECT_WHERECLAUSE] = analyze->partstate[SELECT_FROMCLAUSE];
if(aggrewrite)
writeSelectAggFooter(message,str,analyze);
else
ChangeStateRewriteFooter(message,str,SELECT_WHERECLAUSE, SELECT_GROUPBYCLAUSE);
/* GROUPBY CLAUSE */
if (node->groupClause)
{
analyze->part = SELECT_GROUPBYCLAUSE;
delay_string_append_char(message, str, " GROUP BY ");
_rewriteNode(BaseSelect, message, dblink, str, node->groupClause);
KeepMessages(message,count,SELECT_OTHER);
}
ChangeStateByCluase(message,node->groupClause,SELECT_WHERECLAUSE,SELECT_GROUPBYCLAUSE);
/* HAVING CLAUSE */
if (node->havingClause)
{
analyze->part = SELECT_HAVINGCLAUSE;
delay_string_append_char(message, str, " HAVING ");
_rewriteNode(BaseSelect, message, dblink, str, node->havingClause);
KeepMessages(message,count,SELECT_OTHER);
}
if(message->r_code == SELECT_ANALYZE)
analyze->partstate[SELECT_HAVINGCLAUSE] = analyze->partstate[SELECT_GROUPBYCLAUSE];
}
ChangeStateRewriteFooter(message,str,SELECT_HAVINGCLAUSE, SELECT_SORTCLAUSE);
if (node->sortClause)
{
analyze->part = SELECT_SORTCLAUSE;
delay_string_append_char(message, str, " ORDER BY ");
_rewriteNode(BaseSelect, message, dblink, str, node->sortClause);
KeepMessages(message,count,SELECT_OTHER);
}
ChangeStateByCluase(message,node->sortClause,SELECT_HAVINGCLAUSE,SELECT_SORTCLAUSE);
ChangeStateRewriteFooter(message,str, SELECT_SORTCLAUSE, SELECT_OFFSETCLAUSE);
if (node->limitOffset)
{
analyze->part = SELECT_OFFSETCLAUSE;
delay_string_append_char(message, str, " OFFSET ");
_rewriteNode(BaseSelect, message, dblink, str, node->limitOffset);
KeepMessages(message,count,SELECT_OTHER);
}
ChangeStateByCluase(message,node->limitOffset,SELECT_SORTCLAUSE,SELECT_OFFSETCLAUSE);
ChangeStateRewriteFooter(message,str,SELECT_OFFSETCLAUSE,SELECT_LIMITCLAUSE);
if (node->limitCount)
{
analyze->part = SELECT_LIMITCLAUSE;
delay_string_append_char(message, str, " LIMIT ");
if (IsA(node->limitCount, A_Const) &&
((A_Const *)node->limitCount)->val.type == T_Null)
{
delay_string_append_char(message, str, "ALL ");
}
else
{
_rewriteNode(BaseSelect, message, dblink, str, node->limitCount);
KeepMessages(message,count,SELECT_OTHER);
}
}
ChangeStateByCluase(message,node->limitCount,SELECT_OFFSETCLAUSE,SELECT_LIMITCLAUSE);
if(message->r_code == SELECT_ANALYZE)
{
int i;
analyze->state = analyze->partstate[SELECT_LIMITCLAUSE];
for(i = 0; i< 8; i++)
{
char s = analyze->partstate[i];
if(s == 'S')
{
analyze->state = s;
break;
}
}
}
_rewriteNode(BaseSelect, message, dblink, str, node->lockingClause);
KeepMessages(message,count,SELECT_OTHER);
if(message->r_code == SELECT_ANALYZE)
{
if(node->targetList)
AnalyzeReturnRecord(BaseSelect,message,dblink,str,node->targetList);
pool_debug("_rewriteSelectStmt select_no=%d state=%s",message->current_select,analyze->partstate);
if(strstr(analyze->partstate,"E"))
message->is_loadbalance = true;
/* change state */
if(count != 0)
{
AnalyzeSelect *last = message->analyze[analyze->last_select];
if(last->part == SELECT_WHERECLAUSE)
{
char fromstate = last->partstate[SELECT_FROMCLAUSE];
char wherestate = (char) 0;
if(last->partstate[SELECT_WHERECLAUSE])
wherestate = last->partstate[SELECT_WHERECLAUSE];
if(fromstate == 'P' && analyze->state == 'L')
{
if(wherestate && wherestate == 'P')
last->partstate[SELECT_WHERECLAUSE] = 'P';
}
else if(fromstate == 'L' && analyze->state == 'L')
{
last->partstate[SELECT_WHERECLAUSE] = 'L';
}
else
last->partstate[SELECT_WHERECLAUSE] = 'S';
}
if(last->part == SELECT_TARGETLIST)
{
char fromstate = last->partstate[SELECT_FROMCLAUSE];
char targetstate = (char) 0;
if(last->partstate[SELECT_TARGETLIST])
targetstate = last->partstate[SELECT_TARGETLIST];
if(fromstate == 'P' && analyze->state == 'L')
{
last->partstate[SELECT_TARGETLIST] = 'P';
}
else if(fromstate == 'L' && analyze->state == 'L')
{
last->partstate[SELECT_TARGETLIST] = 'L';
}
else
last->partstate[SELECT_TARGETLIST] = 'S';
}
}
}
if(message->r_code == SELECT_DEFAULT && message->rewritelock == count
&& message->ignore_rewrite ==-1 )
{
if(direct)
writeSelectFooter(message,str,analyze,analyze->call_part);
else
writeSelectFooter(message,str,analyze,SELECT_FROMCLAUSE);
message->rewritelock = -1;
}
}
static void
initAggexpr(AnalyzeSelect *analyze)
{
Aggexpr *agg;
if(analyze->aggexpr)
return;
analyze->aggexpr = (Aggexpr *) palloc(sizeof(Aggexpr));
agg = analyze->aggexpr;
agg->usec_p = NULL;
agg->tfunc_p = NULL;
agg->col_p = NULL;
agg->hfunc_p = NULL;
agg->umapc = NULL;
agg->u_num = 0;
agg->t_num = 0;
agg->c_num = 0;
agg->h_num = 0;
agg->hc_num = 0;
agg->s_num = 0;
agg->sc_num = 0;
agg->opt = true;
}
static int
FuncChangebyAggregate(AnalyzeSelect *analyze, FuncCall *fnode)
{
Aggexpr *agg;
int i;
if(analyze->aggregate && analyze->aggexpr)
agg = analyze->aggexpr;
else
return -1;
if(!agg->opt)
return -1;
if(analyze->part == SELECT_TARGETLIST)
{
for(i = 0; i < agg->t_num; i++)
{
if(fnode == agg->tfunc_p[i])
{
return i;
}
}
}
else if(analyze->part == SELECT_HAVINGCLAUSE)
{
for(i = 0; i < agg->h_num; i++)
{
if(fnode == agg->hfunc_p[i])
{
return i;
}
}
}
else if(analyze->part == SELECT_SORTCLAUSE)
{
String *sortfunc;
sortfunc = init_string("");
_outNode(sortfunc, fnode);
for(i = 0; i < agg->t_num; i++)
{
String *having;
having = init_string("");
_outNode(having, agg->tfunc_p[i]);
if(!strcmp(sortfunc->data,having->data))
{
free_string(having);
free_string(sortfunc);
return i;
} else {
if(having)
free_string(having);
}
}
if(sortfunc)
free_string(sortfunc);
}
return -1;
}
static int
ColumnChangebyAggregate(AnalyzeSelect *analyze,ColumnRef *cnode)
{
Aggexpr *agg;
int i;
if(analyze->aggregate && analyze->aggexpr)
agg = analyze->aggexpr;
else
return -1;
if(!agg->opt)
return -1;
if(analyze->part == SELECT_GROUPBYCLAUSE)
{
for(i = 0; i < agg->c_num; i++)
{
if(cnode == agg->col_p[i])
{
return agg->t_num + i;
}
}
}
else if(analyze->part == SELECT_TARGETLIST)
{
for(i = 0; i < agg->u_num; i++)
{
char *n_c = NULL;
char *n_t = NULL;
char *c_c = NULL;
char *c_t = NULL;
n_c = GetNameFromColumnRef(cnode,true);
n_t = GetNameFromColumnRef(cnode,false);
c_c = GetNameFromColumnRef(agg->usec_p[i],true);
c_t = GetNameFromColumnRef(agg->usec_p[i],false);
if(n_t && c_t)
{
if(!strcmp(n_t,c_t) && !strcmp(n_c,c_c))
return agg->t_num + agg->umapc[i];
}
else
{
if(!strcmp(n_c,c_c))
return agg->t_num + agg->umapc[i];
}
}
}
else if(analyze->part == SELECT_HAVINGCLAUSE || analyze->part == SELECT_SORTCLAUSE)
{
for(i = 0; i < agg->c_num; i++)
{
char *n_c = NULL;
char *n_t = NULL;
char *c_c = NULL;
char *c_t = NULL;
n_c = GetNameFromColumnRef(cnode,true);
n_t = GetNameFromColumnRef(cnode,false);
c_c = GetNameFromColumnRef(agg->col_p[i],true);
c_t = GetNameFromColumnRef(agg->col_p[i],false);
if(n_t && c_t)
{
if(!strcmp(n_t,c_t) && !strcmp(n_c,c_c))
return agg->t_num + i;
}
else
{
if(!strcmp(n_c,c_c))
return agg->t_num + i;
}
}
}
return -1;
}
static void
AppendAggregate(AnalyzeSelect *analyze,FuncCall *fnode,ColumnRef *cnode)
{
Aggexpr *agg;
initAggexpr(analyze);
agg = analyze->aggexpr;
if(analyze->part == SELECT_GROUPBYCLAUSE)
{
if(!agg->col_p)
{
agg->col_p = (ColumnRef **) palloc(sizeof(ColumnRef *));
}
else
{
agg->col_p = (ColumnRef **) repalloc(agg->col_p,(agg->c_num + 1) *sizeof(ColumnRef *));
}
agg->col_p[agg->c_num] = cnode;
SeekColumnName(agg,cnode,SELECT_GROUPBYCLAUSE);
agg->c_num++;
}
else if(analyze->part == SELECT_TARGETLIST)
{
if(fnode) /* for function */
{
if(!agg->tfunc_p)
{
agg->tfunc_p = (FuncCall **) palloc(sizeof(FuncCall *));
}
else
{
agg->tfunc_p = (FuncCall **) repalloc(agg->tfunc_p,(agg->t_num + 1) *sizeof(FuncCall *));
}
agg->tfunc_p[agg->t_num] = fnode;
agg->t_num++;
} else { /* for Column */
if(!agg->usec_p)
{
agg->usec_p = (ColumnRef **) palloc(sizeof(ColumnRef *));
agg->umapc = (int *) palloc(sizeof(int));
}
else
{
agg->usec_p = (ColumnRef **) repalloc(agg->usec_p,(agg->u_num + 1) *sizeof(ColumnRef *));
agg->umapc = (int *) repalloc(agg->umapc,(agg->u_num + 1) *sizeof(int));
}
agg->usec_p[agg->u_num] = cnode;
agg->u_num++;
}
}
else if(analyze->part == SELECT_HAVINGCLAUSE)
{
if(fnode) /* for function */
{
if(!agg->hfunc_p)
{
agg->hfunc_p = (FuncCall **) palloc(sizeof(FuncCall *));
}
else
{
agg->hfunc_p = (FuncCall **) repalloc(agg->hfunc_p,(agg->h_num + 1) *sizeof(FuncCall *));
}
agg->hfunc_p[agg->h_num] = fnode;
agg->h_num++;
}
}
}
static void
_rewriteFuncCall(Node *BaseSelect, RewriteQuery *message, ConInfoTodblink *dblink, String *str, FuncCall *node)
{
char *funcname;
bool avg_flag = false;
if(message->r_code == SELECT_AEXPR)
{
KeepRewriteQueryReturnCode(message, SELECT_AEXPR_FALSE);
return;
}
funcname = strVal(lfirst(list_head(node->funcname)));
if (CheckAggOpt(message))
{
int i;
AnalyzeSelect *analyze;
int no = message->current_select;
analyze = message->analyze[no];
i = FuncChangebyAggregate(analyze,node);
if(i != -1)
{
if(!strcmp(funcname,"count"))
delay_string_append_char(message, str, "sum");
else if(!strcmp(funcname,"avg"))
{
delay_string_append_char(message, str, "(sum");
avg_flag =true;
}
else
_rewriteFuncName(BaseSelect, message, dblink, str, node->funcname);
}
else
_rewriteFuncName(BaseSelect, message, dblink, str, node->funcname);
}
else
_rewriteFuncName(BaseSelect, message, dblink, str, node->funcname);
if(message->r_code == SELECT_ANALYZE && funcname)
{
/* aggregate functions */
if(!strcmp(funcname,"count") || !strcmp(funcname,"max") || !strcmp(funcname,"min")
|| !strcmp(funcname,"sum") || !strcmp(funcname,"avg") || !strcmp(funcname,"bit_and")
|| !strcmp(funcname,"bit_or") || !strcmp(funcname,"bool_and") || !strcmp(funcname,"bool_or")
|| !strcmp(funcname,"every") || !strcmp(funcname,"corr") || !strcmp(funcname,"covar_pop")
|| !strcmp(funcname,"covar_samp") || !strcmp(funcname,"regr_avgx") || !strcmp(funcname,"regr_avgy")
|| !strcmp(funcname,"regr_count") || !strcmp(funcname,"regr_intercept") || !strcmp(funcname,"regr_r2")
|| !strcmp(funcname,"regr_slope") || !strcmp(funcname,"regr_sxx") || !strcmp(funcname,"regr_sxy")
|| !strcmp(funcname,"regr_syy") || !strcmp(funcname,"stddev") || !strcmp(funcname,"stddev_pop")
|| !strcmp(funcname,"stddev_samp") || !strcmp(funcname,"variance") || !strcmp(funcname,"var_pop")
|| !strcmp(funcname,"var_samp"))
{
AnalyzeSelect *analyze;
int no = message->current_select;
analyze = message->analyze[no];
analyze->aggregate = true;
if(analyze->part == SELECT_TARGETLIST || analyze->part == SELECT_HAVINGCLAUSE)
{
if(!strcmp(funcname,"count") || !strcmp(funcname,"max") ||
!strcmp(funcname,"min") || !strcmp(funcname,"sum") || !strcmp(funcname,"avg"))
{
AppendAggregate(analyze,node,NULL);
}
else