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

39

40

41

42

43

44typedef struct

45{

50

51

52

53

54

55

56

57

58

59

60

61

62typedef enum

63{

66

68{

71 bool setsResult;

72 bool lazyEval;

76

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

112{

114

115 char *fname;

116 char *src;

117

120

123 bool typbyval;

124 bool returnsSet;

125 bool returnsTuple;

127 char prokind;

128

130

132 int num_queries;

133 bool raw_source;

134

136

140

142{

144

146 bool shutdown_reg;

147 bool lazyEval;

148 bool randomAccess;

149 bool ownSubcontext;

150

152

155

157 int jf_generation;

158

159

160

161

162

163

164

165

166

167

168

172

176

177

179

181

183

185

186

189

191

192

193

198 int paramno, int location);

200 const char *paramname, int location);

202 bool lazyEvalOK);

209 bool forValidator);

227 char prokind, bool insertDroppedCols);

229 Oid res_type, int32 res_typmod,

230 bool tlist_is_modifiable,

231 List **upper_tlist,

232 bool *upper_tlist_nontrivial);

238

239

240

241

242

243

244

245

246

247

250 Node *call_expr,

251 Oid inputCollation)

252{

255 int nargs;

256

258

259

261

262

263 pinfo->collation = inputCollation;

264

265

266

267

268

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

270 if (nargs > 0)

271 {

272 Oid *argOidVect;

273 int argnum;

274

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

276 memcpy(argOidVect,

277 procedureStruct->proargtypes.values,

278 nargs * sizeof(Oid));

279

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

281 {

282 Oid argtype = argOidVect[argnum];

283

284 if (IsPolymorphicType(argtype))

285 {

289 (errcode(ERRCODE_DATATYPE_MISMATCH),

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

292 argOidVect[argnum] = argtype;

293 }

294 }

295

296 pinfo->argtypes = argOidVect;

297 }

298

299

300

301

302 if (nargs > 0)

303 {

304 Datum proargnames;

305 Datum proargmodes;

306 int n_arg_names;

307 bool isNull;

308

309 proargnames = SysCacheGetAttr(PROCNAMEARGSNSP, procedureTuple,

310 Anum_pg_proc_proargnames,

311 &isNull);

312 if (isNull)

313 proargnames = PointerGetDatum(NULL);

314

315 proargmodes = SysCacheGetAttr(PROCNAMEARGSNSP, procedureTuple,

316 Anum_pg_proc_proargmodes,

317 &isNull);

318 if (isNull)

319 proargmodes = PointerGetDatum(NULL);

320

323

324

325 if (n_arg_names < nargs)

327 }

328 else

330

331 return pinfo;

332}

333

334

335

336

337void

339{

343

345}

346

347

348

349

352{

354 int nnames;

355 Node *field1;

356 Node *subfield = NULL;

357 const char *name1;

358 const char *name2 = NULL;

360

361

362

363

364

365

366 if (var != NULL)

367 return NULL;

368

369

370

371

372

373

374

375

376

377

378

379

380

381

382

383

384

386

387 if (nnames > 3)

388 return NULL;

389

391 nnames--;

392

394 name1 = strVal(field1);

395 if (nnames > 1)

396 {

398 name2 = strVal(subfield);

399 }

400

401 if (nnames == 3)

402 {

403

404

405

406

407

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

409 return NULL;

410

412

415 }

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

417 {

418

419

420

421

423

424 if (param)

425 {

426

427 subfield = NULL;

428 }

429 else

430 {

431

433 }

434 }

435 else

436 {

437

439 }

440

441 if (!param)

442 return NULL;

443

444 if (subfield)

445 {

446

447

448

449

450

455 NULL,

456 false,

458 }

459

460 return param;

461}

462

463

464

465

468{

470 int paramno = pref->number;

471

472

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

474 return NULL;

475

477}

478

479

480

481

484 int paramno, int location)

485{

487

490 param->paramid = paramno;

492 param->paramtypmod = -1;

495

496

497

498

499

500

502 param->paramcollid = pinfo->collation;

503

504 return (Node *) param;

505}

506

507

508

509

510

511

514 const char *paramname, int location)

515{

516 int i;

517

519 return NULL;

520

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

522 {

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

525 }

526

527 return NULL;

528}

529

530

531

532

535{

539

540

541

542

543

544

545

547 if (fcache == NULL)

548 {

553 fcache->mcb.arg = fcache;

556 }

557

558

559

560

561

562

563

564 if (fcache->eslist != NULL)

565 {

567 return fcache;

568 }

569

570

571

572

573

574

575

582 true,

583 false);

584

585

586

587

588

589

590

591 if (func != fcache->func)

592 {

593 if (fcache->func != NULL)

594 {

597 }

598 fcache->func = func;

600

602 }

603

604

605

606

607

609

610

613

614

615 fcache->eslist = NULL;

618

619 return fcache;

620}

621

622

623

624

625

626

627

628static bool

630{

634 int nstmts;

636

637

638

639

640 if (fcache->cplan)

641 {

643 fcache->cplan = NULL;

644 }

645 fcache->eslist = NULL;

646

647

648

649

650

651

652

654 {

656 return false;

659 }

660 else

662

666

667

668

669

670

671

672

677 NULL);

678

679

680

681

684 {

685 if (fcache->esarray == NULL)

689 else

693 }

694

695

696

697

699 {

702

703

704

705

706

708 {

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

712 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),

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

714

717 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),

718

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

721 }

722

725 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),

726

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

729

730

732 if (preves)

733 preves->next = newes;

734 else

735 fcache->eslist = newes;

736

737 newes->next = NULL;

739 newes->setsResult = false;

740 newes->lazyEval = false;

742 newes->qd = NULL;

743

744 if (stmt->canSetTag)

745 lasttages = newes;

746

747 preves = newes;

748 }

749

750

751

752

753

755 return true;

756

757

758

759

760

761

762

763

764

765

766

767

768

769

773 {

775 List *resulttlist;

777

778

781 "SQL function junkfilter",

783 else

786

788

789

790

791

792

793

795

796

797

798

799

800

801

802

803

807 slot);

808 else

810

811

812

813

814

815

816

817

818

819

821

822

825

826

828

830 }

831

835 {

836

837

838

839

840

842 }

843

844

845

846

847

848

849

850

851

852

853

854

855

856

857

859 {

865 }

866

867 return true;

868}

869

870

871

872

873

874

875static void

877{

878 int qindex;

879 bool islast;

881 List *queryTree_list;

883

884

886 Assert(qindex < func->num_queries);

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

888

889

890

891

892

893

894

895

896

897

899 {

900

902

905 func->src,

909 }

910 else

911 {

912

914

917 func->src,

920 func->src,

923 NULL);

924 }

925

926

927

928

930

931

932

933

934

935

936

937

938

939

940

941

942

943

944

945

946

947

948

949 if (islast)

954 false);

955

956

957

958

959

961 queryTree_list,

962 NULL,

963 NULL,

964 0,

968 false);

969

970

971

972

973

976 islast ? func : NULL);

977

978

979

980

981

985

986

987

988

989

991

992

993

994

995

996

997 if (islast)

998 {

999 func->source_list = NIL;

1002 }

1003}

1004

1005

1006

1007

1008

1009

1010

1011

1012

1013

1014

1015static void

1020 bool forValidator)

1021{

1028 Oid rettype;

1031 bool isNull;

1032 List *source_list;

1033

1034

1035

1036

1037

1039 comperrcontext.arg = func;

1042

1043

1044

1045

1046

1048 "SQL function",

1050

1051

1052

1053

1054

1056 "SQL function parse trees",

1059

1060

1061

1062

1063

1065 NameStr(procedureStruct->proname));

1067

1068

1069

1070

1071

1073

1074 func->rettype = rettype;

1075 if (rettupdesc)

1076 {

1080 }

1081

1082

1084

1085

1086 func->returnsSet = procedureStruct->proretset;

1087

1088

1090 (procedureStruct->provolatile != PROVOLATILE_VOLATILE);

1091

1092

1093 func->prokind = procedureStruct->prokind;

1094

1095

1096

1097

1098

1099

1105

1106

1107

1108

1109

1114

1115

1116

1117

1121

1122

1124 procedureTuple,

1125 Anum_pg_proc_prosqlbody,

1126 &isNull);

1127 if (!isNull)

1128 {

1129

1131

1135 else

1138 }

1139 else

1140 {

1141

1144 }

1145

1146

1147

1148

1149

1151

1152

1153

1154

1155

1156

1157

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

1160 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),

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

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

1164

1165

1169

1170

1171

1172

1173

1174

1175

1178

1180}

1181

1182

1183

1184

1185

1186

1187

1188static void

1190{

1193

1194

1196 {

1198

1200 }

1202

1203

1204

1205

1206

1210}

1211

1212

1213

1214

1215

1216

1217

1218static void

1220{

1221

1222

1223

1224

1225

1227

1228

1229

1230

1231

1232

1233 if (arg != NULL)

1234 {

1236 bool returnsTuple;

1237

1242 false);

1245 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),

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

1247 }

1248}

1249

1250

1251static void

1253{

1256

1258

1259

1261

1262

1263

1264

1265

1266

1267

1268

1269

1270

1271

1272

1274 {

1276 "SQL function execution",

1279 }

1281 {

1282

1283

1284

1285

1286

1287

1288

1289

1291 "SQL function execution",

1294 }

1295 else

1296 {

1299 }

1300

1301

1302

1303

1304

1306 {

1309 {

1313 }

1314 }

1315

1316

1318

1319

1320

1321

1322

1324 {

1326

1328

1331 myState->tstore = fcache->tstore;

1333

1334

1336 }

1337 else

1339

1341 NULL,

1348 0);

1349

1350

1352 {

1353

1354

1355

1356

1357

1358

1359

1360 int eflags;

1361

1364 else

1365 eflags = 0;

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

1368 }

1369

1371

1373}

1374

1375

1376

1377static bool

1379{

1380 bool result;

1382

1383

1385

1387 {

1390 true,

1395 NULL);

1396 result = true;

1397 }

1398 else

1399 {

1400

1402

1404

1405

1406

1407

1408

1410 }

1411

1413

1414 return result;

1415}

1416

1417

1418static void

1420{

1422

1423

1425

1426

1428

1429

1431 {

1434 }

1435

1437

1439 es->qd = NULL;

1440

1442

1443

1447}

1448

1449

1450static void

1453{

1454 int nargs = fcinfo->nargs;

1455

1456 if (nargs > 0)

1457 {

1461

1462 if (fcache->paramLI == NULL)

1463 {

1464

1466

1469 fcache->paramLI = paramLI;

1471 }

1472 else

1473 {

1474 paramLI = fcache->paramLI;

1476 }

1477

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

1479 {

1481

1482

1483

1484

1485

1486

1487

1488

1489

1490

1491

1492

1493

1497 argtyplen[i]);

1498

1500 prm->ptype = argtypes[i];

1501 }

1502 }

1503 else

1505}

1506

1507

1508

1509

1510

1511

1512

1517{

1519

1520

1521

1522

1523

1524

1525

1527 {

1528

1529 fcinfo->isnull = false;

1531 }

1532 else

1533 {

1534

1535

1536

1537

1539

1540 if (!fcinfo->isnull)

1542 }

1543

1544

1546

1548}

1549

1550

1551

1552

1555{

1559 bool randomAccess;

1560 bool lazyEvalOK;

1561 bool pushed_snapshot;

1565

1566

1567 if (fcinfo->flinfo->fn_retset)

1568 {

1570

1571

1572

1573

1574

1575

1576

1581 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),

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

1585

1587 }

1588 else

1589 {

1590 randomAccess = false;

1591 lazyEvalOK = true;

1592

1593 tscontext = NULL;

1594 }

1595

1596

1597

1598

1600

1601

1604

1605

1606

1607

1609 sqlerrcontext.arg = fcache;

1612

1613

1614

1615

1616

1617 do

1618 {

1619 es = fcache->eslist;

1621 es = es->next;

1622 if (es)

1623 break;

1625

1626

1627

1628

1629

1630

1631

1632

1633

1634

1635

1636

1637

1638

1639

1640

1641

1642

1643

1644 pushed_snapshot = false;

1645 while (es)

1646 {

1647 bool completed;

1648

1650 {

1651

1652

1653

1654

1655

1656

1658 {

1660 if (!pushed_snapshot)

1661 {

1663 pushed_snapshot = true;

1664 }

1665 else

1667 }

1668

1670 }

1672 {

1673

1675 pushed_snapshot = true;

1676 }

1677

1679

1680

1681

1682

1683

1684

1685

1686

1687

1688

1691

1692

1693

1694

1695

1696

1697

1698

1699

1700

1702 break;

1703

1704

1705

1706

1707 es = es->next;

1708 while (!es)

1709 {

1710

1711

1712

1713

1714

1715

1716 if (pushed_snapshot)

1717 {

1719 pushed_snapshot = false;

1720 }

1721

1723 break;

1724

1725 es = fcache->eslist;

1726 }

1727 }

1728

1729

1730

1731

1732

1734 {

1736

1737 if (es)

1738 {

1739

1740

1741

1742

1744

1748

1750

1751

1752

1753

1755

1756

1757

1758

1759

1761 {

1766 }

1767 }

1769 {

1770

1771

1772

1773

1775

1776 fcinfo->isnull = true;

1777 result = (Datum) 0;

1778

1779

1781 {

1786 }

1787 }

1788 else

1789 {

1790

1791

1792

1793

1794

1795

1796

1797

1798

1802 fcache->tstore = NULL;

1803

1806

1807 fcinfo->isnull = true;

1808 result = (Datum) 0;

1809

1810

1812 {

1817 }

1818 }

1819 }

1820 else

1821 {

1822

1823

1824

1826 {

1827

1831 else

1832 {

1833 fcinfo->isnull = true;

1834 result = (Datum) 0;

1835 }

1836 }

1837 else

1838 {

1839

1841 fcinfo->isnull = true;

1842 result = (Datum) 0;

1843 }

1844 }

1845

1846

1847 if (pushed_snapshot)

1849

1850

1851

1852

1853

1854 if (es == NULL)

1855 fcache->eslist = NULL;

1856

1858

1859 return result;

1860}

1861

1862

1863

1864

1865

1866static void

1868{

1870 int syntaxerrposition;

1871

1872

1873

1874

1875

1876 if (func->fname == NULL)

1877 return;

1878

1879

1880

1881

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

1884 {

1888 }

1889

1890

1891

1892

1893

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

1895}

1896

1897

1898

1899

1900static void

1902{

1904 int syntaxerrposition;

1905

1906

1907

1908

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

1911 {

1915 }

1916

1917

1918

1919

1920

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

1924 else

1926}

1927

1928

1929

1930

1931

1932

1933

1934

1935

1936

1937

1938static void

1940{

1943

1944 es = fcache->eslist;

1945 while (es)

1946 {

1947

1949 {

1950

1953

1955

1958 }

1959 es = es->next;

1960 }

1961 fcache->eslist = NULL;

1962

1963

1966 fcache->tstore = NULL;

1967

1968

1969 if (fcache->cplan)

1971 fcache->cplan = NULL;

1972

1973

1975}

1976

1977

1978

1979

1980

1981

1982

1983

1984

1985static void

1987{

1989

1990

1991 if (fcache->func != NULL)

1992 {

1995

1996 fcache->func = NULL;

1997 }

1998}

1999

2000

2001

2002

2003

2004

2005

2006void

2008{

2010

2011

2012 foreach(lc, queryTreeLists)

2013 {

2015

2017 }

2018}

2019

2020

2021

2022

2023static void

2025{

2027

2028 foreach(lc, queryTreeList)

2029 {

2031

2032

2033

2034

2035

2036

2037

2038

2041 {

2043

2046 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),

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

2048 }

2049 }

2050}

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

2086

2087bool

2090 char prokind,

2091 bool insertDroppedCols)

2092{

2093 List *queryTreeList;

2094

2095

2096

2097

2098

2099

2100

2101

2102

2103

2104

2105

2106

2107 if (queryTreeLists != NIL)

2109 else

2110 queryTreeList = NIL;

2111

2113 rettype, rettupdesc,

2114 prokind, insertDroppedCols);

2115}

2116

2117

2118

2119

2120

2121static bool

2124 char prokind, bool insertDroppedCols)

2125{

2126 bool is_tuple_result = false;

2129 List *tlist;

2130 int tlistlen;

2131 bool tlist_is_modifiable;

2132 char fn_typtype;

2133 List *upper_tlist = NIL;

2134 bool upper_tlist_nontrivial = false;

2136

2137

2138

2139

2140

2141 if (rettype == VOIDOID)

2142 return false;

2143

2144

2145

2146

2147

2148

2150 parse_cell = NULL;

2151 foreach(lc, queryTreeList)

2152 {

2154

2155 if (q->canSetTag)

2156 {

2158 parse_cell = lc;

2159 }

2160 }

2161

2162

2163

2164

2165

2166

2167

2168

2169

2170

2171

2172

2175 {

2176 tlist = parse->targetList;

2177

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

2179 }

2180 else if (parse &&

2185 parse->returningList)

2186 {

2187 tlist = parse->returningList;

2188

2189 tlist_is_modifiable = true;

2190 }

2191 else

2192 {

2193

2195 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),

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

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

2199 return false;

2200 }

2201

2202

2203

2204

2205

2206

2207

2208

2209

2210

2211

2212

2213

2214

2216

2218

2219 if (fn_typtype == TYPTYPE_BASE ||

2220 fn_typtype == TYPTYPE_DOMAIN ||

2221 fn_typtype == TYPTYPE_ENUM ||

2222 fn_typtype == TYPTYPE_RANGE ||

2223 fn_typtype == TYPTYPE_MULTIRANGE)

2224 {

2225

2226

2227

2228

2230

2231 if (tlistlen != 1)

2233 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),

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

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

2237

2238

2240 Assert(!tle->resjunk);

2241

2243 tlist_is_modifiable,

2244 &upper_tlist,

2245 &upper_tlist_nontrivial))

2247 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),

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

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

2252 }

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

2254 {

2255

2256

2257

2258

2259

2260

2261

2262

2263

2264

2265

2266 int tupnatts;

2267 int tuplogcols;

2268 int colindex;

2269

2270

2271

2272

2273

2274

2275

2276

2277

2278

2279

2280

2281

2282

2283

2284

2285

2286

2287

2288

2289

2290

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

2292 {

2294

2295 Assert(!tle->resjunk);

2297 tlist_is_modifiable,

2298 &upper_tlist,

2299 &upper_tlist_nontrivial))

2300 {

2301

2302 goto tlist_coercion_finished;

2303 }

2304 }

2305

2306

2307

2308

2309

2310 if (rettupdesc == NULL)

2311 return true;

2312

2313

2314

2315

2316

2317

2318

2319 tupnatts = rettupdesc->natts;

2320 tuplogcols = 0;

2321 colindex = 0;

2322

2323 foreach(lc, tlist)

2324 {

2327

2328

2329 if (tle->resjunk)

2330 continue;

2331

2332 do

2333 {

2334 colindex++;

2335 if (colindex > tupnatts)

2337 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),

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

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

2342 if (attr->attisdropped && insertDroppedCols)

2343 {

2344 Expr *null_expr;

2345

2346

2348 -1,

2352 true,

2353 true );

2354 upper_tlist = lappend(upper_tlist,

2357 NULL,

2358 false));

2359 upper_tlist_nontrivial = true;

2360 }

2361 } while (attr->attisdropped);

2362 tuplogcols++;

2363

2365 attr->atttypid, attr->atttypmod,

2366 tlist_is_modifiable,

2367 &upper_tlist,

2368 &upper_tlist_nontrivial))

2370 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),

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

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

2376 tuplogcols)));

2377 }

2378

2379

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

2381 {

2384 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),

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

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

2388 if (insertDroppedCols)

2389 {

2390 Expr *null_expr;

2391

2392

2394 -1,

2398 true,

2399 true );

2400 upper_tlist = lappend(upper_tlist,

2403 NULL,

2404 false));

2405 upper_tlist_nontrivial = true;

2406 }

2407 }

2408

2409

2410 is_tuple_result = true;

2411 }

2412 else

2414 (errcode(ERRCODE_INVALID_FUNCTION_DEFINITION),

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

2417

2418tlist_coercion_finished:

2419

2420

2421

2422

2423

2424

2425

2426 if (upper_tlist_nontrivial)

2427 {

2428 Query *newquery;

2429 List *colnames;

2432

2434

2435

2438 newquery->querySource = parse->querySource;

2439 newquery->canSetTag = true;

2441

2442

2443 colnames = NIL;

2444 foreach(lc, parse->targetList)

2445 {

2447

2448 if (tle->resjunk)

2449 continue;

2450 colnames = lappend(colnames,

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

2452 }

2453

2454

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

2459 rte->lateral = false;

2460 rte->inh = false;

2461 rte->inFromCl = true;

2463

2467

2468

2469

2470

2471

2472 newquery->hasRowSecurity = parse->hasRowSecurity;

2473

2474

2475 lfirst(parse_cell) = newquery;

2476 }

2477

2478 return is_tuple_result;

2479}

2480

2481

2482

2483

2484

2485

2486

2487

2488

2489

2490

2491static bool

2493 Oid res_type,

2494 int32 res_typmod,

2495 bool tlist_is_modifiable,

2496 List **upper_tlist,

2497 bool *upper_tlist_nontrivial)

2498{

2500 Expr *new_tle_expr;

2501 Node *cast_result;

2502

2503

2504

2505

2506

2507

2508

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

2510 {

2511

2515 res_type, res_typmod,

2518 -1);

2519 if (cast_result == NULL)

2520 return false;

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

2523

2525 }

2526 else

2527 {

2528

2530

2532 (Node *) var,

2533 var->vartype,

2534 res_type, res_typmod,

2537 -1);

2538 if (cast_result == NULL)

2539 return false;

2541

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

2543 *upper_tlist_nontrivial = true;

2544 new_tle_expr = (Expr *) cast_result;

2545 }

2548 src_tle->resname, false);

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

2550 return true;

2551}

2552

2553

2554

2555

2556

2557static List *

2559{

2562

2563 foreach(lc, queryTreeList)

2564 {

2566

2567 if (q->canSetTag)

2569 }

2572 return parse->targetList;

2573 else if (parse &&

2578 parse->returningList)

2579 return parse->returningList;

2580 else

2581 return NIL;

2582}

2583

2584

2585

2586

2587

2590{

2592

2598

2599

2600

2602}

2603

2604

2605

2606

2607static void

2609{

2610

2611}

2612

2613

2614

2615

2616static bool

2618{

2620

2621 if (myState->tstore)

2622 {

2623

2624

2625

2627

2628

2630 }

2631 else

2632 {

2633

2634

2635

2636

2638 {

2639

2642

2643

2645 }

2646 }

2647

2648 return true;

2649}

2650

2651

2652

2653

2654static void

2656{

2657

2658}

2659

2660

2661

2662

2663static void

2665{

2667}

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

bool ExecutorStart(QueryDesc *queryDesc, int eflags)

void ExecutorEnd(QueryDesc *queryDesc)

void ExecutorFinish(QueryDesc *queryDesc)

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, CachedPlan *cplan, 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)