PostgreSQL中的User subroutines有什么作用
本篇内容介绍了“PostgreSQL中的User subroutines有什么作用”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!
Flex输入文件由四部分组成:
%{Declarations%}Definitions%%Rules%%UsersubroutinesUser subroutines
在规则之后是自定义例程,在scan.l中定义的例程主要是对输入的SQL语句进行解析以及执行初始化和事后清理工作等.
/*LCOV_EXCL_STOP*//**Arrangeaccesstoyyextraforsubroutinesofthemainyylex()function.*Weexpecteachsubroutinetohaveayyscannerparameter.Ratherthan*usetheyyget_xxxfunctions,whichmightormightnotgetinlinedbythe*compiler,wecheatjustabitandcastyyscannertotherighttype.*为主yylex()函数提供yyextra的访问.*我们期望每一个子例程都有参数:yyscanner.*相对于使用yyget_xxx函数(可能或不可能被编译器内联),我们强制yyscanner为正确的类型.*/#undefyyextra#defineyyextra(((structyyguts_t*)yyscanner)->yyextra_r)/*Likewiseforacoupleofotherthingsweneed.*///定义其他需要的东西:yylloc/yyleng#undefyylloc#defineyylloc(((structyyguts_t*)yyscanner)->yylloc_r)#undefyyleng#defineyyleng(((structyyguts_t*)yyscanner)->yyleng_r)/**scanner_errposition*Reportalexerorgrammarerrorcursorposition,ifpossible.*scanner_errposition:如可以,报告词法或语法错误位置**Thisisexpectedtobeusedwithinanereport()call.Thereturnvalue*isadummy(always0,infact).*该例程在ereport()调用中使用.返回值是伪列(实际上通常为0).**Notethatthiscanonlybeusedformessagesemittedduringrawparsing*(essentially,scan.landgram.y),sinceitrequirestheyyscannerstruct*tostillbeavailable.*注意,这只能用于在原始解析期间产生的消息(scan.l&gram.y),*因为需要yyscanner结构体仍然可用才行.*/intscanner_errposition(intlocation,core_yyscan_tyyscanner){intpos;if(location<0)return0;/*no-opiflocationisunknown*//*Convertbyteoffsettocharacternumber*/pos=pg_mbstrlen_with_len(yyextra->scanbuf,location)+1;/*Andpassittotheereportmechanism*/returnerrposition(pos);}/**scanner_yyerror*Reportalexerorgrammarerror.*报告词法或语法错误.**Themessage'scursorpositioniswhateverYYLLOCwaslastsetto,*ie,thestartofthecurrenttokenifcalledwithinyylex(),orthe*mostrecentlylexedtokenifcalledfromthegrammar.*ThisisOKforsyntaxerrormessagesfromtheBisonparser,becauseBison*parsersreporterrorassoonasthefirstunparsabletokenisreached.*Bewareofusingyyerrorforotherpurposes,asthecursorpositionmight*bemisleading!*该消息游标的位置在于YYLLOC最后设置的地方,比如如果在yylex()中则是当前的token开始位置,*或者如果是grammer调用则为最近一次的词法token.*在Bison解析器中抛出语法错误是没有问题的,因为Bison及诶吸气在遇到第一个无法解析的token时就会报错.*注意:如果处于其他目的使用yyerror,这时候游标的位置可能会出现误导.*/voidscanner_yyerror(constchar*message,core_yyscan_tyyscanner){constchar*loc=yyextra->scanbuf+*yylloc;if(*loc==YY_END_OF_BUFFER_CHAR){ereport(ERROR,(errcode(ERRCODE_SYNTAX_ERROR),/*translator:%sistypicallythetranslationof"syntaxerror"*/errmsg("%satendofinput",_(message)),lexer_errposition()));}else{ereport(ERROR,(errcode(ERRCODE_SYNTAX_ERROR),/*translator:first%sistypicallythetranslationof"syntaxerror"*/errmsg("%satornear\"%s\"",_(message),loc),lexer_errposition()));}}/**Calledbeforeanyactualparsingisdone*初始化扫描器,在实际解析完成前调用*/core_yyscan_tscanner_init(constchar*str,core_yy_extra_type*yyext,constScanKeyword*keywords,intnum_keywords){Sizeslen=strlen(str);yyscan_tscanner;if(yylex_init(&scanner)!=0)elog(ERROR,"yylex_init()failed:%m");core_yyset_extra(yyext,scanner);yyext->keywords=keywords;yyext->num_keywords=num_keywords;yyext->backslash_quote=backslash_quote;yyext->escape_string_warning=escape_string_warning;yyext->standard_conforming_strings=standard_conforming_strings;/**Makeascanbufferwithspecialterminationneededbyflex.*/yyext->scanbuf=(char*)palloc(slen+2);yyext->scanbuflen=slen;memcpy(yyext->scanbuf,str,slen);yyext->scanbuf[slen]=yyext->scanbuf[slen+1]=YY_END_OF_BUFFER_CHAR;yy_scan_buffer(yyext->scanbuf,slen+2,scanner);/*initializeliteralbuffertoareasonablebutexpansiblesize*/yyext->literalalloc=1024;yyext->literalbuf=(char*)palloc(yyext->literalalloc);yyext->literallen=0;returnscanner;}/**Calledafterparsingisdonetocleanupafterscanner_init()*在解析完成后调用,用于在scanner_init()之后进行清理.*/voidscanner_finish(core_yyscan_tyyscanner){/**Wedon'tbothertocallyylex_destroy(),becauseallitwoulddois*pfreeasmallamountofcontrolstorage.It'scheapertoleakthe*storageuntiltheparsingcontextisdestroyed.Theamountofspace*involvedisusuallynegligiblecomparedtotheoutputparsetree*anyway.*不需要调用yylex_destroy(),因为所有需要做的事情只是释放一小块控制内存而已.*在解析上下文被销毁前,保留这部分内存成本会更低.*无论如何,与输出解析树相比,所涉及到的空间大小通常可以忽略不计.**Wedobothertopfreethescanbufandliteralbuffer,butonlyifthey*representanontrivialamountofspace.The8Kcutoffisarbitrary.*需要使用pfree释放扫描缓存和字面值缓存,但前提是它们代表了一个不小的空间才需要.*8K这个数值其实是很随意的.*/if(yyextra->scanbuflen>=8192)pfree(yyextra->scanbuf);if(yyextra->literalalloc>=8192)pfree(yyextra->literalbuf);}staticvoidaddlit(char*ytext,intyleng,core_yyscan_tyyscanner){/*enlargebufferifneeded*///增大缓存if((yyextra->literallen+yleng)>=yyextra->literalalloc){do{yyextra->literalalloc*=2;}while((yyextra->literallen+yleng)>=yyextra->literalalloc);yyextra->literalbuf=(char*)repalloc(yyextra->literalbuf,yyextra->literalalloc);}/*appendnewdata*///追加新数据memcpy(yyextra->literalbuf+yyextra->literallen,ytext,yleng);yyextra->literallen+=yleng;}staticvoidaddlitchar(unsignedcharychar,core_yyscan_tyyscanner){/*enlargebufferifneeded*/if((yyextra->literallen+1)>=yyextra->literalalloc){yyextra->literalalloc*=2;yyextra->literalbuf=(char*)repalloc(yyextra->literalbuf,yyextra->literalalloc);}/*appendnewdata*/yyextra->literalbuf[yyextra->literallen]=ychar;yyextra->literallen+=1;}/**Createapalloc'dcopyofliteralbuf,addingatrailingnull.*创建字面值缓存的拷贝,在末尾增加null.*/staticchar*litbufdup(core_yyscan_tyyscanner){intllen=yyextra->literallen;char*new;new=palloc(llen+1);memcpy(new,yyextra->literalbuf,llen);new[llen]='\0';returnnew;}staticintprocess_integer_literal(constchar*token,YYSTYPE*lval){//处理整型字面值intval;char*endptr;errno=0;val=strtoint(token,&endptr,10);if(*endptr!='\0'||errno==ERANGE){/*integertoolarge,treatitasafloat*/lval->str=pstrdup(token);returnFCONST;}lval->ival=val;returnICONST;}staticunsignedinthexval(unsignedcharc){//十六进制if(c>='0'&&c<='9')returnc-'0';if(c>='a'&&c<='f')returnc-'a'+0xA;if(c>='A'&&c<='F')returnc-'A'+0xA;elog(ERROR,"invalidhexadecimaldigit");return0;/*notreached*/}staticvoidcheck_unicode_value(pg_wcharc,char*loc,core_yyscan_tyyscanner){if(GetDatabaseEncoding()==PG_UTF8)return;if(c>0x7F){ADVANCE_YYLLOC(loc-yyextra->literalbuf+3);/*3forU&"*/yyerror("Unicodeescapevaluescannotbeusedforcodepointvaluesabove007FwhentheserverencodingisnotUTF8");}}staticboolis_utf16_surrogate_first(pg_wcharc){return(c>=0xD800&&c<=0xDBFF);}staticboolis_utf16_surrogate_second(pg_wcharc){return(c>=0xDC00&&c<=0xDFFF);}staticpg_wcharsurrogate_pair_to_codepoint(pg_wcharfirst,pg_wcharsecond){return((first&0x3FF)<<10)+0x10000+(second&0x3FF);}staticvoidaddunicode(pg_wcharc,core_yyscan_tyyscanner){charbuf[8];if(c==0||c>0x10FFFF)yyerror("invalidUnicodeescapevalue");if(c>0x7F){if(GetDatabaseEncoding()!=PG_UTF8)yyerror("Unicodeescapevaluescannotbeusedforcodepointvaluesabove007FwhentheserverencodingisnotUTF8");yyextra->saw_non_ascii=true;}unicode_to_utf8(c,(unsignedchar*)buf);addlit(buf,pg_mblen(buf),yyscanner);}/*is'escape'acceptableasUnicodeescapecharacter(UESCAPEsyntax)?*/staticboolcheck_uescapechar(unsignedcharescape){if(isxdigit(escape)||escape=='+'||escape=='\''||escape=='"'||scanner_isspace(escape)){returnfalse;}elsereturntrue;}/*likelitbufdup,buthandleunicodeescapes*/staticchar*litbuf_udeescape(unsignedcharescape,core_yyscan_tyyscanner){char*new;char*litbuf,*in,*out;pg_wcharpair_first=0;/*Makeliteralbufnull-terminatedtosimplifythescanningloop*/litbuf=yyextra->literalbuf;litbuf[yyextra->literallen]='\0';/**ThisreliesonthesubtleassumptionthataUTF-8expansioncannotbe*longerthanitsescapedrepresentation.*/new=palloc(yyextra->literallen+1);in=litbuf;out=new;while(*in){if(in[0]==escape){if(in[1]==escape){if(pair_first){ADVANCE_YYLLOC(in-litbuf+3);/*3forU&"*/yyerror("invalidUnicodesurrogatepair");}*out++=escape;in+=2;}elseif(isxdigit((unsignedchar)in[1])&&isxdigit((unsignedchar)in[2])&&isxdigit((unsignedchar)in[3])&&isxdigit((unsignedchar)in[4])){pg_wcharunicode;unicode=(hexval(in[1])<<12)+(hexval(in[2])<<8)+(hexval(in[3])<<4)+hexval(in[4]);check_unicode_value(unicode,in,yyscanner);if(pair_first){if(is_utf16_surrogate_second(unicode)){unicode=surrogate_pair_to_codepoint(pair_first,unicode);pair_first=0;}else{ADVANCE_YYLLOC(in-litbuf+3);/*3forU&"*/yyerror("invalidUnicodesurrogatepair");}}elseif(is_utf16_surrogate_second(unicode))yyerror("invalidUnicodesurrogatepair");if(is_utf16_surrogate_first(unicode))pair_first=unicode;else{unicode_to_utf8(unicode,(unsignedchar*)out);out+=pg_mblen(out);}in+=5;}elseif(in[1]=='+'&&isxdigit((unsignedchar)in[2])&&isxdigit((unsignedchar)in[3])&&isxdigit((unsignedchar)in[4])&&isxdigit((unsignedchar)in[5])&&isxdigit((unsignedchar)in[6])&&isxdigit((unsignedchar)in[7])){pg_wcharunicode;unicode=(hexval(in[2])<<20)+(hexval(in[3])<<16)+(hexval(in[4])<<12)+(hexval(in[5])<<8)+(hexval(in[6])<<4)+hexval(in[7]);check_unicode_value(unicode,in,yyscanner);if(pair_first){if(is_utf16_surrogate_second(unicode)){unicode=surrogate_pair_to_codepoint(pair_first,unicode);pair_first=0;}else{ADVANCE_YYLLOC(in-litbuf+3);/*3forU&"*/yyerror("invalidUnicodesurrogatepair");}}elseif(is_utf16_surrogate_second(unicode))yyerror("invalidUnicodesurrogatepair");if(is_utf16_surrogate_first(unicode))pair_first=unicode;else{unicode_to_utf8(unicode,(unsignedchar*)out);out+=pg_mblen(out);}in+=8;}else{ADVANCE_YYLLOC(in-litbuf+3);/*3forU&"*/yyerror("invalidUnicodeescapevalue");}}else{if(pair_first){ADVANCE_YYLLOC(in-litbuf+3);/*3forU&"*/yyerror("invalidUnicodesurrogatepair");}*out++=*in++;}}/*unfinishedsurrogatepair?*/if(pair_first){ADVANCE_YYLLOC(in-litbuf+3);/*3forU&"*/yyerror("invalidUnicodesurrogatepair");}*out='\0';/**Wecouldskippg_verifymbstrifwedidn'tprocessanynon-7-bit-ASCII*codes;butit'sprobablynotworththetrouble,sincethisisn'tlikely*tobeaperformance-criticalpath.*/pg_verifymbstr(new,out-new,false);returnnew;}staticunsignedcharunescape_single_char(unsignedcharc,core_yyscan_tyyscanner){switch(c){case'b':return'\b';case'f':return'\f';case'n':return'\n';case'r':return'\r';case't':return'\t';default:/*checkforbackslashfollowedbynon-7-bit-ASCII*/if(c=='\0'||IS_HIGHBIT_SET(c))yyextra->saw_non_ascii=true;returnc;}}staticvoidcheck_string_escape_warning(unsignedcharychar,core_yyscan_tyyscanner){if(ychar=='\''){if(yyextra->warn_on_first_escape&&yyextra->escape_string_warning)ereport(WARNING,(errcode(ERRCODE_NONSTANDARD_USE_OF_ESCAPE_CHARACTER),errmsg("nonstandarduseof\\'inastringliteral"),errhint("Use''towritequotesinstrings,orusetheescapestringsyntax(E'...')."),lexer_errposition()));yyextra->warn_on_first_escape=false;/*warnonlyonceperstring*/}elseif(ychar=='\\'){if(yyextra->warn_on_first_escape&&yyextra->escape_string_warning)ereport(WARNING,(errcode(ERRCODE_NONSTANDARD_USE_OF_ESCAPE_CHARACTER),errmsg("nonstandarduseof\\\\inastringliteral"),errhint("Usetheescapestringsyntaxforbackslashes,e.g.,E'\\\\'."),lexer_errposition()));yyextra->warn_on_first_escape=false;/*warnonlyonceperstring*/}elsecheck_escape_warning(yyscanner);}staticvoidcheck_escape_warning(core_yyscan_tyyscanner){if(yyextra->warn_on_first_escape&&yyextra->escape_string_warning)ereport(WARNING,(errcode(ERRCODE_NONSTANDARD_USE_OF_ESCAPE_CHARACTER),errmsg("nonstandarduseofescapeinastringliteral"),errhint("Usetheescapestringsyntaxforescapes,e.g.,E'\\r\\n'."),lexer_errposition()));yyextra->warn_on_first_escape=false;/*warnonlyonceperstring*/}/**Interfacefunctionstomakeflexusepalloc()insteadofmalloc().*It'dbebettertomakethesestatic,butflexinsistsotherwise.*/void*core_yyalloc(yy_size_tbytes,core_yyscan_tyyscanner){returnpalloc(bytes);}void*core_yyrealloc(void*ptr,yy_size_tbytes,core_yyscan_tyyscanner){if(ptr)returnrepalloc(ptr,bytes);elsereturnpalloc(bytes);}voidcore_yyfree(void*ptr,core_yyscan_tyyscanner){if(ptr)pfree(ptr);}
“PostgreSQL中的User subroutines有什么作用”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注亿速云网站,小编将为大家输出更多高质量的实用文章!
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。