Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2951472
  • 博文数量: 199
  • 博客积分: 1400
  • 博客等级: 上尉
  • 技术积分: 4126
  • 用 户 组: 普通用户
  • 注册时间: 2008-07-06 19:06
个人简介

半个PostgreSQL DBA,热衷于数据库相关的技术。我的ppt分享https://pan.baidu.com/s/1eRQsdAa https://github.com/chenhuajun https://chenhuajun.github.io

文章分类

全部博文(199)

文章存档

2020年(5)

2019年(1)

2018年(12)

2017年(23)

2016年(43)

2015年(51)

2014年(27)

2013年(21)

2011年(1)

2010年(4)

2009年(5)

2008年(6)

分类: Mysql/postgreSQL

2015-01-15 19:42:29

简单查询和扩展查询是PG前端和后端交互的时候,2种不同交互方法。简单查询时,前端发一个包含SQL的包过去,后端执行后返回结果。扩展查询则是把简单查询切分成Parse,Bind,Describe,Execute,Close等几个步骤,以达到执行计划复用的目的。扩展查询还有防止SQL注入,减少通信数据量(使用binary形式传参)的效果。

更详细的描述,可参考手册:



下面是服务端处理简单查询和扩展查询的代码概要

1.简单查询

点击(此处)折叠或打开
  1. exec_simple_query(const char *query_string)
  2.  ->parsetree_list = pg_parse_query(query_string);
  3.  ->foreach(parsetree_item, parsetree_list)
  4.       ->querytree_list = pg_analyze_and_rewrite(parsetree, query_string,NULL, 0);
  5.       ->plantree_list = pg_plan_queries(querytree_list, 0, NULL);
  6.       ->portal = CreatePortal("", true, true);
  7.       ->PortalDefineQuery(portal,NULL,query_string,commandTag,plantree_list,NULL);
  8.       ->PortalStart(portal, NULL, 0, InvalidSnapshot);
  9.       ->PortalRun(portal,FETCH_ALL,isTopLevel,receiver,receiver,completionTag);
  10.       ->PortalDrop(portal, false);

2.扩展查询

parse消息的处理(命名语句):

点击(此处)折叠或打开

  1. exec_parse_message(const char *query_string,const char *stmt_name,Oid *paramTypes,int numParams)
  2.       ->parsetree_list = pg_parse_query(query_string);
  3.       ->raw_parse_tree = (Node *) linitial(parsetree_list);
  4.       ->psrc = CreateCachedPlan(raw_parse_tree, query_string, commandTag);
  5.       ->query = parse_analyze_varparams(raw_parse_tree,query_string,&paramTypes,&numParams);
  6.       ->querytree_list = pg_rewrite_query(query);
  7.       ->CompleteCachedPlan(psrc,querytree_list,unnamed_stmt_context,paramTypes,numParams,NULL,NULL,0,true);
  8.       ->StorePreparedStatement(stmt_name, psrc, false);

bind消息的处理:

点击(此处)折叠或打开

  1. exec_bind_message(StringInfo input_message)
  2.       ->portal_name = pq_getmsgstring(input_message);
  3.       ->stmt_name = pq_getmsgstring(input_message);
  4.       ->pstmt = FetchPreparedStatement(stmt_name, true);
  5.       ->psrc = pstmt->plansource;
  6.       ->cplan = GetCachedPlan(psrc, params, false);
  7.       ->portal = CreatePortal(portal_name, true, true);
  8.       ->PortalDefineQuery(portal,saved_stmt_name,query_string,psrc->commandTag,cplan->stmt_list,cplan);
  9.       ->PortalStart(portal, params, 0, InvalidSnapshot);
GetCachedPlan()会决定新创建一个定制的执行计划还是使用之前保存的通用的执行计划。

execute消息的处理:

点击(此处)折叠或打开

  1. exec_execute_message(const char *portal_name, long max_rows)
  2.       ->portal = GetPortalByName(portal_name);
  3.       ->completed = PortalRun(portal,max_rows,true,receiver,receiver,completionTag);

close消息的处理:

点击(此处)折叠或打开

  1. PostgresMain(int argc, char *argv[],const char *dbname,const char *username)
  2.   case 'C':
  3.       ->DropPreparedStatement(close_target, false);
  4.       or
  5.       ->PortalDrop(portal, false);

3.参考


http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=20726500&id=4150218
src/backend/tcop/postgres.c

阅读(4289) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~