pl_comp.c
来自「关系型数据库 Postgresql 6.5.2」· C语言 代码 · 共 1,370 行 · 第 1/3 页
C
1,370 行
/* ---------- * Create the magic found variable indicating if the * last FOR or SELECT statement returned data * ---------- */ var = malloc(sizeof(PLpgSQL_var)); memset(var, 0, sizeof(PLpgSQL_var)); var->dtype = PLPGSQL_DTYPE_VAR; var->refname = strdup("found"); var->lineno = 0; plpgsql_parse_word("bool"); var->datatype = plpgsql_yylval.dtype; var->isconst = false; var->notnull = false; var->default_val = NULL; plpgsql_adddatum((PLpgSQL_datum *) var); plpgsql_ns_additem(PLPGSQL_NSTYPE_VAR, var->varno, strdup("found")); function->found_varno = var->varno; /* ---------- * Forget about the above created variables * ---------- */ plpgsql_add_initdatums(NULL); /* ---------- * Now parse the functions text * ---------- */ parse_rc = plpgsql_yyparse(); if (parse_rc != 0) { plpgsql_comperrinfo(); elog(ERROR, "plpgsql: parser returned %d ???", parse_rc); } /* ---------- * If that was successful, complete the functions info. * ---------- */ function->fn_nargs = procStruct->pronargs; for (i = 0; i < function->fn_nargs; i++) function->fn_argvarnos[i] = arg_varnos[i]; function->ndatums = plpgsql_nDatums; function->datums = malloc(sizeof(PLpgSQL_datum *) * plpgsql_nDatums); for (i = 0; i < plpgsql_nDatums; i++) function->datums[i] = plpgsql_Datums[i]; function->action = plpgsql_yylval.program; /* ---------- * Finally return the compiled function * ---------- */ if (plpgsql_DumpExecTree) plpgsql_dumptree(function); return function;}/* ---------- * plpgsql_parse_word The scanner calls this to postparse * any single word not found by a * keyword rule. * ---------- */intplpgsql_parse_word(char *word){ PLpgSQL_nsitem *nse; char *cp; HeapTuple typeTup; Form_pg_type typeStruct; char *typeXlated; /* ---------- * We do our lookups case insensitive * ---------- */ cp = plpgsql_tolower(word); /* ---------- * Special handling when compiling triggers * ---------- */ if (plpgsql_curr_compile->fn_functype == T_TRIGGER) { if (!strcmp(cp, "tg_argv")) { int save_spacescanned = plpgsql_SpaceScanned; PLpgSQL_trigarg *trigarg; trigarg = malloc(sizeof(PLpgSQL_trigarg)); memset(trigarg, 0, sizeof(PLpgSQL_trigarg)); trigarg->dtype = PLPGSQL_DTYPE_TRIGARG; if (plpgsql_yylex() != '[') plpgsql_yyerror("expected ["); trigarg->argnum = plpgsql_read_expression(']', "]"); plpgsql_adddatum((PLpgSQL_datum *) trigarg); plpgsql_yylval.trigarg = trigarg; plpgsql_SpaceScanned = save_spacescanned; return T_TGARGV; } } /* ---------- * Do a lookup on the compilers namestack * ---------- */ nse = plpgsql_ns_lookup(cp, NULL); if (nse != NULL) { pfree(cp); switch (nse->itemtype) { case PLPGSQL_NSTYPE_LABEL: return T_LABEL; case PLPGSQL_NSTYPE_VAR: plpgsql_yylval.var = (PLpgSQL_var *) (plpgsql_Datums[nse->itemno]); return T_VARIABLE; case PLPGSQL_NSTYPE_REC: plpgsql_yylval.rec = (PLpgSQL_rec *) (plpgsql_Datums[nse->itemno]); return T_RECORD; case PLPGSQL_NSTYPE_ROW: plpgsql_yylval.row = (PLpgSQL_row *) (plpgsql_Datums[nse->itemno]); return T_ROW; default: return T_ERROR; } } /* ---------- * Try to find a data type with that name, but ignore * pg_type entries that are in fact class types. * ---------- */ typeXlated = xlateSqlType(cp); typeTup = SearchSysCacheTuple(TYPNAME, PointerGetDatum(typeXlated), 0, 0, 0); if (HeapTupleIsValid(typeTup)) { PLpgSQL_type *typ; typeStruct = (Form_pg_type) GETSTRUCT(typeTup); if (typeStruct->typrelid != InvalidOid) { pfree(cp); return T_WORD; } typ = (PLpgSQL_type *) malloc(sizeof(PLpgSQL_type)); typ->typname = strdup(nameout(&(typeStruct->typname))); typ->typoid = typeTup->t_data->t_oid; fmgr_info(typeStruct->typinput, &(typ->typinput)); typ->typbyval = typeStruct->typbyval; typ->atttypmod = -1; plpgsql_yylval.dtype = typ; pfree(cp); return T_DTYPE; } /* ---------- * Nothing found - up to now it's a word without any * special meaning for us. * ---------- */ pfree(cp); return T_WORD;}/* ---------- * plpgsql_parse_dblword Same lookup for two words * separated by a dot. * ---------- */intplpgsql_parse_dblword(char *string){ char *word1; char *word2; PLpgSQL_nsitem *ns; /* ---------- * Convert to lower case and separate the words * ---------- */ word1 = plpgsql_tolower(string); word2 = strchr(word1, '.'); *word2++ = '\0'; /* ---------- * Lookup the first word * ---------- */ ns = plpgsql_ns_lookup(word1, NULL); if (ns == NULL) { pfree(word1); return T_ERROR; } switch (ns->itemtype) { case PLPGSQL_NSTYPE_LABEL: /* ---------- * First word is a label, so second word could be * a variable, record or row in that bodies namestack. * Anything else could only be something in a query * given to the SPI manager and T_ERROR will get eaten * up by the collector routines. * ---------- */ ns = plpgsql_ns_lookup(word2, word1); if (ns == NULL) { pfree(word1); return T_ERROR; } switch (ns->itemtype) { case PLPGSQL_NSTYPE_VAR: plpgsql_yylval.var = (PLpgSQL_var *) (plpgsql_Datums[ns->itemno]); pfree(word1); return T_VARIABLE; case PLPGSQL_NSTYPE_REC: plpgsql_yylval.rec = (PLpgSQL_rec *) (plpgsql_Datums[ns->itemno]); pfree(word1); return T_RECORD; case PLPGSQL_NSTYPE_ROW: plpgsql_yylval.row = (PLpgSQL_row *) (plpgsql_Datums[ns->itemno]); pfree(word1); return T_ROW; default: pfree(word1); return T_ERROR; } case PLPGSQL_NSTYPE_REC: { /* ---------- * First word is a record name, so second word * must be a field in this record. * ---------- */ PLpgSQL_recfield *new; new = malloc(sizeof(PLpgSQL_recfield)); new->dtype = PLPGSQL_DTYPE_RECFIELD; new->fieldname = strdup(word2); new->recno = ns->itemno; plpgsql_adddatum((PLpgSQL_datum *) new); pfree(word1); plpgsql_yylval.recfield = new; return T_RECFIELD; } case PLPGSQL_NSTYPE_ROW: { /* ---------- * First word is a row name, so second word must * be a field in this row. * ---------- */ PLpgSQL_row *row; int i; row = (PLpgSQL_row *) (plpgsql_Datums[ns->itemno]); for (i = 0; i < row->nfields; i++) { if (!strcmp(row->fieldnames[i], word2)) { plpgsql_yylval.var = (PLpgSQL_var *) (plpgsql_Datums[row->varnos[i]]); pfree(word1); return T_VARIABLE; } } plpgsql_comperrinfo(); elog(ERROR, "row %s doesn't have a field %s", word1, word2); } default: break; } pfree(word1); return T_ERROR;}/* ---------- * plpgsql_parse_tripword Same lookup for three words * separated by dots. * ---------- */intplpgsql_parse_tripword(char *string){ char *word1; char *word2; char *word3; PLpgSQL_nsitem *ns; /* ---------- * Convert to lower case and separate the words * ---------- */ word1 = plpgsql_tolower(string); word2 = strchr(word1, '.'); *word2++ = '\0'; word3 = strchr(word2, '.'); *word3++ = '\0'; /* ---------- * Lookup the first word - it must be a label * ---------- */ ns = plpgsql_ns_lookup(word1, NULL); if (ns == NULL) { pfree(word1); return T_ERROR; } if (ns->itemtype != PLPGSQL_NSTYPE_LABEL) { pfree(word1); return T_ERROR; } /* ---------- * First word is a label, so second word could be * a record or row * ---------- */ ns = plpgsql_ns_lookup(word2, word1); if (ns == NULL) { pfree(word1); return T_ERROR; } switch (ns->itemtype) { case PLPGSQL_NSTYPE_REC: { /* ---------- * This word is a record name, so third word * must be a field in this record. * ---------- */ PLpgSQL_recfield *new; new = malloc(sizeof(PLpgSQL_recfield)); new->dtype = PLPGSQL_DTYPE_RECFIELD; new->fieldname = strdup(word3); new->recno = ns->itemno; plpgsql_adddatum((PLpgSQL_datum *) new); pfree(word1); plpgsql_yylval.recfield = new; return T_RECFIELD; } case PLPGSQL_NSTYPE_ROW: { /* ---------- * This word is a row name, so third word must * be a field in this row. * ---------- */ PLpgSQL_row *row; int i; row = (PLpgSQL_row *) (plpgsql_Datums[ns->itemno]); for (i = 0; i < row->nfields; i++) { if (!strcmp(row->fieldnames[i], word3)) { plpgsql_yylval.var = (PLpgSQL_var *) (plpgsql_Datums[row->varnos[i]]); pfree(word1); return T_VARIABLE; } } plpgsql_comperrinfo(); elog(ERROR, "row %s.%s doesn't have a field %s", word1, word2, word3); } default: break; } pfree(word1); return T_ERROR;}/* ---------- * plpgsql_parse_wordtype The scanner found word%TYPE. word can be * a variable name or a basetype. * ---------- */intplpgsql_parse_wordtype(char *word){ PLpgSQL_nsitem *nse; char *cp; HeapTuple typeTup; Form_pg_type typeStruct; char *typeXlated; bool old_nsstate; /* ---------- * We do our lookups case insensitive * ---------- */ cp = plpgsql_tolower(word); *(strchr(cp, '%')) = '\0'; /* ---------- * Do a lookup on the compilers namestack. * But ensure it moves up to the toplevel. * ---------- */ old_nsstate = plpgsql_ns_setlocal(false); nse = plpgsql_ns_lookup(cp, NULL); plpgsql_ns_setlocal(old_nsstate); if (nse != NULL) { pfree(cp); switch (nse->itemtype) { case PLPGSQL_NSTYPE_VAR: plpgsql_yylval.dtype = ((PLpgSQL_var *) (plpgsql_Datums[nse->itemno]))->datatype;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?