广告
返回顶部
首页 > 资讯 > 数据库 >PostgreSQL中表达式预处理主要的函数有哪些
  • 187
分享到

PostgreSQL中表达式预处理主要的函数有哪些

2024-04-02 19:04:59 187人浏览 泡泡鱼
摘要

这篇文章主要为大家展示了“postgresql中表达式预处理主要的函数有哪些”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Postgresql中表达式预处理主要

这篇文章主要为大家展示了“postgresql中表达式预处理主要的函数有哪些”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“Postgresql中表达式预处理主要的函数有哪些”这篇文章吧。

表达式预处理主要的函数主要有preprocess_expression和preprocess_qual_conditions(调用preprocess_expression),在文件src/backend/optimizer/plan/planner.c中。preprocess_expression调用了eval_const_expressions,该函数调用了mutator函数通过遍历的方式对表达式进行处理。

一、基本概念

PG源码对简化表达式的注释如下:

 

比如表达式1 + 2,直接求解得到3;x OR true,直接求解得到true而无需理会x的值,类似的x AND false直接求解得到false而无需理会x的值.
不过,这里的简化只是执行了基础分析,并没有做深入分析:

testdb=# explain verbose select max(a.dwbh::int+(1+2)) from t_dwxx a;
                               QUERY PLAN                                
-------------------------------------------------------------------------
 Aggregate  (cost=13.20..13.21 rows=1 width=4)
   Output: max(((dwbh)::integer + 3))
   ->  Seq Scan on public.t_dwxx a  (cost=0.00..11.60 rows=160 width=38)
         Output: dwmc, dwbh, dwdz
(4 rows)

testdb=# explain verbose select max(a.dwbh::int+1+2) from t_dwxx a;
                               QUERY PLAN                                
-------------------------------------------------------------------------
 Aggregate  (cost=13.60..13.61 rows=1 width=4)
   Output: max((((dwbh)::integer + 1) + 2))
   ->  Seq Scan on public.t_dwxx a  (cost=0.00..11.60 rows=160 width=38)
         Output: dwmc, dwbh, dwdz
(4 rows)

见上测试脚本,如(1+2),把括号去掉,a.dwbh先跟1运算,再跟2运算,没有执行简化.

二、源码解读

主函数入口:
subquery_planner

 

 PlannerInfo *
 subquery_planner(PlannerGlobal *glob, Query *parse,
                  PlannerInfo *parent_root,
                  bool hasRecursion, double tuple_fraction)
 {
     PlannerInfo *root;//返回值
     List       *newWithCheckOptions;//
     List       *newHaving;//Having子句
     bool        hasOuterJoins;//是否存在Outer Join?
     RelOptInfo *final_rel;//
     ListCell   *l;//临时变量
 
     
     root = makenode(PlannerInfo);//构造返回值
     root->parse = parse;
     root->glob = glob;
     root->query_level = parent_root ? parent_root->query_level + 1 : 1;
     root->parent_root = parent_root;
     root->plan_params = NIL;
     root->outer_params = NULL;
     root->planner_cxt = CurrentMemoryContext;
     root->init_plans = NIL;
     root->cte_plan_ids = NIL;
     root->multiexpr_params = NIL;
     root->eq_classes = NIL;
     root->append_rel_list = NIL;
     root->rowMarks = NIL;
     memset(root->upper_rels, 0, sizeof(root->upper_rels));
     memset(root->upper_targets, 0, sizeof(root->upper_targets));
     root->processed_tlist = NIL;
     root->grouping_map = NULL;
     root->minmax_aggs = NIL;
     root->qual_security_level = 0;
     root->inhTargetKind = INHKIND_NONE;
     root->hasRecursion = hasRecursion;
     if (hasRecursion)
         root->wt_param_id = SS_assign_special_param(root);
     else
         root->wt_param_id = -1;
     root->non_recursive_path = NULL;
     root->partColsUpdated = false;
 
     
     if (parse->cteList)
         SS_process_ctes(root);//处理With 语句
 
     
     if (parse->hasSubLinks)
         pull_up_sublinks(root); //上拉子链接
 
     
     inline_set_returning_functions(root);//
 
     
     pull_up_subqueries(root);//上拉子查询
 
     
     if (parse->setOperations)
         flatten_simple_uNIOn_all(root);//扁平化处理UNION ALL
 
     
     //判断RTE中是否存在RTE_JOIN?
     root->hasJoinRTEs = false;
     root->hasLateralRTEs = false;
     hasOuterJoins = false;
     foreach(l, parse->rtable)
     {
         RangeTblEntry *rte = lfirst_node(RangeTblEntry, l);
 
         if (rte->rtekind == RTE_JOIN)
         {
             root->hasJoinRTEs = true;
             if (IS_OUTER_JOIN(rte->jointype))
                 hasOuterJoins = true;
         }
         if (rte->lateral)
             root->hasLateralRTEs = true;
     }
 
     
     //预处理RowMark信息
     preprocess_rowmarks(root);
 
     
     //展开继承表
     expand_inherited_tables(root);
 
     
     //是否存在Having表达式
     root->hasHavingQual = (parse->havingQual != NULL);
 
     
     root->hasPseudoConstantQuals = false;
 
     
     //预处理表达式:targetList(投影列)
     parse->targetList = (List *)
         preprocess_expression(root, (Node *) parse->targetList,
                               EXPRKIND_TARGET);
 
     
     if (parse->hasTargetSRFs)
         parse->hasTargetSRFs = expression_returns_set((Node *) parse->targetList);
 
     newWithCheckOptions = NIL;
     foreach(l, parse->withCheckOptions)//witch Check Options
     {
         WithCheckOption *wco = lfirst_node(WithCheckOption, l);
 
         wco->qual = preprocess_expression(root, wco->qual,
                                           EXPRKIND_QUAL);
         if (wco->qual != NULL)
             newWithCheckOptions = lappend(newWithCheckOptions, wco);
     }
     parse->withCheckOptions = newWithCheckOptions;
     //返回列信息returningList
     parse->returningList = (List *)
         preprocess_expression(root, (Node *) parse->returningList,
                               EXPRKIND_TARGET);
     //预处理条件表达式
     preprocess_qual_conditions(root, (Node *) parse->jointree);
     //预处理Having表达式
     parse->havingQual = preprocess_expression(root, parse->havingQual,
                                               EXPRKIND_QUAL);
     //窗口函数
     foreach(l, parse->windowClause)
     {
         WindowClause *wc = lfirst_node(WindowClause, l);
 
         
         wc->startOffset = preprocess_expression(root, wc->startOffset,
                                                 EXPRKIND_LIMIT);
         wc->endOffset = preprocess_expression(root, wc->endOffset,
                                               EXPRKIND_LIMIT);
     }
     //Limit子句
     parse->limitOffset = preprocess_expression(root, parse->limitOffset,
                                                EXPRKIND_LIMIT);
     parse->limitCount = preprocess_expression(root, parse->limitCount,
                                               EXPRKIND_LIMIT);
     //On Conflict子句
     if (parse->onConflict)
     {
         parse->onConflict->arbiterElems = (List *)
             preprocess_expression(root,
                                   (Node *) parse->onConflict->arbiterElems,
                                   EXPRKIND_ARBITER_ELEM);
         parse->onConflict->arbiterWhere =
             preprocess_expression(root,
                                   parse->onConflict->arbiterWhere,
                                   EXPRKIND_QUAL);
         parse->onConflict->onConflictSet = (List *)
             preprocess_expression(root,
                                   (Node *) parse->onConflict->onConflictSet,
                                   EXPRKIND_TARGET);
         parse->onConflict->onConflictWhere =
             preprocess_expression(root,
                                   parse->onConflict->onConflictWhere,
                                   EXPRKIND_QUAL);
         
     }
     //集合操作(AppendRelInfo)
     root->append_rel_list = (List *)
         preprocess_expression(root, (Node *) root->append_rel_list,
                               EXPRKIND_APPINFO);
     //RTE
     
     foreach(l, parse->rtable)
     {
         RangeTblEntry *rte = lfirst_node(RangeTblEntry, l);
         int         kind;
         ListCell   *lcsq;
 
         if (rte->rtekind == RTE_RELATION)
         {
             if (rte->tablesample)
                 rte->tablesample = (TableSampleClause *)
                     preprocess_expression(root,
                                           (Node *) rte->tablesample,
                                           EXPRKIND_TABLESAMPLE);//数据表采样语句
         }
         else if (rte->rtekind == RTE_SUBQUERY)//子查询
         {
             
             if (rte->lateral && root->hasJoinRTEs)
                 rte->subquery = (Query *)
                     flatten_join_alias_vars(root, (Node *) rte->subquery);
         }
         else if (rte->rtekind == RTE_FUNCTION)//函数
         {
             
             kind = rte->lateral ? EXPRKIND_RTFUNC_LATERAL : EXPRKIND_RTFUNC;
             rte->functions = (List *)
                 preprocess_expression(root, (Node *) rte->functions, kind);
         }
         else if (rte->rtekind == RTE_TABLEFUNC)//TABLE FUNC
         {
             
             kind = rte->lateral ? EXPRKIND_TABLEFUNC_LATERAL : EXPRKIND_TABLEFUNC;
             rte->tablefunc = (TableFunc *)
                 preprocess_expression(root, (Node *) rte->tablefunc, kind);
         }
         else if (rte->rtekind == RTE_VALUES)//VALUES子句
         {
             
             kind = rte->lateral ? EXPRKIND_VALUES_LATERAL : EXPRKIND_VALUES;
             rte->values_lists = (List *)
                 preprocess_expression(root, (Node *) rte->values_lists, kind);
         }
 
         
         foreach(lcsq, rte->securityQuals)
         {
             lfirst(lcsq) = preprocess_expression(root,
                                                  (Node *) lfirst(lcsq),
                                                  EXPRKIND_QUAL);
         }
     }
 
     ...//其他
     
     return root;
 }

preprocess_expression

 
 static Node *
 preprocess_expression(PlannerInfo *root, Node *expr, int kind)
 {
     
     if (expr == NULL)
         return NULL;
 
     
     if (root->hasJoinRTEs &&
         !(kind == EXPRKIND_RTFUNC ||
           kind == EXPRKIND_VALUES ||
           kind == EXPRKIND_TABLESAMPLE ||
           kind == EXPRKIND_TABLEFUNC))
         expr = flatten_join_alias_vars(root, expr);//扁平化处理joinaliasvars,上节已介绍
 
     
     expr = eval_const_expressions(root, expr);//简化常量表达式
 
     
     if (kind == EXPRKIND_QUAL)
     {
         expr = (Node *) canonicalize_qual((Expr *) expr, false);//表达式规约,下节介绍
 
 #ifdef OPTIMIZER_DEBUG
         printf("After canonicalize_qual()\n");
         pprint(expr);
 #endif
     }
 
     
     if (root->parse->hasSubLinks)//扩展子链接为子计划
         expr = SS_process_sublinks(root, expr, (kind == EXPRKIND_QUAL));
 
     
 
     
     if (root->query_level > 1)
         expr = SS_replace_correlation_vars(root, expr);//使用Param节点替换上层的Vars
 
     
     if (kind == EXPRKIND_QUAL)
         expr = (Node *) make_ands_implicit((Expr *) expr);
 
     return expr;
 }

preprocess_qual_conditions

 
 static void
 preprocess_qual_conditions(PlannerInfo *root, Node *jtnode)
 {
     if (jtnode == NULL)
         return;
     if (IsA(jtnode, RangeTblRef))
     {
         
     }
     else if (IsA(jtnode, FromExpr))
     {
         FromExpr   *f = (FromExpr *) jtnode;
         ListCell   *l;
 
         foreach(l, f->fromlist)
             preprocess_qual_conditions(root, lfirst(l));//递归调用
 
         f->quals = preprocess_expression(root, f->quals, EXPRKIND_QUAL);
     }
     else if (IsA(jtnode, JoinExpr))
     {
         JoinExpr   *j = (JoinExpr *) jtnode;
 
         preprocess_qual_conditions(root, j->larg);//递归调用
         preprocess_qual_conditions(root, j->rarg);//递归调用
 
         j->quals = preprocess_expression(root, j->quals, EXPRKIND_QUAL);
     }
     else
         elog(ERROR, "unrecognized node type: %d",
              (int) nodeTag(jtnode));
 }

eval_const_expressions

 Node *
 eval_const_expressions(PlannerInfo *root, Node *node)
 {
     eval_const_expressions_context context;
 
     if (root)
         context.boundParams = root->glob->boundParams;  
     else
         context.boundParams = NULL;
     context.root = root;        
     context.active_fns = NIL;   
     context.case_val = NULL;    
     context.estimate = false;   
     //调用XX_mutator函数遍历处理
     return eval_const_expressions_mutator(node, &context);
 }

eval_const_expressions_mutator


 static Node *
 eval_const_expressions_mutator(Node *node,
                                eval_const_expressions_context *context)
 {
     if (node == NULL)
         return NULL;
     switch (nodeTag(node))
     {
         case T_Param:
             {
                 Param      *param = (Param *) node;
                 ParamListInfo paramLI = context->boundParams;
 
                 
                 if (param->paramkind == PARAM_EXTERN &&
                     paramLI != NULL &&
                     param->paramid > 0 &&
                     param->paramid <= paramLI->numParams)
                 {
                     ParamExternData *prm;
                     ParamExternData prmdata;
 
                     
                     if (paramLI->paramFetch != NULL)
                         prm = paramLI->paramFetch(paramLI, param->paramid,
                                                   true, &prmdata);
                     else
                         prm = &paramLI->params[param->paramid - 1];
 
                     
                     if (OidIsValid(prm->ptype) &&
                         prm->ptype == param->paramtype)
                     {
                         
                         if (context->estimate ||
                             (prm->pflags & PARAM_FLAG_CONST))
                         {
                             
                             int16       typLen;
                             bool        typByVal;
                             Datum       pval;
 
                             get_typlenbyval(param->paramtype,
                                             &typLen, &typByVal);
                             if (prm->isnull || typByVal)
                                 pval = prm->value;
                             else
                                 pval = datumCopy(prm->value, typByVal, typLen);
                             return (Node *) makeConst(param->paramtype,
                                                       param->paramtypmod,
                                                       param->paramcollid,
                                                       (int) typLen,
                                                       pval,
                                                       prm->isnull,
                                                       typByVal);
                         }
                     }
                 }
 
                 
                 return (Node *) copyObject(param);
             }
         case T_WindowFunc:
             {
                 WindowFunc *expr = (WindowFunc *) node;
                 Oid         funcid = expr->winfnoid;
                 List       *args;
                 Expr       *aggfilter;
                 HeapTuple   func_tuple;
                 WindowFunc *newexpr;
 
                 
                 func_tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
                 if (!HeapTupleIsValid(func_tuple))
                     elog(ERROR, "cache lookup failed for function %u", funcid);
 
                 args = expand_function_arguments(expr->args, expr->wintype,
                                                  func_tuple);
 
                 ReleaseSysCache(func_tuple);
 
                 
                 args = (List *)
                     expression_tree_mutator((Node *) args,
                                             eval_const_expressions_mutator,
                                             (void *) context);
                 
                 aggfilter = (Expr *)
                     eval_const_expressions_mutator((Node *) expr->aggfilter,
                                                    context);
 
                 
                 newexpr = makeNode(WindowFunc);
                 newexpr->winfnoid = expr->winfnoid;
                 newexpr->wintype = expr->wintype;
                 newexpr->wincollid = expr->wincollid;
                 newexpr->inputcollid = expr->inputcollid;
                 newexpr->args = args;
                 newexpr->aggfilter = aggfilter;
                 newexpr->winref = expr->winref;
                 newexpr->winstar = expr->winstar;
                 newexpr->winagg = expr->winagg;
                 newexpr->location = expr->location;
 
                 return (Node *) newexpr;
             }
         case T_FuncExpr:
             {
                 FuncExpr   *expr = (FuncExpr *) node;
                 List       *args = expr->args;
                 Expr       *simple;
                 FuncExpr   *newexpr;
 
                 
                 simple = simplify_function(expr->funcid,
                                            expr->funcresulttype,
                                            exprTypmod(node),
                                            expr->funccollid,
                                            expr->inputcollid,
                                            &args,
                                            expr->funcvariadic,
                                            true,
                                            true,
                                            context);
                 if (simple)     
                     return (Node *) simple;
 
                 
                 newexpr = makeNode(FuncExpr);
                 newexpr->funcid = expr->funcid;
                 newexpr->funcresulttype = expr->funcresulttype;
                 newexpr->funcretset = expr->funcretset;
                 newexpr->funcvariadic = expr->funcvariadic;
                 newexpr->funcfORMat = expr->funcformat;
                 newexpr->funccollid = expr->funccollid;
                 newexpr->inputcollid = expr->inputcollid;
                 newexpr->args = args;
                 newexpr->location = expr->location;
                 return (Node *) newexpr;
             }
         case T_OpExpr://操作(运算)表达式
             {
                 OpExpr     *expr = (OpExpr *) node;
                 List       *args = expr->args;
                 Expr       *simple;
                 OpExpr     *newexpr;
 
                 
                 set_opfuncid(expr);
 
                 
                 simple = simplify_function(expr->opfuncid,
                                            expr->opresulttype, -1,
                                            expr->opcollid,
                                            expr->inputcollid,
                                            &args,
                                            false,
                                            true,
                                            true,
                                            context);
                 if (simple)     
                     return (Node *) simple;
 
                 
                 if (expr->opno == BooleanEqualOperator ||
                     expr->opno == BooleanNotEqualOperator)
                 {
                     simple = (Expr *) simplify_boolean_equality(expr->opno,
                                                                 args);
                     if (simple) 
                         return (Node *) simple;
                 }
 
                 
                 newexpr = makeNode(OpExpr);
                 newexpr->opno = expr->opno;
                 newexpr->opfuncid = expr->opfuncid;
                 newexpr->opresulttype = expr->opresulttype;
                 newexpr->opretset = expr->opretset;
                 newexpr->opcollid = expr->opcollid;
                 newexpr->inputcollid = expr->inputcollid;
                 newexpr->args = args;
                 newexpr->location = expr->location;
                 return (Node *) newexpr;
             }
         case T_DistinctExpr:
             {
                 DistinctExpr *expr = (DistinctExpr *) node;
                 List       *args;
                 ListCell   *arg;
                 bool        has_null_input = false;
                 bool        all_null_input = true;
                 bool        has_nonconst_input = false;
                 Expr       *simple;
                 DistinctExpr *newexpr;
 
                 
                 args = (List *) expression_tree_mutator((Node *) expr->args,
                                                         eval_const_expressions_mutator,
                                                         (void *) context);
 
                 
                 foreach(arg, args)
                 {
                     if (IsA(lfirst(arg), Const))
                     {
                         has_null_input |= ((Const *) lfirst(arg))->constisnull;
                         all_null_input &= ((Const *) lfirst(arg))->constisnull;
                     }
                     else
                         has_nonconst_input = true;
                 }
 
                 
                 if (!has_nonconst_input)
                 {
                     
                     if (all_null_input)
                         return makeBoolConst(false, false);
 
                     
                     if (has_null_input)
                         return makeBoolConst(true, false);
 
                     
                     
 
                     
                     set_opfuncid((OpExpr *) expr);  
 
                     
                     simple = simplify_function(expr->opfuncid,
                                                expr->opresulttype, -1,
                                                expr->opcollid,
                                                expr->inputcollid,
                                                &args,
                                                false,
                                                false,
                                                false,
                                                context);
                     if (simple) 
                     {
                         
                         Const      *csimple = castNode(Const, simple);
 
                         csimple->constvalue =
                             BoolGetDatum(!DatumGetBool(csimple->constvalue));
                         return (Node *) csimple;
                     }
                 }
 
                 
                 newexpr = makeNode(DistinctExpr);
                 newexpr->opno = expr->opno;
                 newexpr->opfuncid = expr->opfuncid;
                 newexpr->opresulttype = expr->opresulttype;
                 newexpr->opretset = expr->opretset;
                 newexpr->opcollid = expr->opcollid;
                 newexpr->inputcollid = expr->inputcollid;
                 newexpr->args = args;
                 newexpr->location = expr->location;
                 return (Node *) newexpr;
             }
         case T_ScalarArrayOpExpr:
             {
                 ScalarArrayOpExpr *saop;
 
                 
                 saop = (ScalarArrayOpExpr *) ece_generic_processing(node);
 
                 
                 set_sa_opfuncid(saop);
 
                 
                 if (ece_all_arguments_const(saop) &&
                     ece_function_is_safe(saop->opfuncid, context))
                     return ece_evaluate_expr(saop);
                 return (Node *) saop;
             }
         case T_BoolExpr:
             {
                 BoolExpr   *expr = (BoolExpr *) node;
 
                 switch (expr->boolop)
                 {
                     case OR_EXPR:
                         {
                             List       *newargs;
                             bool        haveNull = false;
                             bool        forceTrue = false;
 
                             newargs = simplify_or_arguments(expr->args,
                                                             context,
                                                             &haveNull,
                                                             &forceTrue);
                             if (forceTrue)
                                 return makeBoolConst(true, false);
                             if (haveNull)
                                 newargs = lappend(newargs,
                                                   makeBoolConst(false, true));
                             
                             if (newargs == NIL)
                                 return makeBoolConst(false, false);
 
                             
                             if (list_length(newargs) == 1)
                                 return (Node *) linitial(newargs);
                             
                             return (Node *) make_orclause(newargs);
                         }
                     case AND_EXPR:
                         {
                             List       *newargs;
                             bool        haveNull = false;
                             bool        forceFalse = false;
 
                             newargs = simplify_and_arguments(expr->args,
                                                              context,
                                                              &haveNull,
                                                              &forceFalse);
                             if (forceFalse)
                                 return makeBoolConst(false, false);
                             if (haveNull)
                                 newargs = lappend(newargs,
                                                   makeBoolConst(false, true));
                             
                             if (newargs == NIL)
                                 return makeBoolConst(true, false);
 
                             
                             if (list_length(newargs) == 1)
                                 return (Node *) linitial(newargs);
                             
                             return (Node *) make_andclause(newargs);
                         }
                     case NOT_EXPR:
                         {
                             Node       *arg;
 
                             Assert(list_length(expr->args) == 1);
                             arg = eval_const_expressions_mutator(linitial(expr->args),
                                                                  context);
 
                             
                             return negate_clause(arg);
                         }
                     default:
                         elog(ERROR, "unrecognized boolop: %d",
                              (int) expr->boolop);
                         break;
                 }
                 break;
             }
         case T_SubPlan:
         case T_AlternativeSubPlan:
 
             
             return node;
         case T_RelabelType:
             {
                 
                 RelabelType *relabel = (RelabelType *) node;
                 Node       *arg;
 
                 arg = eval_const_expressions_mutator((Node *) relabel->arg,
                                                      context);
 
                 
                 while (arg && IsA(arg, RelabelType))
                     arg = (Node *) ((RelabelType *) arg)->arg;
 
                 if (arg && IsA(arg, Const))
                 {
                     Const      *con = (Const *) arg;
 
                     con->consttype = relabel->resulttype;
                     con->consttypmod = relabel->resulttypmod;
                     con->constcollid = relabel->resultcollid;
                     return (Node *) con;
                 }
                 else
                 {
                     RelabelType *newrelabel = makeNode(RelabelType);
 
                     newrelabel->arg = (Expr *) arg;
                     newrelabel->resulttype = relabel->resulttype;
                     newrelabel->resulttypmod = relabel->resulttypmod;
                     newrelabel->resultcollid = relabel->resultcollid;
                     newrelabel->relabelformat = relabel->relabelformat;
                     newrelabel->location = relabel->location;
                     return (Node *) newrelabel;
                 }
             }
         case T_CoerceViaIO:
             {
                 CoerceViaIO *expr = (CoerceViaIO *) node;
                 List       *args;
                 Oid         outfunc;
                 bool        outtypisvarlena;
                 Oid         infunc;
                 Oid         intypioparam;
                 Expr       *simple;
                 CoerceViaIO *newexpr;
 
                 
                 args = list_make1(expr->arg);
 
                 
                 getTypeOutputInfo(exprType((Node *) expr->arg),
                                   &outfunc, &outtypisvarlena);
                 getTypeInputInfo(expr->resulttype,
                                  &infunc, &intypioparam);
 
                 simple = simplify_function(outfunc,
                                            CSTRINGoID, -1,
                                            InvalidOid,
                                            InvalidOid,
                                            &args,
                                            false,
                                            true,
                                            true,
                                            context);
                 if (simple)     
                 {
                     
                     args = list_make3(simple,
                                       makeConst(OIDOID,
                                                 -1,
                                                 InvalidOid,
                                                 sizeof(Oid),
                                                 ObjectIdGetDatum(intypioparam),
                                                 false,
                                                 true),
                                       makeConst(INT4OID,
                                                 -1,
                                                 InvalidOid,
                                                 sizeof(int32),
                                                 Int32GetDatum(-1),
                                                 false,
                                                 true));
 
                     simple = simplify_function(infunc,
                                                expr->resulttype, -1,
                                                expr->resultcollid,
                                                InvalidOid,
                                                &args,
                                                false,
                                                false,
                                                true,
                                                context);
                     if (simple) 
                         return (Node *) simple;
                 }
 
                 
                 newexpr = makeNode(CoerceViaIO);
                 newexpr->arg = (Expr *) linitial(args);
                 newexpr->resulttype = expr->resulttype;
                 newexpr->resultcollid = expr->resultcollid;
                 newexpr->coerceformat = expr->coerceformat;
                 newexpr->location = expr->location;
                 return (Node *) newexpr;
             }
         case T_ArrayCoerceExpr:
             {
                 ArrayCoerceExpr *ac;
 
                 
                 ac = (ArrayCoerceExpr *) ece_generic_processing(node);
 
                 
                 if (ac->arg && IsA(ac->arg, Const) &&
                     ac->elemexpr && !IsA(ac->elemexpr, CoerceToDomain) &&
                     !contain_mutable_functions((Node *) ac->elemexpr))
                     return ece_evaluate_expr(ac);
                 return (Node *) ac;
             }
         case T_CollateExpr:
             {
                 
                 CollateExpr *collate = (CollateExpr *) node;
                 Node       *arg;
 
                 arg = eval_const_expressions_mutator((Node *) collate->arg,
                                                      context);
 
                 if (arg && IsA(arg, Const))
                 {
                     Const      *con = (Const *) arg;
 
                     con->constcollid = collate->collOid;
                     return (Node *) con;
                 }
                 else if (collate->collOid == exprCollation(arg))
                 {
                     
                     return arg;
                 }
                 else
                 {
                     RelabelType *relabel = makeNode(RelabelType);
 
                     relabel->resulttype = exprType(arg);
                     relabel->resulttypmod = exprTypmod(arg);
                     relabel->resultcollid = collate->collOid;
                     relabel->relabelformat = COERCE_IMPLICIT_CAST;
                     relabel->location = collate->location;
 
                     
                     while (arg && IsA(arg, RelabelType))
                         arg = (Node *) ((RelabelType *) arg)->arg;
                     relabel->arg = (Expr *) arg;
 
                     return (Node *) relabel;
                 }
             }
         case T_CaseExpr:
             {
                 
                 CaseExpr   *caseexpr = (CaseExpr *) node;
                 CaseExpr   *newcase;
                 Node       *save_case_val;
                 Node       *newarg;
                 List       *newargs;
                 bool        const_true_cond;
                 Node       *defresult = NULL;
                 ListCell   *arg;
 
                 
                 newarg = eval_const_expressions_mutator((Node *) caseexpr->arg,
                                                         context);
 
                 
                 save_case_val = context->case_val;
                 if (newarg && IsA(newarg, Const))
                 {
                     context->case_val = newarg;
                     newarg = NULL;  
                 }
                 else
                     context->case_val = NULL;
 
                 
                 newargs = NIL;
                 const_true_cond = false;
                 foreach(arg, caseexpr->args)
                 {
                     CaseWhen   *oldcasewhen = lfirst_node(CaseWhen, arg);
                     Node       *casecond;
                     Node       *caseresult;
 
                     
                     casecond = eval_const_expressions_mutator((Node *) oldcasewhen->expr,
                                                               context);
 
                     
                     if (casecond && IsA(casecond, Const))
                     {
                         Const      *const_input = (Const *) casecond;
 
                         if (const_input->constisnull ||
                             !DatumGetBool(const_input->constvalue))
                             continue;   
                         
                         const_true_cond = true;
                     }
 
                     
                     caseresult = eval_const_expressions_mutator((Node *) oldcasewhen->result,
                                                                 context);
 
                     
                     if (!const_true_cond)
                     {
                         CaseWhen   *newcasewhen = makeNode(CaseWhen);
 
                         newcasewhen->expr = (Expr *) casecond;
                         newcasewhen->result = (Expr *) caseresult;
                         newcasewhen->location = oldcasewhen->location;
                         newargs = lappend(newargs, newcasewhen);
                         continue;
                     }
 
                     
                     defresult = caseresult;
                     break;
                 }
 
                 
                 if (!const_true_cond)
                     defresult = eval_const_expressions_mutator((Node *) caseexpr->defresult,
                                                                context);
 
                 context->case_val = save_case_val;
 
                 
                 if (newargs == NIL)
                     return defresult;
                 
                 newcase = makeNode(CaseExpr);
                 newcase->casetype = caseexpr->casetype;
                 newcase->casecollid = caseexpr->casecollid;
                 newcase->arg = (Expr *) newarg;
                 newcase->args = newargs;
                 newcase->defresult = (Expr *) defresult;
                 newcase->location = caseexpr->location;
                 return (Node *) newcase;
             }
         case T_CaseTestExpr:
             {
                 
                 if (context->case_val)
                     return copyObject(context->case_val);
                 else
                     return copyObject(node);
             }
         case T_ArrayRef:
         case T_ArrayExpr:
         case T_RowExpr:
             {
                 
 
                 
                 node = ece_generic_processing(node);
                 
                 if (ece_all_arguments_const(node))
                     return ece_evaluate_expr(node);
                 return node;
             }
         case T_CoalesceExpr:
             {
                 CoalesceExpr *coalesceexpr = (CoalesceExpr *) node;
                 CoalesceExpr *newcoalesce;
                 List       *newargs;
                 ListCell   *arg;
 
                 newargs = NIL;
                 foreach(arg, coalesceexpr->args)
                 {
                     Node       *e;
 
                     e = eval_const_expressions_mutator((Node *) lfirst(arg),
                                                        context);
 
                     
                     if (IsA(e, Const))
                     {
                         if (((Const *) e)->constisnull)
                             continue;   
                         if (newargs == NIL)
                             return e;   
                         newargs = lappend(newargs, e);
                         break;
                     }
                     newargs = lappend(newargs, e);
                 }
 
                 
                 if (newargs == NIL)
                     return (Node *) makeNullConst(coalesceexpr->coalescetype,
                                                   -1,
                                                   coalesceexpr->coalescecollid);
 
                 newcoalesce = makeNode(CoalesceExpr);
                 newcoalesce->coalescetype = coalesceexpr->coalescetype;
                 newcoalesce->coalescecollid = coalesceexpr->coalescecollid;
                 newcoalesce->args = newargs;
                 newcoalesce->location = coalesceexpr->location;
                 return (Node *) newcoalesce;
             }
         case T_SQLValueFunction:
             {
                 
                 SQLValueFunction *svf = (SQLValueFunction *) node;
 
                 if (context->estimate)
                     return (Node *) evaluate_expr((Expr *) svf,
                                                   svf->type,
                                                   svf->typmod,
                                                   InvalidOid);
                 else
                     return copyObject((Node *) svf);
             }
         case T_FieldSelect:
             {
                 
                 FieldSelect *fselect = (FieldSelect *) node;
                 FieldSelect *newfselect;
                 Node       *arg;
 
                 arg = eval_const_expressions_mutator((Node *) fselect->arg,
                                                      context);
                 if (arg && IsA(arg, Var) &&
                     ((Var *) arg)->varattno == InvalidAttrNumber &&
                     ((Var *) arg)->varlevelsup == 0)
                 {
                     if (rowtype_field_matches(((Var *) arg)->vartype,
                                               fselect->fieldnum,
                                               fselect->resulttype,
                                               fselect->resulttypmod,
                                               fselect->resultcollid))
                         return (Node *) makeVar(((Var *) arg)->varno,
                                                 fselect->fieldnum,
                                                 fselect->resulttype,
                                                 fselect->resulttypmod,
                                                 fselect->resultcollid,
                                                 ((Var *) arg)->varlevelsup);
                 }
                 if (arg && IsA(arg, RowExpr))
                 {
                     RowExpr    *rowexpr = (RowExpr *) arg;
 
                     if (fselect->fieldnum > 0 &&
                         fselect->fieldnum <= list_length(rowexpr->args))
                     {
                         Node       *fld = (Node *) list_nth(rowexpr->args,
                                                             fselect->fieldnum - 1);
 
                         if (rowtype_field_matches(rowexpr->row_typeid,
                                                   fselect->fieldnum,
                                                   fselect->resulttype,
                                                   fselect->resulttypmod,
                                                   fselect->resultcollid) &&
                             fselect->resulttype == exprType(fld) &&
                             fselect->resulttypmod == exprTypmod(fld) &&
                             fselect->resultcollid == exprCollation(fld))
                             return fld;
                     }
                 }
                 newfselect = makeNode(FieldSelect);
                 newfselect->arg = (Expr *) arg;
                 newfselect->fieldnum = fselect->fieldnum;
                 newfselect->resulttype = fselect->resulttype;
                 newfselect->resulttypmod = fselect->resulttypmod;
                 newfselect->resultcollid = fselect->resultcollid;
                 if (arg && IsA(arg, Const))
                 {
                     Const      *con = (Const *) arg;
 
                     if (rowtype_field_matches(con->consttype,
                                               newfselect->fieldnum,
                                               newfselect->resulttype,
                                               newfselect->resulttypmod,
                                               newfselect->resultcollid))
                         return ece_evaluate_expr(newfselect);
                 }
                 return (Node *) newfselect;
             }
         case T_NullTest:
             {
                 NullTest   *ntest = (NullTest *) node;
                 NullTest   *newntest;
                 Node       *arg;
 
                 arg = eval_const_expressions_mutator((Node *) ntest->arg,
                                                      context);
                 if (ntest->arGISrow && arg && IsA(arg, RowExpr))
                 {
                     
                     RowExpr    *rarg = (RowExpr *) arg;
                     List       *newargs = NIL;
                     ListCell   *l;
 
                     foreach(l, rarg->args)
                     {
                         Node       *relem = (Node *) lfirst(l);
 
                         
                         if (relem && IsA(relem, Const))
                         {
                             Const      *carg = (Const *) relem;
 
                             if (carg->constisnull ?
                                 (ntest->nulltesttype == IS_NOT_NULL) :
                                 (ntest->nulltesttype == IS_NULL))
                                 return makeBoolConst(false, false);
                             continue;
                         }
 
                         
                         newntest = makeNode(NullTest);
                         newntest->arg = (Expr *) relem;
                         newntest->nulltesttype = ntest->nulltesttype;
                         newntest->argisrow = false;
                         newntest->location = ntest->location;
                         newargs = lappend(newargs, newntest);
                     }
                     
                     if (newargs == NIL)
                         return makeBoolConst(true, false);
                     
                     if (list_length(newargs) == 1)
                         return (Node *) linitial(newargs);
                     
                     return (Node *) make_andclause(newargs);
                 }
                 if (!ntest->argisrow && arg && IsA(arg, Const))
                 {
                     Const      *carg = (Const *) arg;
                     bool        result;
 
                     switch (ntest->nulltesttype)
                     {
                         case IS_NULL:
                             result = carg->constisnull;
                             break;
                         case IS_NOT_NULL:
                             result = !carg->constisnull;
                             break;
                         default:
                             elog(ERROR, "unrecognized nulltesttype: %d",
                                  (int) ntest->nulltesttype);
                             result = false; 
                             break;
                     }
 
                     return makeBoolConst(result, false);
                 }
 
                 newntest = makeNode(NullTest);
                 newntest->arg = (Expr *) arg;
                 newntest->nulltesttype = ntest->nulltesttype;
                 newntest->argisrow = ntest->argisrow;
                 newntest->location = ntest->location;
                 return (Node *) newntest;
             }
         case T_BooleanTest:
             {
                 
                 BooleanTest *btest = (BooleanTest *) node;
                 BooleanTest *newbtest;
                 Node       *arg;
 
                 arg = eval_const_expressions_mutator((Node *) btest->arg,
                                                      context);
                 if (arg && IsA(arg, Const))
                 {
                     Const      *carg = (Const *) arg;
                     bool        result;
 
                     switch (btest->booltesttype)
                     {
                         case IS_TRUE:
                             result = (!carg->constisnull &&
                                       DatumGetBool(carg->constvalue));
                             break;
                         case IS_NOT_TRUE:
                             result = (carg->constisnull ||
                                       !DatumGetBool(carg->constvalue));
                             break;
                         case IS_FALSE:
                             result = (!carg->constisnull &&
                                       !DatumGetBool(carg->constvalue));
                             break;
                         case IS_NOT_FALSE:
                             result = (carg->constisnull ||
                                       DatumGetBool(carg->constvalue));
                             break;
                         case IS_UNKNOWN:
                             result = carg->constisnull;
                             break;
                         case IS_NOT_UNKNOWN:
                             result = !carg->constisnull;
                             break;
                         default:
                             elog(ERROR, "unrecognized booltesttype: %d",
                                  (int) btest->booltesttype);
                             result = false; 
                             break;
                     }
 
                     return makeBoolConst(result, false);
                 }
 
                 newbtest = makeNode(BooleanTest);
                 newbtest->arg = (Expr *) arg;
                 newbtest->booltesttype = btest->booltesttype;
                 newbtest->location = btest->location;
                 return (Node *) newbtest;
             }
         case T_PlaceHolderVar:
 
             
             if (context->estimate)
             {
                 PlaceHolderVar *phv = (PlaceHolderVar *) node;
 
                 return eval_const_expressions_mutator((Node *) phv->phexpr,
                                                       context);
             }
             break;
         default:
             break;
     }
 
     
     return ece_generic_processing(node);
 }

simplify_function

 
 static Expr *
 simplify_function(Oid funcid, Oid result_type, int32 result_typmod,
                   Oid result_collid, Oid input_collid, List **args_p,
                   bool funcvariadic, bool process_args, bool allow_non_const,
                   eval_const_expressions_context *context)
 {
     List       *args = *args_p;
     HeapTuple   func_tuple;
     Form_pg_proc func_form;
     Expr       *newexpr;
 
     
     //查询proc(视为Tuple) 
     func_tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
     if (!HeapTupleIsValid(func_tuple))
         elog(ERROR, "cache lookup failed for function %u", funcid);
     //从Tuple中分解得到函数体
     func_form = (Form_pg_proc) GETSTRUCT(func_tuple);
 
     
     if (process_args)//参数不为空
     {
         args = expand_function_arguments(args, result_type, func_tuple);//展开参数
         args = (List *) expression_tree_mutator((Node *) args,
                                                 eval_const_expressions_mutator,
                                                 (void *) context);//递归处理
         
         *args_p = args;//重新赋值
     }
 
     
 
     newexpr = evaluate_function(funcid, result_type, result_typmod,
                                 result_collid, input_collid,
                                 args, funcvariadic,
                                 func_tuple, context);//对函数进行预求解
     //求解成功并且允许非Const值并且(func_form->protransform是合法的Oid
     if (!newexpr && allow_non_const && OidIsValid(func_form->protransform))
     {
         
         FuncExpr    fexpr;
 
         fexpr.xpr.type = T_FuncExpr;
         fexpr.funcid = funcid;
         fexpr.funcresulttype = result_type;
         fexpr.funcretset = func_form->proretset;
         fexpr.funcvariadic = funcvariadic;
         fexpr.funcformat = COERCE_EXPLICIT_CALL;
         fexpr.funccollid = result_collid;
         fexpr.inputcollid = input_collid;
         fexpr.args = args;
         fexpr.location = -1;
 
         newexpr = (Expr *)
             DatumGetPointer(OidFunctionCall1(func_form->protransform,
                                              PointerGetDatum(&fexpr)));
     }
 
     if (!newexpr && allow_non_const)
         newexpr = inline_function(funcid, result_type, result_collid,
                                   input_collid, args, funcvariadic,
                                   func_tuple, context);
 
     ReleaseSysCache(func_tuple);
 
     return newexpr;
 }

 
 static 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;
 
     
     estate = CreateExecutorState();
 
     
     oldcontext = MemoryContextSwitchTo(estate->es_query_cxt);
 
     
     fix_opfuncids((Node *) expr);
 
     
     //初始化表达式,为执行作准备
     //把函数放在exprstate->evalfunc中
     exprstate = ExecInitExpr(expr, NULL);
 
     
     const_val = ExecEvalExprSwitchContext(exprstate,
                                           GetPerTupleExprContext(estate),
                                           &const_is_null);//执行表达式求解
 
     
     get_typlenbyval(result_type, &resultTypLen, &resultTypByVal);
 
     
     MemoryContextSwitchTo(oldcontext);
 
     
     if (!const_is_null)
     {
         if (resultTypLen == -1)
             const_val = PointerGetDatum(PG_DETOAST_DATUM_COPY(const_val));
         else
             const_val = datumCopy(const_val, resultTypByVal, resultTypLen);
     }
 
     
     FreeExecutorState(estate);
 
     
     return (Expr *) makeConst(result_type, result_typmod, result_collation,
                               resultTypLen,
                               const_val, const_is_null,
                               resultTypByVal);
 }

 
 #ifndef FRONTEND
 static inline Datum
 ExecEvalExprSwitchContext(ExprState *state,
                           ExprContext *econtext,
                           bool *isNull)
 {
     Datum       retDatum;
     MemoryContext oldContext;
 
     oldContext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
     retDatum = state->evalfunc(state, econtext, isNull);
     MemoryContextSwitchTo(oldContext);
     return retDatum;
 }
 #endif

三、跟踪分析

测试脚本,表达式位于targetList中:

select max(a.dwbh::int+(1+2)) 
from t_dwxx a;

gdb跟踪:

Breakpoint 1, preprocess_expression (root=0x133eca8, expr=0x13441a8, kind=1) at planner.c:1007
1007        if (expr == NULL)
...
(gdb) p *(TargetEntry *)((List *)expr)->head->data.ptr_value
$6 = {xpr = {type = T_TargetEntry}, expr = 0x1343fb8, resno = 1, resname = 0x124bb38 "max", ressortgroupref = 0, 
  resorigtbl = 0, resoriGCol = 0, resjunk = false}
...
#OpExpr,参数args链表,第1个参数是1,第2个参数是2
(gdb) p *(Const *)$opexpr->args->head->data.ptr_value
$25 = {xpr = {type = T_Const}, consttype = 23, consttypmod = -1, constcollid = 0, constlen = 4, constvalue = 1, 
  constisnull = false, constbyval = true, location = 24}
(gdb) p *(Const *)$opexpr->args->tail->data.ptr_value
$26 = {xpr = {type = T_Const}, consttype = 23, consttypmod = -1, constcollid = 0, constlen = 4, constvalue = 2, 
  constisnull = false, constbyval = true, location = 26}
(gdb) 
#调整断点
(gdb) info break
Num     Type           Disp Enb Address            What
1       breakpoint     keep y   0x000000000076ac6f in preprocess_expression at planner.c:1007
    breakpoint already hit 8 times
(gdb) del 1
(gdb) b clauses.c:2713
Breakpoint 2 at 0x78952a: file clauses.c, line 2713.
(gdb) c
Continuing.

Breakpoint 2, eval_const_expressions_mutator (node=0x124cbf0, context=0x7ffebc48f630) at clauses.c:2716
2716                    set_opfuncid(expr);
#这个表达式是a.dwbh::int+(1+2)
(gdb) p *((OpExpr *)node)->args
$29 = {type = T_List, length = 2, head = 0x124cbd0, tail = 0x124cb80}
(gdb) p *(Node *)((OpExpr *)node)->args->head->data.ptr_value
$30 = {type = T_CoerceViaIO}
(gdb) c
Continuing.

Breakpoint 2, eval_const_expressions_mutator (node=0x124cb30, context=0x7ffebc48f630) at clauses.c:2716
2716                    set_opfuncid(expr);
#这个表达式是1+2,对此表达式进行求解
(gdb) p *(Node *)((OpExpr *)node)->args->head->data.ptr_value
$34 = {type = T_Const}
(gdb) p *(Const *)((OpExpr *)node)->args->head->data.ptr_value
$35 = {xpr = {type = T_Const}, consttype = 23, consttypmod = -1, constcollid = 0, constlen = 4, constvalue = 1, 
  constisnull = false, constbyval = true, location = 24}
#进入simplify_function
(gdb) step
simplify_function (funcid=177, result_type=23, result_typmod=-1, result_collid=0, input_collid=0, args_p=0x7ffebc48c838, 
    funcvariadic=false, process_args=true, allow_non_const=true, context=0x7ffebc48f630) at clauses.c:4022
4022        List       *args = *args_p; 
...
#函数是int4pl
(gdb) p *func_form
$38 = {proname = {data = "int4pl", '\000' <repeats 57 times>}, pronamespace = 11, proowner = 10, prolang = 12, procost = 1, 
  prorows = 0, provariadic = 0, protransform = 0, prokind = 102 'f', prosecdef = false, proleakproof = false, 
  proisstrict = true, proretset = false, provolatile = 105 'i', proparallel = 115 's', pronargs = 2, pronargdefaults = 0, 
  prorettype = 23, proargtypes = {vl_len_ = 128, ndim = 1, dataoffset = 0, elemtype = 26, dim1 = 2, lbound1 = 0, 
    values = 0x7fd820a599a4}}
...
#求解,得到结果为3
(gdb) p const_val
$48 = 3
(gdb) 
evaluate_function (funcid=177, result_type=23, result_typmod=-1, result_collid=0, input_collid=0, args=0x13135c8, 
    funcvariadic=false, func_tuple=0x7fd820a598d8, context=0x7ffebc48f630) at clauses.c:4424
4424    }
(gdb) 
simplify_function (funcid=177, result_type=23, result_typmod=-1, result_collid=0, input_collid=0, args_p=0x7ffebc48c838, 
    funcvariadic=false, process_args=true, allow_non_const=true, context=0x7ffebc48f630) at clauses.c:4067
4067        if (!newexpr && allow_non_const && OidIsValid(func_form->protransform))
(gdb) p *newexpr
$50 = {type = T_Const}
(gdb) p *(Const *)newexpr
$51 = {xpr = {type = T_Const}, consttype = 23, consttypmod = -1, constcollid = 0, constlen = 4, constvalue = 3, 
  constisnull = false, constbyval = true, location = -1}
...
#DONE!
#把1+2的T_OpExpr变换为T_Const

四、小结

1、简化过程:通过eval_const_expressions_mutator函数遍历相关节点,根据函数信息读取pg_proc中的函数并通过这些函数对表达式逐个处理;
2、表达式求解:通过调用evaluate_expr进而调用内置函数进行求解。

以上是“PostgreSQL中表达式预处理主要的函数有哪些”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注编程网数据库频道!

您可能感兴趣的文档:

--结束END--

本文标题: PostgreSQL中表达式预处理主要的函数有哪些

本文链接: https://www.lsjlt.com/news/64729.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • PostgreSQL中表达式预处理主要的函数有哪些
    这篇文章主要为大家展示了“PostgreSQL中表达式预处理主要的函数有哪些”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“PostgreSQL中表达式预处理主要...
    99+
    2022-10-18
  • JS中的正则表达式函数有哪些
    本篇内容主要讲解“JS中的正则表达式函数有哪些”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“JS中的正则表达式函数有哪些”吧!在JavaScript中,能够使用...
    99+
    2022-10-19
  • 生成正则表达式的函数有哪些
    生成正则表达式的函数有很多种,以下列举其中几种常见的:1. re.compile(pattern):将字符串 pattern 编译成...
    99+
    2023-05-25
    生成正则表达式 正则表达式
  • 数据库中通用函数和条件表达式有哪些
    这篇文章将为大家详细讲解有关数据库中通用函数和条件表达式有哪些,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。 一、通用函数 函数 说明 ...
    99+
    2022-10-19
  • PostgreSQL查询优化对表达式预处理中连接Var溯源的过程是什么
    本篇内容介绍了“PostgreSQL查询优化对表达式预处理中连接Var溯源的过程是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大...
    99+
    2022-10-19
  • Python中正则表达式及其常用匹配函数有哪些
    这篇文章主要介绍Python中正则表达式及其常用匹配函数有哪些,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配。/简介/Python 自1...
    99+
    2023-06-01
  • PostgreSQL中分区表查询相关的重要数据结构有哪些
    本篇内容介绍了“PostgreSQL中分区表查询相关的重要数据结构有哪些”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能...
    99+
    2022-10-18
  • Java8中需要知道的函数式接口有哪些
    这篇“Java8中需要知道的函数式接口有哪些”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Java8中需要知道的函数式接口有...
    99+
    2023-07-05
  • php中的异常处理函数有哪些
    php中的异常处理函数有set_exception_handler函数set_exception_handler函数作用:php中set_exception_handler函数的作用是用于创建运行期间的用户自己的异常处理方法。set_exc...
    99+
    2022-10-15
  • Java 大数据处理中常用的函数有哪些?
    随着数据量的不断增加,大数据处理已经成为了企业中不可或缺的一部分。在 Java 大数据处理中,一些常用的函数可以帮助开发人员更加高效地处理海量数据。本文将介绍 Java 大数据处理中常用的函数,并配以相应的演示代码。 一、MapReduc...
    99+
    2023-09-22
    大数据 shell 函数
  • 在微型计算机中微处理器的主要功能有哪些
    小编给大家分享一下在微型计算机中微处理器的主要功能有哪些,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!在微型计算机中,微处理器的主要功能是进行算术逻辑运算及全机的...
    99+
    2023-06-14
  • sql中的常用的字符串处理函数都有哪些
    sql中的常用的字符串处理函数都有哪些,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。具体内容如下所示:一、常用函数1、ASCII()返...
    99+
    2022-10-19
  • 大数据处理中的函数有哪些常见的应用场景?
    大数据处理是当今互联网时代的一个热门话题,越来越多的企业和组织开始使用大数据技术来处理海量的数据。而在大数据处理中,函数是一个非常重要的部分。下面我们将介绍一些大数据处理中常见的函数及其应用场景。 一、Map函数 Map函数是大数据处理中最...
    99+
    2023-09-22
    大数据 shell 函数
  • PHP中处理SQL查询结果的常用函数有哪些
    这篇文章主要为大家展示了“PHP中处理SQL查询结果的常用函数有哪些”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“PHP中处理SQL查询结果的常用函数有哪些”这篇文章吧。mysqli_fetch...
    99+
    2023-06-25
  • 计算机内部采用二进制运行和处理数据的主要原因有哪些
    这篇文章主要介绍计算机内部采用二进制运行和处理数据的主要原因有哪些,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!计算机内部运行和处理的数据是二进制。原因:1、计算机是由逻辑电路组成,逻辑电路通常只有两个状态,开关的接...
    99+
    2023-06-06
  • 分布式大数据处理中,ASP技术的优势有哪些?
    随着大数据时代的到来,数据处理变得越来越复杂,数据量越来越大。在这种情况下,传统的数据处理方法已经不能满足需求。为了解决这个问题,分布式大数据处理技术应运而生。在分布式大数据处理中,ASP(Apache Spark)技术是一种非常流行的技...
    99+
    2023-11-15
    分布式 大数据 leetcode
  • Python中有哪些强大的NumPy函数可以帮助您更好地处理数据?
    Python中的NumPy库是一个广泛使用的库,用于处理大型数组和矩阵。NumPy提供了许多强大的函数,可以帮助您更好地处理数据。在本文中,我们将介绍一些最常用的NumPy函数,以及它们如何帮助您更好地处理数据。 np.zeros n...
    99+
    2023-08-06
    numy 函数 bash
  • GO语言在分布式大数据处理中的应用场景有哪些?
    随着大数据时代的到来,数据量的快速增长和复杂性的提高,传统的单机处理方式已经无法满足我们的需求。因此,分布式大数据处理技术逐渐成为了处理海量数据的主流方案。而GO语言作为一门新兴的编程语言,不仅具有高效、安全、简洁等特点,还有着丰富的分布...
    99+
    2023-07-18
    分布式 大数据 npm
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作