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

146 bool active;

148 bool shutdown_reg;

149 bool lazyEval;

150 bool randomAccess;

151 bool ownSubcontext;

152

154

157

159 int jf_generation;

160

161

162

163

164

165

166

167

168

169

170

174

178

179

181

183

185

187

188

191

193

194

195

200 int paramno, int location);

202 const char *paramname, int location);

204 bool lazyEvalOK);

211 bool forValidator);

229 char prokind, bool insertDroppedCols);

231 Oid res_type, int32 res_typmod,

232 bool tlist_is_modifiable,

233 List **upper_tlist,

234 bool *upper_tlist_nontrivial);

240

241

242

243

244

245

246

247

248

249

252 Node *call_expr,

253 Oid inputCollation)

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}

335

336

337

338

339void

341{

345

347}

348

349

350

351

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}

464

465

466

467

470{

472 int paramno = pref->number;

473

474

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

476 return NULL;

477

479}

480

481

482

483

486 int paramno, int location)

487{

489

492 param->paramid = paramno;

497

498

499

500

501

502

505

506 return (Node *) param;

507}

508

509

510

511

512

513

516 const char *paramname, int location)

517{

518 int i;

519

521 return NULL;

522

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

524 {

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

527 }

528

529 return NULL;

530}

531

532

533

534

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}

645

646

647

648

649

650

651

652static bool

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}

893

894

895

896

897

898

899static void

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}

1028

1029

1030

1031

1032

1033

1034

1035

1036

1037

1038

1039static void

1044 bool forValidator)

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}

1205

1206

1207

1208

1209

1210

1211

1212static void

1214{

1217

1218

1220 {

1222

1224 }

1226

1227

1228

1229

1230

1234}

1235

1236

1237

1238

1239

1240

1241

1242static void

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}

1273

1274

1275static void

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}

1396

1397

1398

1399static bool

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}

1438

1439

1440static void

1442{

1444

1445

1447

1448

1450

1451

1453 {

1456 }

1457

1459

1461 es->qd = NULL;

1462

1464

1465

1469}

1470

1471

1472static void

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}

1528

1529

1530

1531

1532

1533

1534

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}

1571

1572

1573

1574

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}

1889

1890

1891

1892

1893

1894static void

1896{

1898 int syntaxerrposition;

1899

1900

1901

1902

1903

1904 if (func->fname == NULL)

1905 return;

1906

1907

1908

1909

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

1912 {

1916 }

1917

1918

1919

1920

1921

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

1923}

1924

1925

1926

1927

1928static void

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}

1955

1956

1957

1958

1959

1960

1961

1962

1963

1964

1965

1966static void

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}

2004

2005

2006

2007

2008

2009

2010

2011

2012

2013static void

2015{

2017

2018

2019 if (fcache->func != NULL)

2020 {

2023

2024 fcache->func = NULL;

2025 }

2026}

2027

2028

2029

2030

2031

2032

2033

2034void

2036{

2038

2039

2040 foreach(lc, queryTreeLists)

2041 {

2043

2045 }

2046}

2047

2048

2049

2050

2051static void

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}

2079

2080

2081

2082

2083

2084

2085

2086

2087

2088

2089

2090

2091

2092

2093

2094

2095

2096

2097

2098

2099

2100

2101

2102

2103

2104

2105

2106

2107

2108

2109

2110

2111

2112

2113

2114

2115bool

2118 char prokind,

2119 bool insertDroppedCols)

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}

2144

2145

2146

2147

2148

2149static bool

2152 char prokind, bool insertDroppedCols)

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}

2508

2509

2510

2511

2512

2513

2514

2515

2516

2517

2518

2519static bool

2521 Oid res_type,

2522 int32 res_typmod,

2523 bool tlist_is_modifiable,

2524 List **upper_tlist,

2525 bool *upper_tlist_nontrivial)

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}

2580

2581

2582

2583

2584

2585static List *

2587{

2590

2591 foreach(lc, queryTreeList)

2592 {

2594

2595 if (q->canSetTag)

2597 }

2600 return parse->targetList;

2601 else if (parse &&

2606 parse->returningList)

2607 return parse->returningList;

2608 else

2609 return NIL;

2610}

2611

2612

2613

2614

2615

2618{

2620

2626

2627

2628

2630}

2631

2632

2633

2634

2635static void

2637{

2638

2639}

2640

2641

2642

2643

2644static bool

2646{

2648

2649 if (myState->tstore)

2650 {

2651

2652

2653

2655

2656

2658 }

2659 else

2660 {

2661

2662

2663

2664

2666 {

2667

2670

2671

2673 }

2674 }

2675

2676 return true;

2677}

2678

2679

2680

2681

2682static void

2684{

2685

2686}

2687

2688

2689

2690

2691static void

2693{

2695}

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

#define palloc0_object(type)

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)

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