How to realize the output of PostgreSQL
This article mainly introduces how to achieve PostgreSQL output, has a certain reference value, interested friends can refer to, I hope you can learn a lot after reading this article, the following let the editor take you to understand it.
I. output
Refer to the current_date function, first track its parse tree through the log, focusing on targetList
2019-04-19 17 testdb 06 CST 15.591 CST, "xdb", "testdb", 1693, "[local]", 5cb98b16.69dPower3, "SELECT", 2019-04-19 16:47:18 CST,3/4,0,LOG,00000, "parse tree:" "{QUERY: commandType 1...: targetList ({TARGETENTRY: expr {SQLVALUEFUNCTION: op 0: type 1082: typmod-1: location 7}: resno 1: resname current_date: ressortgroupref 0: resorigtbl 0: resorigcol 0: resjunk false}) ...: stmt_len 27}
Analyze the source code and find that the file related to the output is src/backend/parser/parse_target.c, and the related function is transformTargetEntry. Trace this function and print the call stack:
(gdb) bt#0 transformTargetEntry (pstate=0x16afae8, node=0x16af770, expr=0x0, exprKind=EXPR_KIND_SELECT_TARGET, colname=0x0, resjunk=false) at parse_target.c:93#1 0x000000000060b1f9 in transformTargetList (pstate=0x16afae8, targetlist=0x16af828, exprKind=EXPR_KIND_SELECT_TARGET) at parse_target.c:191#2 0x00000000005b1e3a in transformSelectStmt (pstate=0x16afae8, stmt=0x16af938) at analyze.c:1243#3 0x00000000005b03db in transformStmt (pstate=0x16afae8, parseTree=0x16af938) at analyze.c:301#4 0x00000000005b02b6 in transformOptionalSelectInto (pstate=0x16afae8, parseTree=0x16af938) at analyze.c:246#5 0x00000000005b0174 in transformTopLevelStmt ParseTree=0x16afa50) at analyze.c:196#6 0x00000000005affcc in parse_analyze (parseTree=0x16afa50, sourceText=0x16aed78 "select current_date from T1) ", paramTypes=0x0, numParams=0, queryEnv=0x0) at analyze.c:116#7 0x00000000008bb78c in pg_analyze_and_rewrite (parsetree=0x16afa50, query_string=0x16aed78" select current_date from T1; ", paramTypes=0x0, numParams=0, queryEnv=0x0) at postgres.c:689#8 0x00000000008bbddd in exec_simple_query (query_string=0x16aed78" select current_date from T1 At postgres.c:1070#9 0x00000000008c01f3 in PostgresMain (argc=1, argv=0x16dcd28, dbname=0x16dcb90 "testdb", username=0x16aba98 "xdb") at postgres.c:4182#10 0x000000000081e0ce in BackendRun (port=0x16d0b50) at postmaster.c:4361#11 0x000000000081d841 in BackendStartup (port=0x16d0b50) at postmaster.c:4033#12 0x0000000000819c3b in ServerLoop () at postmaster.c:1706#13 0x00000000008194f1 in PostmasterMain (argc=1, argv=0x16a9a50) at postmaster.c:1379#14 0x0000000000742993 in main (argc=1, argv=0x16a9a50) at main.c:228
Where the FigureColnameInternal function sets the output column name for current_date and adds the following code to achieve the output sysdate:
/ / Hacker: add the system column case SVFOP_ZZ_SYSDATE: * name = "sysdate"; / / zz_sysdate-> sysdate return 2
Interpretation of related source code
/ * transformTargetEntry () * Transform any ordinary "expression-type" node into a targetlist entry. * This is exported so that parse_clause.c can generate targetlist entries * for ORDER/GROUP BY items that are not already in the targetlist. * convert all normal expression type expression-type nodes to tagetlist entries. * TargetEntry as the output parameter so that parse_clause.c * can generate targetlist entries for items such as ORDER/GROUP BY that are not in targetlist * * node the (untransformed) parse tree for the value expression. * node untransformed value expression * * expr the transformed expression, or NULL if caller didn't do it yet. * expr converted expression. If the caller is not converted, it is NULL * * exprKind expression kind (EXPR_KIND_SELECT_TARGET, etc) * exprKind expression type (such as EXPR_KIND_SELECT_TARGET, etc.) * * colname the column name to be assigned, or NULL if none yet set. * the column name assigned by colname may be NULL * * resjunk true if the target should be marked resjunk, ie, it is not * wanted in the final projected tuple. * resjunk is T if the target should be marked as resjunk. For example, the column does not want to be projected as the final tuple * / TargetEntry * transformTargetEntry (ParseState * pstate, Node * node, Node * expr, ParseExprKind exprKind, char * colname). Bool resjunk) {/ * Transform the node if caller didn't do it already * / / expr is NULL, then the converted if (expr = = NULL) {/ * * If it's a SetToDefault node and we should allow that, pass it * through unmodified. (transformExpr will throw the appropriate * error if we're disallowing it.) * / if (exprKind = = EXPR_KIND_UPDATE_SOURCE & & IsA (node, SetToDefault)) expr = node; else expr = transformExpr (pstate, node, exprKind) } if (colname = = NULL & &! resjunk) {/ * Generate a suitable column name for a column without any explicit *'AS ColumnName' clause. * if the column name (AS ColumnName) is not explicitly specified, generate an appropriate column name * / colname = FigureColname (node);} / / return TargetEntry return makeTargetEntry ((Expr *) expr, (AttrNumber) pstate- > pairnextresnotations, colname, resjunk) } / * * FigureColname-* if the name of the resulting column is not specified in the target * list, we have to guess a suitable name. The SQL spec provides some * guidance, but not much... * * Note that the argument is the * untransformed* parse tree for the target * item. This is a shade easier to work with than the transformed tree. * / char * FigureColname (Node * node) {char * name = NULL; (void) FigureColnameInternal (node, & name); if (name! = NULL) return name; / * default result if we can't guess anything * / return "? column?" } / * FigureColnameInternal-* internal workhorse for FigureColname * * Return value indicates strength of confidence in result: * 0-no information * 1-second-best name choice * 2-good name choice * The return value is actually only used internally. * If the result isn't zero, * name is set to the chosen name. * / static intFigureColnameInternal (Node * node, char * * name) {int strength = 0; if (node = = NULL) return strength; switch (nodeTag (node)) {. Case T_SQLValueFunction: / * make these act like a function or variable * / switch (SQLValueFunction *) node)-> op) {case SVFOP_CURRENT_DATE: * name = "current_date"; return 2 . / / Hacker: add the system column case SVFOP_ZZ_SYSDATE: * name = "sysdate"; / / zz_sysdate-> sysdate return 2;} break .}} Thank you for reading this article carefully. I hope the article "how to achieve PostgreSQL output" shared by the editor will be helpful to everyone. At the same time, I also hope that you will support us and pay attention to the industry information channel. More related knowledge is waiting for you to learn!