/* * makeBoolConst - * creates a Const node representing a boolean value (can be NULL too) */ Node * makeBoolConst(bool value, bool isnull) { /* note that pg_type.h hardwires size of bool as 1 ... duplicate it */ return (Node *) makeConst(BOOLOID, -1, InvalidOid, 1, BoolGetDatum(value), isnull, true); }
/* * Transform the subscript expressions. */ foreach(idx, indirection) { A_Indices *ai = (A_Indices *) lfirst(idx); Node *subexpr; Assert(IsA(ai, A_Indices)); if (isSlice) { if (ai->lidx) { subexpr = transformExpr(pstate, ai->lidx); /* If it's not int4 already, try to coerce */ subexpr = coerce_to_target_type(pstate, subexpr, exprType(subexpr), INT4OID, -1, COERCION_ASSIGNMENT, COERCE_IMPLICIT_CAST, -1); if (subexpr == NULL) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("array subscript must have type integer"), parser_errposition(pstate, exprLocation(ai->lidx)))); } else { /* Make a constant 1 */ subexpr = (Node *) makeConst(INT4OID, -1, InvalidOid, sizeof(int32), Int32GetDatum(1), false, true); /* pass by value */ } lowerIndexpr = lappend(lowerIndexpr, subexpr); } subexpr = transformExpr(pstate, ai->uidx); /* If it's not int4 already, try to coerce */ subexpr = coerce_to_target_type(pstate, subexpr, exprType(subexpr), INT4OID, -1, COERCION_ASSIGNMENT, COERCE_IMPLICIT_CAST, -1); if (subexpr == NULL) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("array subscript must have type integer"), parser_errposition(pstate, exprLocation(ai->uidx)))); upperIndexpr = lappend(upperIndexpr, subexpr); }
/* * makeNullConst - * creates a Const node representing a NULL of the specified type */ Const * makeNullConst(Oid consttype) { int16 typLen; bool typByVal; get_typlenbyval(consttype, &typLen, &typByVal); return makeConst(consttype, (int) typLen, (Datum) 0, true, typByVal); }
/* * makeNullConst - * creates a Const node representing a NULL of the specified type/typmod * * This is a convenience routine that just saves a lookup of the type's * storage properties. */ Const * makeNullConst(Oid consttype, int32 consttypmod, Oid constcollid) { int16 typLen; bool typByVal; get_typlenbyval(consttype, &typLen, &typByVal); return makeConst(consttype, consttypmod, constcollid, (int) typLen, (Datum) 0, true, typByVal); }
/* * infer_tupledesc * * Given a stream, infer a TupleDesc based on the supertype of all * the casted types for each of the stream's columns */ static void infer_tupledesc(StreamTargetsEntry *stream) { HASH_SEQ_STATUS status; StreamColumnsEntry *entry; List *names = NIL; List *types = NIL; List *mods = NIL; List *collations = NIL; Const *preferred = makeConst(NUMERIC_OID, -1, 0, -1, 0, false, false); hash_seq_init(&status, stream->colstotypes); while ((entry = (StreamColumnsEntry *) hash_seq_search(&status)) != NULL) { char err[128]; Oid supertype; char category; bool typispreferred; Oid t = exprType(linitial(entry->types)); /* * If there are any numeric types in our target types, we prepend a float8 * to the list of types to select from, as that is our preferred type when * there is any ambiguity about how to interpret numeric types. */ get_type_category_preferred(t, &category, &typispreferred); if (category == TYPCATEGORY_NUMERIC) entry->types = lcons(preferred, entry->types); sprintf(err, "type conflict with stream \"%s\":", get_rel_name(stream->relid)); supertype = select_common_type(NULL, entry->types, err, NULL); names = lappend(names, makeString(entry->name)); types = lappend_int(types, supertype); mods = lappend_int(mods, -1); collations = lappend_int(collations, 0); } stream->desc = BuildDescFromLists(names, types, mods, collations); }
/* * Transform the subscript expressions. */ foreach(idx, indirection) { A_Indices *ai = (A_Indices *) lfirst(idx); node_n *subexpr; ASSERT(IS_A(ai, A_Indices)); if (isSlice) { if (ai->lidx) { subexpr = xfrm_expr(pstate, ai->lidx); /* If it's not int4 already, try to coerce */ subexpr = coerce_to_target_type(pstate, subexpr, expr_type(subexpr), INT4OID, -1, COERCION_ASSIGNMENT, COERCE_IMPLICIT_CAST, -1); if (subexpr == NULL) ereport(ERROR, ( errcode(E_DATATYPE_MISMATCH), errmsg("array subscript must have type integer"), parser_errpos(pstate, expr_location(ai->lidx)))); } else { /* Make a constant 1 */ subexpr = (node_n *) makeConst(INT4OID, -1, INVALID_OID, sizeof(int32), INT32_TO_D(1), false, true); /* pass by value */ } lowerIndexpr = lappend(lowerIndexpr, subexpr); } subexpr = xfrm_expr(pstate, ai->uidx); /* If it's not int4 already, try to coerce */ subexpr = coerce_to_target_type(pstate, subexpr, expr_type(subexpr), INT4OID, -1, COERCION_ASSIGNMENT, COERCE_IMPLICIT_CAST, -1); if (subexpr == NULL) ereport(ERROR, ( errcode(E_DATATYPE_MISMATCH), errmsg("array subscript must have type integer"), parser_errpos(pstate, expr_location(ai->uidx)))); upperIndexpr = lappend(upperIndexpr, subexpr); }
/* * Transform the subscript expressions. */ foreach(idx, indirection) { A_Indices *ai = castNode(A_Indices, lfirst(idx)); Node *subexpr; if (isSlice) { if (ai->lidx) { subexpr = transformExpr(pstate, ai->lidx, pstate->p_expr_kind); /* If it's not int4 already, try to coerce */ subexpr = coerce_to_target_type(pstate, subexpr, exprType(subexpr), INT4OID, -1, COERCION_ASSIGNMENT, COERCE_IMPLICIT_CAST, -1); if (subexpr == NULL) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("array subscript must have type integer"), parser_errposition(pstate, exprLocation(ai->lidx)))); } else if (!ai->is_slice) { /* Make a constant 1 */ subexpr = (Node *) makeConst(INT4OID, -1, InvalidOid, sizeof(int32), Int32GetDatum(1), false, true); /* pass by value */ } else { /* Slice with omitted lower bound, put NULL into the list */ subexpr = NULL; } lowerIndexpr = lappend(lowerIndexpr, subexpr); } else Assert(ai->lidx == NULL && !ai->is_slice); if (ai->uidx) { subexpr = transformExpr(pstate, ai->uidx, pstate->p_expr_kind); /* If it's not int4 already, try to coerce */ subexpr = coerce_to_target_type(pstate, subexpr, exprType(subexpr), INT4OID, -1, COERCION_ASSIGNMENT, COERCE_IMPLICIT_CAST, -1); if (subexpr == NULL) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg("array subscript must have type integer"), parser_errposition(pstate, exprLocation(ai->uidx)))); } else { /* Slice with omitted upper bound, put NULL into the list */ Assert(isSlice && ai->is_slice); subexpr = NULL; } upperIndexpr = lappend(upperIndexpr, subexpr); }
Vreg Vunit::makeConst(double d) { union { double d; uint64_t i; } u; u.d = d; return makeConst(u.i); }
Node * my_mutator (Node *node, context_modifier *context) { if (node == NULL) return NULL; /* elog(LOG,"%d",nodeTag(node)); */ if(IsA(node,BoolExpr)){ BoolExpr * bExpr =(BoolExpr *) node; if(bExpr->boolop == NOT_EXPR){ /* elog(LOG,"\nTHERENOT\n"); */ context->positive = !context->positive; Node * retour = expression_tree_mutator(node, my_mutator, (void *) context); context->positive = !context->positive; return retour; } if(bExpr->boolop == OR_EXPR || bExpr->boolop == AND_EXPR){ /*Pré traitement*/ List * l_save = context->list_of_not_null_in_current; context->list_of_not_null_in_current = list_copy(l_save); if(context->positive){ context->list_of_not_null_in_current = list_concat(context->list_of_not_null_in_current,list_nth(context->list_list_true,context->list_list_true->length - context->where_i_am - 1)); } else{ context->list_of_not_null_in_current = list_concat(context->list_of_not_null_in_current,list_nth(context->list_list_false,context->list_list_true->length - context->where_i_am - 1)); } /* elog(LOG,"\n LIST_NOT_NULL: %s \n",nodeToString(context->list_of_not_null_in_current)); */ context->where_i_am ++; Node * retour = expression_tree_mutator(node, my_mutator, (void *) context); /*Post traitement*/ context->list_of_not_null_in_current = l_save; return retour; } } if(IsA(node,Query)){ Query * q = (Query *) node; /* context->current_varlevelsup ++; */ List * save_current_trueVar = context->current_trueVar; context->current_trueVar = list_nth(context->trueVars,context->where_i_am_querry); context->where_i_am_querry = context->where_i_am_querry + 1; q->jointree = expression_tree_mutator((Node *) q->jointree, my_mutator, (void *) context); /* context->where_i_am_querry = context->where_i_am_querry - 1; */ context->current_trueVar = save_current_trueVar; /* context->current_varlevelsup --; */ return node; } if(IsA(node,OpExpr)){ /* elog(LOG,"\nTHEREOP = \n"); */ OpExpr * oExpr = (OpExpr *) node; if(context->positive && oExpr->opno == 518){ /*<>*/ context->ready = true; } if(!context->positive && oExpr->opno == 96){ /* = */ context->ready = true; } /* if(context->positive && oExpr->opno == 521){ #<{(| > |)}># */ /* context->ready = true; */ /* } */ if(oExpr->opno == 525){ /* >= */ OpExpr * equa = makeNode(OpExpr); equa->opno = 96; /*=*/ equa->args = list_concat(equa->args,oExpr->args); OpExpr * stric = makeNode(OpExpr); stric->opno = 521; /*>*/ stric->args = list_concat(stric->args,oExpr->args); List * tmp = NULL; tmp = lappend(tmp,equa); tmp = lappend(tmp,stric); Node * result = expression_tree_mutator((Node *)makeBoolExpr(OR_EXPR,tmp,-1),my_mutator,context); return result; } if(oExpr->opno == 523){ /* <= */ OpExpr * equa = makeNode(OpExpr); equa->opno = 96; /*=*/ equa->args = list_concat(equa->args,oExpr->args); OpExpr * stric = makeNode(OpExpr); stric->opno = 97; /*<*/ stric->args = list_concat(stric->args,oExpr->args); List * tmp = NULL; tmp = lappend(tmp,equa); tmp = lappend(tmp,stric); Node * result = expression_tree_mutator((Node *)makeBoolExpr(OR_EXPR,tmp,-1),my_mutator,context); return result; } /* if(context->positive && oExpr->opno == 97){ #<{(| < |)}># */ /* context->ready = true; */ /* } */ if(!context->positive && oExpr->opno == 1209){ /* LIKE */ context->ready = true; } Node * result = expression_tree_mutator(node, my_mutator, (void *) context); if(context->constraint_to_add != NULL){ if(!context->positive /* && oExpr->opno == 518 */){ context->constraint_to_add = lappend(context->constraint_to_add,result); Node * to_return = makeBoolExpr(OR_EXPR,context->constraint_to_add,-1); context->constraint_to_add = NULL; context->ready = false; /* elog(LOG,"inter :%s\n",nodeToString(to_return)); */ return to_return; } if(context->positive /* && oExpr->opno == 96 */){ context->constraint_to_add = lappend(context->constraint_to_add,result); Node * to_return = makeBoolExpr(AND_EXPR,context->constraint_to_add,-1); context->constraint_to_add = NULL; context->ready = false; return to_return; } } else return result; } if(context->ready && IsA(node, Var)) { /* elog(LOG,"\n LIST_NOT_NULL: %s \n",nodeToString(context->list_of_not_null_in_current)); */ Var * v = (Var *) node; Var * rv = getTrueVar(context->current_trueVar,v); /* elog(LOG,"\nTRUE VARS : %s \n",nodeToString(context->current_trueVar)); */ /* elog(LOG,"\nV check %s \n",nodeToString(v)); */ /* elog(LOG,"\nRV check %s \n",nodeToString(rv)); */ /* elog(LOG,"\nNOT NULL CUR: %s \n",nodeToString(context->list_of_not_null_in_current)); */ if(!context->positive && !isInListTrueVar(context->list_of_not_null_in_current,rv)){ /* elog(LOG,"\nHERE !\n"); */ OpExpr * inf0 = makeNode(OpExpr); inf0->opno = 97; /*<*/ inf0->args = lappend(inf0->args,node); Const * c0 = makeConst(23,-1,0,4,Int16GetDatum(0),false, true); inf0->args = lappend(inf0->args,c0); context->constraint_to_add = lappend(context->constraint_to_add,inf0); } if(context->positive){ /* elog(LOG,"\nHERE !\n"); */ OpExpr * inf0 = makeNode(OpExpr); inf0->opno = 521; /*>*/ inf0->args = lappend(inf0->args,node); Const * c0 = makeConst(23,-1,0,4,Int16GetDatum(0),false, true); inf0->args = lappend(inf0->args,c0); context->constraint_to_add = lappend(context->constraint_to_add,inf0); } } return expression_tree_mutator(node, my_mutator, (void *) context); }
/* * get_typdefault * Given a type OID, return the type's default value, if any. * * The result is a palloc'd expression node tree, or NULL if there * is no defined default for the datatype. * * NB: caller should be prepared to coerce result to correct datatype; * the returned expression tree might produce something of the wrong type. */ Node * get_typdefault(Oid typid) { HeapTuple typeTuple; Form_pg_type type; Datum datum; bool isNull; Node *expr; typeTuple = SearchSysCache(TYPEOID, ObjectIdGetDatum(typid), 0, 0, 0); if (!HeapTupleIsValid(typeTuple)) elog(ERROR, "cache lookup failed for type %u", typid); type = (Form_pg_type) GETSTRUCT(typeTuple); /* * typdefault and typdefaultbin are potentially null, so don't try to * access 'em as struct fields. Must do it the hard way with * SysCacheGetAttr. */ datum = SysCacheGetAttr(TYPEOID, typeTuple, Anum_pg_type_typdefaultbin, &isNull); if (!isNull) { /* We have an expression default */ expr = stringToNode(DatumGetCString(DirectFunctionCall1(textout, datum))); } else { /* Perhaps we have a plain literal default */ datum = SysCacheGetAttr(TYPEOID, typeTuple, Anum_pg_type_typdefault, &isNull); if (!isNull) { char *strDefaultVal; /* Convert text datum to C string */ strDefaultVal = DatumGetCString(DirectFunctionCall1(textout, datum)); /* Convert C string to a value of the given type */ datum = OidInputFunctionCall(type->typinput, strDefaultVal, getTypeIOParam(typeTuple), -1); /* Build a Const node containing the value */ expr = (Node *) makeConst(typid, type->typlen, datum, false, type->typbyval); pfree(strDefaultVal); } else { /* No default */ expr = NULL; } } ReleaseSysCache(typeTuple); return expr; }
/* * Copied from Postgres' src/backend/optimizer/util/clauses.c * * evaluate_expr: pre-evaluate a constant expression * * We use the executor's routine ExecEvalExpr() to avoid duplication of * code and ensure we get the same result as the executor would get. */ Expr * evaluate_expr(Expr *expr, Oid result_type, int32 result_typmod, Oid result_collation) { EState *estate; ExprState *exprstate; MemoryContext oldcontext; Datum const_val; bool const_is_null; int16 resultTypLen; bool resultTypByVal; /* * To use the executor, we need an EState. */ estate = CreateExecutorState(); /* We can use the estate's working context to avoid memory leaks. */ oldcontext = MemoryContextSwitchTo(estate->es_query_cxt); /* Make sure any opfuncids are filled in. */ fix_opfuncids((Node *) expr); /* * Prepare expr for execution. (Note: we can't use ExecPrepareExpr * because it'd result in recursively invoking eval_const_expressions.) */ exprstate = ExecInitExpr(expr, NULL); /* * And evaluate it. * * It is OK to use a default econtext because none of the ExecEvalExpr() * code used in this situation will use econtext. That might seem * fortuitous, but it's not so unreasonable --- a constant expression does * not depend on context, by definition, n'est ce pas? */ const_val = ExecEvalExprSwitchContext(exprstate, GetPerTupleExprContext(estate), &const_is_null, NULL); /* Get info needed about result datatype */ get_typlenbyval(result_type, &resultTypLen, &resultTypByVal); /* Get back to outer memory context */ MemoryContextSwitchTo(oldcontext); /* * Must copy result out of sub-context used by expression eval. * * Also, if it's varlena, forcibly detoast it. This protects us against * storing TOAST pointers into plans that might outlive the referenced * data. (makeConst would handle detoasting anyway, but it's worth a few * extra lines here so that we can do the copy and detoast in one step.) */ if (!const_is_null) { if (resultTypLen == -1) const_val = PointerGetDatum(PG_DETOAST_DATUM_COPY(const_val)); else const_val = datumCopy(const_val, resultTypByVal, resultTypLen); } /* Release all the junk we just created */ FreeExecutorState(estate); /* * Make the constant result node. */ return (Expr *) makeConst(result_type, result_typmod, result_collation, resultTypLen, const_val, const_is_null, resultTypByVal); }