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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

16

36

37

38

39

40

41

42

43

47

52

54{

58

61

63

65

68 bool fire_triggers);

69

72

74

76

80

83

89

90

91

92

93int

95{

97}

98

99int

101{

102 int newdepth;

103

104

106 {

108 elog(ERROR, "SPI stack corrupted");

109 newdepth = 16;

114 }

115 else

116 {

118 elog(ERROR, "SPI stack corrupted");

120 {

126 }

127 }

128

129

132

147

148

149

150

151

152

153

154

155

156

157

158

159

160

162 "SPI Proc",

165 "SPI Exec",

167

169

170

171

172

173

177

179}

180

181int

183{

184 int res;

185

186 res = _SPI_begin_call(false);

187 if (res < 0)

188 return res;

189

190

192

193

198

199

200

201

202

206

207

211 else

213

215}

216

217

218

219

220

221void

223{

224}

225

226static void

228{

231

232

233

234

235

236

237

240 (errcode(ERRCODE_INVALID_TRANSACTION_TERMINATION),

241 errmsg("invalid transaction termination")));

242

243

244

245

246

247

248

249

250

251

252

255 (errcode(ERRCODE_INVALID_TRANSACTION_TERMINATION),

256 errmsg("cannot commit while a subtransaction is active")));

257

258 if (chain)

260

261

263 {

264

266

267

268

269

270

271

273

274

276

277

279

280

282 if (chain)

284

286

288 }

290 {

292

293

297

298

299

300

301

303

304

306 if (chain)

308

310

312

313

315 }

317}

318

319void

321{

323}

324

325void

327{

329}

330

331static void

333{

336

337

340 (errcode(ERRCODE_INVALID_TRANSACTION_TERMINATION),

341 errmsg("invalid transaction termination")));

342

343

346 (errcode(ERRCODE_INVALID_TRANSACTION_TERMINATION),

347 errmsg("cannot roll back while a subtransaction is active")));

348

349 if (chain)

351

352

354 {

355

357

358

359

360

361

362

363

365

366

368

369

371

372

374 if (chain)

376

378

380 }

382 {

384

385

389

390

391

392

393

394

396

397

399 if (chain)

401

403

405

406

408 }

410}

411

412void

414{

416}

417

418void

420{

422}

423

424

425

426

427void

429{

430 bool found = false;

431

432

433

434

435

437 {

439

441 break;

442

443 found = true;

444

445

446

447

448

449

450

451

452

453

454

455

459

463 else

465 }

466

467

468 if (found && isCommit)

470 (errcode(ERRCODE_WARNING),

471 errmsg("transaction left non-empty SPI stack"),

472 errhint("Check for missing \"SPI_finish\" calls.")));

473}

474

475

476

477

478

479

480

481void

483{

484 bool found = false;

485

487 {

489

490 if (connection->connectSubid != mySubid)

491 break;

492

494 break;

495

496 found = true;

497

498

499

500

502 {

505 }

507 {

510 }

511

512

513

514

515

516

520

524 else

526 }

527

528 if (found && isCommit)

530 (errcode(ERRCODE_WARNING),

531 errmsg("subtransaction left non-empty SPI stack"),

532 errhint("Check for missing \"SPI_finish\" calls.")));

533

534

535

536

537

539 {

541

542

543

544

545

547 {

550 }

551

552

554 {

556

558 if (tuptable->subid >= mySubid)

559 {

560

561

562

563

564

565

572 }

573 }

574 }

575}

576

577

578

579

580bool

582{

584 return false;

585

587 return false;

589 return false;

590 return true;

591}

592

593

594

595int

596SPI_execute(const char *src, bool read_only, long tcount)

597{

600 int res;

601

602 if (src == NULL || tcount < 0)

604

606 if (res < 0)

607 return res;

608

613

615

617 options.read_only = read_only;

619

622 true);

623

625 return res;

626}

627

628

629int

631{

633}

634

635

636int

639{

640 int res;

642

643 if (src == NULL || options == NULL)

645

647 if (res < 0)

648 return res;

649

655 {

656 plan.parserSetup = options->params->parserSetup;

657 plan.parserSetupArg = options->params->parserSetupArg;

658 }

659

661

664 true);

665

667 return res;

668}

669

670

671int

673 bool read_only, long tcount)

674{

676 int res;

677

680

681 if (plan->nargs > 0 && Values == NULL)

683

685 if (res < 0)

686 return res;

687

691 options.read_only = read_only;

693

696 true);

697

699 return res;

700}

701

702

703int

705{

707}

708

709

710int

713{

714 int res;

715

718

720 if (res < 0)

721 return res;

722

725 true);

726

728 return res;

729}

730

731

732int

734 bool read_only, long tcount)

735{

737 int res;

738

741

743 if (res < 0)

744 return res;

745

748 options.read_only = read_only;

750

753 true);

754

756 return res;

757}

758

759

760

761

762

763

764

765

766

767

768

769

770

771

772int

776 bool read_only, bool fire_triggers, long tcount)

777{

779 int res;

780

783

784 if (plan->nargs > 0 && Values == NULL)

786

788 if (res < 0)

789 return res;

790

794 options.read_only = read_only;

796

798 snapshot, crosscheck_snapshot,

799 fire_triggers);

800

802 return res;

803}

804

805

806

807

808

809

810

811int

813 int nargs, Oid *argtypes,

815 bool read_only, long tcount)

816{

817 int res;

821

822 if (src == NULL || nargs < 0 || tcount < 0)

824

825 if (nargs > 0 && (argtypes == NULL || Values == NULL))

827

829 if (res < 0)

830 return res;

831

836 plan.nargs = nargs;

837 plan.argtypes = argtypes;

838 plan.parserSetup = NULL;

839 plan.parserSetupArg = NULL;

840

843

845

847 options.params = paramLI;

848 options.read_only = read_only;

850

853 true);

854

856 return res;

857}

858

861{

863}

864

867 int cursorOptions)

868{

871

872 if (src == NULL || nargs < 0 || (nargs > 0 && argtypes == NULL))

873 {

875 return NULL;

876 }

877

880 return NULL;

881

885 plan.cursor_options = cursorOptions;

886 plan.nargs = nargs;

887 plan.argtypes = argtypes;

888 plan.parserSetup = NULL;

889 plan.parserSetupArg = NULL;

890

892

893

895

897

898 return result;

899}

900

904{

907

908 if (src == NULL || options == NULL)

909 {

911 return NULL;

912 }

913

916 return NULL;

917

921 plan.cursor_options = options->cursorOptions;

922 plan.nargs = 0;

923 plan.argtypes = NULL;

925 plan.parserSetupArg = options->parserSetupArg;

926

928

929

931

933

934 return result;

935}

936

940 void *parserSetupArg,

941 int cursorOptions)

942{

945

946 if (src == NULL)

947 {

949 return NULL;

950 }

951

954 return NULL;

955

959 plan.cursor_options = cursorOptions;

960 plan.nargs = 0;

961 plan.argtypes = NULL;

962 plan.parserSetup = parserSetup;

963 plan.parserSetupArg = parserSetupArg;

964

966

967

969

971

972 return result;

973}

974

975int

977{

979

981 plan->saved || plan->oneshot)

983

984

985

986

987

988

989 plan->saved = true;

991

992 foreach(lc, plan->plancache_list)

993 {

995

997 }

998

999 return 0;

1000}

1001

1004{

1006

1008 {

1010 return NULL;

1011 }

1012

1015 return NULL;

1016

1018

1020

1021 return newplan;

1022}

1023

1024int

1026{

1028

1031

1032

1033 foreach(lc, plan->plancache_list)

1034 {

1036

1038 }

1039

1040

1042

1043 return 0;

1044}

1045

1048{

1051

1052 if (tuple == NULL)

1053 {

1055 return NULL;

1056 }

1057

1059 {

1061 return NULL;

1062 }

1063

1065

1067

1069

1070 return ctuple;

1071}

1072

1075{

1078

1079 if (tuple == NULL || tupdesc == NULL)

1080 {

1082 return NULL;

1083 }

1084

1086 {

1088 return NULL;

1089 }

1090

1091

1092 if (tupdesc->tdtypeid == RECORDOID &&

1095

1097

1099

1101

1102 return dtup;

1103}

1104

1108{

1111 int numberOfAttributes;

1113 bool *n;

1114 int i;

1115

1116 if (rel == NULL || tuple == NULL || natts < 0 || attnum == NULL || Values == NULL)

1117 {

1119 return NULL;

1120 }

1121

1123 {

1125 return NULL;

1126 }

1127

1129

1131

1132 numberOfAttributes = rel->rd_att->natts;

1134 n = (bool *) palloc(numberOfAttributes * sizeof(bool));

1135

1136

1138

1139

1140 for (i = 0; i < natts; i++)

1141 {

1142 if (attnum[i] <= 0 || attnum[i] > numberOfAttributes)

1143 break;

1144 v[attnum[i] - 1] = Values[i];

1146 }

1147

1148 if (i == natts)

1149 {

1151

1152

1153

1154

1155

1159 }

1160 else

1161 {

1162 mtuple = NULL;

1164 }

1165

1168

1170

1171 return mtuple;

1172}

1173

1174int

1176{

1177 int res;

1179

1180 for (res = 0; res < tupdesc->natts; res++)

1181 {

1183

1184 if (namestrcmp(&attr->attname, fname) == 0 &&

1185 !attr->attisdropped)

1186 return res + 1;

1187 }

1188

1190 if (sysatt != NULL)

1191 return sysatt->attnum;

1192

1193

1195}

1196

1197char *

1199{

1201

1203

1204 if (fnumber > tupdesc->natts || fnumber == 0 ||

1206 {

1208 return NULL;

1209 }

1210

1211 if (fnumber > 0)

1213 else

1215

1217}

1218

1219char *

1221{

1223 bool isnull;

1224 Oid typoid,

1225 foutoid;

1226 bool typisvarlena;

1227

1229

1230 if (fnumber > tupdesc->natts || fnumber == 0 ||

1232 {

1234 return NULL;

1235 }

1236

1238 if (isnull)

1239 return NULL;

1240

1241 if (fnumber > 0)

1242 typoid = TupleDescAttr(tupdesc, fnumber - 1)->atttypid;

1243 else

1245

1247

1249}

1250

1253{

1255

1256 if (fnumber > tupdesc->natts || fnumber == 0 ||

1258 {

1260 *isnull = true;

1261 return (Datum) NULL;

1262 }

1263

1264 return heap_getattr(tuple, fnumber, tupdesc, isnull);

1265}

1266

1267char *

1269{

1270 Oid typoid;

1272 char *result;

1273

1275

1276 if (fnumber > tupdesc->natts || fnumber == 0 ||

1278 {

1280 return NULL;

1281 }

1282

1283 if (fnumber > 0)

1284 typoid = TupleDescAttr(tupdesc, fnumber - 1)->atttypid;

1285 else

1287

1289

1291 {

1293 return NULL;

1294 }

1295

1298 return result;

1299}

1300

1301

1302

1303

1304

1305

1306

1309{

1311

1312 if (fnumber > tupdesc->natts || fnumber == 0 ||

1314 {

1317 }

1318

1319 if (fnumber > 0)

1320 return TupleDescAttr(tupdesc, fnumber - 1)->atttypid;

1321 else

1323}

1324

1325char *

1327{

1329}

1330

1331char *

1333{

1335}

1336

1337void *

1339{

1341 elog(ERROR, "SPI_palloc called while not connected to SPI");

1342

1344}

1345

1346void *

1348{

1349

1350 return repalloc(pointer, size);

1351}

1352

1353void

1355{

1356

1358}

1359

1362{

1365

1367 elog(ERROR, "SPI_datumTransfer called while not connected to SPI");

1368

1370

1372

1374

1375 return result;

1376}

1377

1378void

1380{

1381

1383}

1384

1385void

1387{

1388 bool found = false;

1389

1390

1391 if (tuptable == NULL)

1392 return;

1393

1394

1395

1396

1398 {

1400

1401

1403 {

1405

1407 if (tt == tuptable)

1408 {

1410 found = true;

1411 break;

1412 }

1413 }

1414 }

1415

1416

1417

1418

1419

1420

1421

1422 if (!found)

1423 {

1424 elog(WARNING, "attempt to delete invalid SPITupleTable %p", tuptable);

1425 return;

1426 }

1427

1428

1433

1434

1436}

1437

1438

1439

1440

1441

1442

1443

1447 bool read_only)

1448{

1451

1452

1455

1457

1458

1459 if (paramLI)

1461

1462 return portal;

1463}

1464

1465

1466

1467

1468

1469

1470

1473 const char *src,

1474 int nargs, Oid *argtypes,

1476 bool read_only, int cursorOptions)

1477{

1481

1482 if (src == NULL || nargs < 0)

1483 elog(ERROR, "SPI_cursor_open_with_args called with invalid arguments");

1484

1485 if (nargs > 0 && (argtypes == NULL || Values == NULL))

1486 elog(ERROR, "SPI_cursor_open_with_args called with missing parameters");

1487

1490 elog(ERROR, "SPI_cursor_open_with_args called while not connected");

1491

1495 plan.cursor_options = cursorOptions;

1496 plan.nargs = nargs;

1497 plan.argtypes = argtypes;

1498 plan.parserSetup = NULL;

1499 plan.parserSetupArg = NULL;

1500

1501

1504

1506

1507

1508

1510

1511

1513

1514 return result;

1515}

1516

1517

1518

1519

1520

1521

1522

1523

1527{

1529}

1530

1531

1534 const char *src,

1536{

1539

1540 if (src == NULL || options == NULL)

1541 elog(ERROR, "SPI_cursor_parse_open called with invalid arguments");

1542

1545 elog(ERROR, "SPI_cursor_parse_open called while not connected");

1546

1550 plan.cursor_options = options->cursorOptions;

1552 {

1553 plan.parserSetup = options->params->parserSetup;

1554 plan.parserSetupArg = options->params->parserSetupArg;

1555 }

1556

1558

1559

1560

1563

1564

1566

1567 return result;

1568}

1569

1570

1571

1572

1573

1574

1575

1579{

1582 List *stmt_list;

1583 char *query_string;

1589

1590

1591

1592

1593

1595 {

1596

1597 const char *cmdtag;

1598

1601 (errcode(ERRCODE_INVALID_CURSOR_DEFINITION),

1602 errmsg("cannot open multi-query plan as cursor")));

1604

1605 if (plansource->commandTag == CMDTAG_SELECT)

1606 cmdtag = "SELECT INTO";

1607 else

1610 (errcode(ERRCODE_INVALID_CURSOR_DEFINITION),

1611

1612 errmsg("cannot open %s query as cursor", cmdtag)));

1613 }

1614

1617

1618

1620 elog(ERROR, "SPI_cursor_open called while not connected");

1621

1622

1627

1628

1629 if (name == NULL || name[0] == '\0')

1630 {

1631

1633 }

1634 else

1635 {

1636

1638 }

1639

1640

1643

1644

1645

1646

1647

1649 spicallbackarg.mode = plan->parse_mode;

1651 spierrcontext.arg = &spicallbackarg;

1654

1655

1656

1657

1658

1659

1660

1661

1664

1665 if (plan->saved)

1666 {

1667

1668

1669

1670

1671

1672

1677 cplan = NULL;

1678 }

1679

1680

1681

1682

1684 NULL,

1685 query_string,

1687 stmt_list,

1688 cplan);

1689

1690

1691

1692

1693

1696 {

1702 else

1704 }

1705

1706

1707

1708

1709

1710

1712 {

1717 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),

1718 errmsg("DECLARE SCROLL CURSOR ... FOR UPDATE/SHARE is not supported"),

1719 errdetail("Scrollable cursors must be READ ONLY.")));

1720 }

1721

1722

1724

1725

1726

1727

1728

1729

1730

1731

1732 if (read_only)

1733 {

1735

1736 foreach(lc, stmt_list)

1737 {

1739

1742 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),

1743

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

1746 }

1747 }

1748

1749

1750 if (read_only)

1752 else

1753 {

1756 }

1757

1758

1759

1760

1761

1762

1763 if (paramLI)

1764 {

1768 }

1769

1770

1771

1772

1773 PortalStart(portal, paramLI, 0, snapshot);

1774

1776

1777

1779

1780

1782

1783

1784 return portal;

1785}

1786

1787

1788

1789

1790

1791

1792

1795{

1797}

1798

1799

1800

1801

1802

1803

1804

1805void

1807{

1811

1812}

1813

1814

1815

1816

1817

1818

1819

1820void

1822{

1826}

1827

1828

1829

1830

1831

1832

1833

1834void

1836{

1838 direction, count,

1840

1841}

1842

1843

1844

1845

1846

1847

1848

1849void

1851{

1853}

1854

1855

1856

1857

1858

1859

1860

1861void

1863{

1865 elog(ERROR, "invalid portal in SPI cursor operation");

1866

1868}

1869

1870

1871

1872

1873

1876{

1878 argIndex < 0 || argIndex >= plan->nargs)

1879 {

1882 }

1883 return plan->argtypes[argIndex];

1884}

1885

1886

1887

1888

1889int

1891{

1893 {

1895 return -1;

1896 }

1897 return plan->nargs;

1898}

1899

1900

1901

1902

1903

1904

1905

1906

1907

1908

1909bool

1911{

1913

1915 {

1917 return false;

1918 }

1919

1921 {

1923 return false;

1924 }

1926

1927

1928

1929

1930

1931

1933

1934

1936 return true;

1937

1938 return false;

1939}

1940

1941

1942

1943

1944

1945

1946

1947bool

1949{

1951

1953

1954 foreach(lc, plan->plancache_list)

1955 {

1957

1959 return false;

1960 }

1961 return true;

1962}

1963

1964

1965

1966

1967

1968

1969

1970

1971const char *

1973{

1974 static char buf[64];

1975

1976 switch (code)

1977 {

1979 return "SPI_ERROR_CONNECT";

1981 return "SPI_ERROR_COPY";

1983 return "SPI_ERROR_OPUNKNOWN";

1985 return "SPI_ERROR_UNCONNECTED";

1987 return "SPI_ERROR_ARGUMENT";

1989 return "SPI_ERROR_PARAM";

1991 return "SPI_ERROR_TRANSACTION";

1993 return "SPI_ERROR_NOATTRIBUTE";

1995 return "SPI_ERROR_NOOUTFUNC";

1997 return "SPI_ERROR_TYPUNKNOWN";

1999 return "SPI_ERROR_REL_DUPLICATE";

2001 return "SPI_ERROR_REL_NOT_FOUND";

2003 return "SPI_OK_CONNECT";

2005 return "SPI_OK_FINISH";

2007 return "SPI_OK_FETCH";

2009 return "SPI_OK_UTILITY";

2011 return "SPI_OK_SELECT";

2013 return "SPI_OK_SELINTO";

2015 return "SPI_OK_INSERT";

2017 return "SPI_OK_DELETE";

2019 return "SPI_OK_UPDATE";

2021 return "SPI_OK_CURSOR";

2023 return "SPI_OK_INSERT_RETURNING";

2025 return "SPI_OK_DELETE_RETURNING";

2027 return "SPI_OK_UPDATE_RETURNING";

2029 return "SPI_OK_REWRITTEN";

2031 return "SPI_OK_REL_REGISTER";

2033 return "SPI_OK_REL_UNREGISTER";

2035 return "SPI_OK_TD_REGISTER";

2037 return "SPI_OK_MERGE";

2039 return "SPI_OK_MERGE_RETURNING";

2040 }

2041

2042 sprintf(buf, "Unrecognized SPI code %d", code);

2043 return buf;

2044}

2045

2046

2047

2048

2049

2050

2051

2052

2053

2054

2055

2058{

2060 return plan->plancache_list;

2061}

2062

2063

2064

2065

2066

2067

2068

2069

2070

2071

2072

2073

2074

2077{

2082

2084

2085

2086 if (plan->oneshot)

2087 return NULL;

2088

2089

2091 return NULL;

2093

2094

2096 spicallbackarg.mode = plan->parse_mode;

2098 spierrcontext.arg = &spicallbackarg;

2101

2102

2107

2108

2110

2111 return cplan;

2112}

2113

2114

2115

2116

2117

2118

2119

2120

2121

2122void

2124{

2128

2130 elog(ERROR, "spi_dest_startup called while not connected to SPI");

2131

2133 elog(ERROR, "improper call to spi_dest_startup");

2134

2135

2136

2137 oldcxt = _SPI_procmem();

2138

2140 "SPI TupTable",

2143

2146 tuptable->tuptabcxt = tuptabcxt;

2148

2149

2150

2151

2152

2153

2155

2156

2157 tuptable->alloced = 128;

2161

2163}

2164

2165

2166

2167

2168

2169

2170bool

2172{

2175

2177 elog(ERROR, "spi_printtup called while not connected to SPI");

2178

2180 if (tuptable == NULL)

2181 elog(ERROR, "improper call to spi_printtup");

2182

2184

2186 {

2187

2189

2191 newalloced * sizeof(HeapTuple));

2192 tuptable->alloced = newalloced;

2193 }

2194

2197

2199

2200 return true;

2201}

2202

2203

2204

2205

2206

2207

2208

2209

2210

2211

2212

2213

2214

2215

2216

2217

2218

2219

2220static void

2222{

2223 List *raw_parsetree_list;

2224 List *plancache_list;

2228

2229

2230

2231

2232 spicallbackarg.query = src;

2233 spicallbackarg.mode = plan->parse_mode;

2235 spierrcontext.arg = &spicallbackarg;

2238

2239

2240

2241

2242 raw_parsetree_list = raw_parser(src, plan->parse_mode);

2243

2244

2245

2246

2247

2248 plancache_list = NIL;

2249

2250 foreach(list_item, raw_parsetree_list)

2251 {

2253 List *stmt_list;

2255

2256

2257

2258

2259

2261 src,

2263

2264

2265

2266

2267

2268 if (plan->parserSetup != NULL)

2269 {

2272 src,

2273 plan->parserSetup,

2274 plan->parserSetupArg,

2276 }

2277 else

2278 {

2280 src,

2281 plan->argtypes,

2282 plan->nargs,

2284 }

2285

2286

2288 stmt_list,

2289 NULL,

2290 plan->argtypes,

2291 plan->nargs,

2292 plan->parserSetup,

2293 plan->parserSetupArg,

2294 plan->cursor_options,

2295 false);

2296

2297 plancache_list = lappend(plancache_list, plansource);

2298 }

2299

2300 plan->plancache_list = plancache_list;

2301 plan->oneshot = false;

2302

2303

2304

2305

2307}

2308

2309

2310

2311

2312

2313

2314

2315

2316

2317

2318

2319

2320

2321

2322

2323

2324

2325

2326

2327

2328static void

2330{

2331 List *raw_parsetree_list;

2332 List *plancache_list;

2336

2337

2338

2339

2340 spicallbackarg.query = src;

2341 spicallbackarg.mode = plan->parse_mode;

2343 spierrcontext.arg = &spicallbackarg;

2346

2347

2348

2349

2350 raw_parsetree_list = raw_parser(src, plan->parse_mode);

2351

2352

2353

2354

2355 plancache_list = NIL;

2356

2357 foreach(list_item, raw_parsetree_list)

2358 {

2361

2363 src,

2365

2366 plancache_list = lappend(plancache_list, plansource);

2367 }

2368

2369 plan->plancache_list = plancache_list;

2370 plan->oneshot = true;

2371

2372

2373

2374

2376}

2377

2378

2379

2380

2381

2382

2383

2384

2385

2386

2387

2388

2389

2390

2391

2392

2393

2394

2395

2396

2397

2398static int

2401 bool fire_triggers)

2402{

2403 int my_res = 0;

2404 uint64 my_processed = 0;

2406 int res = 0;

2407 bool allow_nonatomic;

2408 bool pushed_active_snap = false;

2414

2415

2416

2417

2418

2419

2420

2421 allow_nonatomic = options->allow_nonatomic &&

2423

2424

2425

2426

2427 spicallbackarg.query = NULL;

2428 spicallbackarg.mode = plan->parse_mode;

2430 spierrcontext.arg = &spicallbackarg;

2433

2434

2435

2436

2437

2438

2439

2440

2441

2442

2443

2444

2445

2446

2447

2448

2449

2450

2451

2452

2453

2454

2455

2456

2457

2458

2459

2460

2462 {

2463

2466 {

2468 pushed_active_snap = true;

2469 }

2470 else

2471 {

2472

2474 pushed_active_snap = true;

2475 }

2476 }

2477

2478

2479

2480

2481

2482 if (plan->saved)

2483 plan_owner = NULL;

2484 else if (plan_owner == NULL)

2486

2487

2488

2489

2490

2491

2492

2493 if (options->must_return_tuples && plan->plancache_list == NIL)

2495 (errcode(ERRCODE_SYNTAX_ERROR),

2496 errmsg("empty query does not return tuples")));

2497

2498 foreach(lc1, plan->plancache_list)

2499 {

2501 List *stmt_list;

2503

2505

2506

2507

2508

2509 if (plan->oneshot)

2510 {

2513 List *querytree_list;

2514

2515

2516

2517

2518

2519 if (parsetree == NULL)

2520 querytree_list = NIL;

2521 else if (plan->parserSetup != NULL)

2522 {

2525 src,

2526 plan->parserSetup,

2527 plan->parserSetupArg,

2529 }

2530 else

2531 {

2533 src,

2534 plan->argtypes,

2535 plan->nargs,

2537 }

2538

2539

2541 querytree_list,

2542 NULL,

2543 plan->argtypes,

2544 plan->nargs,

2545 plan->parserSetup,

2546 plan->parserSetupArg,

2547 plan->cursor_options,

2548 false);

2549 }

2550

2551

2552

2553

2554

2555

2556

2558 {

2559

2560 const char *cmdtag;

2561

2562

2563 if (plansource->commandTag == CMDTAG_SELECT)

2564 cmdtag = "SELECT INTO";

2565 else

2568 (errcode(ERRCODE_SYNTAX_ERROR),

2569

2570 errmsg("%s query does not return tuples", cmdtag)));

2571 }

2572

2573

2574

2575

2576

2579

2581

2582

2583

2584

2585

2590 stmt_list)))))

2591 {

2592

2593

2594

2595

2596

2597

2598

2599

2600

2602

2603

2604

2605

2606

2607

2608

2609 if (options->read_only && !allow_nonatomic)

2610 {

2611 if (pushed_active_snap)

2614 pushed_active_snap = true;

2615 }

2616 }

2617

2618 foreach(lc2, stmt_list)

2619 {

2621 bool canSetTag = stmt->canSetTag;

2623

2624

2625

2626

2627

2628

2629

2632

2633

2634 if (stmt->utilityStmt)

2635 {

2637 {

2639

2641 {

2643 goto fail;

2644 }

2645 }

2647 {

2649 goto fail;

2650 }

2651 }

2652

2655 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),

2656

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

2659

2660

2661

2662

2663

2664

2665 if (options->read_only && pushed_active_snap)

2666 {

2669 }

2670

2671

2672

2673

2674

2675 if (!canSetTag)

2679 else

2681

2682 if (stmt->utilityStmt == NULL)

2683 {

2686

2689 else

2691

2694 snap, crosscheck_snapshot,

2698 0);

2700 canSetTag ? options->tcount : 0);

2702 }

2703 else

2704 {

2707

2708

2709

2710

2711

2712 if (allow_nonatomic)

2714 else

2716

2720 true,

2721 context,

2725 &qc);

2726

2727

2730

2732

2733

2734

2735

2736

2738 {

2740

2743 else

2744 {

2745

2746

2747

2748

2752 }

2753

2754

2755

2756

2757

2760 }

2762 {

2765 }

2766 }

2767

2768

2769

2770

2771

2772

2773 if (canSetTag)

2774 {

2778 my_res = res;

2779 }

2780 else

2781 {

2784 }

2785

2786

2787

2788

2789

2790

2791

2792 if (res < 0)

2793 {

2794 my_res = res;

2795 goto fail;

2796 }

2797 }

2798

2799

2801 cplan = NULL;

2802

2803

2804

2805

2806

2807

2808 if (options->read_only)

2810 }

2811

2812fail:

2813

2814

2815 if (pushed_active_snap)

2817

2818

2819 if (cplan)

2821

2822

2823

2824

2826

2827

2830

2831

2833

2834

2835

2836

2837

2838

2839 if (my_res == 0)

2841

2842 return my_res;

2843}

2844

2845

2846

2847

2851{

2853

2854 if (nargs > 0)

2855 {

2857

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

2859 {

2861

2862 prm->value = Values[i];

2865 prm->ptype = argtypes[i];

2866 }

2867 }

2868 else

2869 paramLI = NULL;

2870 return paramLI;

2871}

2872

2873static int

2875{

2876 int operation = queryDesc->operation;

2877 int eflags;

2878 int res;

2879

2880 switch (operation)

2881 {

2884 {

2885

2887 }

2888 else

2890 break;

2894 else

2896 break;

2900 else

2902 break;

2906 else

2908 break;

2912 else

2914 break;

2915 default:

2917 }

2918

2919#ifdef SPI_EXECUTOR_STATS

2920 if (ShowExecutorStats)

2922#endif

2923

2924

2925 if (fire_triggers)

2926 eflags = 0;

2927 else

2929

2931

2933

2935

2938 {

2940 elog(ERROR, "consistency check on SPI tuple count failed");

2941 }

2942

2945

2946

2947#ifdef SPI_EXECUTOR_STATS

2948 if (ShowExecutorStats)

2949 ShowUsage("SPI EXECUTOR STATS");

2950#endif

2951

2952 return res;

2953}

2954

2955

2956

2957

2958

2959

2960static void

2962{

2964 const char *query = carg->query;

2965 int syntaxerrposition;

2966

2967 if (query == NULL)

2968 return;

2969

2970

2971

2972

2973

2975 if (syntaxerrposition > 0)

2976 {

2980 }

2981 else

2982 {

2983

2984 switch (carg->mode)

2985 {

2987 errcontext("PL/pgSQL expression \"%s\"", query);

2988 break;

2992 errcontext("PL/pgSQL assignment \"%s\"", query);

2993 break;

2994 default:

2995 errcontext("SQL statement \"%s\"", query);

2996 break;

2997 }

2998 }

2999}

3000

3001

3002

3003

3004

3005

3006static void

3009{

3011

3012

3014 elog(ERROR, "invalid portal in SPI cursor operation");

3015

3016

3018 elog(ERROR, "SPI cursor operation called while not connected");

3019

3020

3025

3026

3028 direction,

3029 count,

3031

3032

3033

3034

3035

3036

3037

3038

3039

3041

3043 elog(ERROR, "consistency check on SPI tuple count failed");

3044

3045

3048

3049

3051

3052

3054}

3055

3056

3059{

3061}

3062

3065{

3067}

3068

3069

3070

3071

3072

3073

3074

3075

3076static int

3078{

3081

3082 if (use_exec)

3083 {

3084

3086

3088 }

3089

3090 return 0;

3091}

3092

3093

3094

3095

3096

3097

3098

3099

3100static int

3102{

3103 if (use_exec)

3104 {

3105

3107

3109

3111 }

3112

3113 return 0;

3114}

3115

3116static bool

3118{

3121 bool failed = false;

3122

3123 if (tuptable == NULL)

3124 failed = true;

3125 else if (processed != tuptable->numvals)

3126 failed = true;

3127

3128 return failed;

3129}

3130

3131

3132

3133

3134

3135

3136

3137

3138

3139

3142{

3148

3149

3152

3154

3155

3156

3157

3158

3160 "SPI Plan",

3163

3164

3167 newplan->plancxt = plancxt;

3171 if (plan->nargs > 0)

3172 {

3175 }

3176 else

3180

3181

3182

3183

3184

3185

3186

3187 foreach(lc, plan->plancache_list)

3188 {

3190

3192

3193

3195 }

3196

3198

3199

3200 plan->plancache_list = NIL;

3201

3202 return newplan;

3203}

3204

3205

3206

3207

3210{

3215

3216

3218

3219

3220

3221

3222

3223

3225 "SPI Plan",

3228

3229

3232 newplan->plancxt = plancxt;

3236 if (plan->nargs > 0)

3237 {

3240 }

3241 else

3245

3246

3247 foreach(lc, plan->plancache_list)

3248 {

3251

3254 }

3255

3257

3258

3259

3260

3261

3262

3263 newplan->saved = true;

3265

3267 {

3269

3271 }

3272

3273 return newplan;

3274}

3275

3276

3277

3278

3281{

3282

3284

3285

3287 return NULL;

3288

3290}

3291

3292

3293

3294

3295

3296int

3298{

3300 int res;

3301

3302 if (enr == NULL || enr->md.name == NULL)

3304

3305 res = _SPI_begin_call(false);

3306 if (res < 0)

3307 return res;

3308

3310 if (match)

3312 else

3313 {

3316

3319 }

3320

3322

3323 return res;

3324}

3325

3326

3327

3328

3329

3330int

3332{

3334 int res;

3335

3336 if (name == NULL)

3338

3339 res = _SPI_begin_call(false);

3340 if (res < 0)

3341 return res;

3342

3344 if (match)

3345 {

3348 }

3349 else

3351

3353

3354 return res;

3355}

3356

3357

3358

3359

3360

3361

3362

3363int

3365{

3366 if (tdata == NULL)

3368

3370 {

3373 int rc;

3374

3383 return rc;

3384 }

3385

3387 {

3390 int rc;

3391

3400 return rc;

3401 }

3402

3404}

List * raw_parser(const char *str, RawParseMode mode)

static bool Nulls[MAXATTR]

#define InvalidSubTransactionId

void InitializeQueryCompletion(QueryCompletion *qc)

const char * GetCommandTagName(CommandTag commandTag)

Datum datumTransfer(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

void ReThrowError(ErrorData *edata)

ErrorData * CopyErrorData(void)

void FlushErrorState(void)

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

int errcode(int sqlerrcode)

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

int errposition(int cursorpos)

#define ereport(elevel,...)

bool ExecSupportsBackwardScan(Plan *node)

void ExecutorEnd(QueryDesc *queryDesc)

void ExecutorFinish(QueryDesc *queryDesc)

void ExecutorStart(QueryDesc *queryDesc, int eflags)

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

#define EXEC_FLAG_SKIP_TRIGGERS

char * OidOutputFunctionCall(Oid functionId, Datum val)

#define DatumGetHeapTupleHeader(X)

Assert(PointerIsAligned(start, uint64))

const FormData_pg_attribute * SystemAttributeByName(const char *attname)

const FormData_pg_attribute * SystemAttributeDefinition(AttrNumber attno)

HeapTuple heap_copytuple(HeapTuple tuple)

HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)

void heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *values, bool *isnull)

Datum heap_copy_tuple_as_datum(HeapTuple tuple, TupleDesc tupleDesc)

void heap_freetuple(HeapTuple htup)

#define HeapTupleIsValid(tuple)

static Datum heap_getattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)

static void * GETSTRUCT(const HeapTupleData *tuple)

static void slist_delete_current(slist_mutable_iter *iter)

#define slist_foreach_modify(iter, lhead)

static void slist_init(slist_head *head)

static void slist_push_head(slist_head *head, slist_node *node)

#define slist_container(type, membername, ptr)

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

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

void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)

char * get_namespace_name(Oid nspid)

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

void * MemoryContextAlloc(MemoryContext context, Size size)

void MemoryContextReset(MemoryContext context)

MemoryContext TopTransactionContext

char * pstrdup(const char *in)

void MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)

void * repalloc(void *pointer, Size size)

void pfree(void *pointer)

void * palloc0(Size size)

MemoryContext TopMemoryContext

MemoryContext CurrentMemoryContext

MemoryContext CacheMemoryContext

void MemoryContextDelete(MemoryContext context)

void * repalloc_huge(void *pointer, Size size)

MemoryContext PortalContext

#define AllocSetContextCreate

#define ALLOCSET_DEFAULT_SIZES

#define ALLOCSET_SMALL_SIZES

int namestrcmp(Name name, const char *str)

#define IsA(nodeptr, _type_)

static MemoryContext MemoryContextSwitchTo(MemoryContext context)

ParamListInfo makeParamList(int numParams)

ParamListInfo copyParamList(ParamListInfo from)

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

#define CURSOR_OPT_SCROLL

#define CURSOR_OPT_PARALLEL_OK

#define CURSOR_OPT_NO_SCROLL

@ RAW_PARSE_PLPGSQL_ASSIGN2

@ RAW_PARSE_PLPGSQL_ASSIGN1

@ RAW_PARSE_PLPGSQL_ASSIGN3

FormData_pg_attribute * Form_pg_attribute

#define lfirst_node(type, lc)

static int list_length(const List *l)

#define linitial_node(type, l)

FormData_pg_type * Form_pg_type

void CachedPlanSetParentContext(CachedPlanSource *plansource, MemoryContext newcontext)

bool CachedPlanIsValid(CachedPlanSource *plansource)

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 * CreateOneShotCachedPlan(RawStmt *raw_parse_tree, const char *query_string, CommandTag commandTag)

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

CachedPlanSource * CopyCachedPlan(CachedPlanSource *plansource)

void ReleaseCachedPlan(CachedPlan *plan, ResourceOwner owner)

Portal CreateNewPortal(void)

void HoldPinnedPortals(void)

void PortalDrop(Portal portal, bool isTopCommit)

Portal GetPortalByName(const char *name)

void PortalDefineQuery(Portal portal, const char *prepStmtName, const char *sourceText, CommandTag commandTag, List *stmts, CachedPlan *cplan)

Portal CreatePortal(const char *name, bool allowDup, bool dupSilent)

void ForgetPortalSnapshots(void)

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

List * pg_analyze_and_rewrite_fixedparams(RawStmt *parsetree, const char *query_string, const Oid *paramTypes, int numParams, QueryEnvironment *queryEnv)

void ShowUsage(const char *title)

static Datum ObjectIdGetDatum(Oid 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)

bool PlannedStmtRequiresSnapshot(PlannedStmt *pstmt)

void EnsurePortalSnapshotExists(void)

void PortalStart(Portal portal, ParamListInfo params, int eflags, Snapshot snapshot)

uint64 PortalRunFetch(Portal portal, FetchDirection fdirection, long count, DestReceiver *dest)

EphemeralNamedRelation get_ENR(QueryEnvironment *queryEnv, const char *name)

void unregister_ENR(QueryEnvironment *queryEnv, const char *name)

QueryEnvironment * create_queryEnv(void)

void register_ENR(QueryEnvironment *queryEnv, EphemeralNamedRelation enr)

#define RelationGetRelationName(relation)

#define RelationGetNamespace(relation)

ResourceOwner CurrentResourceOwner

Snapshot GetTransactionSnapshot(void)

void PushActiveSnapshot(Snapshot snapshot)

void UpdateActiveSnapshotCommandId(void)

bool ActiveSnapshotSet(void)

void PopActiveSnapshot(void)

void PushCopiedSnapshot(Snapshot snapshot)

Snapshot GetActiveSnapshot(void)

void AtEOSubXact_SPI(bool isCommit, SubTransactionId mySubid)

List * SPI_plan_get_plan_sources(SPIPlanPtr plan)

SPIPlanPtr SPI_prepare_cursor(const char *src, int nargs, Oid *argtypes, int cursorOptions)

static int _SPI_execute_plan(SPIPlanPtr plan, const SPIExecuteOptions *options, Snapshot snapshot, Snapshot crosscheck_snapshot, bool fire_triggers)

int SPI_execute_plan_with_paramlist(SPIPlanPtr plan, ParamListInfo params, bool read_only, long tcount)

bool spi_printtup(TupleTableSlot *slot, DestReceiver *self)

static void _SPI_error_callback(void *arg)

static int _SPI_connected

void SPI_scroll_cursor_move(Portal portal, FetchDirection direction, long count)

static SPIPlanPtr _SPI_save_plan(SPIPlanPtr plan)

void SPI_cursor_move(Portal portal, bool forward, long count)

void SPI_freetuple(HeapTuple tuple)

int SPI_fnumber(TupleDesc tupdesc, const char *fname)

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

static int _SPI_end_call(bool use_exec)

bool SPI_plan_is_valid(SPIPlanPtr plan)

void SPI_commit_and_chain(void)

bool SPI_is_cursor_plan(SPIPlanPtr plan)

char * SPI_gettype(TupleDesc tupdesc, int fnumber)

void * SPI_repalloc(void *pointer, Size size)

SPIPlanPtr SPI_prepare_extended(const char *src, const SPIPrepareOptions *options)

Oid SPI_gettypeid(TupleDesc tupdesc, int fnumber)

static _SPI_connection * _SPI_stack

HeapTupleHeader SPI_returntuple(HeapTuple tuple, TupleDesc tupdesc)

int SPI_freeplan(SPIPlanPtr plan)

const char * SPI_result_code_string(int code)

void SPI_rollback_and_chain(void)

SPITupleTable * SPI_tuptable

static int _SPI_pquery(QueryDesc *queryDesc, bool fire_triggers, uint64 tcount)

Portal SPI_cursor_find(const char *name)

int SPI_unregister_relation(const char *name)

bool SPI_inside_nonatomic_context(void)

static void _SPI_cursor_operation(Portal portal, FetchDirection direction, long count, DestReceiver *dest)

int SPI_execute_snapshot(SPIPlanPtr plan, Datum *Values, const char *Nulls, Snapshot snapshot, Snapshot crosscheck_snapshot, bool read_only, bool fire_triggers, long tcount)

int SPI_execute_plan_extended(SPIPlanPtr plan, const SPIExecuteOptions *options)

SPIPlanPtr SPI_prepare_params(const char *src, ParserSetupHook parserSetup, void *parserSetupArg, int cursorOptions)

SPIPlanPtr SPI_saveplan(SPIPlanPtr plan)

void SPI_cursor_fetch(Portal portal, bool forward, long count)

Portal SPI_cursor_parse_open(const char *name, const char *src, const SPIParseOpenOptions *options)

int SPI_execute_plan(SPIPlanPtr plan, Datum *Values, const char *Nulls, bool read_only, long tcount)

static _SPI_connection * _SPI_current

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

CachedPlan * SPI_plan_get_cached_plan(SPIPlanPtr plan)

int SPI_register_trigger_data(TriggerData *tdata)

static int _SPI_stack_depth

static void _SPI_prepare_plan(const char *src, SPIPlanPtr plan)

Portal SPI_cursor_open_with_paramlist(const char *name, SPIPlanPtr plan, ParamListInfo params, bool read_only)

Portal SPI_cursor_open_with_args(const char *name, const char *src, int nargs, Oid *argtypes, Datum *Values, const char *Nulls, bool read_only, int cursorOptions)

void SPI_freetuptable(SPITupleTable *tuptable)

Portal SPI_cursor_open(const char *name, SPIPlanPtr plan, Datum *Values, const char *Nulls, bool read_only)

int SPI_exec(const char *src, long tcount)

static int _SPI_begin_call(bool use_exec)

static ParamListInfo _SPI_convert_params(int nargs, Oid *argtypes, Datum *Values, const char *Nulls)

int SPI_register_relation(EphemeralNamedRelation enr)

HeapTuple SPI_modifytuple(Relation rel, HeapTuple tuple, int natts, int *attnum, Datum *Values, const char *Nulls)

SPIPlanPtr SPI_prepare(const char *src, int nargs, Oid *argtypes)

int SPI_keepplan(SPIPlanPtr plan)

void SPI_cursor_close(Portal portal)

void SPI_pfree(void *pointer)

int SPI_connect_ext(int options)

int SPI_execp(SPIPlanPtr plan, Datum *Values, const char *Nulls, long tcount)

static void _SPI_prepare_oneshot_plan(const char *src, SPIPlanPtr plan)

char * SPI_getvalue(HeapTuple tuple, TupleDesc tupdesc, int fnumber)

void SPI_scroll_cursor_fetch(Portal portal, FetchDirection direction, long count)

char * SPI_getnspname(Relation rel)

static void _SPI_commit(bool chain)

int SPI_execute_extended(const char *src, const SPIExecuteOptions *options)

static Portal SPI_cursor_open_internal(const char *name, SPIPlanPtr plan, ParamListInfo paramLI, bool read_only)

void * SPI_palloc(Size size)

static bool _SPI_checktuples(void)

static EphemeralNamedRelation _SPI_find_ENR_by_name(const char *name)

static MemoryContext _SPI_execmem(void)

static MemoryContext _SPI_procmem(void)

int SPI_execute_with_args(const char *src, int nargs, Oid *argtypes, Datum *Values, const char *Nulls, bool read_only, long tcount)

void SPI_start_transaction(void)

HeapTuple SPI_copytuple(HeapTuple tuple)

int SPI_getargcount(SPIPlanPtr plan)

struct SPICallbackArg SPICallbackArg

void AtEOXact_SPI(bool isCommit)

int SPI_execute(const char *src, bool read_only, long tcount)

Datum SPI_getbinval(HeapTuple tuple, TupleDesc tupdesc, int fnumber, bool *isnull)

static void _SPI_rollback(bool chain)

char * SPI_getrelname(Relation rel)

char * SPI_fname(TupleDesc tupdesc, int fnumber)

Oid SPI_getargtypeid(SPIPlanPtr plan, int argIndex)

static SPIPlanPtr _SPI_make_plan_non_temp(SPIPlanPtr plan)

#define SPI_ERROR_TRANSACTION

#define SPI_ERROR_REL_NOT_FOUND

#define SPI_ERROR_REL_DUPLICATE

#define SPI_OPT_NONATOMIC

#define SPI_OK_TD_REGISTER

#define SPI_OK_REL_REGISTER

#define SPI_ERROR_OPUNKNOWN

#define SPI_OK_UPDATE_RETURNING

#define SPI_ERROR_UNCONNECTED

#define SPI_OK_REL_UNREGISTER

#define SPI_ERROR_ARGUMENT

#define SPI_ERROR_NOATTRIBUTE

#define SPI_OK_INSERT_RETURNING

#define SPI_ERROR_NOOUTFUNC

#define SPI_OK_DELETE_RETURNING

struct _SPI_plan * SPIPlanPtr

#define SPI_ERROR_TYPUNKNOWN

#define SPI_OK_MERGE_RETURNING

#define SPI_ERROR_CONNECT

struct CachedPlan * gplan

const char * query_string

struct RawStmt * raw_parse_tree

EphemeralNamedRelationMetadataData md

struct ErrorContextCallback * previous

void(* callback)(void *arg)

ParamExternData params[FLEXIBLE_ARRAY_MEMBER]

QueryEnvironment * queryEnv

MemoryContext portalContext

PlannedStmt * plannedstmt

Tuplestorestate * tg_oldtable

Tuplestorestate * tg_newtable

SubTransactionId connectSubid

SPITupleTable * outer_tuptable

QueryEnvironment * queryEnv

SubTransactionId execSubid

ParserSetupHook parserSetup

#define FirstLowInvalidHeapAttributeNumber

void ReleaseSysCache(HeapTuple tuple)

HeapTuple SearchSysCache1(int cacheId, Datum key1)

TupleDesc CreateTupleDescCopy(TupleDesc tupdesc)

static FormData_pg_attribute * TupleDescAttr(TupleDesc tupdesc, int i)

int64 tuplestore_tuple_count(Tuplestorestate *state)

static HeapTuple ExecCopySlotHeapTuple(TupleTableSlot *slot)

void assign_record_type_typmod(TupleDesc tupDesc)

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)

@ PROCESS_UTILITY_QUERY_NONATOMIC

void SaveTransactionCharacteristics(SavedTransactionCharacteristics *s)

void RestoreTransactionCharacteristics(const SavedTransactionCharacteristics *s)

SubTransactionId GetCurrentSubTransactionId(void)

void CommandCounterIncrement(void)

void StartTransactionCommand(void)

bool IsSubTransaction(void)

void CommitTransactionCommand(void)

void AbortCurrentTransaction(void)