| Line | Hits | Source | Commit |
| 395 |
- |
overexplain_range_table(PlannedStmt *plannedstmt, ExplainState *es) |
- |
| 396 |
- |
{ |
- |
| 397 |
- |
Index rti; |
- |
| 398 |
- |
|
- |
| 399 |
- |
/* Open group, one entry per RangeTblEntry */ |
- |
| 400 |
- |
ExplainOpenGroup("Range Table", "Range Table", false, es); |
- |
| 401 |
- |
|
- |
| 402 |
- |
/* Iterate over the range table */ |
- |
| 403 |
- |
for (rti = 1; rti <= list_length(plannedstmt->rtable); ++rti) |
- |
| 404 |
- |
{ |
- |
| 405 |
- |
RangeTblEntry *rte = rt_fetch(rti, plannedstmt->rtable); |
- |
| 406 |
- |
char *kind = NULL; |
- |
| 407 |
- |
char *relkind; |
- |
| 408 |
- |
|
- |
| 409 |
- |
/* NULL entries are possible; skip them */ |
- |
| 410 |
- |
if (rte == NULL) |
- |
| 411 |
- |
continue; |
- |
| 412 |
- |
|
- |
| 413 |
- |
/* Translate rtekind to a string */ |
- |
| 414 |
- |
switch (rte->rtekind) |
- |
| 415 |
- |
{ |
- |
| 416 |
- |
case RTE_RELATION: |
- |
| 417 |
- |
kind = "relation"; |
- |
| 418 |
- |
break; |
- |
| 419 |
- |
case RTE_SUBQUERY: |
- |
| 420 |
- |
kind = "subquery"; |
- |
| 421 |
- |
break; |
- |
| 422 |
- |
case RTE_JOIN: |
- |
| 423 |
- |
kind = "join"; |
- |
| 424 |
- |
break; |
- |
| 425 |
- |
case RTE_FUNCTION: |
- |
| 426 |
- |
kind = "function"; |
- |
| 427 |
- |
break; |
- |
| 428 |
- |
case RTE_TABLEFUNC: |
- |
| 429 |
- |
kind = "tablefunc"; |
- |
| 430 |
- |
break; |
- |
| 431 |
- |
case RTE_VALUES: |
- |
| 432 |
- |
kind = "values"; |
- |
| 433 |
- |
break; |
- |
| 434 |
- |
case RTE_CTE: |
- |
| 435 |
- |
kind = "cte"; |
- |
| 436 |
- |
break; |
- |
| 437 |
- |
case RTE_NAMEDTUPLESTORE: |
- |
| 438 |
- |
kind = "namedtuplestore"; |
- |
| 439 |
- |
break; |
- |
| 440 |
- |
case RTE_RESULT: |
- |
| 441 |
- |
kind = "result"; |
- |
| 442 |
- |
break; |
- |
| 443 |
- |
case RTE_GROUP: |
- |
| 444 |
- |
kind = "group"; |
- |
| 445 |
- |
break; |
- |
| 446 |
0 |
case RTE_GRAPH_TABLE: |
86c14eaWIP: SQL Property Graph Queries (SQL/PGQ) |
| 447 |
- |
|
86c14eaWIP: SQL Property Graph Queries (SQL/PGQ) |
| 448 |
- |
/* |
86c14eaWIP: SQL Property Graph Queries (SQL/PGQ) |
| 449 |
- |
* We should not see RTE of this kind here since property |
86c14eaWIP: SQL Property Graph Queries (SQL/PGQ) |
| 450 |
- |
* graph RTE gets converted to subquery RTE in |
86c14eaWIP: SQL Property Graph Queries (SQL/PGQ) |
| 451 |
- |
* RewriteGraphTable(). In case we decide not to do the |
86c14eaWIP: SQL Property Graph Queries (SQL/PGQ) |
| 452 |
- |
* conversion and leave RTEkind unchanged in future, print |
86c14eaWIP: SQL Property Graph Queries (SQL/PGQ) |
| 453 |
- |
* correct name of RTE kind. |
86c14eaWIP: SQL Property Graph Queries (SQL/PGQ) |
| 454 |
- |
*/ |
86c14eaWIP: SQL Property Graph Queries (SQL/PGQ) |
| 455 |
0 |
kind = "graph_table"; |
86c14eaWIP: SQL Property Graph Queries (SQL/PGQ) |
| 456 |
0 |
break; |
86c14eaWIP: SQL Property Graph Queries (SQL/PGQ) |
| 457 |
- |
} |
- |
| 458 |
- |
|
- |
| 459 |
- |
/* Begin group for this specific RTE */ |
- |
| 460 |
- |
ExplainOpenGroup("Range Table Entry", NULL, true, es); |
- |
| 461 |
- |
|
- |
| 462 |
- |
/* |
- |
| 463 |
- |
* In text format, the summary line displays the range table index and |
- |
| 464 |
- |
* rtekind, plus indications if rte->inh and/or rte->inFromCl are set. |
- |
| 465 |
- |
* In other formats, we display those as separate properties. |
- |
| 466 |
- |
*/ |
- |
| 467 |
- |
if (es->format == EXPLAIN_FORMAT_TEXT) |
- |
| 468 |
- |
{ |
- |
| 469 |
- |
ExplainIndentText(es); |
- |
| 470 |
- |
appendStringInfo(es->str, "RTI %u (%s%s%s):\n", rti, kind, |
- |
| 471 |
- |
rte->inh ? ", inherited" : "", |
- |
| 472 |
- |
rte->inFromCl ? ", in-from-clause" : ""); |
- |
| 473 |
- |
es->indent++; |
- |
| 474 |
- |
} |
- |
| 475 |
- |
else |
- |
| 476 |
- |
{ |
- |
| 477 |
- |
ExplainPropertyUInteger("RTI", NULL, rti, es); |
- |
| 478 |
- |
ExplainPropertyText("Kind", kind, es); |
- |
| 479 |
- |
ExplainPropertyBool("Inherited", rte->inh, es); |
- |
| 480 |
- |
ExplainPropertyBool("In From Clause", rte->inFromCl, es); |
- |
| 481 |
- |
} |
- |
| 482 |
- |
|
- |
| 483 |
- |
/* rte->alias is optional; rte->eref is requested */ |
- |
| 484 |
- |
if (rte->alias != NULL) |
- |
| 485 |
- |
overexplain_alias("Alias", rte->alias, es); |
- |
| 486 |
- |
overexplain_alias("Eref", rte->eref, es); |
- |
| 487 |
- |
|
- |
| 488 |
- |
/* |
- |
| 489 |
- |
* We adhere to the usual EXPLAIN convention that schema names are |
- |
| 490 |
- |
* displayed only in verbose mode, and we emit nothing if there is no |
- |
| 491 |
- |
* relation OID. |
- |
| 492 |
- |
*/ |
- |
| 493 |
- |
if (rte->relid != 0) |
- |
| 494 |
- |
{ |
- |
| 495 |
- |
const char *relname; |
- |
| 496 |
- |
const char *qualname; |
- |
| 497 |
- |
|
- |
| 498 |
- |
relname = quote_identifier(get_rel_name(rte->relid)); |
- |
| 499 |
- |
|
- |
| 500 |
- |
if (es->verbose) |
- |
| 501 |
- |
{ |
- |
| 502 |
- |
Oid nspoid = get_rel_namespace(rte->relid); |
- |
| 503 |
- |
char *nspname; |
- |
| 504 |
- |
|
- |
| 505 |
- |
nspname = get_namespace_name_or_temp(nspoid); |
- |
| 506 |
- |
qualname = psprintf("%s.%s", quote_identifier(nspname), |
- |
| 507 |
- |
relname); |
- |
| 508 |
- |
} |
- |
| 509 |
- |
else |
- |
| 510 |
- |
qualname = relname; |
- |
| 511 |
- |
|
- |
| 512 |
- |
ExplainPropertyText("Relation", qualname, es); |
- |
| 513 |
- |
} |
- |
| 514 |
- |
|
- |
| 515 |
- |
/* Translate relkind, if any, to a string */ |
- |
| 516 |
- |
switch (rte->relkind) |
- |
| 517 |
- |
{ |
- |
| 518 |
- |
case RELKIND_RELATION: |
- |
| 519 |
- |
relkind = "relation"; |
- |
| 520 |
- |
break; |
- |
| 521 |
- |
case RELKIND_INDEX: |
- |
| 522 |
- |
relkind = "index"; |
- |
| 523 |
- |
break; |
- |
| 524 |
- |
case RELKIND_SEQUENCE: |
- |
| 525 |
- |
relkind = "sequence"; |
- |
| 526 |
- |
break; |
- |
| 527 |
- |
case RELKIND_TOASTVALUE: |
- |
| 528 |
- |
relkind = "toastvalue"; |
- |
| 529 |
- |
break; |
- |
| 530 |
- |
case RELKIND_VIEW: |
- |
| 531 |
- |
relkind = "view"; |
- |
| 532 |
- |
break; |
- |
| 533 |
- |
case RELKIND_MATVIEW: |
- |
| 534 |
- |
relkind = "matview"; |
- |
| 535 |
- |
break; |
- |
| 536 |
- |
case RELKIND_COMPOSITE_TYPE: |
- |
| 537 |
- |
relkind = "composite_type"; |
- |
| 538 |
- |
break; |
- |
| 539 |
- |
case RELKIND_FOREIGN_TABLE: |
- |
| 540 |
- |
relkind = "foreign_table"; |
- |
| 541 |
- |
break; |
- |
| 542 |
- |
case RELKIND_PARTITIONED_TABLE: |
- |
| 543 |
- |
relkind = "partitioned_table"; |
- |
| 544 |
- |
break; |
- |
| 545 |
- |
case RELKIND_PARTITIONED_INDEX: |
- |
| 546 |
- |
relkind = "partitioned_index"; |
- |
| 547 |
- |
break; |
- |
| 548 |
- |
case RELKIND_PROPGRAPH: |
86c14eaWIP: SQL Property Graph Queries (SQL/PGQ) |
| 549 |
- |
relkind = "property_graph"; |
86c14eaWIP: SQL Property Graph Queries (SQL/PGQ) |
| 550 |
- |
break; |
86c14eaWIP: SQL Property Graph Queries (SQL/PGQ) |
| 551 |
- |
case '\0': |
- |
| 552 |
- |
relkind = NULL; |
- |
| 553 |
- |
break; |
- |
| 554 |
- |
default: |
- |
| 555 |
- |
relkind = psprintf("%c", rte->relkind); |
- |
| 556 |
- |
break; |
- |
| 557 |
- |
} |
- |
| 558 |
- |
|
- |
| 559 |
- |
/* If there is a relkind, show it */ |
- |
| 560 |
- |
if (relkind != NULL) |
- |
| 561 |
- |
ExplainPropertyText("Relation Kind", relkind, es); |
- |
| 562 |
- |
|
- |
| 563 |
- |
/* If there is a lock mode, show it */ |
- |
| 564 |
- |
if (rte->rellockmode != 0) |
- |
| 565 |
- |
ExplainPropertyText("Relation Lock Mode", |
- |
| 566 |
- |
GetLockmodeName(DEFAULT_LOCKMETHOD, |
- |
| 567 |
- |
rte->rellockmode), es); |
- |
| 568 |
- |
|
- |
| 569 |
- |
/* |
- |
| 570 |
- |
* If there is a perminfoindex, show it. We don't try to display |
- |
| 571 |
- |
* information from the RTEPermissionInfo node here because they are |
- |
| 572 |
- |
* just indexes plannedstmt->permInfos which could be separately |
- |
| 573 |
- |
* dumped if someone wants to add EXPLAIN (PERMISSIONS) or similar. |
- |
| 574 |
- |
*/ |
- |
| 575 |
- |
if (rte->perminfoindex != 0) |
- |
| 576 |
- |
ExplainPropertyInteger("Permission Info Index", NULL, |
- |
| 577 |
- |
rte->perminfoindex, es); |
- |
| 578 |
- |
|
- |
| 579 |
- |
/* |
- |
| 580 |
- |
* add_rte_to_flat_rtable will clear rte->tablesample and |
- |
| 581 |
- |
* rte->subquery in the finished plan, so skip those fields. |
- |
| 582 |
- |
* |
- |
| 583 |
- |
* However, the security_barrier flag is not shown by the core code, |
- |
| 584 |
- |
* so let's print it here. |
- |
| 585 |
- |
*/ |
- |
| 586 |
- |
if (es->format != EXPLAIN_FORMAT_TEXT || rte->security_barrier) |
- |
| 587 |
- |
ExplainPropertyBool("Security Barrier", rte->security_barrier, es); |
- |
| 588 |
- |
|
- |
| 589 |
- |
/* |
- |
| 590 |
- |
* If this is a join, print out the fields that are specifically valid |
- |
| 591 |
- |
* for joins. |
- |
| 592 |
- |
*/ |
- |
| 593 |
- |
if (rte->rtekind == RTE_JOIN) |
- |
| 594 |
- |
{ |
- |
| 595 |
- |
char *jointype; |
- |
| 596 |
- |
|
- |
| 597 |
- |
switch (rte->jointype) |
- |
| 598 |
- |
{ |
- |
| 599 |
- |
case JOIN_INNER: |
- |
| 600 |
- |
jointype = "Inner"; |
- |
| 601 |
- |
break; |
- |
| 602 |
- |
case JOIN_LEFT: |
- |
| 603 |
- |
jointype = "Left"; |
- |
| 604 |
- |
break; |
- |
| 605 |
- |
case JOIN_FULL: |
- |
| 606 |
- |
jointype = "Full"; |
- |
| 607 |
- |
break; |
- |
| 608 |
- |
case JOIN_RIGHT: |
- |
| 609 |
- |
jointype = "Right"; |
- |
| 610 |
- |
break; |
- |
| 611 |
- |
case JOIN_SEMI: |
- |
| 612 |
- |
jointype = "Semi"; |
- |
| 613 |
- |
break; |
- |
| 614 |
- |
case JOIN_ANTI: |
- |
| 615 |
- |
jointype = "Anti"; |
- |
| 616 |
- |
break; |
- |
| 617 |
- |
case JOIN_RIGHT_SEMI: |
- |
| 618 |
- |
jointype = "Right Semi"; |
- |
| 619 |
- |
break; |
- |
| 620 |
- |
case JOIN_RIGHT_ANTI: |
- |
| 621 |
- |
jointype = "Right Anti"; |
- |
| 622 |
- |
break; |
- |
| 623 |
- |
default: |
- |
| 624 |
- |
jointype = "???"; |
- |
| 625 |
- |
break; |
- |
| 626 |
- |
} |
- |
| 627 |
- |
|
- |
| 628 |
- |
/* Join type */ |
- |
| 629 |
- |
ExplainPropertyText("Join Type", jointype, es); |
- |
| 630 |
- |
|
- |
| 631 |
- |
/* # of JOIN USING columns */ |
- |
| 632 |
- |
if (es->format != EXPLAIN_FORMAT_TEXT || rte->joinmergedcols != 0) |
- |
| 633 |
- |
ExplainPropertyInteger("JOIN USING Columns", NULL, |
- |
| 634 |
- |
rte->joinmergedcols, es); |
- |
| 635 |
- |
|
- |
| 636 |
- |
/* |
- |
| 637 |
- |
* add_rte_to_flat_rtable will clear joinaliasvars, joinleftcols, |
- |
| 638 |
- |
* joinrightcols, and join_using_alias here, so skip those fields. |
- |
| 639 |
- |
*/ |
- |
| 640 |
- |
} |
- |
| 641 |
- |
|
- |
| 642 |
- |
/* |
- |
| 643 |
- |
* add_rte_to_flat_rtable will clear functions, tablefunc, and |
- |
| 644 |
- |
* values_lists, but we can display funcordinality. |
- |
| 645 |
- |
*/ |
- |
| 646 |
- |
if (rte->rtekind == RTE_FUNCTION) |
- |
| 647 |
- |
ExplainPropertyBool("WITH ORDINALITY", rte->funcordinality, es); |
- |
| 648 |
- |
|
- |
| 649 |
- |
/* |
- |
| 650 |
- |
* If this is a CTE, print out CTE-related properties. |
- |
| 651 |
- |
*/ |
- |
| 652 |
- |
if (rte->rtekind == RTE_CTE) |
- |
| 653 |
- |
{ |
- |
| 654 |
- |
ExplainPropertyText("CTE Name", rte->ctename, es); |
- |
| 655 |
- |
ExplainPropertyUInteger("CTE Levels Up", NULL, rte->ctelevelsup, |
- |
| 656 |
- |
es); |
- |
| 657 |
- |
ExplainPropertyBool("CTE Self-Reference", rte->self_reference, es); |
- |
| 658 |
- |
} |
- |
| 659 |
- |
|
- |
| 660 |
- |
/* |
- |
| 661 |
- |
* add_rte_to_flat_rtable will clear coltypes, coltypmods, and |
- |
| 662 |
- |
* colcollations, so skip those fields. |
- |
| 663 |
- |
* |
- |
| 664 |
- |
* If this is an ephemeral named relation, print out ENR-related |
- |
| 665 |
- |
* properties. |
- |
| 666 |
- |
*/ |
- |
| 667 |
- |
if (rte->rtekind == RTE_NAMEDTUPLESTORE) |
- |
| 668 |
- |
{ |
- |
| 669 |
- |
ExplainPropertyText("ENR Name", rte->enrname, es); |
- |
| 670 |
- |
ExplainPropertyFloat("ENR Tuples", NULL, rte->enrtuples, 0, es); |
- |
| 671 |
- |
} |
- |
| 672 |
- |
|
- |
| 673 |
- |
/* |
86c14eaWIP: SQL Property Graph Queries (SQL/PGQ) |
| 674 |
- |
* rewriteGraphTable() clears graph_pattern and graph_table_columns |
86c14eaWIP: SQL Property Graph Queries (SQL/PGQ) |
| 675 |
- |
* fields, so skip them. No graph table specific fields are required |
86c14eaWIP: SQL Property Graph Queries (SQL/PGQ) |
| 676 |
- |
* to be printed. |
86c14eaWIP: SQL Property Graph Queries (SQL/PGQ) |
| 677 |
- |
*/ |
86c14eaWIP: SQL Property Graph Queries (SQL/PGQ) |
| 678 |
- |
|
86c14eaWIP: SQL Property Graph Queries (SQL/PGQ) |
| 679 |
- |
/* |
- |
| 680 |
- |
* add_rte_to_flat_rtable will clear groupexprs and securityQuals, so |
- |
| 681 |
- |
* skip that field. We have handled inFromCl above, so the only thing |
- |
| 682 |
- |
* left to handle here is rte->lateral. |
- |
| 683 |
- |
*/ |
- |
| 684 |
- |
if (es->format != EXPLAIN_FORMAT_TEXT || rte->lateral) |
- |
| 685 |
- |
ExplainPropertyBool("Lateral", rte->lateral, es); |
- |
| 686 |
- |
|
- |
| 687 |
- |
/* Done with this RTE */ |
- |
| 688 |
- |
if (es->format == EXPLAIN_FORMAT_TEXT) |
- |
| 689 |
- |
es->indent--; |
- |
| 690 |
- |
ExplainCloseGroup("Range Table Entry", NULL, true, es); |
- |
| 691 |
- |
} |
- |
| 692 |
- |
|
- |
| 693 |
- |
/* Print PlannedStmt fields that contain RTIs. */ |
- |
| 694 |
- |
if (es->format != EXPLAIN_FORMAT_TEXT || |
- |
| 695 |
- |
!bms_is_empty(plannedstmt->unprunableRelids)) |
- |
| 696 |
- |
overexplain_bitmapset("Unprunable RTIs", plannedstmt->unprunableRelids, |
- |
| 697 |
- |
es); |
- |
| 698 |
- |
if (es->format != EXPLAIN_FORMAT_TEXT || |
- |
| 699 |
- |
plannedstmt->resultRelations != NIL) |
- |
| 700 |
- |
overexplain_intlist("Result RTIs", plannedstmt->resultRelations, es); |
- |
| 701 |
- |
|
- |
| 702 |
- |
/* Close group, we're all done */ |
- |
| 703 |
- |
ExplainCloseGroup("Range Table", "Range Table", false, es); |
- |
| 704 |
- |
} |
- |