Postgre SQL   发布时间:2022-05-20  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了PostgreSQL源码简单分析大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

POSTGResql源码简单分析(by linux_prog@loveopensource.com) POSTGResql是一个非常强大的开源数据库,既然使开源,当然,我们可以去修改他的代码做任何事情。最近,忙着设计一个分布式数据库系统,所以,理所当然,就想到了在PostgreSQl的基础上直接改。因此,分析其源代码就必不可少了。 简单讲一下分析内容。 源码目录: $ cd POSTGResql-8.2.4/src/BACkend/ $ ls access catalog executorlibpqMakefilenodes parserport postmasterrewritetcop bootstrapcommandslib main nls.mk optimizerpo POSTGResregex storageutils 其中:main/main.c是程序启动主文件 主文件没有作什么重要的事情,主要是作成为daemon等等一些我们并不关心的事情。 tcop/POSTGRes.c是BACkend执行入口文件。 请看第3414行: case /* simple query */ { const char *query_String; /* Set statement_timestamp() */ SetCurrentStatementStarttimestamp(); query_String = pq_getmsgString(&input_messagE); //拿到通过libpq传过来的sql语句 pq_getmsgend(&input_messagE); exec_simple_query(query_String); //执行这个sql,并把结果通过libpq返回 send_ready_for_query = true; } break; 再看看POSTGRes.c的第745行:static voIDexec_simple_query(const char *query_String){CommandDest dest = wheretoSendOutput;MemoryContext oldcontext;List *parsetree_List;ListCell *parsetree_item;boolsave_log_statement_stats = log_statement_stats;boolwas_logged = false;charmsec_str[32];/** Report query to varIoUs monitoring facilitIEs.*/deBUG_query_String = query_String;pgstat_report_activity(query_String);/** We use save_log_statement_stats so ShowUsage doesn’t report incorrect* results because resetUsage wasn’t called.*/if (save_log_statement_stats)resetUsage();/** Start up a transaction command. All querIEs generated by the* query_String will be in this same command block,*unless* we find a* BEGIN/COMMIT/ABORT statement; we have to force a new xact command after* one of those,else bad things will happen in xact.c. (Note that this* will normally change current memory context.)*/start_xact_command();/** Zap any pre-exisTing unnamed statement. (While not Strictly necessary,* it seems best to define simple-query mode as if it used the unnamed* statement and portal; this ensures we recover any storage used by prior* unnamed operations.)*/unnamed_stmt_pstmt = NulL;if (unnamed_stmt_context){DropDependentPortals(unnamed_stmt_context);MemoryContextdelete(unnamed_stmt_context);}unnamed_stmt_context = NulL;/** Switch to appropriate context for construcTing parsetrees.*/oldcontext = MemoryContextSwitchTo(messageContext);queryContext = CurrentMemoryContext;/** Do basic parsing of the query or querIEs (this should be safe even if* we are in aborted transaction state!)*/ // 解析这个sql语句到一个语法树结构中parsetree_List = pg_parse_query(query_String); 我想做的事情如下: 在PostgreSQl的基础上作一个分布式数据库,但sql parse和BACkend/frontend的通信都不想自己写, 也就是说要使用PostgreSQL的libpq。 因此做如下实验: 任何sql语句进来后,我会在exec_simple_query里面捷获,如果是一个SELEct语句, 我会返回一行记录:列名—name 列值– lijianghua 继续分析文件: src/access/common/printtup.c//以下函数使通过libpq发送返回的列的column 描述信息的voIDSendRowDescriptionmessage(TupleDesc typeinfo,List *targetList,int16 *formats){Form_@R_674_10900@ttribute *attrs = typeinfo->attrs;int natts = typeinfo->natts;int proto = pg_PROTOCol_MAJOR(FrontendProtocol);int i;StringInfoData buf;ListCell *tList_item = List_head(targetList);pq_beginmessage(&buf,‘T’); /* tuple descriptor message type */pq_sendint(&buf,natts,2); /* # of attrs in tuples */for (i = 0; i < natts; ++i){OID atttypID = attrs->atttypID;int32atttypmod = attrs->atttypmod;pq_sendString(&buf,nameStr(attrs->attName));/* column ID info appears in protocol 3.0 and up */if (proto >= 3){ /* Do we have a non-resjunk tList item? */ while (tList_item && ((TargetEntry *) lfirst(tList_item))->resjunk) tList_item = lnext(tList_item); if (tList_item) { TargetEntry *tle = (TargetEntry *) lfirst(tList_item); pq_sendint(&buf,tle->resorigtbl,4); pq_sendint(&buf,tle->resorigcol,2); tList_item = lnext(tList_item); } else { /* No info available,so send zeroes */ pq_sendint(&buf,2); }}/* If column is a domain,send the base type and typmod instead */atttypID = getBaseTypeAndTypmod(atttypID,&atttypmod);pq_sendint(&buf,(int) atttypID,sizeof(atttypID));pq_sendint(&buf,attrs->attlen,sizeof(attrs->attlen));/* typmod appears in protocol 2.0 and up */if (proto >= 2) pq_sendint(&buf,atttypmod,sizeof(atttypmod));/* format info appears in protocol 3.0 and up */if (proto >= 3){ if (formats) pq_sendint(&buf,formats,2); else pq_sendint(&buf,2);}}pq_endmessage(&buf);}//下面这个函数是SELEct返回的数据的值,每一行数据都会调用一下这个函数static voIDprinttup(TupletableSlot *slot,DestReceiver *self){TupleDesc typeinfo = slot->tts_tupleDescriptor;DR_printtup *myState = (DR_printtup *) self;StringInfoData buf;int natts = typeinfo->natts;int i;/* Set or update my derived attribute info,if needed */if (myState->attrinfo != typeinfo || myState->nattrs != natts)printtup_prepare_info(myState,typeinfo,natts);/* Make sure the tuple is fully deconstructed */slot_getallattrs(slot);/** Prepare a DaTarow message*/pq_beginmessage(&buf,‘D’);pq_sendint(&buf,2);/** send the attributes of this tuple*/for (i = 0; i < natts; ++i){PrinttupAttrInfo *thisstate = myState->myinfo + i;Datumorigattr = slot->tts_values,attr;if (slot->tts_isnull){ pq_sendint(&buf,-1,4); conTinue;}/* * If we have a toasted datum,forcibly detoast it here to avoid * memory leakage insIDe the type’s output routIne. */if (thisstate->typisvarlena) attr = PointerGetDatum(pg_DetoAST_DATUM(origattr));else attr = origattr;if (thisstate->format == 0){ /* Text output */ char *outputstr; outputstr = OutputFunctionCall(&thisstate->finfo,attr); pq_sendcountedtext(&buf,outputstr,strlen(outputstr),falsE); pfree(outputstr);}else{ /* Binary output */ bytea *outputbytes; outputbytes = SendFunctionCall(&thisstate->finfo,attr); pq_sendint(&buf,VARSIZE(outputbytes) - VARHDRSZ,4); pq_sendbytes(&buf,VARDATA(outputbytes),VARSIZE(outputbytes) - VARHDRSz); pfree(outputbytes);}/* Clean up detoasted copy,if any */if (attr != origattr) pfree(DatumGetPointer(attr));}pq_endmessage(&buf);}根据以上分析,我来修改exec_simple_query: 在833行加入如下内容: //此范例只处理SELEct语句 if(parsetree->type == T_SELEctStmt) { StringInfoData buf; pq_beginmessage(&buf,‘T’);/* tuple descriptor message type */ pq_sendint(&buf,1,2); /* number of columns in tuples */ pq_sendString(&buf,“name”); // column名称 pq_sendint(&buf,4); pq_sendint(&buf,2); pq_sendint(&buf,2,2); pq_endmessage(&buf); pq_beginmessage(&buf,‘D’); pq_sendint(&buf,2); pq_sendcountedtext(&buf,“lijianghua”,10,falsE); pq_endmessage(&buf); //此行必须加上,告诉libpq返回结果结束(C代表completed) pq_puttextmessage(’C',“SELEct return 1 rows”); return; } 修改结束,按照正常流程编译POSTGResql,并启动。 测试结果:[mypg@webtrends/copyright for diStribution terms /h for Help with sql commands /? for Help with psql commands /g or terminate with semicolon to execute query /q to quitmypg=# /dList of relations name ————lijianghua(1 row)mypg=# SELEct * FROM test2; name ————lijianghua(1 row)mypg=# SELEct * FROM test3; name ————lijianghua(1 row)mypg=# SELEct * FROM test5; name ————lijianghua(1 row) 可以看到任何SELEct语句都只返回我们预定义的结果,说明我们当初的想法是可行的(/d其实也是一个SELEct语句)。 下一目标是基于POSTGResql自己开发一个分布式数据库,有得忙了。

大佬总结

以上是大佬教程为你收集整理的PostgreSQL源码简单分析全部内容,希望文章能够帮你解决PostgreSQL源码简单分析所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。
标签:当然所以