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 62 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 2088 of file functions.c.

2092{

2093 List *queryTreeList;

2094

2095

2096

2097

2098

2099

2100

2101

2102

2103

2104

2105

2106

2107 if (queryTreeLists != NIL)

2109 else

2110 queryTreeList = NIL;

2111

2113 rettype, rettupdesc,

2114 prokind, insertDroppedCols);

2115}

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_set_returning_function().

check_sql_fn_statement()

static void check_sql_fn_statement ( List * queryTreeList) static

Definition at line 2024 of file functions.c.

2025{

2027

2028 foreach(lc, queryTreeList)

2029 {

2031

2032

2033

2034

2035

2036

2037

2038

2041 {

2043

2046 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),

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

2048 }

2049 }

2050}

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 2122 of file functions.c.

2125{

2126 bool is_tuple_result = false;

2129 List *tlist;

2130 int tlistlen;

2131 bool tlist_is_modifiable;

2132 char fn_typtype;

2133 List *upper_tlist = NIL;

2134 bool upper_tlist_nontrivial = false;

2136

2137

2138

2139

2140

2141 if (rettype == VOIDOID)

2142 return false;

2143

2144

2145

2146

2147

2148

2150 parse_cell = NULL;

2151 foreach(lc, queryTreeList)

2152 {

2154

2155 if (q->canSetTag)

2156 {

2158 parse_cell = lc;

2159 }

2160 }

2161

2162

2163

2164

2165

2166

2167

2168

2169

2170

2171

2172

2175 {

2176 tlist = parse->targetList;

2177

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

2179 }

2180 else if (parse &&

2185 parse->returningList)

2186 {

2187 tlist = parse->returningList;

2188

2189 tlist_is_modifiable = true;

2190 }

2191 else

2192 {

2193

2195 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),

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

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

2199 return false;

2200 }

2201

2202

2203

2204

2205

2206

2207

2208

2209

2210

2211

2212

2213

2214

2216

2218

2219 if (fn_typtype == TYPTYPE_BASE ||

2220 fn_typtype == TYPTYPE_DOMAIN ||

2221 fn_typtype == TYPTYPE_ENUM ||

2222 fn_typtype == TYPTYPE_RANGE ||

2223 fn_typtype == TYPTYPE_MULTIRANGE)

2224 {

2225

2226

2227

2228

2230

2231 if (tlistlen != 1)

2233 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),

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

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

2237

2238

2240 Assert(!tle->resjunk);

2241

2243 tlist_is_modifiable,

2244 &upper_tlist,

2245 &upper_tlist_nontrivial))

2247 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),

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

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

2252 }

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

2254 {

2255

2256

2257

2258

2259

2260

2261

2262

2263

2264

2265

2266 int tupnatts;

2267 int tuplogcols;

2268 int colindex;

2269

2270

2271

2272

2273

2274

2275

2276

2277

2278

2279

2280

2281

2282

2283

2284

2285

2286

2287

2288

2289

2290

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

2292 {

2294

2295 Assert(!tle->resjunk);

2297 tlist_is_modifiable,

2298 &upper_tlist,

2299 &upper_tlist_nontrivial))

2300 {

2301

2302 goto tlist_coercion_finished;

2303 }

2304 }

2305

2306

2307

2308

2309

2310 if (rettupdesc == NULL)

2311 return true;

2312

2313

2314

2315

2316

2317

2318

2319 tupnatts = rettupdesc->natts;

2320 tuplogcols = 0;

2321 colindex = 0;

2322

2323 foreach(lc, tlist)

2324 {

2327

2328

2329 if (tle->resjunk)

2330 continue;

2331

2332 do

2333 {

2334 colindex++;

2335 if (colindex > tupnatts)

2337 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),

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

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

2342 if (attr->attisdropped && insertDroppedCols)

2343 {

2344 Expr *null_expr;

2345

2346

2348 -1,

2352 true,

2353 true );

2354 upper_tlist = lappend(upper_tlist,

2357 NULL,

2358 false));

2359 upper_tlist_nontrivial = true;

2360 }

2361 } while (attr->attisdropped);

2362 tuplogcols++;

2363

2365 attr->atttypid, attr->atttypmod,

2366 tlist_is_modifiable,

2367 &upper_tlist,

2368 &upper_tlist_nontrivial))

2370 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),

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

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

2376 tuplogcols)));

2377 }

2378

2379

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

2381 {

2384 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),

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

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

2388 if (insertDroppedCols)

2389 {

2390 Expr *null_expr;

2391

2392

2394 -1,

2398 true,

2399 true );

2400 upper_tlist = lappend(upper_tlist,

2403 NULL,

2404 false));

2405 upper_tlist_nontrivial = true;

2406 }

2407 }

2408

2409

2410 is_tuple_result = true;

2411 }

2412 else

2414 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),

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

2417

2418tlist_coercion_finished:

2419

2420

2421

2422

2423

2424

2425

2426 if (upper_tlist_nontrivial)

2427 {

2428 Query *newquery;

2429 List *colnames;

2432

2434

2435

2438 newquery->querySource = parse->querySource;

2439 newquery->canSetTag = true;

2441

2442

2443 colnames = NIL;

2444 foreach(lc, parse->targetList)

2445 {

2447

2448 if (tle->resjunk)

2449 continue;

2450 colnames = lappend(colnames,

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

2452 }

2453

2454

2458 rte->eref = rte->alias = makeAlias("*SELECT*", colnames);

2459 rte->lateral = false;

2460 rte->inh = false;

2461 rte->inFromCl = true;

2463

2467

2468

2469

2470

2471

2472 newquery->hasRowSecurity = parse->hasRowSecurity;

2473

2474

2475 lfirst(parse_cell) = newquery;

2476 }

2477

2478 return is_tuple_result;

2479}

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 2492 of file functions.c.

2498{

2500 Expr *new_tle_expr;

2501 Node *cast_result;

2502

2503

2504

2505

2506

2507

2508

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

2510 {

2511

2515 res_type, res_typmod,

2518 -1);

2519 if (cast_result == NULL)

2520 return false;

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

2523

2525 }

2526 else

2527 {

2528

2530

2532 (Node *) var,

2533 var->vartype,

2534 res_type, res_typmod,

2537 -1);

2538 if (cast_result == NULL)

2539 return false;

2541

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

2543 *upper_tlist_nontrivial = true;

2544 new_tle_expr = (Expr *) cast_result;

2545 }

2548 src_tle->resname, false);

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

2550 return true;

2551}

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 2589 of file functions.c.

2590{

2592

2598

2599

2600

2602}

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 * palloc0(Size size)

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(), 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 1554 of file functions.c.

1555{

1559 bool randomAccess;

1560 bool lazyEvalOK;

1561 bool pushed_snapshot;

1565

1566

1567 if (fcinfo->flinfo->fn_retset)

1568 {

1570

1571

1572

1573

1574

1575

1576

1581 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),

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

1585

1587 }

1588 else

1589 {

1590 randomAccess = false;

1591 lazyEvalOK = true;

1592

1593 tscontext = NULL;

1594 }

1595

1596

1597

1598

1600

1601

1604

1605

1606

1607

1609 sqlerrcontext.arg = fcache;

1612

1613

1614

1615

1616

1617 do

1618 {

1619 es = fcache->eslist;

1621 es = es->next;

1622 if (es)

1623 break;

1625

1626

1627

1628

1629

1630

1631

1632

1633

1634

1635

1636

1637

1638

1639

1640

1641

1642

1643

1644 pushed_snapshot = false;

1645 while (es)

1646 {

1647 bool completed;

1648

1650 {

1651

1652

1653

1654

1655

1656

1658 {

1660 if (!pushed_snapshot)

1661 {

1663 pushed_snapshot = true;

1664 }

1665 else

1667 }

1668

1670 }

1672 {

1673

1675 pushed_snapshot = true;

1676 }

1677

1679

1680

1681

1682

1683

1684

1685

1686

1687

1688

1691

1692

1693

1694

1695

1696

1697

1698

1699

1700

1702 break;

1703

1704

1705

1706

1707 es = es->next;

1708 while (!es)

1709 {

1710

1711

1712

1713

1714

1715

1716 if (pushed_snapshot)

1717 {

1719 pushed_snapshot = false;

1720 }

1721

1723 break;

1724

1725 es = fcache->eslist;

1726 }

1727 }

1728

1729

1730

1731

1732

1734 {

1736

1737 if (es)

1738 {

1739

1740

1741

1742

1744

1748

1750

1751

1752

1753

1755

1756

1757

1758

1759

1761 {

1766 }

1767 }

1769 {

1770

1771

1772

1773

1775

1776 fcinfo->isnull = true;

1777 result = (Datum) 0;

1778

1779

1781 {

1786 }

1787 }

1788 else

1789 {

1790

1791

1792

1793

1794

1795

1796

1797

1798

1802 fcache->tstore = NULL;

1803

1806

1807 fcinfo->isnull = true;

1808 result = (Datum) 0;

1809

1810

1812 {

1817 }

1818 }

1819 }

1820 else

1821 {

1822

1823

1824

1826 {

1827

1831 else

1832 {

1833 fcinfo->isnull = true;

1834 result = (Datum) 0;

1835 }

1836 }

1837 else

1838 {

1839

1841 fcinfo->isnull = true;

1842 result = (Datum) 0;

1843 }

1844 }

1845

1846

1847 if (pushed_snapshot)

1849

1850

1851

1852

1853

1854 if (es == NULL)

1855 fcache->eslist = NULL;

1856

1858

1859 return result;

1860}

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 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 629 of file functions.c.

630{

634 int nstmts;

636

637

638

639

640 if (fcache->cplan)

641 {

643 fcache->cplan = NULL;

644 }

645 fcache->eslist = NULL;

646

647

648

649

650

651

652

654 {

656 return false;

659 }

660 else

662

666

667

668

669

670

671

672

677 NULL);

678

679

680

681

684 {

685 if (fcache->esarray == NULL)

689 else

693 }

694

695

696

697

699 {

702

703

704

705

706

708 {

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

712 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),

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

714

717 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),

718

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

721 }

722

725 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),

726

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

729

730

732 if (preves)

733 preves->next = newes;

734 else

735 fcache->eslist = newes;

736

737 newes->next = NULL;

739 newes->setsResult = false;

740 newes->lazyEval = false;

742 newes->qd = NULL;

743

744 if (stmt->canSetTag)

745 lasttages = newes;

746

747 preves = newes;

748 }

749

750

751

752

753

755 return true;

756

757

758

759

760

761

762

763

764

765

766

767

768

769

773 {

775 List *resulttlist;

777

778

781 "SQL function junkfilter",

783 else

786

788

789

790

791

792

793

795

796

797

798

799

800

801

802

803

807 slot);

808 else

810

811

812

813

814

815

816

817

818

819

821

822

825

826

828

830 }

831

835 {

836

837

838

839

840

842 }

843

844

845

846

847

848

849

850

851

852

853

854

855

856

857

859 {

865 }

866

867 return true;

868}

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 534 of file functions.c.

535{

539

540

541

542

543

544

545

547 if (fcache == NULL)

548 {

553 fcache->mcb.arg = fcache;

556 }

557

558

559

560

561

562

563

564 if (fcache->eslist != NULL)

565 {

567 return fcache;

568 }

569

570

571

572

573

574

575

582 true,

583 false);

584

585

586

587

588

589

590

591 if (func != fcache->func)

592 {

593 if (fcache->func != NULL)

594 {

597 }

598 fcache->func = func;

600

602 }

603

604

605

606

607

609

610

613

614

615 fcache->eslist = NULL;

618

619 return fcache;

620}

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 MemoryContextCallback::arg, Assert(), cached_function_compile(), SQLFunctionHashEntry::cfunc, 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(), sql_compile_callback(), sql_delete_callback(), and CachedFunction::use_count.

Referenced by fmgr_sql().

postquel_end()

Definition at line 1419 of file functions.c.

1420{

1422

1423

1425

1426

1428

1429

1431 {

1434 }

1435

1437

1439 es->qd = NULL;

1440

1442

1443

1447}

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 1514 of file functions.c.

1517{

1519

1520

1521

1522

1523

1524

1525

1527 {

1528

1529 fcinfo->isnull = false;

1531 }

1532 else

1533 {

1534

1535

1536

1537

1539

1540 if (!fcinfo->isnull)

1542 }

1543

1544

1546

1548}

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 1378 of file functions.c.

1379{

1380 bool result;

1382

1383

1385

1387 {

1390 true,

1395 NULL);

1396 result = true;

1397 }

1398 else

1399 {

1400

1402

1404

1405

1406

1407

1408

1410 }

1411

1413

1414 return result;

1415}

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 1252 of file functions.c.

1253{

1256

1258

1259

1261

1262

1263

1264

1265

1266

1267

1268

1269

1270

1271

1272

1274 {

1276 "SQL function execution",

1279 }

1281 {

1282

1283

1284

1285

1286

1287

1288

1289

1291 "SQL function execution",

1294 }

1295 else

1296 {

1299 }

1300

1301

1302

1303

1304

1306 {

1309 {

1313 }

1314 }

1315

1316

1318

1319

1320

1321

1322

1324 {

1326

1328

1331 myState->tstore = fcache->tstore;

1333

1334

1336 }

1337 else

1339

1341 NULL,

1348 0);

1349

1350

1352 {

1353

1354

1355

1356

1357

1358

1359

1360 int eflags;

1361

1364 else

1365 eflags = 0;

1367 elog(ERROR, "ExecutorStart() failed unexpectedly");

1368 }

1369

1371

1373}

DestReceiver * CreateDestReceiver(CommandDest dest)

DestReceiver * None_Receiver

bool ExecutorStart(QueryDesc *queryDesc, int eflags)

#define EXEC_FLAG_SKIP_TRIGGERS

MemoryContext CurrentMemoryContext

#define ALLOCSET_DEFAULT_SIZES

QueryDesc * CreateQueryDesc(PlannedStmt *plannedstmt, CachedPlan *cplan, 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, elog, ERROR, 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 1451 of file functions.c.

1453{

1454 int nargs = fcinfo->nargs;

1455

1456 if (nargs > 0)

1457 {

1461

1462 if (fcache->paramLI == NULL)

1463 {

1464

1466

1469 fcache->paramLI = paramLI;

1471 }

1472 else

1473 {

1474 paramLI = fcache->paramLI;

1476 }

1477

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

1479 {

1481

1482

1483

1484

1485

1486

1487

1488

1489

1490

1491

1492

1493

1497 argtyplen[i]);

1498

1500 prm->ptype = argtypes[i];

1501 }

1502 }

1503 else

1505}

#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 876 of file functions.c.

877{

878 int qindex;

879 bool islast;

881 List *queryTree_list;

883

884

886 Assert(qindex < func->num_queries);

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

888

889

890

891

892

893

894

895

896

897

899 {

900

902

905 func->src,

909 }

910 else

911 {

912

914

917 func->src,

920 func->src,

923 NULL);

924 }

925

926

927

928

930

931

932

933

934

935

936

937

938

939

940

941

942

943

944

945

946

947

948

949 if (islast)

954 false);

955

956

957

958

959

961 queryTree_list,

962 NULL,

963 NULL,

964 0,

968 false);

969

970

971

972

973

976 islast ? func : NULL);

977

978

979

980

981

985

986

987

988

989

991

992

993

994

995

996

997 if (islast)

998 {

999 func->source_list = NIL;

1002 }

1003}

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

void sql_fn_parser_setup(struct ParseState *pstate, SQLFunctionParseInfoPtr pinfo)

void(* ParserSetupHook)(struct 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 249 of file functions.c.

252{

255 int nargs;

256

258

259

261

262

263 pinfo->collation = inputCollation;

264

265

266

267

268

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

270 if (nargs > 0)

271 {

272 Oid *argOidVect;

273 int argnum;

274

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

276 memcpy(argOidVect,

277 procedureStruct->proargtypes.values,

278 nargs * sizeof(Oid));

279

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

281 {

282 Oid argtype = argOidVect[argnum];

283

284 if (IsPolymorphicType(argtype))

285 {

289 (errcode(ERRCODE_DATATYPE_MISMATCH),

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

292 argOidVect[argnum] = argtype;

293 }

294 }

295

296 pinfo->argtypes = argOidVect;

297 }

298

299

300

301

302 if (nargs > 0)

303 {

304 Datum proargnames;

305 Datum proargmodes;

306 int n_arg_names;

307 bool isNull;

308

309 proargnames = SysCacheGetAttr(PROCNAMEARGSNSP, procedureTuple,

310 Anum_pg_proc_proargnames,

311 &isNull);

312 if (isNull)

313 proargnames = PointerGetDatum(NULL);

314

315 proargmodes = SysCacheGetAttr(PROCNAMEARGSNSP, procedureTuple,

316 Anum_pg_proc_proargmodes,

317 &isNull);

318 if (isNull)

319 proargmodes = PointerGetDatum(NULL);

320

323

324

325 if (n_arg_names < nargs)

327 }

328 else

330

331 return pinfo;

332}

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(), PointerGetDatum(), pstrdup(), and SysCacheGetAttr().

Referenced by fmgr_sql_validator(), inline_function(), inline_set_returning_function(), and sql_compile_callback().

RemoveSQLFunctionCache()

static void RemoveSQLFunctionCache ( void * arg) static

ShutdownSQLFunction()

static void ShutdownSQLFunction ( Datum arg) static

Definition at line 1939 of file functions.c.

1940{

1943

1944 es = fcache->eslist;

1945 while (es)

1946 {

1947

1949 {

1950

1953

1955

1958 }

1959 es = es->next;

1960 }

1961 fcache->eslist = NULL;

1962

1963

1966 fcache->tstore = NULL;

1967

1968

1969 if (fcache->cplan)

1971 fcache->cplan = NULL;

1972

1973

1975}

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 1016 of file functions.c.

1021{

1028 Oid rettype;

1031 bool isNull;

1032 List *source_list;

1033

1034

1035

1036

1037

1039 comperrcontext.arg = func;

1042

1043

1044

1045

1046

1048 "SQL function",

1050

1051

1052

1053

1054

1056 "SQL function parse trees",

1059

1060

1061

1062

1063

1065 NameStr(procedureStruct->proname));

1067

1068

1069

1070

1071

1073

1074 func->rettype = rettype;

1075 if (rettupdesc)

1076 {

1080 }

1081

1082

1084

1085

1086 func->returnsSet = procedureStruct->proretset;

1087

1088

1090 (procedureStruct->provolatile != PROVOLATILE_VOLATILE);

1091

1092

1093 func->prokind = procedureStruct->prokind;

1094

1095

1096

1097

1098

1099

1105

1106

1107

1108

1109

1114

1115

1116

1117

1121

1122

1124 procedureTuple,

1125 Anum_pg_proc_prosqlbody,

1126 &isNull);

1127 if (!isNull)

1128 {

1129

1131

1135 else

1138 }

1139 else

1140 {

1141

1144 }

1145

1146

1147

1148

1149

1151

1152

1153

1154

1155

1156

1157

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

1160 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),

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

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

1164

1165

1169

1170

1171

1172

1173

1174

1175

1178

1180}

#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 1901 of file functions.c.

1902{

1904 int syntaxerrposition;

1905

1906

1907

1908

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

1911 {

1915 }

1916

1917

1918

1919

1920

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

1924 else

1926}

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 483 of file functions.c.

485{

487

490 param->paramid = paramno;

492 param->paramtypmod = -1;

495

496

497

498

499

500

502 param->paramcollid = pinfo->collation;

503

504 return (Node *) param;

505}

#define OidIsValid(objectId)

Oid get_typcollation(Oid typid)

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

Referenced by sql_fn_param_ref(), and sql_fn_resolve_param_name().

sql_fn_param_ref()

sql_fn_parser_setup()

Definition at line 338 of file functions.c.

339{

343

345}

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_set_returning_function(), interpret_AS_clause(), and prepare_next_query().

sql_fn_post_column_ref()

Definition at line 351 of file functions.c.

352{

354 int nnames;

355 Node *field1;

356 Node *subfield = NULL;

357 const char *name1;

358 const char *name2 = NULL;

360

361

362

363

364

365

366 if (var != NULL)

367 return NULL;

368

369

370

371

372

373

374

375

376

377

378

379

380

381

382

383

384

386

387 if (nnames > 3)

388 return NULL;

389

391 nnames--;

392

394 name1 = strVal(field1);

395 if (nnames > 1)

396 {

398 name2 = strVal(subfield);

399 }

400

401 if (nnames == 3)

402 {

403

404

405

406

407

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

409 return NULL;

410

412

415 }

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

417 {

418

419

420

421

423

424 if (param)

425 {

426

427 subfield = NULL;

428 }

429 else

430 {

431

433 }

434 }

435 else

436 {

437

439 }

440

441 if (!param)

442 return NULL;

443

444 if (subfield)

445 {

446

447

448

449

450

455 NULL,

456 false,

458 }

459

460 return param;

461}

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 1219 of file functions.c.

1220{

1221

1222

1223

1224

1225

1227

1228

1229

1230

1231

1232

1233 if (arg != NULL)

1234 {

1236 bool returnsTuple;

1237

1242 false);

1245 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),

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

1247 }

1248}

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()