文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

PostgreSQL怎么实现用户自定义

2024-04-02 19:55

关注

本篇内容介绍了“PostgreSQL怎么实现用户自定义”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!


Bison输入文件的组成:

%{
Declarations
%}
Definitions
%%
Productions
%%
User subroutines

一、User subroutines

用户自定义例程会原封不动的拷贝到gram.c文件中,详细请参考gram.c文件.

二、源码

下面是gram.y用户自定义部分的源码


static void
base_yyerror(YYLTYPE *yylloc, core_yyscan_t yyscanner, const char *msg)
{
    parser_yyerror(msg);
}
static RawStmt *
makeRawStmt(Node *stmt, int stmt_location)
{
    RawStmt    *rs = makeNode(RawStmt);
    rs->stmt = stmt;
    rs->stmt_location = stmt_location;
    rs->stmt_len = 0;            
    return rs;
}

static void
updateRawStmtEnd(RawStmt *rs, int end_location)
{
    
    if (rs->stmt_len > 0)
        return;
    
    rs->stmt_len = end_location - rs->stmt_location;
}
static Node *
makeColumnRef(char *colname, List *indirection,
              int location, core_yyscan_t yyscanner)
{
    
    ColumnRef  *c = makeNode(ColumnRef);
    int        nfields = 0;
    ListCell *l;
    c->location = location;
    foreach(l, indirection)
    {
        if (IsA(lfirst(l), A_Indices))
        {
            A_Indirection *i = makeNode(A_Indirection);
            if (nfields == 0)
            {
                
                c->fields = list_make1(makeString(colname));
                i->indirection = check_indirection(indirection, yyscanner);
            }
            else
            {
                
                i->indirection = check_indirection(list_copy_tail(indirection,
                                                                  nfields),
                                                   yyscanner);
                indirection = list_truncate(indirection, nfields);
                c->fields = lcons(makeString(colname), indirection);
            }
            i->arg = (Node *) c;
            return (Node *) i;
        }
        else if (IsA(lfirst(l), A_Star))
        {
            
            if (lnext(l) != NULL)
                parser_yyerror("improper use of \"*\"");
        }
        nfields++;
    }
    
    c->fields = lcons(makeString(colname), indirection);
    return (Node *) c;
}
static Node *
makeTypeCast(Node *arg, TypeName *typename, int location)
{
    TypeCast *n = makeNode(TypeCast);
    n->arg = arg;
    n->typeName = typename;
    n->location = location;
    return (Node *) n;
}
static Node *
makeStringConst(char *str, int location)
{
    A_Const *n = makeNode(A_Const);
    n->val.type = T_String;
    n->val.val.str = str;
    n->location = location;
    return (Node *)n;
}
static Node *
makeStringConstCast(char *str, int location, TypeName *typename)
{
    Node *s = makeStringConst(str, location);
    return makeTypeCast(s, typename, -1);
}
static Node *
makeIntConst(int val, int location)
{
    A_Const *n = makeNode(A_Const);
    n->val.type = T_Integer;
    n->val.val.ival = val;
    n->location = location;
    return (Node *)n;
}
static Node *
makeFloatConst(char *str, int location)
{
    A_Const *n = makeNode(A_Const);
    n->val.type = T_Float;
    n->val.val.str = str;
    n->location = location;
    return (Node *)n;
}
static Node *
makeBitStringConst(char *str, int location)
{
    A_Const *n = makeNode(A_Const);
    n->val.type = T_BitString;
    n->val.val.str = str;
    n->location = location;
    return (Node *)n;
}
static Node *
makeNullAConst(int location)
{
    A_Const *n = makeNode(A_Const);
    n->val.type = T_Null;
    n->location = location;
    return (Node *)n;
}
static Node *
makeAConst(Value *v, int location)
{
    Node *n;
    switch (v->type)
    {
        case T_Float:
            n = makeFloatConst(v->val.str, location);
            break;
        case T_Integer:
            n = makeIntConst(v->val.ival, location);
            break;
        case T_String:
        default:
            n = makeStringConst(v->val.str, location);
            break;
    }
    return n;
}

static Node *
makeBoolAConst(bool state, int location)
{
    A_Const *n = makeNode(A_Const);
    n->val.type = T_String;
    n->val.val.str = (state ? "t" : "f");
    n->location = location;
    return makeTypeCast((Node *)n, SystemTypeName("bool"), -1);
}

static RoleSpec *
makeRoleSpec(RoleSpecType type, int location)
{
    RoleSpec *spec = makeNode(RoleSpec);
    spec->roletype = type;
    spec->location = location;
    return spec;
}

static void
check_qualified_name(List *names, core_yyscan_t yyscanner)
{
    ListCell   *i;
    foreach(i, names)
    {
        if (!IsA(lfirst(i), String))
            parser_yyerror("syntax error");
    }
}

static List *
check_func_name(List *names, core_yyscan_t yyscanner)
{
    ListCell   *i;
    foreach(i, names)
    {
        if (!IsA(lfirst(i), String))
            parser_yyerror("syntax error");
    }
    return names;
}

static List *
check_indirection(List *indirection, core_yyscan_t yyscanner)
{
    ListCell *l;
    foreach(l, indirection)
    {
        if (IsA(lfirst(l), A_Star))
        {
            if (lnext(l) != NULL)
                parser_yyerror("improper use of \"*\"");
        }
    }
    return indirection;
}

static List *
extractArgTypes(List *parameters)
{
    List       *result = NIL;
    ListCell   *i;
    foreach(i, parameters)
    {
        FunctionParameter *p = (FunctionParameter *) lfirst(i);
        if (p->mode != FUNC_PARAM_OUT && p->mode != FUNC_PARAM_TABLE)
            result = lappend(result, p->argType);
    }
    return result;
}

static List *
extractAggrArgTypes(List *aggrargs)
{
    Assert(list_length(aggrargs) == 2);
    return extractArgTypes((List *) linitial(aggrargs));
}

static List *
makeOrderedSetArgs(List *directargs, List *orderedargs,
                   core_yyscan_t yyscanner)
{
    FunctionParameter *lastd = (FunctionParameter *) llast(directargs);
    int            ndirectargs;
    
    if (lastd->mode == FUNC_PARAM_VARIADIC)
    {
        FunctionParameter *firsto = (FunctionParameter *) linitial(orderedargs);
        
        if (list_length(orderedargs) != 1 ||
            firsto->mode != FUNC_PARAM_VARIADIC ||
            !equal(lastd->argType, firsto->argType))
            ereport(ERROR,
                    (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                     errmsg("an ordered-set aggregate with a VARIADIC direct argument must have one VARIADIC aggregated argument of the same data type"),
                     parser_errposition(exprLocation((Node *) firsto))));
        
        orderedargs = NIL;
    }
    
    ndirectargs = list_length(directargs);
    return list_make2(list_concat(directargs, orderedargs),
                      makeInteger(ndirectargs));
}

static void
insertSelectOptions(SelectStmt *stmt,
                    List *sortClause, List *lockingClause,
                    Node *limitOffset, Node *limitCount,
                    WithClause *withClause,
                    core_yyscan_t yyscanner)
{
    Assert(IsA(stmt, SelectStmt));
    
    if (sortClause)
    {
        if (stmt->sortClause)
            ereport(ERROR,
                    (errcode(ERRCODE_SYNTAX_ERROR),
                     errmsg("multiple ORDER BY clauses not allowed"),
                     parser_errposition(exprLocation((Node *) sortClause))));
        stmt->sortClause = sortClause;
    }
    
    stmt->lockingClause = list_concat(stmt->lockingClause, lockingClause);
    if (limitOffset)
    {
        if (stmt->limitOffset)
            ereport(ERROR,
                    (errcode(ERRCODE_SYNTAX_ERROR),
                     errmsg("multiple OFFSET clauses not allowed"),
                     parser_errposition(exprLocation(limitOffset))));
        stmt->limitOffset = limitOffset;
    }
    if (limitCount)
    {
        if (stmt->limitCount)
            ereport(ERROR,
                    (errcode(ERRCODE_SYNTAX_ERROR),
                     errmsg("multiple LIMIT clauses not allowed"),
                     parser_errposition(exprLocation(limitCount))));
        stmt->limitCount = limitCount;
    }
    if (withClause)
    {
        if (stmt->withClause)
            ereport(ERROR,
                    (errcode(ERRCODE_SYNTAX_ERROR),
                     errmsg("multiple WITH clauses not allowed"),
                     parser_errposition(exprLocation((Node *) withClause))));
        stmt->withClause = withClause;
    }
}
static Node *
makeSetOp(SetOperation op, bool all, Node *larg, Node *rarg)
{
    SelectStmt *n = makeNode(SelectStmt);
    n->op = op;
    n->all = all;
    n->larg = (SelectStmt *) larg;
    n->rarg = (SelectStmt *) rarg;
    return (Node *) n;
}

List *
SystemFuncName(char *name)
{
    return list_make2(makeString("pg_catalog"), makeString(name));
}

TypeName *
SystemTypeName(char *name)
{
    return makeTypeNameFromNameList(list_make2(makeString("pg_catalog"),
                                               makeString(name)));
}

static Node *
doNegate(Node *n, int location)
{
    if (IsA(n, A_Const))
    {
        A_Const *con = (A_Const *)n;
        
        con->location = location;
        if (con->val.type == T_Integer)
        {
            con->val.val.ival = -con->val.val.ival;
            return n;
        }
        if (con->val.type == T_Float)
        {
            doNegateFloat(&con->val);
            return n;
        }
    }
    return (Node *) makeSimpleA_Expr(AEXPR_OP, "-", NULL, n, location);
}
static void
doNegateFloat(Value *v)
{
    char   *oldval = v->val.str;
    Assert(IsA(v, Float));
    if (*oldval == '+')
        oldval++;
    if (*oldval == '-')
        v->val.str = oldval+1;    
    else
        v->val.str = psprintf("-%s", oldval);
}
static Node *
makeAndExpr(Node *lexpr, Node *rexpr, int location)
{
    Node       *lexp = lexpr;
    
    while (IsA(lexp, A_Expr) &&
           ((A_Expr *) lexp)->kind == AEXPR_PAREN)
        lexp = ((A_Expr *) lexp)->lexpr;
    
    if (IsA(lexp, BoolExpr))
    {
        BoolExpr *blexpr = (BoolExpr *) lexp;
        if (blexpr->boolop == AND_EXPR)
        {
            blexpr->args = lappend(blexpr->args, rexpr);
            return (Node *) blexpr;
        }
    }
    return (Node *) makeBoolExpr(AND_EXPR, list_make2(lexpr, rexpr), location);
}
static Node *
makeOrExpr(Node *lexpr, Node *rexpr, int location)
{
    Node       *lexp = lexpr;
    
    while (IsA(lexp, A_Expr) &&
           ((A_Expr *) lexp)->kind == AEXPR_PAREN)
        lexp = ((A_Expr *) lexp)->lexpr;
    
    if (IsA(lexp, BoolExpr))
    {
        BoolExpr *blexpr = (BoolExpr *) lexp;
        if (blexpr->boolop == OR_EXPR)
        {
            blexpr->args = lappend(blexpr->args, rexpr);
            return (Node *) blexpr;
        }
    }
    return (Node *) makeBoolExpr(OR_EXPR, list_make2(lexpr, rexpr), location);
}
static Node *
makeNotExpr(Node *expr, int location)
{
    return (Node *) makeBoolExpr(NOT_EXPR, list_make1(expr), location);
}
static Node *
makeAArrayExpr(List *elements, int location)
{
    A_ArrayExpr *n = makeNode(A_ArrayExpr);
    n->elements = elements;
    n->location = location;
    return (Node *) n;
}
static Node *
makeSQLValueFunction(SQLValueFunctionOp op, int32 typmod, int location)
{
    SQLValueFunction *svf = makeNode(SQLValueFunction);
    svf->op = op;
    
    svf->typmod = typmod;
    svf->location = location;
    return (Node *) svf;
}
static Node *
makeXmlExpr(XmlExprOp op, char *name, List *named_args, List *args,
            int location)
{
    XmlExpr        *x = makeNode(XmlExpr);
    x->op = op;
    x->name = name;
    
    x->named_args = named_args;
    x->arg_names = NIL;
    x->args = args;
    
    
    x->type = InvalidOid;            
    x->location = location;
    return (Node *) x;
}

static List *
mergeTableFuncParameters(List *func_args, List *columns)
{
    ListCell   *lc;
    
    foreach(lc, func_args)
    {
        FunctionParameter *p = (FunctionParameter *) lfirst(lc);
        if (p->mode != FUNC_PARAM_IN && p->mode != FUNC_PARAM_VARIADIC)
            ereport(ERROR,
                    (errcode(ERRCODE_SYNTAX_ERROR),
                     errmsg("OUT and INOUT arguments aren't allowed in TABLE functions")));
    }
    return list_concat(func_args, columns);
}

static TypeName *
TableFuncTypeName(List *columns)
{
    TypeName *result;
    if (list_length(columns) == 1)
    {
        FunctionParameter *p = (FunctionParameter *) linitial(columns);
        result = copyObject(p->argType);
    }
    else
        result = SystemTypeName("record");
    result->setof = true;
    return result;
}

static RangeVar *
makeRangeVarFromAnyName(List *names, int position, core_yyscan_t yyscanner)
{
    RangeVar *r = makeNode(RangeVar);
    switch (list_length(names))
    {
        case 1:
            r->catalogname = NULL;
            r->schemaname = NULL;
            r->relname = strVal(linitial(names));
            break;
        case 2:
            r->catalogname = NULL;
            r->schemaname = strVal(linitial(names));
            r->relname = strVal(lsecond(names));
            break;
        case 3:
            r->catalogname = strVal(linitial(names));
            r->schemaname = strVal(lsecond(names));
            r->relname = strVal(lthird(names));
            break;
        default:
            ereport(ERROR,
                    (errcode(ERRCODE_SYNTAX_ERROR),
                     errmsg("improper qualified name (too many dotted names): %s",
                            NameListToString(names)),
                     parser_errposition(position)));
            break;
    }
    r->relpersistence = RELPERSISTENCE_PERMANENT;
    r->location = position;
    return r;
}

static void
SplitColQualList(List *qualList,
                 List **constraintList, CollateClause **collClause,
                 core_yyscan_t yyscanner)
{
    ListCell   *cell;
    ListCell   *prev;
    ListCell   *next;
    *collClause = NULL;
    prev = NULL;
    for (cell = list_head(qualList); cell; cell = next)
    {
        Node   *n = (Node *) lfirst(cell);
        next = lnext(cell);
        if (IsA(n, Constraint))
        {
            
            prev = cell;
            continue;
        }
        if (IsA(n, CollateClause))
        {
            CollateClause *c = (CollateClause *) n;
            if (*collClause)
                ereport(ERROR,
                        (errcode(ERRCODE_SYNTAX_ERROR),
                         errmsg("multiple COLLATE clauses not allowed"),
                         parser_errposition(c->location)));
            *collClause = c;
        }
        else
            elog(ERROR, "unexpected node type %d", (int) n->type);
        
        qualList = list_delete_cell(qualList, cell, prev);
    }
    *constraintList = qualList;
}

static void
processCASbits(int cas_bits, int location, const char *constrType,
               bool *deferrable, bool *initdeferred, bool *not_valid,
               bool *no_inherit, core_yyscan_t yyscanner)
{
    
    if (deferrable)
        *deferrable = false;
    if (initdeferred)
        *initdeferred = false;
    if (not_valid)
        *not_valid = false;
    if (cas_bits & (CAS_DEFERRABLE | CAS_INITIALLY_DEFERRED))
    {
        if (deferrable)
            *deferrable = true;
        else
            ereport(ERROR,
                    (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                     
                     errmsg("%s constraints cannot be marked DEFERRABLE",
                            constrType),
                     parser_errposition(location)));
    }
    if (cas_bits & CAS_INITIALLY_DEFERRED)
    {
        if (initdeferred)
            *initdeferred = true;
        else
            ereport(ERROR,
                    (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                     
                     errmsg("%s constraints cannot be marked DEFERRABLE",
                            constrType),
                     parser_errposition(location)));
    }
    if (cas_bits & CAS_NOT_VALID)
    {
        if (not_valid)
            *not_valid = true;
        else
            ereport(ERROR,
                    (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                     
                     errmsg("%s constraints cannot be marked NOT VALID",
                            constrType),
                     parser_errposition(location)));
    }
    if (cas_bits & CAS_NO_INHERIT)
    {
        if (no_inherit)
            *no_inherit = true;
        else
            ereport(ERROR,
                    (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                     
                     errmsg("%s constraints cannot be marked NO INHERIT",
                            constrType),
                     parser_errposition(location)));
    }
}

static Node *
makeRecursiveViewSelect(char *relname, List *aliases, Node *query)
{
    SelectStmt *s = makeNode(SelectStmt);
    WithClause *w = makeNode(WithClause);
    CommonTableExpr *cte = makeNode(CommonTableExpr);
    List       *tl = NIL;
    ListCell   *lc;
    
    cte->ctename = relname;
    cte->aliascolnames = aliases;
    cte->ctequery = query;
    cte->location = -1;
    
    w->recursive = true;
    w->ctes = list_make1(cte);
    w->location = -1;
    
    foreach (lc, aliases)
    {
        ResTarget *rt = makeNode(ResTarget);
        rt->name = NULL;
        rt->indirection = NIL;
        rt->val = makeColumnRef(strVal(lfirst(lc)), NIL, -1, 0);
        rt->location = -1;
        tl = lappend(tl, rt);
    }
    
    s->withClause = w;
    s->targetList = tl;
    s->fromClause = list_make1(makeRangeVar(NULL, relname, -1));
    return (Node *) s;
}

void
parser_init(base_yy_extra_type *yyext)
{
    yyext->parsetree = NIL;        
}

“PostgreSQL怎么实现用户自定义”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注亿速云网站,小编将为大家输出更多高质量的实用文章!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-数据库
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯