簡單查詢和擴充查詢是PG前端和後端互動的時候,2種不同互動方法。簡單查詢時,前端發一個包含SQL的包過去,後端執行後傳回結果。擴充查詢則是把簡單查詢切分成Parse,Bind,Describe,Execute,Close等幾個步驟,以達到執行計劃複用的目的。擴充查詢還有防止SQL注入,減少通信資料量(使用binary形式傳參)的效果。
更詳細的描述,可參考手冊:
http://58.58.27.50:8079/doc/html/9.3.1_zh/protocol-flow.html#AEN98678
下面是服務端處理簡單查詢和擴充查詢的代碼概要
點選(此處)折疊或打開
exec_simple_query(const char *query_string)
->parsetree_list = pg_parse_query(query_string);
->foreach(parsetree_item, parsetree_list)
->querytree_list = pg_analyze_and_rewrite(parsetree, query_string,NULL, 0);
->plantree_list = pg_plan_queries(querytree_list, 0, NULL);
->portal = CreatePortal("", true, true);
->PortalDefineQuery(portal,NULL,query_string,commandTag,plantree_list,NULL);
->PortalStart(portal, NULL, 0, InvalidSnapshot);
->PortalRun(portal,FETCH_ALL,isTopLevel,receiver,receiver,completionTag);
->PortalDrop(portal, false);
parse消息的處理(命名語句):
exec_parse_message(const char *query_string,const char *stmt_name,Oid *paramTypes,int numParams)
->parsetree_list = pg_parse_query(query_string);
->raw_parse_tree = (Node *) linitial(parsetree_list);
->psrc = CreateCachedPlan(raw_parse_tree, query_string, commandTag);
->query = parse_analyze_varparams(raw_parse_tree,query_string,&paramTypes,&numParams);
->querytree_list = pg_rewrite_query(query);
->CompleteCachedPlan(psrc,querytree_list,unnamed_stmt_context,paramTypes,numParams,NULL,NULL,0,true);
->StorePreparedStatement(stmt_name, psrc, false);
bind消息的處理:
exec_bind_message(StringInfo input_message)
->portal_name = pq_getmsgstring(input_message);
->stmt_name = pq_getmsgstring(input_message);
->pstmt = FetchPreparedStatement(stmt_name, true);
->psrc = pstmt->plansource;
->cplan = GetCachedPlan(psrc, params, false);
->portal = CreatePortal(portal_name, true, true);
->PortalDefineQuery(portal,saved_stmt_name,query_string,psrc->commandTag,cplan->stmt_list,cplan);
->PortalStart(portal, params, 0, InvalidSnapshot);
GetCachedPlan()會決定新建立一個定制的執行計劃還是使用之前儲存的通用的執行計劃。
execute消息的處理:
exec_execute_message(const char *portal_name, long max_rows)
->portal = GetPortalByName(portal_name);
->completed = PortalRun(portal,max_rows,true,receiver,receiver,completionTag);
close消息的處理:
PostgresMain(int argc, char *argv[],const char *dbname,const char *username)
case 'C':
->DropPreparedStatement(close_target, false);
or
http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=20726500&id=4150218
src/backend/tcop/postgres.c