|
22 | 22 | #include "executor/execdesc.h" |
23 | 23 | #include "executor/executor.h" |
24 | 24 | #include "executor/svariableReceiver.h" |
| 25 | +#include "funcapi.h" |
25 | 26 | #include "miscadmin.h" |
26 | 27 | #include "nodes/plannodes.h" |
27 | 28 | #include "parser/parse_type.h" |
@@ -600,3 +601,102 @@ ExecuteLetStmt(ParseState *pstate, |
600 | 601 |
|
601 | 602 | PopActiveSnapshot(); |
602 | 603 | } |
| 604 | + |
| 605 | +/* |
| 606 | + * pg_get_session_variables_memory - designed for testing |
| 607 | + * |
| 608 | + * This is a function designed for testing and debugging. It returns the |
| 609 | + * content of session variables as-is, and can therefore display data about |
| 610 | + * session variables that were dropped, but for which this backend didn't |
| 611 | + * process the shared invalidations yet. |
| 612 | + */ |
| 613 | +Datum |
| 614 | +pg_get_session_variables_memory(PG_FUNCTION_ARGS) |
| 615 | +{ |
| 616 | +#define NUM_PG_GET_SESSION_VARIABLES_MEMORY_ATTS 8 |
| 617 | + |
| 618 | + /* |
| 619 | + * Make sure syscache entries are flushed for recent catalog changes. For |
| 620 | + * stable behavior we need to reliably detect which variables were |
| 621 | + * dropped. |
| 622 | + */ |
| 623 | + AcceptInvalidationMessages(); |
| 624 | + |
| 625 | + InitMaterializedSRF(fcinfo, 0); |
| 626 | + |
| 627 | + if (sessionvars) |
| 628 | + { |
| 629 | + ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo; |
| 630 | + HASH_SEQ_STATUS status; |
| 631 | + SVariable svar; |
| 632 | + |
| 633 | + hash_seq_init(&status, sessionvars); |
| 634 | + |
| 635 | + while ((svar = (SVariable) hash_seq_search(&status)) != NULL) |
| 636 | + { |
| 637 | + Datum values[NUM_PG_GET_SESSION_VARIABLES_MEMORY_ATTS]; |
| 638 | + bool nulls[NUM_PG_GET_SESSION_VARIABLES_MEMORY_ATTS]; |
| 639 | + HeapTuple tp; |
| 640 | + bool var_is_valid = false; |
| 641 | + |
| 642 | + memset(values, 0, sizeof(values)); |
| 643 | + memset(nulls, 0, sizeof(nulls)); |
| 644 | + |
| 645 | + values[0] = ObjectIdGetDatum(svar->varid); |
| 646 | + values[3] = ObjectIdGetDatum(svar->typid); |
| 647 | + |
| 648 | + /* |
| 649 | + * It is possible that the variable has been dropped from the |
| 650 | + * catalog, but not yet purged from the hash table. |
| 651 | + */ |
| 652 | + tp = SearchSysCache1(VARIABLEOID, ObjectIdGetDatum(svar->varid)); |
| 653 | + |
| 654 | + if (HeapTupleIsValid(tp)) |
| 655 | + { |
| 656 | + Form_pg_variable varform = (Form_pg_variable) GETSTRUCT(tp); |
| 657 | + |
| 658 | + /* |
| 659 | + * It is also possible that a variable has been dropped and |
| 660 | + * someone created a new variable with the same object ID. |
| 661 | + * Use the catalog information only if that is not the case. |
| 662 | + */ |
| 663 | + if (svar->create_lsn == varform->varcreate_lsn) |
| 664 | + { |
| 665 | + values[1] = CStringGetTextDatum( |
| 666 | + get_namespace_name(varform->varnamespace)); |
| 667 | + |
| 668 | + values[2] = CStringGetTextDatum(NameStr(varform->varname)); |
| 669 | + values[4] = CStringGetTextDatum(format_type_be(svar->typid)); |
| 670 | + values[5] = BoolGetDatum(false); |
| 671 | + |
| 672 | + values[6] = BoolGetDatum( |
| 673 | + object_aclcheck(VariableRelationId, svar->varid, |
| 674 | + GetUserId(), ACL_SELECT) == ACLCHECK_OK); |
| 675 | + |
| 676 | + values[7] = BoolGetDatum( |
| 677 | + object_aclcheck(VariableRelationId, svar->varid, |
| 678 | + GetUserId(), ACL_UPDATE) == ACLCHECK_OK); |
| 679 | + |
| 680 | + var_is_valid = true; |
| 681 | + } |
| 682 | + |
| 683 | + ReleaseSysCache(tp); |
| 684 | + } |
| 685 | + |
| 686 | + /* if there is no matching catalog entry, return null values */ |
| 687 | + if (!var_is_valid) |
| 688 | + { |
| 689 | + nulls[1] = true; |
| 690 | + nulls[2] = true; |
| 691 | + nulls[4] = true; |
| 692 | + values[5] = BoolGetDatum(true); |
| 693 | + nulls[6] = true; |
| 694 | + nulls[7] = true; |
| 695 | + } |
| 696 | + |
| 697 | + tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls); |
| 698 | + } |
| 699 | + } |
| 700 | + |
| 701 | + return (Datum) 0; |
| 702 | +} |
0 commit comments