PostgreSQL Source Code: src/backend/executor/functions.c File Reference (original) (raw)

Go to the source code of this file.

Data Structures
struct DR_sqlfunction
struct execution_state
struct SQLFunctionHashEntry
struct SQLFunctionCache
Typedefs
typedef struct execution_state execution_state
typedef struct SQLFunctionHashEntry SQLFunctionHashEntry
typedef struct SQLFunctionCache SQLFunctionCache
typedef SQLFunctionCache * SQLFunctionCachePtr
static Node * sql_fn_param_ref (ParseState *pstate, ParamRef *pref)
static Node * sql_fn_post_column_ref (ParseState *pstate, ColumnRef *cref, Node *var)
static Node * sql_fn_make_param (SQLFunctionParseInfoPtr pinfo, int paramno, int location)
static Node * sql_fn_resolve_param_name (SQLFunctionParseInfoPtr pinfo, const char *paramname, int location)
static SQLFunctionCache * init_sql_fcache (FunctionCallInfo fcinfo, bool lazyEvalOK)
static bool init_execution_state (SQLFunctionCachePtr fcache)
static void prepare_next_query (SQLFunctionHashEntry *func)
static void sql_compile_callback (FunctionCallInfo fcinfo, HeapTuple procedureTuple, const CachedFunctionHashKey *hashkey, CachedFunction *cfunc, bool forValidator)
static void sql_delete_callback (CachedFunction *cfunc)
static void sql_postrewrite_callback (List *querytree_list, void *arg)
static void postquel_start (execution_state *es, SQLFunctionCachePtr fcache)
static bool postquel_getnext (execution_state *es, SQLFunctionCachePtr fcache)
static void postquel_end (execution_state *es, SQLFunctionCachePtr fcache)
static void postquel_sub_params (SQLFunctionCachePtr fcache, FunctionCallInfo fcinfo)
static Datum postquel_get_single_result (TupleTableSlot *slot, FunctionCallInfo fcinfo, SQLFunctionCachePtr fcache)
static void sql_compile_error_callback (void *arg)
static void sql_exec_error_callback (void *arg)
static void ShutdownSQLFunction (Datum arg)
static void RemoveSQLFunctionCache (void *arg)
static void check_sql_fn_statement (List *queryTreeList)
static bool check_sql_stmt_retval (List *queryTreeList, Oid rettype, TupleDesc rettupdesc, char prokind, bool insertDroppedCols)
static bool coerce_fn_result_column (TargetEntry *src_tle, Oid res_type, int32 res_typmod, bool tlist_is_modifiable, List **upper_tlist, bool *upper_tlist_nontrivial)
static List * get_sql_fn_result_tlist (List *queryTreeList)
static void sqlfunction_startup (DestReceiver *self, int operation, TupleDesc typeinfo)
static bool sqlfunction_receive (TupleTableSlot *slot, DestReceiver *self)
static void sqlfunction_shutdown (DestReceiver *self)
static void sqlfunction_destroy (DestReceiver *self)
SQLFunctionParseInfoPtr prepare_sql_fn_parse_info (HeapTuple procedureTuple, Node *call_expr, Oid inputCollation)
void sql_fn_parser_setup (struct ParseState *pstate, SQLFunctionParseInfoPtr pinfo)
Datum fmgr_sql (PG_FUNCTION_ARGS)
void check_sql_fn_statements (List *queryTreeLists)
bool check_sql_fn_retval (List *queryTreeLists, Oid rettype, TupleDesc rettupdesc, char prokind, bool insertDroppedCols)
DestReceiver * CreateSQLFunctionDestReceiver (void)

execution_state

SQLFunctionCache

SQLFunctionCachePtr

SQLFunctionHashEntry

ExecStatus

Enumerator
F_EXEC_START
F_EXEC_RUN
F_EXEC_DONE

Definition at line 63 of file functions.c.

check_sql_fn_retval()

bool check_sql_fn_retval ( List * queryTreeLists,
Oid rettype,
TupleDesc rettupdesc,
char prokind,
bool insertDroppedCols
)

Definition at line 2116 of file functions.c.

2120{

2121 List *queryTreeList;

2122

2123

2124

2125

2126

2127

2128

2129

2130

2131

2132

2133

2134

2135 if (queryTreeLists != NIL)

2137 else

2138 queryTreeList = NIL;

2139

2141 rettype, rettupdesc,

2142 prokind, insertDroppedCols);

2143}

static bool check_sql_stmt_retval(List *queryTreeList, Oid rettype, TupleDesc rettupdesc, char prokind, bool insertDroppedCols)

#define llast_node(type, l)

References check_sql_stmt_retval(), llast_node, and NIL.

Referenced by fmgr_sql_validator(), inline_function(), and inline_sql_function_in_from().

check_sql_fn_statement()

static void check_sql_fn_statement ( List * queryTreeList) static

Definition at line 2052 of file functions.c.

2053{

2055

2056 foreach(lc, queryTreeList)

2057 {

2059

2060

2061

2062

2063

2064

2065

2066

2069 {

2071

2074 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),

2075 errmsg("calling procedures with output arguments is not supported in SQL functions")));

2076 }

2077 }

2078}

int errcode(int sqlerrcode)

int errmsg(const char *fmt,...)

#define ereport(elevel,...)

if(TABLE==NULL||TABLE_index==NULL)

#define IsA(nodeptr, _type_)

#define lfirst_node(type, lc)

References CMD_UTILITY, Query::commandType, ereport, errcode(), errmsg(), ERROR, if(), IsA, lfirst_node, NIL, stmt, and Query::utilityStmt.

Referenced by check_sql_fn_statements(), prepare_next_query(), and sql_postrewrite_callback().

check_sql_fn_statements()

void check_sql_fn_statements ( List * queryTreeLists )

check_sql_stmt_retval()

static bool check_sql_stmt_retval ( List * queryTreeList, Oid rettype, TupleDesc rettupdesc, char prokind, bool insertDroppedCols ) static

Definition at line 2150 of file functions.c.

2153{

2154 bool is_tuple_result = false;

2157 List *tlist;

2158 int tlistlen;

2159 bool tlist_is_modifiable;

2160 char fn_typtype;

2161 List *upper_tlist = NIL;

2162 bool upper_tlist_nontrivial = false;

2164

2165

2166

2167

2168

2169 if (rettype == VOIDOID)

2170 return false;

2171

2172

2173

2174

2175

2176

2178 parse_cell = NULL;

2179 foreach(lc, queryTreeList)

2180 {

2182

2183 if (q->canSetTag)

2184 {

2186 parse_cell = lc;

2187 }

2188 }

2189

2190

2191

2192

2193

2194

2195

2196

2197

2198

2199

2200

2203 {

2204 tlist = parse->targetList;

2205

2206 tlist_is_modifiable = (parse->setOperations == NULL);

2207 }

2208 else if (parse &&

2213 parse->returningList)

2214 {

2215 tlist = parse->returningList;

2216

2217 tlist_is_modifiable = true;

2218 }

2219 else

2220 {

2221

2223 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),

2224 errmsg("return type mismatch in function declared to return %s",

2226 errdetail("Function's final statement must be SELECT or INSERT/UPDATE/DELETE/MERGE RETURNING.")));

2227 return false;

2228 }

2229

2230

2231

2232

2233

2234

2235

2236

2237

2238

2239

2240

2241

2242

2244

2246

2247 if (fn_typtype == TYPTYPE_BASE ||

2248 fn_typtype == TYPTYPE_DOMAIN ||

2249 fn_typtype == TYPTYPE_ENUM ||

2250 fn_typtype == TYPTYPE_RANGE ||

2251 fn_typtype == TYPTYPE_MULTIRANGE)

2252 {

2253

2254

2255

2256

2258

2259 if (tlistlen != 1)

2261 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),

2262 errmsg("return type mismatch in function declared to return %s",

2264 errdetail("Final statement must return exactly one column.")));

2265

2266

2268 Assert(!tle->resjunk);

2269

2271 tlist_is_modifiable,

2272 &upper_tlist,

2273 &upper_tlist_nontrivial))

2275 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),

2276 errmsg("return type mismatch in function declared to return %s",

2278 errdetail("Actual return type is %s.",

2280 }

2281 else if (fn_typtype == TYPTYPE_COMPOSITE || rettype == RECORDOID)

2282 {

2283

2284

2285

2286

2287

2288

2289

2290

2291

2292

2293

2294 int tupnatts;

2295 int tuplogcols;

2296 int colindex;

2297

2298

2299

2300

2301

2302

2303

2304

2305

2306

2307

2308

2309

2310

2311

2312

2313

2314

2315

2316

2317

2318

2319 if (tlistlen == 1 && prokind != PROKIND_PROCEDURE)

2320 {

2322

2323 Assert(!tle->resjunk);

2325 tlist_is_modifiable,

2326 &upper_tlist,

2327 &upper_tlist_nontrivial))

2328 {

2329

2330 goto tlist_coercion_finished;

2331 }

2332 }

2333

2334

2335

2336

2337

2338 if (rettupdesc == NULL)

2339 return true;

2340

2341

2342

2343

2344

2345

2346

2347 tupnatts = rettupdesc->natts;

2348 tuplogcols = 0;

2349 colindex = 0;

2350

2351 foreach(lc, tlist)

2352 {

2355

2356

2357 if (tle->resjunk)

2358 continue;

2359

2360 do

2361 {

2362 colindex++;

2363 if (colindex > tupnatts)

2365 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),

2366 errmsg("return type mismatch in function declared to return %s",

2368 errdetail("Final statement returns too many columns.")));

2370 if (attr->attisdropped && insertDroppedCols)

2371 {

2372 Expr *null_expr;

2373

2374

2376 -1,

2380 true,

2381 true );

2382 upper_tlist = lappend(upper_tlist,

2385 NULL,

2386 false));

2387 upper_tlist_nontrivial = true;

2388 }

2389 } while (attr->attisdropped);

2390 tuplogcols++;

2391

2393 attr->atttypid, attr->atttypmod,

2394 tlist_is_modifiable,

2395 &upper_tlist,

2396 &upper_tlist_nontrivial))

2398 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),

2399 errmsg("return type mismatch in function declared to return %s",

2401 errdetail("Final statement returns %s instead of %s at column %d.",

2404 tuplogcols)));

2405 }

2406

2407

2408 for (colindex++; colindex <= tupnatts; colindex++)

2409 {

2412 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),

2413 errmsg("return type mismatch in function declared to return %s",

2415 errdetail("Final statement returns too few columns.")));

2416 if (insertDroppedCols)

2417 {

2418 Expr *null_expr;

2419

2420

2422 -1,

2426 true,

2427 true );

2428 upper_tlist = lappend(upper_tlist,

2431 NULL,

2432 false));

2433 upper_tlist_nontrivial = true;

2434 }

2435 }

2436

2437

2438 is_tuple_result = true;

2439 }

2440 else

2442 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),

2443 errmsg("return type %s is not supported for SQL functions",

2445

2446tlist_coercion_finished:

2447

2448

2449

2450

2451

2452

2453

2454 if (upper_tlist_nontrivial)

2455 {

2456 Query *newquery;

2457 List *colnames;

2460

2462

2463

2466 newquery->querySource = parse->querySource;

2467 newquery->canSetTag = true;

2469

2470

2471 colnames = NIL;

2472 foreach(lc, parse->targetList)

2473 {

2475

2476 if (tle->resjunk)

2477 continue;

2478 colnames = lappend(colnames,

2479 makeString(tle->resname ? tle->resname : ""));

2480 }

2481

2482

2486 rte->eref = makeAlias("unnamed_subquery", colnames);

2487 rte->lateral = false;

2488 rte->inh = false;

2489 rte->inFromCl = true;

2491

2495

2496

2497

2498

2499

2500 newquery->hasRowSecurity = parse->hasRowSecurity;

2501

2502

2503 lfirst(parse_cell) = newquery;

2504 }

2505

2506 return is_tuple_result;

2507}

int errdetail(const char *fmt,...)

int ExecCleanTargetListLength(List *targetlist)

char * format_type_be(Oid type_oid)

static bool coerce_fn_result_column(TargetEntry *src_tle, Oid res_type, int32 res_typmod, bool tlist_is_modifiable, List **upper_tlist, bool *upper_tlist_nontrivial)

Assert(PointerIsAligned(start, uint64))

List * lappend(List *list, void *datum)

char get_typtype(Oid typid)

Alias * makeAlias(const char *aliasname, List *colnames)

FromExpr * makeFromExpr(List *fromlist, Node *quals)

TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)

Const * makeConst(Oid consttype, int32 consttypmod, Oid constcollid, int constlen, Datum constvalue, bool constisnull, bool constbyval)

Oid exprType(const Node *expr)

FormData_pg_attribute * Form_pg_attribute

static int list_length(const List *l)

static struct subre * parse(struct vars *v, int stopper, int type, struct state *init, struct state *final)

static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)

static CompactAttribute * TupleDescCompactAttr(TupleDesc tupdesc, int i)

String * makeString(char *str)

References Assert(), CMD_DELETE, CMD_INSERT, CMD_MERGE, CMD_SELECT, CMD_UPDATE, coerce_fn_result_column(), Query::commandType, ereport, errcode(), errdetail(), errmsg(), ERROR, ExecCleanTargetListLength(), TargetEntry::expr, exprType(), format_type_be(), get_typtype(), RangeTblEntry::inh, InvalidOid, Query::jointree, lappend(), lfirst, lfirst_node, linitial, list_length(), list_make1, makeAlias(), makeConst(), makeFromExpr(), makeNode, makeString(), makeTargetEntry(), TupleDescData::natts, NIL, parse(), Query::rtable, RTE_SUBQUERY, RangeTblEntry::rtekind, RangeTblRef::rtindex, RangeTblEntry::subquery, Query::targetList, TupleDescAttr(), and TupleDescCompactAttr().

Referenced by check_sql_fn_retval(), prepare_next_query(), and sql_postrewrite_callback().

coerce_fn_result_column()

static bool coerce_fn_result_column ( TargetEntry * src_tle, Oid res_type, int32 res_typmod, bool tlist_is_modifiable, List ** upper_tlist, bool * upper_tlist_nontrivial ) static

Definition at line 2520 of file functions.c.

2526{

2528 Expr *new_tle_expr;

2529 Node *cast_result;

2530

2531

2532

2533

2534

2535

2536

2537 if (tlist_is_modifiable && src_tle->ressortgroupref == 0)

2538 {

2539

2543 res_type, res_typmod,

2546 -1);

2547 if (cast_result == NULL)

2548 return false;

2550 src_tle->expr = (Expr *) cast_result;

2551

2553 }

2554 else

2555 {

2556

2558

2560 (Node *) var,

2561 var->vartype,

2562 res_type, res_typmod,

2565 -1);

2566 if (cast_result == NULL)

2567 return false;

2569

2570 if (cast_result != (Node *) var)

2571 *upper_tlist_nontrivial = true;

2572 new_tle_expr = (Expr *) cast_result;

2573 }

2576 src_tle->resname, false);

2577 *upper_tlist = lappend(*upper_tlist, new_tle);

2578 return true;

2579}

Var * makeVarFromTargetEntry(int varno, TargetEntry *tle)

Node * coerce_to_target_type(ParseState *pstate, Node *expr, Oid exprtype, Oid targettype, int32 targettypmod, CoercionContext ccontext, CoercionForm cformat, int location)

void assign_expr_collations(ParseState *pstate, Node *expr)

References assign_expr_collations(), COERCE_IMPLICIT_CAST, coerce_to_target_type(), COERCION_ASSIGNMENT, TargetEntry::expr, exprType(), lappend(), list_length(), makeTargetEntry(), makeVarFromTargetEntry(), and TargetEntry::ressortgroupref.

Referenced by check_sql_stmt_retval().

CreateSQLFunctionDestReceiver()

Definition at line 2617 of file functions.c.

2618{

2620

2626

2627

2628

2630}

#define palloc0_object(type)

static void sqlfunction_startup(DestReceiver *self, int operation, TupleDesc typeinfo)

static bool sqlfunction_receive(TupleTableSlot *slot, DestReceiver *self)

static void sqlfunction_destroy(DestReceiver *self)

static void sqlfunction_shutdown(DestReceiver *self)

void(* rStartup)(DestReceiver *self, int operation, TupleDesc typeinfo)

void(* rShutdown)(DestReceiver *self)

bool(* receiveSlot)(TupleTableSlot *slot, DestReceiver *self)

void(* rDestroy)(DestReceiver *self)

References DestSQLFunction, _DestReceiver::mydest, palloc0_object, DR_sqlfunction::pub, _DestReceiver::rDestroy, _DestReceiver::receiveSlot, _DestReceiver::rShutdown, _DestReceiver::rStartup, sqlfunction_destroy(), sqlfunction_receive(), sqlfunction_shutdown(), and sqlfunction_startup().

Referenced by CreateDestReceiver().

fmgr_sql()

Definition at line 1576 of file functions.c.

1577{

1581 bool randomAccess;

1582 bool lazyEvalOK;

1583 bool pushed_snapshot;

1587

1588

1589 if (fcinfo->flinfo->fn_retset)

1590 {

1592

1593

1594

1595

1596

1597

1598

1603 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),

1604 errmsg("set-valued function called in context that cannot accept a set")));

1607

1609 }

1610 else

1611 {

1612 randomAccess = false;

1613 lazyEvalOK = true;

1614

1615 tscontext = NULL;

1616 }

1617

1618

1619

1620

1622

1623

1624 fcache->active = true;

1625

1626

1629

1630

1631

1632

1634 sqlerrcontext.arg = fcache;

1637

1638

1639

1640

1641

1642 do

1643 {

1644 es = fcache->eslist;

1646 es = es->next;

1647 if (es)

1648 break;

1650

1651

1652

1653

1654

1655

1656

1657

1658

1659

1660

1661

1662

1663

1664

1665

1666

1667

1668

1669 pushed_snapshot = false;

1670 while (es)

1671 {

1672 bool completed;

1673

1675 {

1676

1677

1678

1679

1680

1681

1683 {

1685 if (!pushed_snapshot)

1686 {

1688 pushed_snapshot = true;

1689 }

1690 else

1692 }

1693

1695 }

1697 {

1698

1700 pushed_snapshot = true;

1701 }

1702

1704

1705

1706

1707

1708

1709

1710

1711

1712

1713

1716

1717

1718

1719

1720

1721

1722

1723

1724

1725

1727 break;

1728

1729

1730

1731

1732 es = es->next;

1733 while (!es)

1734 {

1735

1736

1737

1738

1739

1740

1741 if (pushed_snapshot)

1742 {

1744 pushed_snapshot = false;

1745 }

1746

1748 break;

1749

1750 es = fcache->eslist;

1751 }

1752 }

1753

1754

1755

1756

1757

1759 {

1761

1762 if (es)

1763 {

1764

1765

1766

1767

1769

1773

1775

1776

1777

1778

1780

1781

1782

1783

1784

1786 {

1791 }

1792 }

1794 {

1795

1796

1797

1798

1800

1801 fcinfo->isnull = true;

1802 result = (Datum) 0;

1803

1804

1806 {

1811 }

1812 }

1813 else

1814 {

1815

1816

1817

1818

1819

1820

1821

1822

1823

1827 fcache->tstore = NULL;

1828

1831

1832 fcinfo->isnull = true;

1833 result = (Datum) 0;

1834

1835

1837 {

1842 }

1843 }

1844 }

1845 else

1846 {

1847

1848

1849

1851 {

1852

1856 else

1857 {

1858 fcinfo->isnull = true;

1859 result = (Datum) 0;

1860 }

1861 }

1862 else

1863 {

1864

1866 fcinfo->isnull = true;

1867 result = (Datum) 0;

1868 }

1869 }

1870

1871

1872 if (pushed_snapshot)

1874

1875

1876

1877

1878

1879 if (es == NULL)

1880 fcache->eslist = NULL;

1881

1882

1883 fcache->active = false;

1884

1886

1887 return result;

1888}

ErrorContextCallback * error_context_stack

void UnregisterExprContextCallback(ExprContext *econtext, ExprContextCallbackFunction function, Datum arg)

void RegisterExprContextCallback(ExprContext *econtext, ExprContextCallbackFunction function, Datum arg)

@ SFRM_Materialize_Preferred

@ SFRM_Materialize_Random

static Datum postquel_get_single_result(TupleTableSlot *slot, FunctionCallInfo fcinfo, SQLFunctionCachePtr fcache)

static bool postquel_getnext(execution_state *es, SQLFunctionCachePtr fcache)

static void postquel_start(execution_state *es, SQLFunctionCachePtr fcache)

static bool init_execution_state(SQLFunctionCachePtr fcache)

static void postquel_end(execution_state *es, SQLFunctionCachePtr fcache)

static void sql_exec_error_callback(void *arg)

static void ShutdownSQLFunction(Datum arg)

static SQLFunctionCache * init_sql_fcache(FunctionCallInfo fcinfo, bool lazyEvalOK)

static Datum PointerGetDatum(const void *X)

Snapshot GetTransactionSnapshot(void)

void PushActiveSnapshot(Snapshot snapshot)

void UpdateActiveSnapshotCommandId(void)

void PopActiveSnapshot(void)

struct ErrorContextCallback * previous

void(* callback)(void *arg)

MemoryContext ecxt_per_query_memory

TupleDesc jf_cleanTupType

TupleTableSlot * jf_resultSlot

SetFunctionReturnMode returnMode

Tuplestorestate * setResult

SQLFunctionHashEntry * func

struct execution_state * next

TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)

void CommandCounterIncrement(void)

References SQLFunctionCache::active, ReturnSetInfo::allowedModes, ErrorContextCallback::arg, Assert(), ErrorContextCallback::callback, CommandCounterIncrement(), CreateTupleDescCopy(), ReturnSetInfo::econtext, ExprContext::ecxt_per_query_memory, ereport, errcode(), errmsg(), ERROR, error_context_stack, SQLFunctionCache::eslist, ExprEndResult, ExprMultipleResult, F_EXEC_DONE, F_EXEC_START, SQLFunctionCache::func, GetTransactionSnapshot(), if(), init_execution_state(), init_sql_fcache(), IsA, ReturnSetInfo::isDone, JunkFilter::jf_cleanTupType, JunkFilter::jf_resultSlot, SQLFunctionCache::junkFilter, execution_state::lazyEval, SQLFunctionCache::lazyEval, execution_state::next, PointerGetDatum(), PopActiveSnapshot(), postquel_end(), postquel_get_single_result(), postquel_getnext(), postquel_start(), ErrorContextCallback::previous, PushActiveSnapshot(), execution_state::qd, SQLFunctionCache::randomAccess, SQLFunctionHashEntry::readonly_func, RegisterExprContextCallback(), SQLFunctionHashEntry::rettype, ReturnSetInfo::returnMode, SQLFunctionHashEntry::returnsSet, ReturnSetInfo::setDesc, ReturnSetInfo::setResult, SFRM_Materialize, SFRM_Materialize_Preferred, SFRM_Materialize_Random, SFRM_ValuePerCall, SQLFunctionCache::shutdown_reg, ShutdownSQLFunction(), QueryDesc::snapshot, sql_exec_error_callback(), execution_state::status, SQLFunctionCache::tscontext, SQLFunctionCache::tstore, TTS_EMPTY, UnregisterExprContextCallback(), and UpdateActiveSnapshotCommandId().

Referenced by fmgr_info_cxt_security().

get_sql_fn_result_tlist()

static List * get_sql_fn_result_tlist ( List * queryTreeList) static

init_execution_state()

Definition at line 653 of file functions.c.

654{

658 int nstmts;

660

661

662

663

664 if (fcache->cplan)

665 {

667 fcache->cplan = NULL;

668 }

669 fcache->eslist = NULL;

670

671

672

673

674

675

676

678 {

680 return false;

683 }

684 else

686

690

691

692

693

694

695

696

701 NULL);

702

703

704

705

708 {

709 if (fcache->esarray == NULL)

713 else

717 }

718

719

720

721

723 {

726

727

728

729

730

732 {

734 ((CopyStmt *) stmt->utilityStmt)->filename == NULL)

736 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),

737 errmsg("cannot COPY to/from client in an SQL function")));

738

741 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),

742

743 errmsg("%s is not allowed in an SQL function",

745 }

746

749 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),

750

751 errmsg("%s is not allowed in a non-volatile function",

753

754

756 if (preves)

757 preves->next = newes;

758 else

759 fcache->eslist = newes;

760

761 newes->next = NULL;

763 newes->setsResult = false;

764 newes->lazyEval = false;

766 newes->qd = NULL;

767

768 if (stmt->canSetTag)

769 lasttages = newes;

770

771 preves = newes;

772 }

773

774

775

776

777

779 return true;

780

781

782

783

784

785

786

787

788

789

790

791

792

793

797 {

799 List *resulttlist;

801

802

805 "SQL function junkfilter",

807 else

810

812

813

814

815

816

817

819

820

821

822

823

824

825

826

827

831 slot);

832 else

834

835

836

837

838

839

840

841

842

843

845

846

849

850

852

854 }

855

859 {

860

861

862

863

864

866 }

867

868

869

870

871

872

873

874

875

876

877

878

879

880

881

883 {

889 }

890

891 return true;

892}

JunkFilter * ExecInitJunkFilterConversion(List *targetList, TupleDesc cleanTupType, TupleTableSlot *slot)

JunkFilter * ExecInitJunkFilter(List *targetList, TupleTableSlot *slot)

TupleDesc BlessTupleDesc(TupleDesc tupdesc)

TupleTableSlot * MakeSingleTupleTableSlot(TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)

const TupleTableSlotOps TTSOpsMinimalTuple

#define repalloc_array(pointer, type, count)

static void prepare_next_query(SQLFunctionHashEntry *func)

static List * get_sql_fn_result_tlist(List *queryTreeList)

bool type_is_rowtype(Oid typid)

void * MemoryContextAlloc(MemoryContext context, Size size)

void MemoryContextReset(MemoryContext context)

#define AllocSetContextCreate

#define ALLOCSET_SMALL_SIZES

static MemoryContext MemoryContextSwitchTo(MemoryContext context)

#define foreach_current_index(var_or_cell)

static void * list_nth(const List *list, int n)

CachedPlan * GetCachedPlan(CachedPlanSource *plansource, ParamListInfo boundParams, ResourceOwner owner, QueryEnvironment *queryEnv)

void ReleaseCachedPlan(CachedPlan *plan, ResourceOwner owner)

ResourceOwner CurrentResourceOwner

execution_state * esarray

TupleDesc tts_tupleDescriptor

bool CommandIsReadOnly(PlannedStmt *pstmt)

static const char * CreateCommandName(Node *parsetree)

References ALLOCSET_SMALL_SIZES, AllocSetContextCreate, BlessTupleDesc(), CMD_SELECT, CMD_UTILITY, CommandIsReadOnly(), PlannedStmt::commandType, SQLFunctionCache::cowner, SQLFunctionCache::cplan, CreateCommandName(), CurrentResourceOwner, ereport, errcode(), errmsg(), ERROR, SQLFunctionCache::error_query_index, SQLFunctionCache::esarray, SQLFunctionCache::esarray_len, SQLFunctionCache::eslist, ExecInitJunkFilter(), ExecInitJunkFilterConversion(), F_EXEC_START, SQLFunctionCache::fcontext, foreach_current_index, SQLFunctionCache::func, CachedPlan::generation, get_sql_fn_result_tlist(), GetCachedPlan(), PlannedStmt::hasModifyingCTE, IsA, SQLFunctionCache::jf_generation, JunkFilter::jf_resultSlot, JunkFilter::jf_targetList, SQLFunctionCache::jfcontext, SQLFunctionCache::junkFilter, execution_state::lazyEval, SQLFunctionCache::lazyEval, SQLFunctionCache::lazyEvalOK, lfirst_node, list_length(), list_nth(), MakeSingleTupleTableSlot(), MemoryContextAlloc(), MemoryContextReset(), MemoryContextSwitchTo(), execution_state::next, SQLFunctionCache::next_query_index, NIL, SQLFunctionHashEntry::num_queries, SQLFunctionCache::paramLI, SQLFunctionHashEntry::plansource_list, prepare_next_query(), execution_state::qd, CachedPlanSource::query_list, SQLFunctionHashEntry::readonly_func, ReleaseCachedPlan(), repalloc_array, SQLFunctionHashEntry::rettupdesc, SQLFunctionHashEntry::rettype, SQLFunctionHashEntry::returnsSet, SQLFunctionHashEntry::returnsTuple, execution_state::setsResult, execution_state::status, execution_state::stmt, stmt, CachedPlan::stmt_list, TupleTableSlot::tts_tupleDescriptor, TTSOpsMinimalTuple, and type_is_rowtype().

Referenced by fmgr_sql().

init_sql_fcache()

Definition at line 536 of file functions.c.

537{

541

542

543

544

545

546

547

549 if (fcache == NULL)

550 {

555 fcache->mcb.arg = fcache;

558 }

559

560

561

562

563

564

565

567 {

568

569

570

571

572

573

574

575 fcache->cplan = NULL;

576 fcache->eslist = NULL;

577 fcache->tstore = NULL;

579 fcache->active = false;

580 }

581

582

583

584

585

586

587

588 if (fcache->eslist != NULL)

589 {

591 return fcache;

592 }

593

594

595

596

597

598

599

606 true,

607 false);

608

609

610

611

612

613

614

615 if (func != fcache->func)

616 {

617 if (fcache->func != NULL)

618 {

621 }

622 fcache->func = func;

624

626 }

627

628

629

630

631

633

634

637

638

639 fcache->eslist = NULL;

642

643 return fcache;

644}

CachedFunction * cached_function_compile(FunctionCallInfo fcinfo, CachedFunction *function, CachedFunctionCompileCallback ccallback, CachedFunctionDeleteCallback dcallback, Size cacheEntrySize, bool includeResultType, bool forValidator)

static void sql_delete_callback(CachedFunction *cfunc)

static void sql_compile_callback(FunctionCallInfo fcinfo, HeapTuple procedureTuple, const CachedFunctionHashKey *hashkey, CachedFunction *cfunc, bool forValidator)

static void postquel_sub_params(SQLFunctionCachePtr fcache, FunctionCallInfo fcinfo)

static void RemoveSQLFunctionCache(void *arg)

struct SQLFunctionHashEntry SQLFunctionHashEntry

void * MemoryContextAllocZero(MemoryContext context, Size size)

void MemoryContextRegisterResetCallback(MemoryContext context, MemoryContextCallback *cb)

MemoryContextCallbackFunction func

MemoryContextCallback mcb

References SQLFunctionCache::active, MemoryContextCallback::arg, Assert(), cached_function_compile(), SQLFunctionHashEntry::cfunc, SQLFunctionCache::cplan, SQLFunctionCache::error_query_index, SQLFunctionCache::eslist, SQLFunctionCache::fcontext, FunctionCallInfoBaseData::flinfo, FmgrInfo::fn_extra, FmgrInfo::fn_mcxt, SQLFunctionCache::func, MemoryContextCallback::func, SQLFunctionCache::junkFilter, SQLFunctionCache::lazyEval, SQLFunctionCache::lazyEvalOK, SQLFunctionCache::mcb, MemoryContextAllocZero(), MemoryContextRegisterResetCallback(), SQLFunctionCache::next_query_index, postquel_sub_params(), RemoveSQLFunctionCache(), SQLFunctionCache::shutdown_reg, sql_compile_callback(), sql_delete_callback(), SQLFunctionCache::tstore, and CachedFunction::use_count.

Referenced by fmgr_sql().

postquel_end()

Definition at line 1441 of file functions.c.

1442{

1444

1445

1447

1448

1450

1451

1453 {

1456 }

1457

1459

1461 es->qd = NULL;

1462

1464

1465

1469}

void ExecutorEnd(QueryDesc *queryDesc)

void ExecutorFinish(QueryDesc *queryDesc)

void MemoryContextDelete(MemoryContext context)

void FreeQueryDesc(QueryDesc *qdesc)

References CMD_UTILITY, QueryDesc::dest, ExecutorEnd(), ExecutorFinish(), F_EXEC_DONE, FreeQueryDesc(), MemoryContextDelete(), MemoryContextSwitchTo(), QueryDesc::operation, SQLFunctionCache::ownSubcontext, execution_state::qd, _DestReceiver::rDestroy, execution_state::status, and SQLFunctionCache::subcontext.

Referenced by fmgr_sql(), and ShutdownSQLFunction().

postquel_get_single_result()

Definition at line 1536 of file functions.c.

1539{

1541

1542

1543

1544

1545

1546

1547

1549 {

1550

1551 fcinfo->isnull = false;

1553 }

1554 else

1555 {

1556

1557

1558

1559

1561

1562 if (!fcinfo->isnull)

1564 }

1565

1566

1568

1570}

Datum datumCopy(Datum value, bool typByVal, int typLen)

Datum ExecFetchSlotHeapTupleDatum(TupleTableSlot *slot)

static Datum slot_getattr(TupleTableSlot *slot, int attnum, bool *isnull)

static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)

References datumCopy(), ExecClearTuple(), ExecFetchSlotHeapTupleDatum(), SQLFunctionCache::func, FunctionCallInfoBaseData::isnull, SQLFunctionHashEntry::returnsTuple, slot_getattr(), SQLFunctionHashEntry::typbyval, SQLFunctionHashEntry::typlen, and value.

Referenced by fmgr_sql().

postquel_getnext()

Definition at line 1400 of file functions.c.

1401{

1402 bool result;

1404

1405

1407

1409 {

1412 true,

1417 NULL);

1418 result = true;

1419 }

1420 else

1421 {

1422

1424

1426

1427

1428

1429

1430

1432 }

1433

1435

1436 return result;

1437}

void ExecutorRun(QueryDesc *queryDesc, ScanDirection direction, uint64 count)

PlannedStmt * plannedstmt

QueryEnvironment * queryEnv

void ProcessUtility(PlannedStmt *pstmt, const char *queryString, bool readOnlyTree, ProcessUtilityContext context, ParamListInfo params, QueryEnvironment *queryEnv, DestReceiver *dest, QueryCompletion *qc)

References CMD_UTILITY, QueryDesc::dest, EState::es_processed, QueryDesc::estate, ExecutorRun(), ForwardScanDirection, SQLFunctionCache::func, execution_state::lazyEval, MemoryContextSwitchTo(), QueryDesc::operation, QueryDesc::params, QueryDesc::plannedstmt, PROCESS_UTILITY_QUERY, ProcessUtility(), execution_state::qd, QueryDesc::queryEnv, SQLFunctionHashEntry::src, and SQLFunctionCache::subcontext.

Referenced by fmgr_sql().

postquel_start()

Definition at line 1276 of file functions.c.

1277{

1280

1282

1283

1285

1286

1287

1288

1289

1290

1291

1292

1293

1294

1295

1296

1298 {

1300 "SQL function execution",

1303 }

1305 {

1306

1307

1308

1309

1310

1311

1312

1313

1315 "SQL function execution",

1318 }

1319 else

1320 {

1323 }

1324

1325

1326

1327

1328

1330 {

1333 {

1337 }

1338 }

1339

1340

1342

1343

1344

1345

1346

1348 {

1350

1352

1355 myState->tstore = fcache->tstore;

1357

1358

1360 }

1361 else

1363

1371 0);

1372

1373

1375 {

1376

1377

1378

1379

1380

1381

1382

1383 int eflags;

1384

1387 else

1388 eflags = 0;

1390 }

1391

1393

1395}

DestReceiver * CreateDestReceiver(CommandDest dest)

DestReceiver * None_Receiver

void ExecutorStart(QueryDesc *queryDesc, int eflags)

#define EXEC_FLAG_SKIP_TRIGGERS

MemoryContext CurrentMemoryContext

#define ALLOCSET_DEFAULT_SIZES

QueryDesc * CreateQueryDesc(PlannedStmt *plannedstmt, const char *sourceText, Snapshot snapshot, Snapshot crosscheck_snapshot, DestReceiver *dest, ParamListInfo params, QueryEnvironment *queryEnv, int instrument_options)

bool ActiveSnapshotSet(void)

Snapshot GetActiveSnapshot(void)

Tuplestorestate * tuplestore_begin_heap(bool randomAccess, bool interXact, int maxKBytes)

References ActiveSnapshotSet(), ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, Assert(), CMD_UTILITY, PlannedStmt::commandType, CreateDestReceiver(), CreateQueryDesc(), CurrentMemoryContext, generate_unaccent_rules::dest, DestSQLFunction, EXEC_FLAG_SKIP_TRIGGERS, ExecClearTuple(), ExecutorStart(), F_EXEC_RUN, SQLFunctionCache::fcontext, DR_sqlfunction::filter, SQLFunctionCache::func, GetActiveSnapshot(), InvalidSnapshot, JunkFilter::jf_resultSlot, SQLFunctionCache::junkFilter, execution_state::lazyEval, MemoryContextSwitchTo(), _DestReceiver::mydest, None_Receiver, QueryDesc::operation, SQLFunctionCache::ownSubcontext, SQLFunctionCache::paramLI, DR_sqlfunction::pub, execution_state::qd, QueryDesc::queryEnv, SQLFunctionCache::randomAccess, SQLFunctionHashEntry::returnsSet, execution_state::setsResult, SQLFunctionHashEntry::src, execution_state::status, execution_state::stmt, SQLFunctionCache::subcontext, SQLFunctionCache::tscontext, DR_sqlfunction::tstore, SQLFunctionCache::tstore, tuplestore_begin_heap(), and work_mem.

Referenced by fmgr_sql().

postquel_sub_params()

Definition at line 1473 of file functions.c.

1475{

1476 int nargs = fcinfo->nargs;

1477

1478 if (nargs > 0)

1479 {

1483

1484 if (fcache->paramLI == NULL)

1485 {

1486

1488

1491 fcache->paramLI = paramLI;

1493 }

1494 else

1495 {

1496 paramLI = fcache->paramLI;

1498 }

1499

1500 for (int i = 0; i < nargs; i++)

1501 {

1503

1504

1505

1506

1507

1508

1509

1510

1511

1512

1513

1514

1515

1519 argtyplen[i]);

1520

1522 prm->ptype = argtypes[i];

1523 }

1524 }

1525 else

1527}

#define MakeExpandedObjectReadOnly(d, isnull, typlen)

ParamListInfo makeParamList(int numParams)

NullableDatum args[FLEXIBLE_ARRAY_MEMBER]

ParamExternData params[FLEXIBLE_ARRAY_MEMBER]

SQLFunctionParseInfoPtr pinfo

References FunctionCallInfoBaseData::args, SQLFunctionParseInfo::argtypes, SQLFunctionHashEntry::argtyplen, Assert(), SQLFunctionCache::fcontext, SQLFunctionCache::func, i, ParamExternData::isnull, NullableDatum::isnull, MakeExpandedObjectReadOnly, makeParamList(), MemoryContextSwitchTo(), FunctionCallInfoBaseData::nargs, ParamListInfoData::numParams, PARAM_FLAG_CONST, SQLFunctionCache::paramLI, ParamListInfoData::params, ParamExternData::pflags, SQLFunctionHashEntry::pinfo, ParamExternData::ptype, ParamExternData::value, and NullableDatum::value.

Referenced by init_sql_fcache().

prepare_next_query()

Definition at line 900 of file functions.c.

901{

902 int qindex;

903 bool islast;

905 List *queryTree_list;

907

908

910 Assert(qindex < func->num_queries);

911 islast = (qindex + 1 >= func->num_queries);

912

913

914

915

916

917

918

919

920

921

923 {

924

926

929 func->src,

933 }

934 else

935 {

936

938

941 func->src,

944 func->src,

947 NULL);

948 }

949

950

951

952

954

955

956

957

958

959

960

961

962

963

964

965

966

967

968

969

970

971

972

973 if (islast)

978 false);

979

980

981

982

983

985 queryTree_list,

986 NULL,

987 NULL,

988 0,

992 false);

993

994

995

996

997

1000 islast ? func : NULL);

1001

1002

1003

1004

1005

1009

1010

1011

1012

1013

1015

1016

1017

1018

1019

1020

1021 if (islast)

1022 {

1023 func->source_list = NIL;

1026 }

1027}

static void sql_postrewrite_callback(List *querytree_list, void *arg)

void sql_fn_parser_setup(struct ParseState *pstate, SQLFunctionParseInfoPtr pinfo)

void(* ParserSetupHook)(ParseState *pstate, void *arg)

#define CURSOR_OPT_PARALLEL_OK

#define CURSOR_OPT_NO_SCROLL

#define list_nth_node(type, list, n)

void SaveCachedPlan(CachedPlanSource *plansource)

void CompleteCachedPlan(CachedPlanSource *plansource, List *querytree_list, MemoryContext querytree_context, Oid *param_types, int num_params, ParserSetupHook parserSetup, void *parserSetupArg, int cursor_options, bool fixed_result)

CachedPlanSource * CreateCachedPlanForQuery(Query *analyzed_parse_tree, const char *query_string, CommandTag commandTag)

void SetPostRewriteHook(CachedPlanSource *plansource, PostRewriteHook postRewrite, void *postRewriteArg)

CachedPlanSource * CreateCachedPlan(RawStmt *raw_parse_tree, const char *query_string, CommandTag commandTag)

List * pg_analyze_and_rewrite_withcb(RawStmt *parsetree, const char *query_string, ParserSetupHook parserSetup, void *parserSetupArg, QueryEnvironment *queryEnv)

List * pg_rewrite_query(Query *query)

void AcquireRewriteLocks(Query *parsetree, bool forExecute, bool forUpdatePushedDown)

CommandTag CreateCommandTag(Node *parsetree)

References AcquireRewriteLocks(), Assert(), check_sql_fn_statement(), check_sql_stmt_retval(), CompleteCachedPlan(), copyObject, CreateCachedPlan(), CreateCachedPlanForQuery(), CreateCommandTag(), CURSOR_OPT_NO_SCROLL, CURSOR_OPT_PARALLEL_OK, SQLFunctionHashEntry::hcontext, lappend(), list_length(), list_nth_node, MemoryContextDelete(), MemoryContextSwitchTo(), NIL, SQLFunctionHashEntry::num_queries, SQLFunctionHashEntry::pcontext, pg_analyze_and_rewrite_withcb(), pg_rewrite_query(), SQLFunctionHashEntry::pinfo, SQLFunctionHashEntry::plansource_list, SQLFunctionHashEntry::prokind, SQLFunctionHashEntry::raw_source, SQLFunctionHashEntry::rettupdesc, SQLFunctionHashEntry::rettype, SQLFunctionHashEntry::returnsTuple, SaveCachedPlan(), SetPostRewriteHook(), SQLFunctionHashEntry::source_list, sql_fn_parser_setup(), sql_postrewrite_callback(), SQLFunctionHashEntry::src, and RawStmt::stmt.

Referenced by init_execution_state().

prepare_sql_fn_parse_info()

Definition at line 251 of file functions.c.

254{

257 int nargs;

258

260

261

263

264

265 pinfo->collation = inputCollation;

266

267

268

269

270

271 pinfo->nargs = nargs = procedureStruct->pronargs;

272 if (nargs > 0)

273 {

274 Oid *argOidVect;

275 int argnum;

276

277 argOidVect = (Oid *) palloc(nargs * sizeof(Oid));

278 memcpy(argOidVect,

279 procedureStruct->proargtypes.values,

280 nargs * sizeof(Oid));

281

282 for (argnum = 0; argnum < nargs; argnum++)

283 {

284 Oid argtype = argOidVect[argnum];

285

286 if (IsPolymorphicType(argtype))

287 {

291 (errcode(ERRCODE_DATATYPE_MISMATCH),

292 errmsg("could not determine actual type of argument declared %s",

294 argOidVect[argnum] = argtype;

295 }

296 }

297

298 pinfo->argtypes = argOidVect;

299 }

300

301

302

303

304 if (nargs > 0)

305 {

306 Datum proargnames;

307 Datum proargmodes;

308 int n_arg_names;

309 bool isNull;

310

311 proargnames = SysCacheGetAttr(PROCNAMEARGSNSP, procedureTuple,

312 Anum_pg_proc_proargnames,

313 &isNull);

314 if (isNull)

315 proargnames = PointerGetDatum(NULL);

316

317 proargmodes = SysCacheGetAttr(PROCNAMEARGSNSP, procedureTuple,

318 Anum_pg_proc_proargmodes,

319 &isNull);

320 if (isNull)

321 proargmodes = PointerGetDatum(NULL);

322

325

326

327 if (n_arg_names < nargs)

329 }

330 else

332

333 return pinfo;

334}

Oid get_call_expr_argtype(Node *expr, int argnum)

int get_func_input_arg_names(Datum proargnames, Datum proargmodes, char ***arg_names)

SQLFunctionParseInfo * SQLFunctionParseInfoPtr

static void * GETSTRUCT(const HeapTupleData *tuple)

char * pstrdup(const char *in)

FormData_pg_proc * Form_pg_proc

Datum SysCacheGetAttr(int cacheId, HeapTuple tup, AttrNumber attributeNumber, bool *isNull)

References SQLFunctionParseInfo::argnames, SQLFunctionParseInfo::argtypes, SQLFunctionParseInfo::collation, ereport, errcode(), errmsg(), ERROR, SQLFunctionParseInfo::fname, format_type_be(), get_call_expr_argtype(), get_func_input_arg_names(), GETSTRUCT(), InvalidOid, NameStr, SQLFunctionParseInfo::nargs, palloc(), palloc0_object, PointerGetDatum(), pstrdup(), and SysCacheGetAttr().

Referenced by fmgr_sql_validator(), inline_function(), inline_sql_function_in_from(), sql_compile_callback(), and test_inline_in_from_support_func().

RemoveSQLFunctionCache()

static void RemoveSQLFunctionCache ( void * arg) static

ShutdownSQLFunction()

static void ShutdownSQLFunction ( Datum arg) static

Definition at line 1967 of file functions.c.

1968{

1971

1972 es = fcache->eslist;

1973 while (es)

1974 {

1975

1977 {

1978

1981

1983

1986 }

1987 es = es->next;

1988 }

1989 fcache->eslist = NULL;

1990

1991

1994 fcache->tstore = NULL;

1995

1996

1997 if (fcache->cplan)

1999 fcache->cplan = NULL;

2000

2001

2003}

SQLFunctionCache * SQLFunctionCachePtr

static Pointer DatumGetPointer(Datum X)

void tuplestore_end(Tuplestorestate *state)

References arg, SQLFunctionCache::cowner, SQLFunctionCache::cplan, DatumGetPointer(), SQLFunctionCache::eslist, F_EXEC_RUN, SQLFunctionCache::func, execution_state::next, PopActiveSnapshot(), postquel_end(), PushActiveSnapshot(), execution_state::qd, SQLFunctionHashEntry::readonly_func, ReleaseCachedPlan(), SQLFunctionCache::shutdown_reg, QueryDesc::snapshot, execution_state::status, SQLFunctionCache::tstore, and tuplestore_end().

Referenced by fmgr_sql().

sql_compile_callback()

Definition at line 1040 of file functions.c.

1045{

1052 Oid rettype;

1055 bool isNull;

1056 List *source_list;

1057

1058

1059

1060

1061

1063 comperrcontext.arg = func;

1066

1067

1068

1069

1070

1072 "SQL function",

1074

1075

1076

1077

1078

1080 "SQL function parse trees",

1083

1084

1085

1086

1087

1089 NameStr(procedureStruct->proname));

1091

1092

1093

1094

1095

1097

1098 func->rettype = rettype;

1099 if (rettupdesc)

1100 {

1104 }

1105

1106

1108

1109

1110 func->returnsSet = procedureStruct->proretset;

1111

1112

1114 (procedureStruct->provolatile != PROVOLATILE_VOLATILE);

1115

1116

1117 func->prokind = procedureStruct->prokind;

1118

1119

1120

1121

1122

1123

1129

1130

1131

1132

1133

1138

1139

1140

1141

1145

1146

1148 procedureTuple,

1149 Anum_pg_proc_prosqlbody,

1150 &isNull);

1151 if (!isNull)

1152 {

1153

1155

1159 else

1162 }

1163 else

1164 {

1165

1168 }

1169

1170

1171

1172

1173

1175

1176

1177

1178

1179

1180

1181

1182 if (func->num_queries == 0 && rettype != VOIDOID)

1184 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),

1185 errmsg("return type mismatch in function declared to return %s",

1187 errdetail("Function's final statement must be SELECT or INSERT/UPDATE/DELETE/MERGE RETURNING.")));

1188

1189

1193

1194

1195

1196

1197

1198

1199

1202

1204}

#define TextDatumGetCString(d)

#define PG_GET_COLLATION()

TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo, Oid *resultTypeId, TupleDesc *resultTupleDesc)

static void sql_compile_error_callback(void *arg)

SQLFunctionParseInfoPtr prepare_sql_fn_parse_info(HeapTuple procedureTuple, Node *call_expr, Oid inputCollation)

void get_typlenbyval(Oid typid, int16 *typlen, bool *typbyval)

int16 get_typlen(Oid typid)

char * MemoryContextStrdup(MemoryContext context, const char *string)

void MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)

MemoryContext CacheMemoryContext

void MemoryContextSetIdentifier(MemoryContext context, const char *id)

#define castNode(_type_, nodeptr)

#define linitial_node(type, l)

List * pg_parse_query(const char *query_string)

void * stringToNode(const char *str)

Datum SysCacheGetAttrNotNull(int cacheId, HeapTuple tup, AttrNumber attributeNumber)

References ALLOCSET_SMALL_SIZES, AllocSetContextCreate, ErrorContextCallback::arg, SQLFunctionParseInfo::argtypes, SQLFunctionHashEntry::argtyplen, CacheMemoryContext, ErrorContextCallback::callback, castNode, copyObject, CreateTupleDescCopy(), CurrentMemoryContext, ereport, errcode(), errdetail(), errmsg(), ERROR, error_context_stack, FunctionCallInfoBaseData::flinfo, FmgrInfo::fn_expr, SQLFunctionHashEntry::fname, format_type_be(), get_call_result_type(), get_typlen(), get_typlenbyval(), GETSTRUCT(), SQLFunctionHashEntry::hcontext, i, IsA, linitial_node, list_length(), list_make1, MemoryContextAlloc(), MemoryContextSetIdentifier(), MemoryContextSetParent(), MemoryContextStrdup(), MemoryContextSwitchTo(), NameStr, SQLFunctionParseInfo::nargs, SQLFunctionHashEntry::num_queries, SQLFunctionHashEntry::pcontext, PG_GET_COLLATION, pg_parse_query(), SQLFunctionHashEntry::pinfo, prepare_sql_fn_parse_info(), ErrorContextCallback::previous, SQLFunctionHashEntry::prokind, SQLFunctionHashEntry::raw_source, SQLFunctionHashEntry::readonly_func, SQLFunctionHashEntry::rettupdesc, SQLFunctionHashEntry::rettype, SQLFunctionHashEntry::returnsSet, SQLFunctionHashEntry::source_list, sql_compile_error_callback(), SQLFunctionHashEntry::src, stringToNode(), SysCacheGetAttr(), SysCacheGetAttrNotNull(), TextDatumGetCString, SQLFunctionHashEntry::typbyval, and SQLFunctionHashEntry::typlen.

Referenced by init_sql_fcache().

sql_compile_error_callback()

static void sql_compile_error_callback ( void * arg) static

sql_delete_callback()

sql_exec_error_callback()

static void sql_exec_error_callback ( void * arg) static

Definition at line 1929 of file functions.c.

1930{

1932 int syntaxerrposition;

1933

1934

1935

1936

1938 if (syntaxerrposition > 0 && fcache->func->src != NULL)

1939 {

1943 }

1944

1945

1946

1947

1948

1950 errcontext("SQL function \"%s\" statement %d",

1952 else

1954}

References arg, errcontext, SQLFunctionCache::error_query_index, errposition(), SQLFunctionHashEntry::fname, SQLFunctionCache::func, geterrposition(), internalerrposition(), internalerrquery(), and SQLFunctionHashEntry::src.

Referenced by fmgr_sql().

sql_fn_make_param()

Definition at line 485 of file functions.c.

487{

489

492 param->paramid = paramno;

497

498

499

500

501

502

505

506 return (Node *) param;

507}

#define OidIsValid(objectId)

Oid get_typcollation(Oid typid)

References SQLFunctionParseInfo::argtypes, SQLFunctionParseInfo::collation, get_typcollation(), Param::location, makeNode, OidIsValid, PARAM_EXTERN, Param::paramcollid, Param::paramid, Param::paramkind, Param::paramtype, and Param::paramtypmod.

Referenced by sql_fn_param_ref(), and sql_fn_resolve_param_name().

sql_fn_param_ref()

sql_fn_parser_setup()

Definition at line 340 of file functions.c.

341{

345

347}

static Node * sql_fn_param_ref(ParseState *pstate, ParamRef *pref)

static Node * sql_fn_post_column_ref(ParseState *pstate, ColumnRef *cref, Node *var)

ParseParamRefHook p_paramref_hook

PreParseColumnRefHook p_pre_columnref_hook

PostParseColumnRefHook p_post_columnref_hook

References ParseState::p_paramref_hook, ParseState::p_post_columnref_hook, ParseState::p_pre_columnref_hook, ParseState::p_ref_hook_state, sql_fn_param_ref(), and sql_fn_post_column_ref().

Referenced by fmgr_sql_validator(), inline_function(), inline_sql_function_in_from(), interpret_AS_clause(), prepare_next_query(), and test_inline_in_from_support_func().

sql_fn_post_column_ref()

Definition at line 353 of file functions.c.

354{

356 int nnames;

357 Node *field1;

358 Node *subfield = NULL;

359 const char *name1;

360 const char *name2 = NULL;

362

363

364

365

366

367

368 if (var != NULL)

369 return NULL;

370

371

372

373

374

375

376

377

378

379

380

381

382

383

384

385

386

388

389 if (nnames > 3)

390 return NULL;

391

393 nnames--;

394

396 name1 = strVal(field1);

397 if (nnames > 1)

398 {

400 name2 = strVal(subfield);

401 }

402

403 if (nnames == 3)

404 {

405

406

407

408

409

410 if (strcmp(name1, pinfo->fname) != 0)

411 return NULL;

412

414

417 }

418 else if (nnames == 2 && strcmp(name1, pinfo->fname) == 0)

419 {

420

421

422

423

425

426 if (param)

427 {

428

429 subfield = NULL;

430 }

431 else

432 {

433

435 }

436 }

437 else

438 {

439

441 }

442

443 if (!param)

444 return NULL;

445

446 if (subfield)

447 {

448

449

450

451

452

457 NULL,

458 false,

460 }

461

462 return param;

463}

static Node * sql_fn_resolve_param_name(SQLFunctionParseInfoPtr pinfo, const char *paramname, int location)

Node * ParseFuncOrColumn(ParseState *pstate, List *funcname, List *fargs, Node *last_srf, FuncCall *fn, bool proc_call, int location)

References Assert(), ColumnRef::fields, SQLFunctionParseInfo::fname, if(), IsA, linitial, list_length(), list_make1, llast, ColumnRef::location, lsecond, lthird, ParseState::p_last_srf, ParseState::p_ref_hook_state, ParseFuncOrColumn(), sql_fn_resolve_param_name(), and strVal.

Referenced by sql_fn_parser_setup().

sql_fn_resolve_param_name()

sql_postrewrite_callback()

static void sql_postrewrite_callback ( List * querytree_list, void * arg ) static

Definition at line 1243 of file functions.c.

1244{

1245

1246

1247

1248

1249

1251

1252

1253

1254

1255

1256

1257 if (arg != NULL)

1258 {

1260 bool returnsTuple;

1261

1266 false);

1269 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),

1270 errmsg("cached plan must not change result type")));

1271 }

1272}

References arg, check_sql_fn_statement(), check_sql_stmt_retval(), ereport, errcode(), errmsg(), ERROR, SQLFunctionHashEntry::prokind, SQLFunctionHashEntry::rettupdesc, SQLFunctionHashEntry::rettype, and SQLFunctionHashEntry::returnsTuple.

Referenced by prepare_next_query().

sqlfunction_destroy()

static void sqlfunction_destroy ( DestReceiver * self) static

sqlfunction_receive()

sqlfunction_shutdown()

static void sqlfunction_shutdown ( DestReceiver * self) static

sqlfunction_startup()