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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

16

40

41

42

43

44

45typedef struct

46{

51

52

53

54

55

56

57

58

59

60

61

62

63typedef enum

64{

67

69{

72 bool setsResult;

73 bool lazyEval;

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

113{

115

116 char *fname;

117 char *src;

118

121

124 bool typbyval;

125 bool returnsSet;

126 bool returnsTuple;

128 char prokind;

129

131

133 int num_queries;

134 bool raw_source;

135

137

141

143{

145

147 bool shutdown_reg;

148 bool lazyEval;

149 bool randomAccess;

150 bool ownSubcontext;

151

153

156

158 int jf_generation;

159

160

161

162

163

164

165

166

167

168

169

173

177

178

180

182

184

186

187

190

192

193

194

199 int paramno, int location);

201 const char *paramname, int location);

203 bool lazyEvalOK);

210 bool forValidator);

228 char prokind, bool insertDroppedCols);

230 Oid res_type, int32 res_typmod,

231 bool tlist_is_modifiable,

232 List **upper_tlist,

233 bool *upper_tlist_nontrivial);

239

240

241

242

243

244

245

246

247

248

251 Node *call_expr,

252 Oid inputCollation)

253{

256 int nargs;

257

259

260

262

263

264 pinfo->collation = inputCollation;

265

266

267

268

269

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

271 if (nargs > 0)

272 {

273 Oid *argOidVect;

274 int argnum;

275

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

277 memcpy(argOidVect,

278 procedureStruct->proargtypes.values,

279 nargs * sizeof(Oid));

280

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

282 {

283 Oid argtype = argOidVect[argnum];

284

285 if (IsPolymorphicType(argtype))

286 {

290 (errcode(ERRCODE_DATATYPE_MISMATCH),

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

293 argOidVect[argnum] = argtype;

294 }

295 }

296

297 pinfo->argtypes = argOidVect;

298 }

299

300

301

302

303 if (nargs > 0)

304 {

305 Datum proargnames;

306 Datum proargmodes;

307 int n_arg_names;

308 bool isNull;

309

310 proargnames = SysCacheGetAttr(PROCNAMEARGSNSP, procedureTuple,

311 Anum_pg_proc_proargnames,

312 &isNull);

313 if (isNull)

314 proargnames = PointerGetDatum(NULL);

315

316 proargmodes = SysCacheGetAttr(PROCNAMEARGSNSP, procedureTuple,

317 Anum_pg_proc_proargmodes,

318 &isNull);

319 if (isNull)

320 proargmodes = PointerGetDatum(NULL);

321

324

325

326 if (n_arg_names < nargs)

328 }

329 else

331

332 return pinfo;

333}

334

335

336

337

338void

340{

344

346}

347

348

349

350

353{

355 int nnames;

356 Node *field1;

357 Node *subfield = NULL;

358 const char *name1;

359 const char *name2 = NULL;

361

362

363

364

365

366

367 if (var != NULL)

368 return NULL;

369

370

371

372

373

374

375

376

377

378

379

380

381

382

383

384

385

387

388 if (nnames > 3)

389 return NULL;

390

392 nnames--;

393

395 name1 = strVal(field1);

396 if (nnames > 1)

397 {

399 name2 = strVal(subfield);

400 }

401

402 if (nnames == 3)

403 {

404

405

406

407

408

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

410 return NULL;

411

413

416 }

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

418 {

419

420

421

422

424

425 if (param)

426 {

427

428 subfield = NULL;

429 }

430 else

431 {

432

434 }

435 }

436 else

437 {

438

440 }

441

442 if (!param)

443 return NULL;

444

445 if (subfield)

446 {

447

448

449

450

451

456 NULL,

457 false,

459 }

460

461 return param;

462}

463

464

465

466

469{

471 int paramno = pref->number;

472

473

474 if (paramno <= 0 || paramno > pinfo->nargs)

475 return NULL;

476

478}

479

480

481

482

485 int paramno, int location)

486{

488

491 param->paramid = paramno;

493 param->paramtypmod = -1;

496

497

498

499

500

501

503 param->paramcollid = pinfo->collation;

504

505 return (Node *) param;

506}

507

508

509

510

511

512

515 const char *paramname, int location)

516{

517 int i;

518

520 return NULL;

521

522 for (i = 0; i < pinfo->nargs; i++)

523 {

524 if (pinfo->argnames[i] && strcmp(pinfo->argnames[i], paramname) == 0)

526 }

527

528 return NULL;

529}

530

531

532

533

536{

540

541

542

543

544

545

546

548 if (fcache == NULL)

549 {

554 fcache->mcb.arg = fcache;

557 }

558

559

560

561

562

563

564

565 if (fcache->eslist != NULL)

566 {

568 return fcache;

569 }

570

571

572

573

574

575

576

583 true,

584 false);

585

586

587

588

589

590

591

592 if (func != fcache->func)

593 {

594 if (fcache->func != NULL)

595 {

598 }

599 fcache->func = func;

601

603 }

604

605

606

607

608

610

611

614

615

616 fcache->eslist = NULL;

619

620 return fcache;

621}

622

623

624

625

626

627

628

629static bool

631{

635 int nstmts;

637

638

639

640

641 if (fcache->cplan)

642 {

644 fcache->cplan = NULL;

645 }

646 fcache->eslist = NULL;

647

648

649

650

651

652

653

655 {

657 return false;

660 }

661 else

663

667

668

669

670

671

672

673

678 NULL);

679

680

681

682

685 {

686 if (fcache->esarray == NULL)

690 else

694 }

695

696

697

698

700 {

703

704

705

706

707

709 {

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

713 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),

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

715

718 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),

719

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

722 }

723

726 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),

727

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

730

731

733 if (preves)

734 preves->next = newes;

735 else

736 fcache->eslist = newes;

737

738 newes->next = NULL;

740 newes->setsResult = false;

741 newes->lazyEval = false;

743 newes->qd = NULL;

744

745 if (stmt->canSetTag)

746 lasttages = newes;

747

748 preves = newes;

749 }

750

751

752

753

754

756 return true;

757

758

759

760

761

762

763

764

765

766

767

768

769

770

774 {

776 List *resulttlist;

778

779

782 "SQL function junkfilter",

784 else

787

789

790

791

792

793

794

796

797

798

799

800

801

802

803

804

808 slot);

809 else

811

812

813

814

815

816

817

818

819

820

822

823

826

827

829

831 }

832

836 {

837

838

839

840

841

843 }

844

845

846

847

848

849

850

851

852

853

854

855

856

857

858

860 {

866 }

867

868 return true;

869}

870

871

872

873

874

875

876static void

878{

879 int qindex;

880 bool islast;

882 List *queryTree_list;

884

885

887 Assert(qindex < func->num_queries);

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

889

890

891

892

893

894

895

896

897

898

900 {

901

903

906 func->src,

910 }

911 else

912 {

913

915

918 func->src,

921 func->src,

924 NULL);

925 }

926

927

928

929

931

932

933

934

935

936

937

938

939

940

941

942

943

944

945

946

947

948

949

950 if (islast)

955 false);

956

957

958

959

960

962 queryTree_list,

963 NULL,

964 NULL,

965 0,

969 false);

970

971

972

973

974

977 islast ? func : NULL);

978

979

980

981

982

986

987

988

989

990

992

993

994

995

996

997

998 if (islast)

999 {

1000 func->source_list = NIL;

1003 }

1004}

1005

1006

1007

1008

1009

1010

1011

1012

1013

1014

1015

1016static void

1021 bool forValidator)

1022{

1029 Oid rettype;

1032 bool isNull;

1033 List *source_list;

1034

1035

1036

1037

1038

1040 comperrcontext.arg = func;

1043

1044

1045

1046

1047

1049 "SQL function",

1051

1052

1053

1054

1055

1057 "SQL function parse trees",

1060

1061

1062

1063

1064

1066 NameStr(procedureStruct->proname));

1068

1069

1070

1071

1072

1074

1075 func->rettype = rettype;

1076 if (rettupdesc)

1077 {

1081 }

1082

1083

1085

1086

1087 func->returnsSet = procedureStruct->proretset;

1088

1089

1091 (procedureStruct->provolatile != PROVOLATILE_VOLATILE);

1092

1093

1094 func->prokind = procedureStruct->prokind;

1095

1096

1097

1098

1099

1100

1106

1107

1108

1109

1110

1115

1116

1117

1118

1122

1123

1125 procedureTuple,

1126 Anum_pg_proc_prosqlbody,

1127 &isNull);

1128 if (!isNull)

1129 {

1130

1132

1136 else

1139 }

1140 else

1141 {

1142

1145 }

1146

1147

1148

1149

1150

1152

1153

1154

1155

1156

1157

1158

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

1161 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),

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

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

1165

1166

1170

1171

1172

1173

1174

1175

1176

1179

1181}

1182

1183

1184

1185

1186

1187

1188

1189static void

1191{

1194

1195

1197 {

1199

1201 }

1203

1204

1205

1206

1207

1211}

1212

1213

1214

1215

1216

1217

1218

1219static void

1221{

1222

1223

1224

1225

1226

1228

1229

1230

1231

1232

1233

1234 if (arg != NULL)

1235 {

1237 bool returnsTuple;

1238

1243 false);

1246 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),

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

1248 }

1249}

1250

1251

1252static void

1254{

1257

1259

1260

1262

1263

1264

1265

1266

1267

1268

1269

1270

1271

1272

1273

1275 {

1277 "SQL function execution",

1280 }

1282 {

1283

1284

1285

1286

1287

1288

1289

1290

1292 "SQL function execution",

1295 }

1296 else

1297 {

1300 }

1301

1302

1303

1304

1305

1307 {

1310 {

1314 }

1315 }

1316

1317

1319

1320

1321

1322

1323

1325 {

1327

1329

1332 myState->tstore = fcache->tstore;

1334

1335

1337 }

1338 else

1340

1348 0);

1349

1350

1352 {

1353

1354

1355

1356

1357

1358

1359

1360 int eflags;

1361

1364 else

1365 eflags = 0;

1367 }

1368

1370

1372}

1373

1374

1375

1376static bool

1378{

1379 bool result;

1381

1382

1384

1386 {

1389 true,

1394 NULL);

1395 result = true;

1396 }

1397 else

1398 {

1399

1401

1403

1404

1405

1406

1407

1409 }

1410

1412

1413 return result;

1414}

1415

1416

1417static void

1419{

1421

1422

1424

1425

1427

1428

1430 {

1433 }

1434

1436

1438 es->qd = NULL;

1439

1441

1442

1446}

1447

1448

1449static void

1452{

1453 int nargs = fcinfo->nargs;

1454

1455 if (nargs > 0)

1456 {

1460

1461 if (fcache->paramLI == NULL)

1462 {

1463

1465

1468 fcache->paramLI = paramLI;

1470 }

1471 else

1472 {

1473 paramLI = fcache->paramLI;

1475 }

1476

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

1478 {

1480

1481

1482

1483

1484

1485

1486

1487

1488

1489

1490

1491

1492

1496 argtyplen[i]);

1497

1499 prm->ptype = argtypes[i];

1500 }

1501 }

1502 else

1504}

1505

1506

1507

1508

1509

1510

1511

1516{

1518

1519

1520

1521

1522

1523

1524

1526 {

1527

1528 fcinfo->isnull = false;

1530 }

1531 else

1532 {

1533

1534

1535

1536

1538

1539 if (!fcinfo->isnull)

1541 }

1542

1543

1545

1547}

1548

1549

1550

1551

1554{

1558 bool randomAccess;

1559 bool lazyEvalOK;

1560 bool pushed_snapshot;

1564

1565

1566 if (fcinfo->flinfo->fn_retset)

1567 {

1569

1570

1571

1572

1573

1574

1575

1580 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),

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

1584

1586 }

1587 else

1588 {

1589 randomAccess = false;

1590 lazyEvalOK = true;

1591

1592 tscontext = NULL;

1593 }

1594

1595

1596

1597

1599

1600

1603

1604

1605

1606

1608 sqlerrcontext.arg = fcache;

1611

1612

1613

1614

1615

1616 do

1617 {

1618 es = fcache->eslist;

1620 es = es->next;

1621 if (es)

1622 break;

1624

1625

1626

1627

1628

1629

1630

1631

1632

1633

1634

1635

1636

1637

1638

1639

1640

1641

1642

1643 pushed_snapshot = false;

1644 while (es)

1645 {

1646 bool completed;

1647

1649 {

1650

1651

1652

1653

1654

1655

1657 {

1659 if (!pushed_snapshot)

1660 {

1662 pushed_snapshot = true;

1663 }

1664 else

1666 }

1667

1669 }

1671 {

1672

1674 pushed_snapshot = true;

1675 }

1676

1678

1679

1680

1681

1682

1683

1684

1685

1686

1687

1690

1691

1692

1693

1694

1695

1696

1697

1698

1699

1701 break;

1702

1703

1704

1705

1706 es = es->next;

1707 while (!es)

1708 {

1709

1710

1711

1712

1713

1714

1715 if (pushed_snapshot)

1716 {

1718 pushed_snapshot = false;

1719 }

1720

1722 break;

1723

1724 es = fcache->eslist;

1725 }

1726 }

1727

1728

1729

1730

1731

1733 {

1735

1736 if (es)

1737 {

1738

1739

1740

1741

1743

1747

1749

1750

1751

1752

1754

1755

1756

1757

1758

1760 {

1765 }

1766 }

1768 {

1769

1770

1771

1772

1774

1775 fcinfo->isnull = true;

1776 result = (Datum) 0;

1777

1778

1780 {

1785 }

1786 }

1787 else

1788 {

1789

1790

1791

1792

1793

1794

1795

1796

1797

1801 fcache->tstore = NULL;

1802

1805

1806 fcinfo->isnull = true;

1807 result = (Datum) 0;

1808

1809

1811 {

1816 }

1817 }

1818 }

1819 else

1820 {

1821

1822

1823

1825 {

1826

1830 else

1831 {

1832 fcinfo->isnull = true;

1833 result = (Datum) 0;

1834 }

1835 }

1836 else

1837 {

1838

1840 fcinfo->isnull = true;

1841 result = (Datum) 0;

1842 }

1843 }

1844

1845

1846 if (pushed_snapshot)

1848

1849

1850

1851

1852

1853 if (es == NULL)

1854 fcache->eslist = NULL;

1855

1857

1858 return result;

1859}

1860

1861

1862

1863

1864

1865static void

1867{

1869 int syntaxerrposition;

1870

1871

1872

1873

1874

1875 if (func->fname == NULL)

1876 return;

1877

1878

1879

1880

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

1883 {

1887 }

1888

1889

1890

1891

1892

1893 errcontext("SQL function \"%s\" during startup", func->fname);

1894}

1895

1896

1897

1898

1899static void

1901{

1903 int syntaxerrposition;

1904

1905

1906

1907

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

1910 {

1914 }

1915

1916

1917

1918

1919

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

1923 else

1925}

1926

1927

1928

1929

1930

1931

1932

1933

1934

1935

1936

1937static void

1939{

1942

1943 es = fcache->eslist;

1944 while (es)

1945 {

1946

1948 {

1949

1952

1954

1957 }

1958 es = es->next;

1959 }

1960 fcache->eslist = NULL;

1961

1962

1965 fcache->tstore = NULL;

1966

1967

1968 if (fcache->cplan)

1970 fcache->cplan = NULL;

1971

1972

1974}

1975

1976

1977

1978

1979

1980

1981

1982

1983

1984static void

1986{

1988

1989

1990 if (fcache->func != NULL)

1991 {

1994

1995 fcache->func = NULL;

1996 }

1997}

1998

1999

2000

2001

2002

2003

2004

2005void

2007{

2009

2010

2011 foreach(lc, queryTreeLists)

2012 {

2014

2016 }

2017}

2018

2019

2020

2021

2022static void

2024{

2026

2027 foreach(lc, queryTreeList)

2028 {

2030

2031

2032

2033

2034

2035

2036

2037

2040 {

2042

2045 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),

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

2047 }

2048 }

2049}

2050

2051

2052

2053

2054

2055

2056

2057

2058

2059

2060

2061

2062

2063

2064

2065

2066

2067

2068

2069

2070

2071

2072

2073

2074

2075

2076

2077

2078

2079

2080

2081

2082

2083

2084

2085

2086bool

2089 char prokind,

2090 bool insertDroppedCols)

2091{

2092 List *queryTreeList;

2093

2094

2095

2096

2097

2098

2099

2100

2101

2102

2103

2104

2105

2106 if (queryTreeLists != NIL)

2108 else

2109 queryTreeList = NIL;

2110

2112 rettype, rettupdesc,

2113 prokind, insertDroppedCols);

2114}

2115

2116

2117

2118

2119

2120static bool

2123 char prokind, bool insertDroppedCols)

2124{

2125 bool is_tuple_result = false;

2128 List *tlist;

2129 int tlistlen;

2130 bool tlist_is_modifiable;

2131 char fn_typtype;

2132 List *upper_tlist = NIL;

2133 bool upper_tlist_nontrivial = false;

2135

2136

2137

2138

2139

2140 if (rettype == VOIDOID)

2141 return false;

2142

2143

2144

2145

2146

2147

2149 parse_cell = NULL;

2150 foreach(lc, queryTreeList)

2151 {

2153

2154 if (q->canSetTag)

2155 {

2157 parse_cell = lc;

2158 }

2159 }

2160

2161

2162

2163

2164

2165

2166

2167

2168

2169

2170

2171

2174 {

2175 tlist = parse->targetList;

2176

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

2178 }

2179 else if (parse &&

2184 parse->returningList)

2185 {

2186 tlist = parse->returningList;

2187

2188 tlist_is_modifiable = true;

2189 }

2190 else

2191 {

2192

2194 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),

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

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

2198 return false;

2199 }

2200

2201

2202

2203

2204

2205

2206

2207

2208

2209

2210

2211

2212

2213

2215

2217

2218 if (fn_typtype == TYPTYPE_BASE ||

2219 fn_typtype == TYPTYPE_DOMAIN ||

2220 fn_typtype == TYPTYPE_ENUM ||

2221 fn_typtype == TYPTYPE_RANGE ||

2222 fn_typtype == TYPTYPE_MULTIRANGE)

2223 {

2224

2225

2226

2227

2229

2230 if (tlistlen != 1)

2232 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),

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

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

2236

2237

2239 Assert(!tle->resjunk);

2240

2242 tlist_is_modifiable,

2243 &upper_tlist,

2244 &upper_tlist_nontrivial))

2246 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),

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

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

2251 }

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

2253 {

2254

2255

2256

2257

2258

2259

2260

2261

2262

2263

2264

2265 int tupnatts;

2266 int tuplogcols;

2267 int colindex;

2268

2269

2270

2271

2272

2273

2274

2275

2276

2277

2278

2279

2280

2281

2282

2283

2284

2285

2286

2287

2288

2289

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

2291 {

2293

2294 Assert(!tle->resjunk);

2296 tlist_is_modifiable,

2297 &upper_tlist,

2298 &upper_tlist_nontrivial))

2299 {

2300

2301 goto tlist_coercion_finished;

2302 }

2303 }

2304

2305

2306

2307

2308

2309 if (rettupdesc == NULL)

2310 return true;

2311

2312

2313

2314

2315

2316

2317

2318 tupnatts = rettupdesc->natts;

2319 tuplogcols = 0;

2320 colindex = 0;

2321

2322 foreach(lc, tlist)

2323 {

2326

2327

2328 if (tle->resjunk)

2329 continue;

2330

2331 do

2332 {

2333 colindex++;

2334 if (colindex > tupnatts)

2336 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),

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

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

2341 if (attr->attisdropped && insertDroppedCols)

2342 {

2343 Expr *null_expr;

2344

2345

2347 -1,

2351 true,

2352 true );

2353 upper_tlist = lappend(upper_tlist,

2356 NULL,

2357 false));

2358 upper_tlist_nontrivial = true;

2359 }

2360 } while (attr->attisdropped);

2361 tuplogcols++;

2362

2364 attr->atttypid, attr->atttypmod,

2365 tlist_is_modifiable,

2366 &upper_tlist,

2367 &upper_tlist_nontrivial))

2369 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),

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

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

2375 tuplogcols)));

2376 }

2377

2378

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

2380 {

2383 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),

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

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

2387 if (insertDroppedCols)

2388 {

2389 Expr *null_expr;

2390

2391

2393 -1,

2397 true,

2398 true );

2399 upper_tlist = lappend(upper_tlist,

2402 NULL,

2403 false));

2404 upper_tlist_nontrivial = true;

2405 }

2406 }

2407

2408

2409 is_tuple_result = true;

2410 }

2411 else

2413 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),

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

2416

2417tlist_coercion_finished:

2418

2419

2420

2421

2422

2423

2424

2425 if (upper_tlist_nontrivial)

2426 {

2427 Query *newquery;

2428 List *colnames;

2431

2433

2434

2437 newquery->querySource = parse->querySource;

2438 newquery->canSetTag = true;

2440

2441

2442 colnames = NIL;

2443 foreach(lc, parse->targetList)

2444 {

2446

2447 if (tle->resjunk)

2448 continue;

2449 colnames = lappend(colnames,

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

2451 }

2452

2453

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

2458 rte->lateral = false;

2459 rte->inh = false;

2460 rte->inFromCl = true;

2462

2466

2467

2468

2469

2470

2471 newquery->hasRowSecurity = parse->hasRowSecurity;

2472

2473

2474 lfirst(parse_cell) = newquery;

2475 }

2476

2477 return is_tuple_result;

2478}

2479

2480

2481

2482

2483

2484

2485

2486

2487

2488

2489

2490static bool

2492 Oid res_type,

2493 int32 res_typmod,

2494 bool tlist_is_modifiable,

2495 List **upper_tlist,

2496 bool *upper_tlist_nontrivial)

2497{

2499 Expr *new_tle_expr;

2500 Node *cast_result;

2501

2502

2503

2504

2505

2506

2507

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

2509 {

2510

2514 res_type, res_typmod,

2517 -1);

2518 if (cast_result == NULL)

2519 return false;

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

2522

2524 }

2525 else

2526 {

2527

2529

2531 (Node *) var,

2532 var->vartype,

2533 res_type, res_typmod,

2536 -1);

2537 if (cast_result == NULL)

2538 return false;

2540

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

2542 *upper_tlist_nontrivial = true;

2543 new_tle_expr = (Expr *) cast_result;

2544 }

2547 src_tle->resname, false);

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

2549 return true;

2550}

2551

2552

2553

2554

2555

2556static List *

2558{

2561

2562 foreach(lc, queryTreeList)

2563 {

2565

2566 if (q->canSetTag)

2568 }

2571 return parse->targetList;

2572 else if (parse &&

2577 parse->returningList)

2578 return parse->returningList;

2579 else

2580 return NIL;

2581}

2582

2583

2584

2585

2586

2589{

2591

2597

2598

2599

2601}

2602

2603

2604

2605

2606static void

2608{

2609

2610}

2611

2612

2613

2614

2615static bool

2617{

2619

2620 if (myState->tstore)

2621 {

2622

2623

2624

2626

2627

2629 }

2630 else

2631 {

2632

2633

2634

2635

2637 {

2638

2641

2642

2644 }

2645 }

2646

2647 return true;

2648}

2649

2650

2651

2652

2653static void

2655{

2656

2657}

2658

2659

2660

2661

2662static void

2664{

2666}

#define TextDatumGetCString(d)

#define OidIsValid(objectId)

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

DestReceiver * CreateDestReceiver(CommandDest dest)

DestReceiver * None_Receiver

int internalerrquery(const char *query)

int internalerrposition(int cursorpos)

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

ErrorContextCallback * error_context_stack

int errcode(int sqlerrcode)

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

int errposition(int cursorpos)

#define ereport(elevel,...)

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

TupleTableSlot * ExecFilterJunk(JunkFilter *junkfilter, TupleTableSlot *slot)

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

void ExecutorEnd(QueryDesc *queryDesc)

void ExecutorFinish(QueryDesc *queryDesc)

void ExecutorStart(QueryDesc *queryDesc, int eflags)

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

TupleDesc BlessTupleDesc(TupleDesc tupdesc)

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

Datum ExecFetchSlotHeapTupleDatum(TupleTableSlot *slot)

const TupleTableSlotOps TTSOpsMinimalTuple

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

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

int ExecCleanTargetListLength(List *targetlist)

@ SFRM_Materialize_Preferred

@ SFRM_Materialize_Random

#define EXEC_FLAG_SKIP_TRIGGERS

#define MakeExpandedObjectReadOnly(d, isnull, typlen)

#define repalloc_array(pointer, type, count)

Oid get_call_expr_argtype(Node *expr, int argnum)

#define PG_GET_COLLATION()

char * format_type_be(Oid type_oid)

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

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

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

static void check_sql_fn_statement(List *queryTreeList)

static void sql_delete_callback(CachedFunction *cfunc)

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

Datum fmgr_sql(PG_FUNCTION_ARGS)

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

void check_sql_fn_statements(List *queryTreeLists)

static void prepare_next_query(SQLFunctionHashEntry *func)

static List * get_sql_fn_result_tlist(List *queryTreeList)

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

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

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

static bool postquel_getnext(execution_state *es, SQLFunctionCachePtr fcache)

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

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 bool sqlfunction_receive(TupleTableSlot *slot, DestReceiver *self)

static void postquel_start(execution_state *es, SQLFunctionCachePtr fcache)

static bool init_execution_state(SQLFunctionCachePtr fcache)

static void sql_compile_error_callback(void *arg)

DestReceiver * CreateSQLFunctionDestReceiver(void)

struct SQLFunctionCache SQLFunctionCache

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

static void postquel_end(execution_state *es, SQLFunctionCachePtr fcache)

struct execution_state execution_state

static void RemoveSQLFunctionCache(void *arg)

struct SQLFunctionHashEntry SQLFunctionHashEntry

void sql_fn_parser_setup(struct ParseState *pstate, SQLFunctionParseInfoPtr pinfo)

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

static void sqlfunction_destroy(DestReceiver *self)

static void sql_exec_error_callback(void *arg)

static void sqlfunction_shutdown(DestReceiver *self)

static Node * sql_fn_make_param(SQLFunctionParseInfoPtr pinfo, int paramno, int location)

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

static void ShutdownSQLFunction(Datum arg)

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 SQLFunctionCache * init_sql_fcache(FunctionCallInfo fcinfo, bool lazyEvalOK)

SQLFunctionCache * SQLFunctionCachePtr

SQLFunctionParseInfo * SQLFunctionParseInfoPtr

Assert(PointerIsAligned(start, uint64))

static void * GETSTRUCT(const HeapTupleData *tuple)

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

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

bool type_is_rowtype(Oid typid)

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

Oid get_typcollation(Oid typid)

int16 get_typlen(Oid typid)

char get_typtype(Oid typid)

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

Var * makeVarFromTargetEntry(int varno, TargetEntry *tle)

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)

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

void * MemoryContextAlloc(MemoryContext context, Size size)

void MemoryContextReset(MemoryContext context)

void * MemoryContextAllocZero(MemoryContext context, Size size)

char * pstrdup(const char *in)

void MemoryContextRegisterResetCallback(MemoryContext context, MemoryContextCallback *cb)

void MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)

void pfree(void *pointer)

void * palloc0(Size size)

MemoryContext CurrentMemoryContext

MemoryContext CacheMemoryContext

void MemoryContextDelete(MemoryContext context)

void MemoryContextSetIdentifier(MemoryContext context, const char *id)

#define AllocSetContextCreate

#define ALLOCSET_DEFAULT_SIZES

#define ALLOCSET_SMALL_SIZES

Oid exprType(const Node *expr)

#define IsA(nodeptr, _type_)

#define castNode(_type_, nodeptr)

static MemoryContext MemoryContextSwitchTo(MemoryContext context)

ParamListInfo makeParamList(int numParams)

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

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)

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

#define CURSOR_OPT_PARALLEL_OK

#define CURSOR_OPT_NO_SCROLL

FormData_pg_attribute * Form_pg_attribute

#define lfirst_node(type, lc)

static int list_length(const List *l)

#define linitial_node(type, l)

#define foreach_current_index(var_or_cell)

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

#define list_nth_node(type, list, n)

#define llast_node(type, l)

FormData_pg_proc * Form_pg_proc

void DropCachedPlan(CachedPlanSource *plansource)

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)

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

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)

void ReleaseCachedPlan(CachedPlan *plan, ResourceOwner owner)

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

List * pg_parse_query(const char *query_string)

List * pg_rewrite_query(Query *query)

static Datum PointerGetDatum(const void *X)

static Pointer DatumGetPointer(Datum X)

void FreeQueryDesc(QueryDesc *qdesc)

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

void * stringToNode(const char *str)

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

ResourceOwner CurrentResourceOwner

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

Snapshot GetTransactionSnapshot(void)

void PushActiveSnapshot(Snapshot snapshot)

void UpdateActiveSnapshotCommandId(void)

bool ActiveSnapshotSet(void)

void PopActiveSnapshot(void)

Snapshot GetActiveSnapshot(void)

struct ErrorContextCallback * previous

void(* callback)(void *arg)

MemoryContext ecxt_per_query_memory

NullableDatum args[FLEXIBLE_ARRAY_MEMBER]

TupleDesc jf_cleanTupType

TupleTableSlot * jf_resultSlot

MemoryContextCallbackFunction func

ParamExternData params[FLEXIBLE_ARRAY_MEMBER]

ParseParamRefHook p_paramref_hook

PreParseColumnRefHook p_pre_columnref_hook

PostParseColumnRefHook p_post_columnref_hook

PlannedStmt * plannedstmt

QueryEnvironment * queryEnv

SetFunctionReturnMode returnMode

Tuplestorestate * setResult

SQLFunctionHashEntry * func

execution_state * esarray

MemoryContextCallback mcb

SQLFunctionParseInfoPtr pinfo

TupleDesc tts_tupleDescriptor

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

void(* rShutdown)(DestReceiver *self)

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

void(* rDestroy)(DestReceiver *self)

struct execution_state * next

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

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

TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)

static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)

static CompactAttribute * TupleDescCompactAttr(TupleDesc tupdesc, int i)

void tuplestore_puttupleslot(Tuplestorestate *state, TupleTableSlot *slot)

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

void tuplestore_end(Tuplestorestate *state)

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

static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)

static void ExecMaterializeSlot(TupleTableSlot *slot)

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

bool CommandIsReadOnly(PlannedStmt *pstmt)

CommandTag CreateCommandTag(Node *parsetree)

static const char * CreateCommandName(Node *parsetree)

String * makeString(char *str)

void CommandCounterIncrement(void)