文章详情

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

请输入下面的图形验证码

提交验证

短信预约提醒成功

PostgreSQL中Review exec_simple_query函数的实现逻辑是什么

2024-04-02 19:55

关注

这篇文章主要介绍“PostgreSQL中Review exec_simple_query函数的实现逻辑是什么”,在日常操作中,相信很多人在PostgreSQL中Review exec_simple_query函数的实现逻辑是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”PostgreSQL中Review exec_simple_query函数的实现逻辑是什么”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

源码解读

exec_simple_query函数由PostgresMain函数调用,其调用栈如下:

#3  0x00000000008c5c35 in exec_simple_query (query_string=0x2eed1a8 "select * from t1;") at postgres.c:1050
#4  0x00000000008ca0f8 in PostgresMain (argc=1, argv=0x2f16cb8, dbname=0x2f16b20 "testdb", username=0x2ee9d48 "xdb")
    at postgres.c:4159
#5  0x0000000000825880 in BackendRun (port=0x2f0eb00) at postmaster.c:4361
#6  0x0000000000824fe4 in BackendStartup (port=0x2f0eb00) at postmaster.c:4033
#7  0x0000000000821371 in ServerLoop () at postmaster.c:1706
#8  0x0000000000820c09 in PostmasterMain (argc=1, argv=0x2ee7d00) at postmaster.c:1379
#9  0x0000000000747ea7 in main (argc=1, argv=0x2ee7d00) at main.c:228

该函数的实现逻辑详见代码注释.



static void
exec_simple_query(const char *query_string)
{
    CommandDest dest = whereToSendOutput;//输出到哪里的定义
    MemoryContext oldcontext;//存储原内存上下文
    List       *parsetree_list;//分析树列表
    ListCell   *parsetree_item;//分析树中的ITEM
    bool        save_log_statement_stats = log_statement_stats;//是否保存统计信息,false
    bool        was_logged = false;//Log?
    bool        use_implicit_block;//是否使用隐式事务块
    char        msec_str[32];

    
    debug_query_string = query_string;

    pgstat_report_activity(STATE_RUNNING, query_string);//统计信息

    TRACE_POSTGRESQL_QUERY_START(query_string);

    
    if (save_log_statement_stats)
        ResetUsage();

    
    start_xact_command();//启动事务

    
    drop_unnamed_stmt();//清除未命名语句

    
    oldcontext = MemoryContextSwitchTo(MessageContext);//切换内存上下文

    
    parsetree_list = pg_parse_query(query_string);//解析输入的查询语句,获得解析树List(元素是RawStmt nodes)

    
    //如需要记录日志,则Log这些信息
    if (check_log_statement(parsetree_list))//日志记录
    {
        ereport(LOG,
                (errmsg("statement: %s", query_string),
                 errhidestmt(true),
                 errdetail_execute(parsetree_list)));
        was_logged = true;
    }

    
    MemoryContextSwitchTo(oldcontext);//切换回原内存上下文

    
    //如果分析树条目>1,使用隐式事务块(多条SQL语句在同一个事务中)
    use_implicit_block = (list_length(parsetree_list) > 1);

    
    foreach(parsetree_item, parsetree_list)//
    {
        RawStmt    *parsetree = lfirst_node(RawStmt, parsetree_item);//分析树List中的元素为RawStmt指针类型
        bool        snapshot_set = false;//是否设置快照?
        const char *commandTag;//命令标识
        char        completionTag[COMPLETION_TAG_BUFSIZE];//完成标记,如INSERT 0 1之类的字符串
        List       *querytree_list,//查询树List
                   *plantree_list;//执行计划List
        Portal      portal;//“门户”变量
        DestReceiver *receiver;//目标接收端
        int16       format;//

        
        commandTag = CreateCommandTag(parsetree->stmt);//创建命令标记,插入数据则为INSERT

        set_ps_display(commandTag, false);

        BeginCommand(commandTag, dest);//do Nothing!

        
        if (IsAbortedTransactionBlockState() &&
            !IsTransactionExitStmt(parsetree->stmt))
            ereport(ERROR,
                    (errcode(ERRCODE_IN_FAILED_SQL_TRANSACTION),
                     errmsg("current transaction is aborted, "
                            "commands ignored until end of transaction block"),
                     errdetail_abort()));

        
        start_xact_command();//确认在事务中

        
        if (use_implicit_block)
            BeginImplicitTransactionBlock();//隐式事务,进入事务块

        
        //如果在解析或者解析之前接收到取消的信号,则退出
        CHECK_FOR_INTERRUPTS();

        
        if (analyze_requires_snapshot(parsetree))//是否需要快照进行分析?增删改查均需要
        {
            PushActiveSnapshot(GetTransactionSnapshot());//活动快照入栈
            snapshot_set = true;
        }

        
        oldcontext = MemoryContextSwitchTo(MessageContext);//切换内存上下文
        //根据分析树获得查询树,返回List(元素为Query)
        querytree_list = pg_analyze_and_rewrite(parsetree, query_string,
                                                NULL, 0, NULL);
        //根据查询树获取计划树,返回List(元素为PlannedStmt)
        plantree_list = pg_plan_queries(querytree_list,
                                        CURSOR_OPT_PARALLEL_OK, NULL);

        
        //启用了快照,则出栈
        if (snapshot_set)
            PopActiveSnapshot();//

        
        //如接收到取消信号,则退出
        CHECK_FOR_INTERRUPTS();

        
        portal = CreatePortal("", true, true);//创建匿名Portal变量
        
        //该portal不在pg_cursors中出现
        portal->visible = false;

        
        PortalDefineQuery(portal,
                          NULL,
                          query_string,
                          commandTag,
                          plantree_list,
                          NULL);//给Portal变量赋值

        
        PortalStart(portal, NULL, 0, InvalidSnapshot);//为PortalRun作准备

        
        format = 0;             
        if (IsA(parsetree->stmt, FetchStmt))
        {
            FetchStmt  *stmt = (FetchStmt *) parsetree->stmt;

            if (!stmt->ismove)
            {
                Portal      fportal = GetPortalByName(stmt->portalname);

                if (PortalIsValid(fportal) &&
                    (fportal->cursorOptions & CURSOR_OPT_BINARY))
                    format = 1; 
            }
        }
        PortalSetResultFormat(portal, 1, &format);//设置结果返回的格式,默认为TEXT

        
        //创建目标接收器(如使用psql则为:printtup DestReceiver)
        receiver = CreateDestReceiver(dest);
        if (dest == DestRemote)
            SetRemoteDestReceiverParams(receiver, portal);

        
        MemoryContextSwitchTo(oldcontext);//

        
        (void) PortalRun(portal,
                         FETCH_ALL,
                         true,  
                         true,
                         receiver,
                         receiver,
                         completionTag);//执行
        //执行完毕,销毁接收器
        receiver->rDestroy(receiver);
        //清除Portal中的资源
        PortalDrop(portal, false);

        if (lnext(parsetree_item) == NULL)//所有语句已执行完毕
        {
            
            if (use_implicit_block)
                EndImplicitTransactionBlock();//结束事务
            finish_xact_command();//结束事务
        }
        else if (IsA(parsetree->stmt, TransactionStmt))//事务语句?BEGIN/COMMIT/ABORT...
        {
            
            finish_xact_command();
        }
        else
        {
            
            CommandCounterIncrement();//命令+1(对应Tuple中的cid)
        }

        
        EndCommand(completionTag, dest);//命令Done
    }                           
    
    //所有语句结束
    
    finish_xact_command();

    
    if (!parsetree_list)
        NullCommand(dest);

    
    switch (check_log_duration(msec_str, was_logged))
    {
        case 1:
            ereport(LOG,
                    (errmsg("duration: %s ms", msec_str),
                     errhidestmt(true)));
            break;
        case 2:
            ereport(LOG,
                    (errmsg("duration: %s ms  statement: %s",
                            msec_str, query_string),
                     errhidestmt(true),
                     errdetail_execute(parsetree_list)));
            break;
    }

    if (save_log_statement_stats)
        ShowUsage("QUERY STATISTICS");

    TRACE_POSTGRESQL_QUERY_DONE(query_string);

    debug_query_string = NULL;
}

到此,关于“PostgreSQL中Review exec_simple_query函数的实现逻辑是什么”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!

阅读原文内容投诉

免责声明:

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

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

软考中级精品资料免费领

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

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

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

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

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

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

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