This is an automated email from the ASF dual-hosted git repository.

djwang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cloudberry.git

commit 2dc50a79b7bb441d4130594da45a50e587dfe315
Author: NJrslv <[email protected]>
AuthorDate: Mon Jan 19 10:17:05 2026 +0300

    [yagp_hooks_collector] Port backend infrastructure and adapt for Cloudberry
    
    Port GpscQueryKey to QueryDesc and workfile spill counters to
    workfile_mgr.c from gpdb.  Update for Cloudberry API changes:
    ExplainInitState→NewExplainState, gpmon_gettmid→gp_gettmid,
    Gp_session_role→Gp_role, signature changes in standard_ExecutorRun,
    standard_ProcessUtility, InstrAlloc, CreateTemplateTupleDesc.
    Change test functions to SRF.  Remove redundant jumbling copies.
---
 expected/yagp_cursors.out                          |  12 +-
 expected/yagp_dist.out                             |  12 +-
 expected/yagp_select.out                           |  12 +-
 expected/yagp_utility.out                          |  52 +-
 src/EventSender.cpp                                |   2 +-
 src/EventSender.h                                  |   4 +-
 src/PgUtils.cpp                                    |   2 +-
 src/ProtoUtils.cpp                                 |  12 +-
 src/UDSConnector.cpp                               |  10 +-
 src/backend/tcop/pquery.c                          |   3 +
 src/backend/utils/workfile_manager/workfile_mgr.c  |  24 +
 src/hook_wrappers.cpp                              |  34 +-
 src/include/executor/execdesc.h                    |  11 +
 src/include/utils/workfile_mgr.h                   |   4 +
 src/log/LogOps.cpp                                 |  12 +-
 src/log/LogSchema.cpp                              |   2 +-
 src/memory/gpdbwrappers.cpp                        |  48 +-
 src/memory/gpdbwrappers.h                          |   2 +-
 .../pg_stat_statements_ya_parser.c                 | 760 +--------------------
 src/yagp_hooks_collector.c                         |  34 +-
 yagp_hooks_collector--1.0--1.1.sql                 |  16 +-
 yagp_hooks_collector--1.0.sql                      |   6 +-
 yagp_hooks_collector--1.1.sql                      |  16 +-
 23 files changed, 217 insertions(+), 873 deletions(-)

diff --git a/expected/yagp_cursors.out b/expected/yagp_cursors.out
index 9587c00b550..d251ddd3e1c 100644
--- a/expected/yagp_cursors.out
+++ b/expected/yagp_cursors.out
@@ -40,8 +40,7 @@ SELECT segid, query_text, query_status FROM yagpcc.log WHERE 
segid = -1 AND util
 SELECT yagpcc.truncate_log() IS NOT NULL AS t;
  t 
 ---
- t
-(1 row)
+(0 rows)
 
 -- DECLARE WITH HOLD
 SET yagpcc.logging_mode to 'TBL';
@@ -74,8 +73,7 @@ SELECT segid, query_text, query_status FROM yagpcc.log WHERE 
segid = -1 AND util
 SELECT yagpcc.truncate_log() IS NOT NULL AS t;
  t 
 ---
- t
-(1 row)
+(0 rows)
 
 -- ROLLBACK
 SET yagpcc.logging_mode to 'TBL';
@@ -105,8 +103,7 @@ SELECT segid, query_text, query_status FROM yagpcc.log 
WHERE segid = -1 AND util
 SELECT yagpcc.truncate_log() IS NOT NULL AS t;
  t 
 ---
- t
-(1 row)
+(0 rows)
 
 -- FETCH
 SET yagpcc.logging_mode to 'TBL';
@@ -155,8 +152,7 @@ SELECT segid, query_text, query_status FROM yagpcc.log 
WHERE segid = -1 AND util
 SELECT yagpcc.truncate_log() IS NOT NULL AS t;
  t 
 ---
- t
-(1 row)
+(0 rows)
 
 DROP FUNCTION yagp_status_order(text);
 DROP EXTENSION yagp_hooks_collector;
diff --git a/expected/yagp_dist.out b/expected/yagp_dist.out
index ebaf839601d..5fd5ea5fb3e 100644
--- a/expected/yagp_dist.out
+++ b/expected/yagp_dist.out
@@ -46,8 +46,7 @@ SELECT segid, query_text, query_status FROM yagpcc.log ORDER 
BY segid, ccnt, yag
 SELECT yagpcc.truncate_log() IS NOT NULL AS t;
  t 
 ---
- t
-(1 row)
+(0 rows)
 
 SET yagpcc.logging_mode to 'TBL';
 -- Scan all segments.
@@ -83,8 +82,7 @@ SELECT segid, query_text, query_status FROM yagpcc.log ORDER 
BY segid, ccnt, yag
 SELECT yagpcc.truncate_log() IS NOT NULL AS t;
  t 
 ---
- t
-(1 row)
+(0 rows)
 
 -- Replicated table
 CREATE FUNCTION force_segments() RETURNS SETOF text AS $$
@@ -128,8 +126,7 @@ SELECT segid, query_text, query_status FROM yagpcc.log 
ORDER BY segid, ccnt, yag
 SELECT yagpcc.truncate_log() IS NOT NULL AS t;
  t 
 ---
- t
-(1 row)
+(0 rows)
 
 -- Partially distributed table (2 numsegments)
 SET allow_system_table_mods = ON;
@@ -167,8 +164,7 @@ SELECT query_text, query_status FROM yagpcc.log ORDER BY 
segid, ccnt, yagp_statu
 SELECT yagpcc.truncate_log() IS NOT NULL AS t;
  t 
 ---
- t
-(1 row)
+(0 rows)
 
 DROP FUNCTION yagp_status_order(text);
 DROP EXTENSION yagp_hooks_collector;
diff --git a/expected/yagp_select.out b/expected/yagp_select.out
index 4c4a0218150..b6e18dc862f 100644
--- a/expected/yagp_select.out
+++ b/expected/yagp_select.out
@@ -46,8 +46,7 @@ SELECT segid, query_text, query_status FROM yagpcc.log ORDER 
BY segid, ccnt, yag
 SELECT yagpcc.truncate_log() IS NOT NULL AS t;
  t 
 ---
- t
-(1 row)
+(0 rows)
 
 -- Transaction test
 SET yagpcc.logging_mode to 'TBL';
@@ -72,8 +71,7 @@ SELECT segid, query_text, query_status FROM yagpcc.log ORDER 
BY segid, ccnt, yag
 SELECT yagpcc.truncate_log() IS NOT NULL AS t;
  t 
 ---
- t
-(1 row)
+(0 rows)
 
 -- CTE test
 SET yagpcc.logging_mode to 'TBL';
@@ -102,8 +100,7 @@ SELECT segid, query_text, query_status FROM yagpcc.log 
ORDER BY segid, ccnt, yag
 SELECT yagpcc.truncate_log() IS NOT NULL AS t;
  t 
 ---
- t
-(1 row)
+(0 rows)
 
 -- Prepared statement test
 SET yagpcc.logging_mode to 'TBL';
@@ -128,8 +125,7 @@ SELECT segid, query_text, query_status FROM yagpcc.log 
ORDER BY segid, ccnt, yag
 SELECT yagpcc.truncate_log() IS NOT NULL AS t;
  t 
 ---
- t
-(1 row)
+(0 rows)
 
 DROP FUNCTION yagp_status_order(text);
 DROP EXTENSION yagp_hooks_collector;
diff --git a/expected/yagp_utility.out b/expected/yagp_utility.out
index 03c17713575..057f7d7a556 100644
--- a/expected/yagp_utility.out
+++ b/expected/yagp_utility.out
@@ -17,7 +17,7 @@ SET yagpcc.enable_utility TO TRUE;
 SET yagpcc.report_nested_queries TO TRUE;
 SET yagpcc.logging_mode to 'TBL';
 CREATE TABLE test_table (a int, b text);
-NOTICE:  Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' 
as the Greenplum Database data distribution key for this table.
+NOTICE:  Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' 
as the Apache Cloudberry data distribution key for this table.
 HINT:  The 'DISTRIBUTED BY' clause determines the distribution of data. Make 
sure column(s) chosen are the optimal data distribution key to minimize skew.
 CREATE INDEX test_idx ON test_table(a);
 ALTER TABLE test_table ADD COLUMN c int DEFAULT 1;
@@ -41,8 +41,7 @@ SELECT segid, query_text, query_status FROM yagpcc.log WHERE 
segid = -1 AND util
 SELECT yagpcc.truncate_log() IS NOT NULL AS t;
  t 
 ---
- t
-(1 row)
+(0 rows)
 
 -- Partitioning
 SET yagpcc.logging_mode to 'TBL';
@@ -50,34 +49,16 @@ CREATE TABLE pt_test (a int, b int)
 DISTRIBUTED BY (a)
 PARTITION BY RANGE (a)
 (START (0) END (100) EVERY (50));
-NOTICE:  CREATE TABLE will create partition "pt_test_1_prt_1" for table 
"pt_test"
-NOTICE:  CREATE TABLE will create partition "pt_test_1_prt_2" for table 
"pt_test"
 DROP TABLE pt_test;
 RESET yagpcc.logging_mode;
 SELECT segid, query_text, query_status FROM yagpcc.log WHERE segid = -1 AND 
utility = true ORDER BY segid, ccnt, yagp_status_order(query_status) ASC;
  segid |             query_text              |    query_status     
 -------+-------------------------------------+---------------------
-    -1 |                                     | QUERY_STATUS_DONE
+    -1 | SET yagpcc.logging_mode to 'TBL';   | QUERY_STATUS_DONE
     -1 | CREATE TABLE pt_test (a int, b int)+| QUERY_STATUS_SUBMIT
        | DISTRIBUTED BY (a)                 +| 
        | PARTITION BY RANGE (a)             +| 
        | (START (0) END (100) EVERY (50));   | 
-    -1 | CREATE TABLE pt_test (a int, b int)+| QUERY_STATUS_SUBMIT
-       | DISTRIBUTED BY (a)                 +| 
-       | PARTITION BY RANGE (a)             +| 
-       | (START (0) END (100) EVERY (50));   | 
-    -1 | CREATE TABLE pt_test (a int, b int)+| QUERY_STATUS_SUBMIT
-       | DISTRIBUTED BY (a)                 +| 
-       | PARTITION BY RANGE (a)             +| 
-       | (START (0) END (100) EVERY (50));   | 
-    -1 | CREATE TABLE pt_test (a int, b int)+| QUERY_STATUS_DONE
-       | DISTRIBUTED BY (a)                 +| 
-       | PARTITION BY RANGE (a)             +| 
-       | (START (0) END (100) EVERY (50));   | 
-    -1 | CREATE TABLE pt_test (a int, b int)+| QUERY_STATUS_DONE
-       | DISTRIBUTED BY (a)                 +| 
-       | PARTITION BY RANGE (a)             +| 
-       | (START (0) END (100) EVERY (50));   | 
     -1 | CREATE TABLE pt_test (a int, b int)+| QUERY_STATUS_DONE
        | DISTRIBUTED BY (a)                 +| 
        | PARTITION BY RANGE (a)             +| 
@@ -85,13 +66,12 @@ SELECT segid, query_text, query_status FROM yagpcc.log 
WHERE segid = -1 AND util
     -1 | DROP TABLE pt_test;                 | QUERY_STATUS_SUBMIT
     -1 | DROP TABLE pt_test;                 | QUERY_STATUS_DONE
     -1 | RESET yagpcc.logging_mode;          | QUERY_STATUS_SUBMIT
-(10 rows)
+(6 rows)
 
 SELECT yagpcc.truncate_log() IS NOT NULL AS t;
  t 
 ---
- t
-(1 row)
+(0 rows)
 
 -- Views and Functions
 SET yagpcc.logging_mode to 'TBL';
@@ -118,8 +98,7 @@ SELECT segid, query_text, query_status FROM yagpcc.log WHERE 
segid = -1 AND util
 SELECT yagpcc.truncate_log() IS NOT NULL AS t;
  t 
 ---
- t
-(1 row)
+(0 rows)
 
 -- Transaction Operations
 SET yagpcc.logging_mode to 'TBL';
@@ -159,13 +138,12 @@ SELECT segid, query_text, query_status FROM yagpcc.log 
WHERE segid = -1 AND util
 SELECT yagpcc.truncate_log() IS NOT NULL AS t;
  t 
 ---
- t
-(1 row)
+(0 rows)
 
 -- DML Operations
 SET yagpcc.logging_mode to 'TBL';
 CREATE TABLE dml_test (a int, b text);
-NOTICE:  Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' 
as the Greenplum Database data distribution key for this table.
+NOTICE:  Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' 
as the Apache Cloudberry data distribution key for this table.
 HINT:  The 'DISTRIBUTED BY' clause determines the distribution of data. Make 
sure column(s) chosen are the optimal data distribution key to minimize skew.
 INSERT INTO dml_test VALUES (1, 'test');
 UPDATE dml_test SET b = 'updated' WHERE a = 1;
@@ -186,13 +164,12 @@ SELECT segid, query_text, query_status FROM yagpcc.log 
WHERE segid = -1 AND util
 SELECT yagpcc.truncate_log() IS NOT NULL AS t;
  t 
 ---
- t
-(1 row)
+(0 rows)
 
 -- COPY Operations
 SET yagpcc.logging_mode to 'TBL';
 CREATE TABLE copy_test (a int);
-NOTICE:  Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' 
as the Greenplum Database data distribution key for this table.
+NOTICE:  Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'a' 
as the Apache Cloudberry data distribution key for this table.
 HINT:  The 'DISTRIBUTED BY' clause determines the distribution of data. Make 
sure column(s) chosen are the optimal data distribution key to minimize skew.
 COPY (SELECT 1) TO STDOUT;
 1
@@ -214,8 +191,7 @@ SELECT segid, query_text, query_status FROM yagpcc.log 
WHERE segid = -1 AND util
 SELECT yagpcc.truncate_log() IS NOT NULL AS t;
  t 
 ---
- t
-(1 row)
+(0 rows)
 
 -- Prepared Statements and error during execute
 SET yagpcc.logging_mode to 'TBL';
@@ -240,8 +216,7 @@ SELECT segid, query_text, query_status FROM yagpcc.log 
WHERE segid = -1 AND util
 SELECT yagpcc.truncate_log() IS NOT NULL AS t;
  t 
 ---
- t
-(1 row)
+(0 rows)
 
 -- GUC Settings
 SET yagpcc.logging_mode to 'TBL';
@@ -262,8 +237,7 @@ SELECT segid, query_text, query_status FROM yagpcc.log 
WHERE segid = -1 AND util
 SELECT yagpcc.truncate_log() IS NOT NULL AS t;
  t 
 ---
- t
-(1 row)
+(0 rows)
 
 DROP FUNCTION yagp_status_order(text);
 DROP EXTENSION yagp_hooks_collector;
diff --git a/src/EventSender.cpp b/src/EventSender.cpp
index fee435a6dcc..d638d275548 100644
--- a/src/EventSender.cpp
+++ b/src/EventSender.cpp
@@ -169,7 +169,7 @@ void EventSender::executor_after_start(QueryDesc 
*query_desc, int /* eflags*/) {
     if (query_desc->totaltime == NULL) {
       MemoryContext oldcxt =
           ya_gpdb::mem_ctx_switch_to(query_desc->estate->es_query_cxt);
-      query_desc->totaltime = ya_gpdb::instr_alloc(1, INSTRUMENT_ALL);
+      query_desc->totaltime = ya_gpdb::instr_alloc(1, INSTRUMENT_ALL, false);
       ya_gpdb::mem_ctx_switch_to(oldcxt);
     }
   }
diff --git a/src/EventSender.h b/src/EventSender.h
index 4afdf1e14a4..6e195eeacdf 100644
--- a/src/EventSender.h
+++ b/src/EventSender.h
@@ -23,6 +23,8 @@ class SetQueryReq;
 
 #include <cstdint>
 
+extern void gp_gettmid(int32 *);
+
 struct QueryKey {
   int tmid;
   int ssid;
@@ -40,7 +42,7 @@ struct QueryKey {
     query_desc->yagp_query_key =
         (YagpQueryKey *)ya_gpdb::palloc0(sizeof(YagpQueryKey));
     int32 tmid;
-    gpmon_gettmid(&tmid);
+    gp_gettmid(&tmid);
     query_desc->yagp_query_key->tmid = tmid;
     query_desc->yagp_query_key->ssid = gp_session_id;
     query_desc->yagp_query_key->ccnt = gp_command_count;
diff --git a/src/PgUtils.cpp b/src/PgUtils.cpp
index fc58112bfaa..96f46429643 100644
--- a/src/PgUtils.cpp
+++ b/src/PgUtils.cpp
@@ -72,7 +72,7 @@ bool nesting_is_valid(QueryDesc *query_desc, int 
nesting_level) {
 }
 
 bool need_report_nested_query() {
-  return Config::report_nested_queries() && Gp_session_role == 
GP_ROLE_DISPATCH;
+  return Config::report_nested_queries() && Gp_role == GP_ROLE_DISPATCH;
 }
 
 bool filter_query(QueryDesc *query_desc) {
diff --git a/src/ProtoUtils.cpp b/src/ProtoUtils.cpp
index f28714da6ec..aa8632477f5 100644
--- a/src/ProtoUtils.cpp
+++ b/src/ProtoUtils.cpp
@@ -24,6 +24,8 @@ extern "C" {
 #include <ctime>
 #include <string>
 
+extern void gp_gettmid(int32 *);
+
 namespace {
 constexpr uint8_t UTF8_CONTINUATION_BYTE_MASK = (1 << 7) | (1 << 6);
 constexpr uint8_t UTF8_CONTINUATION_BYTE = (1 << 7);
@@ -49,7 +51,7 @@ void set_query_key(yagpcc::QueryKey *key) {
   key->set_ccnt(gp_command_count);
   key->set_ssid(gp_session_id);
   int32 tmid = 0;
-  gpmon_gettmid(&tmid);
+  gp_gettmid(&tmid);
   key->set_tmid(tmid);
 }
 
@@ -81,7 +83,7 @@ std::string trim_str_shrink_utf8(const char *str, size_t len, 
size_t lim) {
 }
 
 void set_query_plan(yagpcc::SetQueryReq *req, QueryDesc *query_desc) {
-  if (Gp_session_role == GP_ROLE_DISPATCH && query_desc->plannedstmt) {
+  if (Gp_role == GP_ROLE_DISPATCH && query_desc->plannedstmt) {
     auto qi = req->mutable_query_info();
     qi->set_generator(query_desc->plannedstmt->planGen == PLANGEN_OPTIMIZER
                           ? yagpcc::PlanGenerator::PLAN_GENERATOR_OPTIMIZER
@@ -106,7 +108,7 @@ void set_query_plan(yagpcc::SetQueryReq *req, QueryDesc 
*query_desc) {
 }
 
 void set_query_text(yagpcc::SetQueryReq *req, QueryDesc *query_desc) {
-  if (Gp_session_role == GP_ROLE_DISPATCH && query_desc->sourceText) {
+  if (Gp_role == GP_ROLE_DISPATCH && query_desc->sourceText) {
     auto qi = req->mutable_query_info();
     *qi->mutable_query_text() = trim_str_shrink_utf8(
         query_desc->sourceText, strlen(query_desc->sourceText),
@@ -118,7 +120,7 @@ void set_query_text(yagpcc::SetQueryReq *req, QueryDesc 
*query_desc) {
 }
 
 void clear_big_fields(yagpcc::SetQueryReq *req) {
-  if (Gp_session_role == GP_ROLE_DISPATCH) {
+  if (Gp_role == GP_ROLE_DISPATCH) {
     auto qi = req->mutable_query_info();
     qi->clear_plan_text();
     qi->clear_template_plan_text();
@@ -129,7 +131,7 @@ void clear_big_fields(yagpcc::SetQueryReq *req) {
 }
 
 void set_query_info(yagpcc::SetQueryReq *req) {
-  if (Gp_session_role == GP_ROLE_DISPATCH) {
+  if (Gp_role == GP_ROLE_DISPATCH) {
     auto qi = req->mutable_query_info();
     qi->set_username(get_user_name());
     if (IsTransactionState())
diff --git a/src/UDSConnector.cpp b/src/UDSConnector.cpp
index b6af303218d..a7eaed539f7 100644
--- a/src/UDSConnector.cpp
+++ b/src/UDSConnector.cpp
@@ -19,10 +19,9 @@ extern "C" {
 
 static void inline log_tracing_failure(const yagpcc::SetQueryReq &req,
                                        const std::string &event) {
-  ereport(LOG,
-          (errmsg("Query {%d-%d-%d} %s tracing failed with error %s",
-                  req.query_key().tmid(), req.query_key().ssid(),
-                  req.query_key().ccnt(), event.c_str(), strerror(errno))));
+  ereport(LOG, (errmsg("Query {%d-%d-%d} %s tracing failed with error %m",
+                       req.query_key().tmid(), req.query_key().ssid(),
+                       req.query_key().ccnt(), event.c_str())));
 }
 
 bool UDSConnector::report_query(const yagpcc::SetQueryReq &req,
@@ -77,8 +76,7 @@ bool UDSConnector::report_query(const yagpcc::SetQueryReq 
&req,
       // That's a very important error that should never happen, so make it
       // visible to an end-user and admins.
       ereport(WARNING,
-              (errmsg("Unable to create non-blocking socket connection %s",
-                      strerror(errno))));
+              (errmsg("Unable to create non-blocking socket connection %m")));
       success = false;
       YagpStat::report_error();
     }
diff --git a/src/backend/tcop/pquery.c b/src/backend/tcop/pquery.c
index 532690f1d51..7c1dbc480bc 100644
--- a/src/backend/tcop/pquery.c
+++ b/src/backend/tcop/pquery.c
@@ -127,6 +127,9 @@ CreateQueryDesc(PlannedStmt *plannedstmt,
        if (Gp_role != GP_ROLE_EXECUTE)
                increment_command_count();
 
+       /* null this field until set by YAGP Hooks collector */
+       qd->yagp_query_key = NULL;
+
        return qd;
 }
 
diff --git a/src/backend/utils/workfile_manager/workfile_mgr.c 
b/src/backend/utils/workfile_manager/workfile_mgr.c
index e5b311cf9ba..21b4463e5f1 100644
--- a/src/backend/utils/workfile_manager/workfile_mgr.c
+++ b/src/backend/utils/workfile_manager/workfile_mgr.c
@@ -192,6 +192,9 @@ static void unpin_workset(workfile_set *work_set);
 
 static bool proc_exit_hook_registered = false;
 
+static uint64 total_bytes_written = 0;
+static uint64 total_files_created = 0;
+
 Datum gp_workfile_mgr_cache_entries(PG_FUNCTION_ARGS);
 Datum gp_workfile_mgr_used_diskspace(PG_FUNCTION_ARGS);
 
@@ -371,6 +374,7 @@ RegisterFileWithSet(File file, workfile_set *work_set)
        localCtl.entries[file].work_set = work_set;
        work_set->num_files++;
        work_set->perquery->num_files++;
+       total_files_created++;
 
        /* Enforce the limit on number of files */
        if (gp_workfile_limit_files_per_query > 0 &&
@@ -447,6 +451,7 @@ UpdateWorkFileSize(File file, uint64 newsize)
                                        
(errcode(ERRCODE_INSUFFICIENT_RESOURCES),
                                         errmsg("workfile per segment size 
limit exceeded")));
                }
+               total_bytes_written += diff;
        }
 
        /*
@@ -986,3 +991,22 @@ workfile_is_active(workfile_set *workfile)
 {
        return workfile ? workfile->active : false;
 }
+
+uint64
+WorkfileTotalBytesWritten(void)
+{
+       return total_bytes_written;
+}
+
+uint64
+WorkfileTotalFilesCreated(void)
+{
+       return total_files_created;
+}
+
+void
+WorkfileResetBackendStats(void)
+{
+       total_bytes_written = 0;
+       total_files_created = 0;
+}
diff --git a/src/hook_wrappers.cpp b/src/hook_wrappers.cpp
index 07ac511d546..56c1da9f4f6 100644
--- a/src/hook_wrappers.cpp
+++ b/src/hook_wrappers.cpp
@@ -36,7 +36,7 @@ static ProcessUtility_hook_type previous_ProcessUtility_hook 
= nullptr;
 
 static void ya_ExecutorStart_hook(QueryDesc *query_desc, int eflags);
 static void ya_ExecutorRun_hook(QueryDesc *query_desc, ScanDirection direction,
-                                long count);
+                                uint64 count, bool execute_once);
 static void ya_ExecutorFinish_hook(QueryDesc *query_desc);
 static void ya_ExecutorEnd_hook(QueryDesc *query_desc);
 static void ya_query_info_collect_hook(QueryMetricsStatus status, void *arg);
@@ -45,10 +45,12 @@ static void ya_ic_teardown_hook(ChunkTransportState 
*transportStates,
 #ifdef ANALYZE_STATS_COLLECT_HOOK
 static void ya_analyze_stats_collect_hook(QueryDesc *query_desc);
 #endif
-static void ya_process_utility_hook(Node *parsetree, const char *queryString,
+static void ya_process_utility_hook(PlannedStmt *pstmt, const char 
*queryString,
+                                    bool readOnlyTree,
                                     ProcessUtilityContext context,
-                                    ParamListInfo params, DestReceiver *dest,
-                                    char *completionTag);
+                                    ParamListInfo params,
+                                    QueryEnvironment *queryEnv,
+                                    DestReceiver *dest, QueryCompletion *qc);
 
 static EventSender *sender = nullptr;
 
@@ -127,14 +129,14 @@ void ya_ExecutorStart_hook(QueryDesc *query_desc, int 
eflags) {
 }
 
 void ya_ExecutorRun_hook(QueryDesc *query_desc, ScanDirection direction,
-                         long count) {
+                         uint64 count, bool execute_once) {
   get_sender()->incr_depth();
   PG_TRY();
   {
     if (previous_ExecutorRun_hook)
-      previous_ExecutorRun_hook(query_desc, direction, count);
+      previous_ExecutorRun_hook(query_desc, direction, count, execute_once);
     else
-      standard_ExecutorRun(query_desc, direction, count);
+      standard_ExecutorRun(query_desc, direction, count, execute_once);
     get_sender()->decr_depth();
   }
   PG_CATCH();
@@ -198,10 +200,12 @@ void ya_analyze_stats_collect_hook(QueryDesc *query_desc) 
{
 }
 #endif
 
-static void ya_process_utility_hook(Node *parsetree, const char *queryString,
+static void ya_process_utility_hook(PlannedStmt *pstmt, const char 
*queryString,
+                                    bool readOnlyTree,
                                     ProcessUtilityContext context,
-                                    ParamListInfo params, DestReceiver *dest,
-                                    char *completionTag) {
+                                    ParamListInfo params,
+                                    QueryEnvironment *queryEnv,
+                                    DestReceiver *dest, QueryCompletion *qc) {
   /* Project utility data on QueryDesc to use existing logic */
   QueryDesc *query_desc = (QueryDesc *)palloc0(sizeof(QueryDesc));
   query_desc->sourceText = queryString;
@@ -214,11 +218,11 @@ static void ya_process_utility_hook(Node *parsetree, 
const char *queryString,
   PG_TRY();
   {
     if (previous_ProcessUtility_hook) {
-      (*previous_ProcessUtility_hook)(parsetree, queryString, context, params,
-                                      dest, completionTag);
+      (*previous_ProcessUtility_hook)(pstmt, queryString, readOnlyTree, 
context,
+                                      params, queryEnv, dest, qc);
     } else {
-      standard_ProcessUtility(parsetree, queryString, context, params, dest,
-                              completionTag);
+      standard_ProcessUtility(pstmt, queryString, readOnlyTree, context, 
params,
+                              queryEnv, dest, qc);
     }
 
     get_sender()->decr_depth();
@@ -264,7 +268,7 @@ Datum yagp_functions_get(FunctionCallInfo fcinfo) {
   const int ATTNUM = 6;
   check_stats_loaded();
   auto stats = YagpStat::get_stats();
-  TupleDesc tupdesc = CreateTemplateTupleDesc(ATTNUM, false);
+  TupleDesc tupdesc = CreateTemplateTupleDesc(ATTNUM);
   TupleDescInitEntry(tupdesc, (AttrNumber)1, "segid", INT4OID, -1 /* typmod */,
                      0 /* attdim */);
   TupleDescInitEntry(tupdesc, (AttrNumber)2, "total_messages", INT8OID,
diff --git a/src/include/executor/execdesc.h b/src/include/executor/execdesc.h
index e3ecf31b664..e469945a4c5 100644
--- a/src/include/executor/execdesc.h
+++ b/src/include/executor/execdesc.h
@@ -22,6 +22,14 @@
 
 struct CdbExplain_ShowStatCtx;  /* private, in "cdb/cdbexplain.c" */
 
+typedef struct YagpQueryKey
+{
+       int tmid; /* transaction time */
+       int ssid; /* session id */
+       int ccnt; /* command count */
+       int nesting_level;
+       uintptr_t query_desc_addr;
+} YagpQueryKey;
 
 /*
  * SerializedParams is used to serialize external query parameters
@@ -330,6 +338,9 @@ typedef struct QueryDesc
 
        /* This is always set NULL by the core system, but plugins can change 
it */
        struct Instrumentation *totaltime;      /* total time spent in 
ExecutorRun */
+
+       /* YAGP Hooks collector */
+       YagpQueryKey *yagp_query_key;
 } QueryDesc;
 
 /* in pquery.c */
diff --git a/src/include/utils/workfile_mgr.h b/src/include/utils/workfile_mgr.h
index dfbd17bca57..48c83620610 100644
--- a/src/include/utils/workfile_mgr.h
+++ b/src/include/utils/workfile_mgr.h
@@ -74,4 +74,8 @@ extern workfile_set *workfile_mgr_cache_entries_get_copy(int* 
num_actives);
 extern uint64 WorkfileSegspace_GetSize(void);
 extern bool workfile_is_active(workfile_set *workfile);
 
+extern uint64 WorkfileTotalBytesWritten(void);
+extern uint64 WorkfileTotalFilesCreated(void);
+extern void WorkfileResetBackendStats(void);
+
 #endif /* __WORKFILE_MGR_H__ */
diff --git a/src/log/LogOps.cpp b/src/log/LogOps.cpp
index 0868dd9fc1c..cec9e33693a 100644
--- a/src/log/LogOps.cpp
+++ b/src/log/LogOps.cpp
@@ -37,12 +37,12 @@ void init_log() {
   relationId = heap_create_with_catalog(
       log_relname.data() /* relname */, namespaceId /* namespace */,
       0 /* tablespace */, InvalidOid /* relid */, InvalidOid /* reltype oid */,
-      InvalidOid /* reloftypeid */, GetUserId() /* owner */,
-      DescribeTuple() /* rel tuple */, NIL, InvalidOid /* relam */,
-      RELKIND_RELATION, RELPERSISTENCE_PERMANENT, RELSTORAGE_HEAP, false, 
false,
-      true, 0, ONCOMMIT_NOOP, NULL /* GP Policy */, (Datum)0,
-      false /* use_user_acl */, true, true, false /* valid_opts */,
-      false /* is_part_child */, false /* is part parent */, NULL);
+      InvalidOid /* reloftypeid */, GetUserId() /* owner */, HEAP_TABLE_AM_OID,
+      DescribeTuple() /* rel tuple */, NIL, RELKIND_RELATION,
+      RELPERSISTENCE_PERMANENT, false, false, ONCOMMIT_NOOP,
+      NULL /* GP Policy */, (Datum)0, false /* use_user_acl */, true, true,
+      InvalidOid /* relrewrite */, NULL /* typaddress */,
+      false /* valid_opts */);
 
   /* Make the table visible */
   CommandCounterIncrement();
diff --git a/src/log/LogSchema.cpp b/src/log/LogSchema.cpp
index 335a3103cfd..2fadcc46599 100644
--- a/src/log/LogSchema.cpp
+++ b/src/log/LogSchema.cpp
@@ -19,7 +19,7 @@ const std::unordered_map<std::string_view, size_t> 
&proto_name_to_col_idx() {
 }
 
 TupleDesc DescribeTuple() {
-  TupleDesc tupdesc = CreateTemplateTupleDesc(natts_yagp_log, false);
+  TupleDesc tupdesc = CreateTemplateTupleDesc(natts_yagp_log);
 
   for (size_t anum = 1; anum <= natts_yagp_log; ++anum) {
     TupleDescInitEntry(tupdesc, anum, log_tbl_desc[anum - 
1].pg_att_name.data(),
diff --git a/src/memory/gpdbwrappers.cpp b/src/memory/gpdbwrappers.cpp
index 0824a3a6808..763e32e539c 100644
--- a/src/memory/gpdbwrappers.cpp
+++ b/src/memory/gpdbwrappers.cpp
@@ -7,6 +7,7 @@ extern "C" {
 #include "commands/dbcommands.h"
 #include "commands/resgroupcmds.h"
 #include "utils/builtins.h"
+#include "utils/varlena.h"
 #include "nodes/pg_list.h"
 #include "commands/explain.h"
 #include "executor/instrument.h"
@@ -115,41 +116,40 @@ bool ya_gpdb::split_identifier_string(char *rawstring, 
char separator,
 ExplainState ya_gpdb::get_explain_state(QueryDesc *query_desc,
                                         bool costs) noexcept {
   return wrap_noexcept([&]() {
-    ExplainState es;
-    ExplainInitState(&es);
-    es.costs = costs;
-    es.verbose = true;
-    es.format = EXPLAIN_FORMAT_TEXT;
-    ExplainBeginOutput(&es);
-    ExplainPrintPlan(&es, query_desc);
-    ExplainEndOutput(&es);
-    return es;
+    ExplainState *es = NewExplainState();
+    es->costs = costs;
+    es->verbose = true;
+    es->format = EXPLAIN_FORMAT_TEXT;
+    ExplainBeginOutput(es);
+    ExplainPrintPlan(es, query_desc);
+    ExplainEndOutput(es);
+    return *es;
   });
 }
 
 ExplainState ya_gpdb::get_analyze_state(QueryDesc *query_desc,
                                         bool analyze) noexcept {
   return wrap_noexcept([&]() {
-    ExplainState es;
-    ExplainInitState(&es);
-    es.analyze = analyze;
-    es.verbose = true;
-    es.buffers = es.analyze;
-    es.timing = es.analyze;
-    es.summary = es.analyze;
-    es.format = EXPLAIN_FORMAT_TEXT;
-    ExplainBeginOutput(&es);
+    ExplainState *es = NewExplainState();
+    es->analyze = analyze;
+    es->verbose = true;
+    es->buffers = es->analyze;
+    es->timing = es->analyze;
+    es->summary = es->analyze;
+    es->format = EXPLAIN_FORMAT_TEXT;
+    ExplainBeginOutput(es);
     if (analyze) {
-      ExplainPrintPlan(&es, query_desc);
-      ExplainPrintExecStatsEnd(&es, query_desc);
+      ExplainPrintPlan(es, query_desc);
+      ExplainPrintExecStatsEnd(es, query_desc);
     }
-    ExplainEndOutput(&es);
-    return es;
+    ExplainEndOutput(es);
+    return *es;
   });
 }
 
-Instrumentation *ya_gpdb::instr_alloc(size_t n, int instrument_options) {
-  return wrap_throw(InstrAlloc, n, instrument_options);
+Instrumentation *ya_gpdb::instr_alloc(size_t n, int instrument_options,
+                                      bool async_mode) {
+  return wrap_throw(InstrAlloc, n, instrument_options, async_mode);
 }
 
 HeapTuple ya_gpdb::heap_form_tuple(TupleDesc tupleDescriptor, Datum *values,
diff --git a/src/memory/gpdbwrappers.h b/src/memory/gpdbwrappers.h
index 8f5f146cc67..920fc1ae6e7 100644
--- a/src/memory/gpdbwrappers.h
+++ b/src/memory/gpdbwrappers.h
@@ -32,7 +32,7 @@ bool split_identifier_string(char *rawstring, char separator,
                              List **namelist) noexcept;
 ExplainState get_explain_state(QueryDesc *query_desc, bool costs) noexcept;
 ExplainState get_analyze_state(QueryDesc *query_desc, bool analyze) noexcept;
-Instrumentation *instr_alloc(size_t n, int instrument_options);
+Instrumentation *instr_alloc(size_t n, int instrument_options, bool 
async_mode);
 HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values,
                           bool *isnull);
 CdbExplain_ShowStatCtx *cdbexplain_showExecStatsBegin(QueryDesc *query_desc,
diff --git a/src/stat_statements_parser/pg_stat_statements_ya_parser.c 
b/src/stat_statements_parser/pg_stat_statements_ya_parser.c
index 1c58d936093..c19805ce506 100644
--- a/src/stat_statements_parser/pg_stat_statements_ya_parser.c
+++ b/src/stat_statements_parser/pg_stat_statements_ya_parser.c
@@ -6,689 +6,48 @@
 #include <sys/stat.h>
 #include <unistd.h>
 
-#include "access/hash.h"
-#include "executor/instrument.h"
-#include "executor/execdesc.h"
-#include "funcapi.h"
+#include "common/hashfn.h"
+#include "lib/stringinfo.h"
 #include "mb/pg_wchar.h"
 #include "miscadmin.h"
-#include "parser/analyze.h"
-#include "parser/parsetree.h"
 #include "parser/scanner.h"
-#include "parser/gram.h"
-#include "pgstat.h"
-#include "storage/fd.h"
-#include "storage/ipc.h"
-#include "storage/spin.h"
-#include "tcop/utility.h"
 #include "utils/builtins.h"
 #include "utils/memutils.h"
+#include "utils/queryjumble.h"
 
 #include "pg_stat_statements_ya_parser.h"
 
-static post_parse_analyze_hook_type prev_post_parse_analyze_hook = NULL;
-
-#define JUMBLE_SIZE 1024 /* query serialization buffer size */
-
-/*
- * Struct for tracking locations/lengths of constants during normalization
- */
-typedef struct pgssLocationLen
-{
-       int location; /* start offset in query text */
-       int length;       /* length in bytes, or -1 to ignore */
-} pgssLocationLen;
-
-/*
- * Working state for computing a query jumble and producing a normalized
- * query string
- */
-typedef struct pgssJumbleState
-{
-       /* Jumble of current query tree */
-       unsigned char *jumble;
-
-       /* Number of bytes used in jumble[] */
-       Size jumble_len;
-
-       /* Array of locations of constants that should be removed */
-       pgssLocationLen *clocations;
-
-       /* Allocated length of clocations array */
-       int clocations_buf_size;
-
-       /* Current number of valid entries in clocations array */
-       int clocations_count;
-
-       /* highest Param id we've seen, in order to start normalization 
correctly */
-       int highest_extern_param_id;
-} pgssJumbleState;
+#ifndef ICONST
+#define ICONST 276
+#endif
+#ifndef FCONST
+#define FCONST 277
+#endif
+#ifndef SCONST
+#define SCONST 278
+#endif
+#ifndef BCONST
+#define BCONST 279
+#endif
+#ifndef XCONST
+#define XCONST 280
+#endif
 
-static void AppendJumble(pgssJumbleState *jstate,
-                                                const unsigned char *item, 
Size size);
-static void JumbleQuery(pgssJumbleState *jstate, Query *query);
-static void JumbleRangeTable(pgssJumbleState *jstate, List *rtable);
-static void JumbleExpr(pgssJumbleState *jstate, Node *node);
-static void RecordConstLocation(pgssJumbleState *jstate, int location);
-static void fill_in_constant_lengths(pgssJumbleState *jstate, const char 
*query);
+static void fill_in_constant_lengths(JumbleState *jstate, const char *query);
 static int comp_location(const void *a, const void *b);
 StringInfo gen_normplan(const char *execution_plan);
 static bool need_replace(int token);
-void pgss_post_parse_analyze(ParseState *pstate, Query *query);
-static char *generate_normalized_query(pgssJumbleState *jstate, const char 
*query,
+static char *generate_normalized_query(JumbleState *jstate, const char *query,
                                                                           int 
*query_len_p, int encoding);
 
-       void stat_statements_parser_init()
-{
-       prev_post_parse_analyze_hook = post_parse_analyze_hook;
-       post_parse_analyze_hook = pgss_post_parse_analyze;
-}
-
-void stat_statements_parser_deinit()
+void stat_statements_parser_init(void)
 {
-       post_parse_analyze_hook = prev_post_parse_analyze_hook;
-}
-
-/*
- * AppendJumble: Append a value that is substantive in a given query to
- * the current jumble.
- */
-static void
-AppendJumble(pgssJumbleState *jstate, const unsigned char *item, Size size)
-{
-       unsigned char *jumble = jstate->jumble;
-       Size jumble_len = jstate->jumble_len;
-
-       /*
-        * Whenever the jumble buffer is full, we hash the current contents and
-        * reset the buffer to contain just that hash value, thus relying on the
-        * hash to summarize everything so far.
-        */
-       while (size > 0)
-       {
-               Size part_size;
-
-               if (jumble_len >= JUMBLE_SIZE)
-               {
-                       uint32 start_hash = hash_any(jumble, JUMBLE_SIZE);
-
-                       memcpy(jumble, &start_hash, sizeof(start_hash));
-                       jumble_len = sizeof(start_hash);
-               }
-               part_size = Min(size, JUMBLE_SIZE - jumble_len);
-               memcpy(jumble + jumble_len, item, part_size);
-               jumble_len += part_size;
-               item += part_size;
-               size -= part_size;
-       }
-       jstate->jumble_len = jumble_len;
+       EnableQueryId();
 }
 
-/*
- * Wrappers around AppendJumble to encapsulate details of serialization
- * of individual local variable elements.
- */
-#define APP_JUMB(item) \
-       AppendJumble(jstate, (const unsigned char *)&(item), sizeof(item))
-#define APP_JUMB_STRING(str) \
-       AppendJumble(jstate, (const unsigned char *)(str), strlen(str) + 1)
-
-/*
- * JumbleQuery: Selectively serialize the query tree, appending significant
- * data to the "query jumble" while ignoring nonsignificant data.
- *
- * Rule of thumb for what to include is that we should ignore anything not
- * semantically significant (such as alias names) as well as anything that can
- * be deduced from child nodes (else we'd just be double-hashing that piece
- * of information).
- */
-void JumbleQuery(pgssJumbleState *jstate, Query *query)
+void stat_statements_parser_deinit(void)
 {
-       Assert(IsA(query, Query));
-       Assert(query->utilityStmt == NULL);
-
-       APP_JUMB(query->commandType);
-       /* resultRelation is usually predictable from commandType */
-       JumbleExpr(jstate, (Node *)query->cteList);
-       JumbleRangeTable(jstate, query->rtable);
-       JumbleExpr(jstate, (Node *)query->jointree);
-       JumbleExpr(jstate, (Node *)query->targetList);
-       JumbleExpr(jstate, (Node *)query->returningList);
-       JumbleExpr(jstate, (Node *)query->groupClause);
-       JumbleExpr(jstate, query->havingQual);
-       JumbleExpr(jstate, (Node *)query->windowClause);
-       JumbleExpr(jstate, (Node *)query->distinctClause);
-       JumbleExpr(jstate, (Node *)query->sortClause);
-       JumbleExpr(jstate, query->limitOffset);
-       JumbleExpr(jstate, query->limitCount);
-       /* we ignore rowMarks */
-       JumbleExpr(jstate, query->setOperations);
-}
-
-/*
- * Jumble a range table
- */
-static void
-JumbleRangeTable(pgssJumbleState *jstate, List *rtable)
-{
-       ListCell *lc;
-
-       foreach (lc, rtable)
-       {
-               RangeTblEntry *rte = (RangeTblEntry *)lfirst(lc);
-
-               Assert(IsA(rte, RangeTblEntry));
-               APP_JUMB(rte->rtekind);
-               switch (rte->rtekind)
-               {
-               case RTE_RELATION:
-                       APP_JUMB(rte->relid);
-                       break;
-               case RTE_SUBQUERY:
-                       JumbleQuery(jstate, rte->subquery);
-                       break;
-               case RTE_JOIN:
-                       APP_JUMB(rte->jointype);
-                       break;
-               case RTE_FUNCTION:
-                       JumbleExpr(jstate, (Node *)rte->functions);
-                       break;
-               case RTE_VALUES:
-                       JumbleExpr(jstate, (Node *)rte->values_lists);
-                       break;
-               case RTE_CTE:
-
-                       /*
-                        * Depending on the CTE name here isn't ideal, but it's 
the
-                        * only info we have to identify the referenced WITH 
item.
-                        */
-                       APP_JUMB_STRING(rte->ctename);
-                       APP_JUMB(rte->ctelevelsup);
-                       break;
-               /* GPDB RTEs */
-               case RTE_VOID:
-                       break;
-               case RTE_TABLEFUNCTION:
-                       JumbleQuery(jstate, rte->subquery);
-                       JumbleExpr(jstate, (Node *)rte->functions);
-                       break;
-               default:
-                       ereport(ERROR, (errmsg("unrecognized RTE kind: %d", 
(int)rte->rtekind)));
-                       break;
-               }
-       }
-}
-
-/*
- * Jumble an expression tree
- *
- * In general this function should handle all the same node types that
- * expression_tree_walker() does, and therefore it's coded to be as parallel
- * to that function as possible.  However, since we are only invoked on
- * queries immediately post-parse-analysis, we need not handle node types
- * that only appear in planning.
- *
- * Note: the reason we don't simply use expression_tree_walker() is that the
- * point of that function is to support tree walkers that don't care about
- * most tree node types, but here we care about all types.  We should complain
- * about any unrecognized node type.
- */
-static void
-JumbleExpr(pgssJumbleState *jstate, Node *node)
-{
-       ListCell *temp;
-
-       if (node == NULL)
-               return;
-
-       /* Guard against stack overflow due to overly complex expressions */
-       check_stack_depth();
-
-       /*
-        * We always emit the node's NodeTag, then any additional fields that 
are
-        * considered significant, and then we recurse to any child nodes.
-        */
-       APP_JUMB(node->type);
-
-       switch (nodeTag(node))
-       {
-       case T_Var:
-       {
-               Var *var = (Var *)node;
-
-               APP_JUMB(var->varno);
-               APP_JUMB(var->varattno);
-               APP_JUMB(var->varlevelsup);
-       }
-       break;
-       case T_Const:
-       {
-               Const *c = (Const *)node;
-
-               /* We jumble only the constant's type, not its value */
-               APP_JUMB(c->consttype);
-               /* Also, record its parse location for query normalization */
-               RecordConstLocation(jstate, c->location);
-       }
-       break;
-       case T_Param:
-       {
-               Param *p = (Param *)node;
-
-               APP_JUMB(p->paramkind);
-               APP_JUMB(p->paramid);
-               APP_JUMB(p->paramtype);
-       }
-       break;
-       case T_Aggref:
-       {
-               Aggref *expr = (Aggref *)node;
-
-               APP_JUMB(expr->aggfnoid);
-               JumbleExpr(jstate, (Node *)expr->aggdirectargs);
-               JumbleExpr(jstate, (Node *)expr->args);
-               JumbleExpr(jstate, (Node *)expr->aggorder);
-               JumbleExpr(jstate, (Node *)expr->aggdistinct);
-               JumbleExpr(jstate, (Node *)expr->aggfilter);
-       }
-       break;
-       case T_WindowFunc:
-       {
-               WindowFunc *expr = (WindowFunc *)node;
-
-               APP_JUMB(expr->winfnoid);
-               APP_JUMB(expr->winref);
-               JumbleExpr(jstate, (Node *)expr->args);
-               JumbleExpr(jstate, (Node *)expr->aggfilter);
-       }
-       break;
-       case T_ArrayRef:
-       {
-               ArrayRef *aref = (ArrayRef *)node;
-
-               JumbleExpr(jstate, (Node *)aref->refupperindexpr);
-               JumbleExpr(jstate, (Node *)aref->reflowerindexpr);
-               JumbleExpr(jstate, (Node *)aref->refexpr);
-               JumbleExpr(jstate, (Node *)aref->refassgnexpr);
-       }
-       break;
-       case T_FuncExpr:
-       {
-               FuncExpr *expr = (FuncExpr *)node;
-
-               APP_JUMB(expr->funcid);
-               JumbleExpr(jstate, (Node *)expr->args);
-       }
-       break;
-       case T_NamedArgExpr:
-       {
-               NamedArgExpr *nae = (NamedArgExpr *)node;
-
-               APP_JUMB(nae->argnumber);
-               JumbleExpr(jstate, (Node *)nae->arg);
-       }
-       break;
-       case T_OpExpr:
-       case T_DistinctExpr: /* struct-equivalent to OpExpr */
-       case T_NullIfExpr:       /* struct-equivalent to OpExpr */
-       {
-               OpExpr *expr = (OpExpr *)node;
-
-               APP_JUMB(expr->opno);
-               JumbleExpr(jstate, (Node *)expr->args);
-       }
-       break;
-       case T_ScalarArrayOpExpr:
-       {
-               ScalarArrayOpExpr *expr = (ScalarArrayOpExpr *)node;
-
-               APP_JUMB(expr->opno);
-               APP_JUMB(expr->useOr);
-               JumbleExpr(jstate, (Node *)expr->args);
-       }
-       break;
-       case T_BoolExpr:
-       {
-               BoolExpr *expr = (BoolExpr *)node;
-
-               APP_JUMB(expr->boolop);
-               JumbleExpr(jstate, (Node *)expr->args);
-       }
-       break;
-       case T_SubLink:
-       {
-               SubLink *sublink = (SubLink *)node;
-
-               APP_JUMB(sublink->subLinkType);
-               JumbleExpr(jstate, (Node *)sublink->testexpr);
-               JumbleQuery(jstate, (Query *)sublink->subselect);
-       }
-       break;
-       case T_FieldSelect:
-       {
-               FieldSelect *fs = (FieldSelect *)node;
-
-               APP_JUMB(fs->fieldnum);
-               JumbleExpr(jstate, (Node *)fs->arg);
-       }
-       break;
-       case T_FieldStore:
-       {
-               FieldStore *fstore = (FieldStore *)node;
-
-               JumbleExpr(jstate, (Node *)fstore->arg);
-               JumbleExpr(jstate, (Node *)fstore->newvals);
-       }
-       break;
-       case T_RelabelType:
-       {
-               RelabelType *rt = (RelabelType *)node;
-
-               APP_JUMB(rt->resulttype);
-               JumbleExpr(jstate, (Node *)rt->arg);
-       }
-       break;
-       case T_CoerceViaIO:
-       {
-               CoerceViaIO *cio = (CoerceViaIO *)node;
-
-               APP_JUMB(cio->resulttype);
-               JumbleExpr(jstate, (Node *)cio->arg);
-       }
-       break;
-       case T_ArrayCoerceExpr:
-       {
-               ArrayCoerceExpr *acexpr = (ArrayCoerceExpr *)node;
-
-               APP_JUMB(acexpr->resulttype);
-               JumbleExpr(jstate, (Node *)acexpr->arg);
-       }
-       break;
-       case T_ConvertRowtypeExpr:
-       {
-               ConvertRowtypeExpr *crexpr = (ConvertRowtypeExpr *)node;
-
-               APP_JUMB(crexpr->resulttype);
-               JumbleExpr(jstate, (Node *)crexpr->arg);
-       }
-       break;
-       case T_CollateExpr:
-       {
-               CollateExpr *ce = (CollateExpr *)node;
-
-               APP_JUMB(ce->collOid);
-               JumbleExpr(jstate, (Node *)ce->arg);
-       }
-       break;
-       case T_CaseExpr:
-       {
-               CaseExpr *caseexpr = (CaseExpr *)node;
-
-               JumbleExpr(jstate, (Node *)caseexpr->arg);
-               foreach (temp, caseexpr->args)
-               {
-                       CaseWhen *when = (CaseWhen *)lfirst(temp);
-
-                       Assert(IsA(when, CaseWhen));
-                       JumbleExpr(jstate, (Node *)when->expr);
-                       JumbleExpr(jstate, (Node *)when->result);
-               }
-               JumbleExpr(jstate, (Node *)caseexpr->defresult);
-       }
-       break;
-       case T_CaseTestExpr:
-       {
-               CaseTestExpr *ct = (CaseTestExpr *)node;
-
-               APP_JUMB(ct->typeId);
-       }
-       break;
-       case T_ArrayExpr:
-               JumbleExpr(jstate, (Node *)((ArrayExpr *)node)->elements);
-               break;
-       case T_RowExpr:
-               JumbleExpr(jstate, (Node *)((RowExpr *)node)->args);
-               break;
-       case T_RowCompareExpr:
-       {
-               RowCompareExpr *rcexpr = (RowCompareExpr *)node;
-
-               APP_JUMB(rcexpr->rctype);
-               JumbleExpr(jstate, (Node *)rcexpr->largs);
-               JumbleExpr(jstate, (Node *)rcexpr->rargs);
-       }
-       break;
-       case T_CoalesceExpr:
-               JumbleExpr(jstate, (Node *)((CoalesceExpr *)node)->args);
-               break;
-       case T_MinMaxExpr:
-       {
-               MinMaxExpr *mmexpr = (MinMaxExpr *)node;
-
-               APP_JUMB(mmexpr->op);
-               JumbleExpr(jstate, (Node *)mmexpr->args);
-       }
-       break;
-       case T_XmlExpr:
-       {
-               XmlExpr *xexpr = (XmlExpr *)node;
-
-               APP_JUMB(xexpr->op);
-               JumbleExpr(jstate, (Node *)xexpr->named_args);
-               JumbleExpr(jstate, (Node *)xexpr->args);
-       }
-       break;
-       case T_NullTest:
-       {
-               NullTest *nt = (NullTest *)node;
-
-               APP_JUMB(nt->nulltesttype);
-               JumbleExpr(jstate, (Node *)nt->arg);
-       }
-       break;
-       case T_BooleanTest:
-       {
-               BooleanTest *bt = (BooleanTest *)node;
-
-               APP_JUMB(bt->booltesttype);
-               JumbleExpr(jstate, (Node *)bt->arg);
-       }
-       break;
-       case T_CoerceToDomain:
-       {
-               CoerceToDomain *cd = (CoerceToDomain *)node;
-
-               APP_JUMB(cd->resulttype);
-               JumbleExpr(jstate, (Node *)cd->arg);
-       }
-       break;
-       case T_CoerceToDomainValue:
-       {
-               CoerceToDomainValue *cdv = (CoerceToDomainValue *)node;
-
-               APP_JUMB(cdv->typeId);
-       }
-       break;
-       case T_SetToDefault:
-       {
-               SetToDefault *sd = (SetToDefault *)node;
-
-               APP_JUMB(sd->typeId);
-       }
-       break;
-       case T_CurrentOfExpr:
-       {
-               CurrentOfExpr *ce = (CurrentOfExpr *)node;
-
-               APP_JUMB(ce->cvarno);
-               if (ce->cursor_name)
-                       APP_JUMB_STRING(ce->cursor_name);
-               APP_JUMB(ce->cursor_param);
-       }
-       break;
-       case T_TargetEntry:
-       {
-               TargetEntry *tle = (TargetEntry *)node;
-
-               APP_JUMB(tle->resno);
-               APP_JUMB(tle->ressortgroupref);
-               JumbleExpr(jstate, (Node *)tle->expr);
-       }
-       break;
-       case T_RangeTblRef:
-       {
-               RangeTblRef *rtr = (RangeTblRef *)node;
-
-               APP_JUMB(rtr->rtindex);
-       }
-       break;
-       case T_JoinExpr:
-       {
-               JoinExpr *join = (JoinExpr *)node;
-
-               APP_JUMB(join->jointype);
-               APP_JUMB(join->isNatural);
-               APP_JUMB(join->rtindex);
-               JumbleExpr(jstate, join->larg);
-               JumbleExpr(jstate, join->rarg);
-               JumbleExpr(jstate, join->quals);
-       }
-       break;
-       case T_FromExpr:
-       {
-               FromExpr *from = (FromExpr *)node;
-
-               JumbleExpr(jstate, (Node *)from->fromlist);
-               JumbleExpr(jstate, from->quals);
-       }
-       break;
-       case T_List:
-               foreach (temp, (List *)node)
-               {
-                       JumbleExpr(jstate, (Node *)lfirst(temp));
-               }
-               break;
-       case T_SortGroupClause:
-       {
-               SortGroupClause *sgc = (SortGroupClause *)node;
-
-               APP_JUMB(sgc->tleSortGroupRef);
-               APP_JUMB(sgc->eqop);
-               APP_JUMB(sgc->sortop);
-               APP_JUMB(sgc->nulls_first);
-       }
-       break;
-       case T_WindowClause:
-       {
-               WindowClause *wc = (WindowClause *)node;
-
-               APP_JUMB(wc->winref);
-               APP_JUMB(wc->frameOptions);
-               JumbleExpr(jstate, (Node *)wc->partitionClause);
-               JumbleExpr(jstate, (Node *)wc->orderClause);
-               JumbleExpr(jstate, wc->startOffset);
-               JumbleExpr(jstate, wc->endOffset);
-       }
-       break;
-       case T_CommonTableExpr:
-       {
-               CommonTableExpr *cte = (CommonTableExpr *)node;
-
-               /* we store the string name because RTE_CTE RTEs need it */
-               APP_JUMB_STRING(cte->ctename);
-               JumbleQuery(jstate, (Query *)cte->ctequery);
-       }
-       break;
-       case T_SetOperationStmt:
-       {
-               SetOperationStmt *setop = (SetOperationStmt *)node;
-
-               APP_JUMB(setop->op);
-               APP_JUMB(setop->all);
-               JumbleExpr(jstate, setop->larg);
-               JumbleExpr(jstate, setop->rarg);
-       }
-       break;
-       case T_RangeTblFunction:
-       {
-               RangeTblFunction *rtfunc = (RangeTblFunction *)node;
-
-               JumbleExpr(jstate, rtfunc->funcexpr);
-       }
-       break;
-       /* GPDB nodes */
-       case T_GroupingClause:
-       {
-               GroupingClause *grpnode = (GroupingClause *)node;
-
-               JumbleExpr(jstate, (Node *)grpnode->groupsets);
-       }
-       break;
-       case T_GroupingFunc:
-       {
-               GroupingFunc *grpnode = (GroupingFunc *)node;
-
-               JumbleExpr(jstate, (Node *)grpnode->args);
-       }
-       break;
-       case T_Grouping:
-       case T_GroupId:
-       case T_Integer:
-       case T_Value:
-               // TODO:seems like nothing to do with it
-               break;
-       /* GPDB-only additions, nothing to do */
-       case T_PartitionBy:
-       case T_PartitionElem:
-       case T_PartitionRangeItem:
-       case T_PartitionBoundSpec:
-       case T_PartitionSpec:
-       case T_PartitionValuesSpec:
-       case T_AlterPartitionId:
-       case T_AlterPartitionCmd:
-       case T_InheritPartitionCmd:
-       case T_CreateFileSpaceStmt:
-       case T_FileSpaceEntry:
-       case T_DropFileSpaceStmt:
-       case T_TableValueExpr:
-       case T_DenyLoginInterval:
-       case T_DenyLoginPoint:
-       case T_AlterTypeStmt:
-       case T_SetDistributionCmd:
-       case T_ExpandStmtSpec:
-               break;
-       default:
-               /* Only a warning, since we can stumble along anyway */
-               ereport(WARNING, (errmsg("unrecognized node type: %d",
-                        (int)nodeTag(node))));
-               break;
-       }
-}
-
-/*
- * Record location of constant within query string of query tree
- * that is currently being walked.
- */
-static void
-RecordConstLocation(pgssJumbleState *jstate, int location)
-{
-       /* -1 indicates unknown or undefined location */
-       if (location >= 0)
-       {
-               /* enlarge array if needed */
-               if (jstate->clocations_count >= jstate->clocations_buf_size)
-               {
-                       jstate->clocations_buf_size *= 2;
-                       jstate->clocations = (pgssLocationLen *)
-                               repalloc(jstate->clocations,
-                                                jstate->clocations_buf_size *
-                                                        
sizeof(pgssLocationLen));
-               }
-               jstate->clocations[jstate->clocations_count].location = 
location;
-               /* initialize lengths to -1 to simplify 
fill_in_constant_lengths */
-               jstate->clocations[jstate->clocations_count].length = -1;
-               jstate->clocations_count++;
-       }
+       /* NO-OP */
 }
 
 /* check if token should be replaced by substitute varable */
@@ -768,60 +127,13 @@ gen_normplan(const char *execution_plan)
 }
 
 /*
- * Post-parse-analysis hook: mark query with a queryId
- */
-void pgss_post_parse_analyze(ParseState *pstate, Query *query)
-{
-       pgssJumbleState jstate;
-
-       if (prev_post_parse_analyze_hook)
-               prev_post_parse_analyze_hook(pstate, query);
-
-       /* Assert we didn't do this already */
-       Assert(query->queryId == 0);
-
-       /*
-        * Utility statements get queryId zero.  We do this even in cases where
-        * the statement contains an optimizable statement for which a queryId
-        * could be derived (such as EXPLAIN or DECLARE CURSOR).  For such 
cases,
-        * runtime control will first go through ProcessUtility and then the
-        * executor, and we don't want the executor hooks to do anything, since 
we
-        * are already measuring the statement's costs at the utility level.
-        */
-       if (query->utilityStmt)
-       {
-               query->queryId = 0;
-               return;
-       }
-
-       /* Set up workspace for query jumbling */
-       jstate.jumble = (unsigned char *)palloc(JUMBLE_SIZE);
-       jstate.jumble_len = 0;
-       jstate.clocations_buf_size = 32;
-       jstate.clocations = (pgssLocationLen *)
-               palloc(jstate.clocations_buf_size * sizeof(pgssLocationLen));
-       jstate.clocations_count = 0;
-
-       /* Compute query ID and mark the Query node with it */
-       JumbleQuery(&jstate, query);
-       query->queryId = hash_any(jstate.jumble, jstate.jumble_len);
-
-       /*
-        * If we are unlucky enough to get a hash of zero, use 1 instead, to
-        * prevent confusion with the utility-statement case.
-        */
-       if (query->queryId == 0)
-               query->queryId = 1;
-}
-
-/*
- * comp_location: comparator for qsorting pgssLocationLen structs by location
+ * comp_location: comparator for qsorting LocationLen structs by location
  */
 static int
 comp_location(const void *a, const void *b)
 {
-       int                     l = ((const pgssLocationLen *) a)->location;
-       int                     r = ((const pgssLocationLen *) b)->location;
+       int                     l = ((const LocationLen *) a)->location;
+       int                     r = ((const LocationLen *) b)->location;
 
        if (l < r)
                return -1;
@@ -854,9 +166,9 @@ comp_location(const void *a, const void *b)
  * reason for a constant to start with a '-'.
  */
 static void
-fill_in_constant_lengths(pgssJumbleState *jstate, const char *query)
+fill_in_constant_lengths(JumbleState *jstate, const char *query)
 {
-       pgssLocationLen *locs;
+       LocationLen *locs;
        core_yyscan_t yyscanner;
        core_yy_extra_type yyextra;
        core_YYSTYPE yylval;
@@ -870,14 +182,14 @@ fill_in_constant_lengths(pgssJumbleState *jstate, const 
char *query)
         */
        if (jstate->clocations_count > 1)
                qsort(jstate->clocations, jstate->clocations_count,
-                         sizeof(pgssLocationLen), comp_location);
+                         sizeof(LocationLen), comp_location);
        locs = jstate->clocations;
 
        /* initialize the flex scanner --- should match raw_parser() */
        yyscanner = scanner_init(query,
                                                         &yyextra,
-                                                        ScanKeywords,
-                                                        NumScanKeywords);
+                                                        &ScanKeywords,
+                                                        ScanKeywordTokens);
 
        /* Search for each constant, in sequence */
        for (i = 0; i < jstate->clocations_count; i++)
@@ -957,7 +269,7 @@ fill_in_constant_lengths(pgssJumbleState *jstate, const 
char *query)
  * Returns a palloc'd string.
  */
 static char *
-generate_normalized_query(pgssJumbleState *jstate, const char *query,
+generate_normalized_query(JumbleState *jstate, const char *query,
                                                  int *query_len_p, int 
encoding)
 {
        char       *norm_query;
@@ -1027,12 +339,12 @@ char *gen_normquery(const char *query)
        if (!query) {
                return NULL;
        }
-       pgssJumbleState jstate;
+       JumbleState jstate;
        jstate.jumble = (unsigned char *)palloc(JUMBLE_SIZE);
        jstate.jumble_len = 0;
        jstate.clocations_buf_size = 32;
-       jstate.clocations = (pgssLocationLen *)
-               palloc(jstate.clocations_buf_size * sizeof(pgssLocationLen));
+       jstate.clocations = (LocationLen *)
+               palloc(jstate.clocations_buf_size * sizeof(LocationLen));
        jstate.clocations_count = 0;
        int query_len = strlen(query);
        return generate_normalized_query(&jstate, query, &query_len, 
GetDatabaseEncoding());
diff --git a/src/yagp_hooks_collector.c b/src/yagp_hooks_collector.c
index 9db73638b24..27fd0e04b26 100644
--- a/src/yagp_hooks_collector.c
+++ b/src/yagp_hooks_collector.c
@@ -1,5 +1,6 @@
 #include "postgres.h"
 #include "cdb/cdbvars.h"
+#include "funcapi.h"
 #include "utils/builtins.h"
 
 #include "hook_wrappers.h"
@@ -26,8 +27,15 @@ void _PG_fini(void) {
 }
 
 Datum yagp_stat_messages_reset(PG_FUNCTION_ARGS) {
-  yagp_functions_reset();
-  PG_RETURN_VOID();
+  FuncCallContext *funcctx;
+
+  if (SRF_IS_FIRSTCALL()) {
+    funcctx = SRF_FIRSTCALL_INIT();
+    yagp_functions_reset();
+  }
+
+  funcctx = SRF_PERCALL_SETUP();
+  SRF_RETURN_DONE(funcctx);
 }
 
 Datum yagp_stat_messages(PG_FUNCTION_ARGS) {
@@ -35,11 +43,25 @@ Datum yagp_stat_messages(PG_FUNCTION_ARGS) {
 }
 
 Datum yagp_init_log(PG_FUNCTION_ARGS) {
-  init_log();
-  PG_RETURN_VOID();
+  FuncCallContext *funcctx;
+
+  if (SRF_IS_FIRSTCALL()) {
+    funcctx = SRF_FIRSTCALL_INIT();
+    init_log();
+  }
+
+  funcctx = SRF_PERCALL_SETUP();
+  SRF_RETURN_DONE(funcctx);
 }
 
 Datum yagp_truncate_log(PG_FUNCTION_ARGS) {
-  truncate_log();
-  PG_RETURN_VOID();
+  FuncCallContext *funcctx;
+
+  if (SRF_IS_FIRSTCALL()) {
+    funcctx = SRF_FIRSTCALL_INIT();
+    truncate_log();
+  }
+
+  funcctx = SRF_PERCALL_SETUP();
+  SRF_RETURN_DONE(funcctx);
 }
diff --git a/yagp_hooks_collector--1.0--1.1.sql 
b/yagp_hooks_collector--1.0--1.1.sql
index 959d4f235d1..8684ca73915 100644
--- a/yagp_hooks_collector--1.0--1.1.sql
+++ b/yagp_hooks_collector--1.0--1.1.sql
@@ -23,17 +23,17 @@ DROP FUNCTION __yagp_stat_messages_reset_f_on_master();
 
 -- Recreate functions and view in new schema.
 CREATE FUNCTION yagpcc.__stat_messages_reset_f_on_master()
-RETURNS void
+RETURNS SETOF void
 AS 'MODULE_PATHNAME', 'yagp_stat_messages_reset'
 LANGUAGE C EXECUTE ON MASTER;
 
 CREATE FUNCTION yagpcc.__stat_messages_reset_f_on_segments()
-RETURNS void
+RETURNS SETOF void
 AS 'MODULE_PATHNAME', 'yagp_stat_messages_reset'
 LANGUAGE C EXECUTE ON ALL SEGMENTS;
 
 CREATE FUNCTION yagpcc.stat_messages_reset()
-RETURNS void
+RETURNS SETOF void
 AS
 $$
   SELECT yagpcc.__stat_messages_reset_f_on_master();
@@ -75,12 +75,12 @@ ORDER BY segid;
 
 -- Create new objects.
 CREATE FUNCTION yagpcc.__init_log_on_master()
-RETURNS void
+RETURNS SETOF void
 AS 'MODULE_PATHNAME', 'yagp_init_log'
 LANGUAGE C STRICT VOLATILE EXECUTE ON MASTER;
 
 CREATE FUNCTION yagpcc.__init_log_on_segments()
-RETURNS void
+RETURNS SETOF void
 AS 'MODULE_PATHNAME', 'yagp_init_log'
 LANGUAGE C STRICT VOLATILE EXECUTE ON ALL SEGMENTS;
 
@@ -95,17 +95,17 @@ CREATE VIEW yagpcc.log AS
   ORDER BY tmid, ssid, ccnt;
 
 CREATE FUNCTION yagpcc.__truncate_log_on_master()
-RETURNS void
+RETURNS SETOF void
 AS 'MODULE_PATHNAME', 'yagp_truncate_log'
 LANGUAGE C STRICT VOLATILE EXECUTE ON MASTER;
 
 CREATE FUNCTION yagpcc.__truncate_log_on_segments()
-RETURNS void
+RETURNS SETOF void
 AS 'MODULE_PATHNAME', 'yagp_truncate_log'
 LANGUAGE C STRICT VOLATILE EXECUTE ON ALL SEGMENTS;
 
 CREATE FUNCTION yagpcc.truncate_log()
-RETURNS void AS $$
+RETURNS SETOF void AS $$
 BEGIN
     PERFORM yagpcc.__truncate_log_on_master();
     PERFORM yagpcc.__truncate_log_on_segments();
diff --git a/yagp_hooks_collector--1.0.sql b/yagp_hooks_collector--1.0.sql
index 7ab4e1b2fb7..270cab92382 100644
--- a/yagp_hooks_collector--1.0.sql
+++ b/yagp_hooks_collector--1.0.sql
@@ -4,17 +4,17 @@
 \echo Use "CREATE EXTENSION yagp_hooks_collector" to load this file. \quit
 
 CREATE FUNCTION __yagp_stat_messages_reset_f_on_master()
-RETURNS void
+RETURNS SETOF void
 AS 'MODULE_PATHNAME', 'yagp_stat_messages_reset'
 LANGUAGE C EXECUTE ON MASTER;
 
 CREATE FUNCTION __yagp_stat_messages_reset_f_on_segments()
-RETURNS void
+RETURNS SETOF void
 AS 'MODULE_PATHNAME', 'yagp_stat_messages_reset'
 LANGUAGE C EXECUTE ON ALL SEGMENTS;
 
 CREATE FUNCTION yagp_stat_messages_reset()
-RETURNS void
+RETURNS SETOF void
 AS
 $$
   SELECT __yagp_stat_messages_reset_f_on_master();
diff --git a/yagp_hooks_collector--1.1.sql b/yagp_hooks_collector--1.1.sql
index 657720a88f2..e0e94b51493 100644
--- a/yagp_hooks_collector--1.1.sql
+++ b/yagp_hooks_collector--1.1.sql
@@ -6,17 +6,17 @@
 CREATE SCHEMA yagpcc;
 
 CREATE FUNCTION yagpcc.__stat_messages_reset_f_on_master()
-RETURNS void
+RETURNS SETOF void
 AS 'MODULE_PATHNAME', 'yagp_stat_messages_reset'
 LANGUAGE C EXECUTE ON MASTER;
 
 CREATE FUNCTION yagpcc.__stat_messages_reset_f_on_segments()
-RETURNS void
+RETURNS SETOF void
 AS 'MODULE_PATHNAME', 'yagp_stat_messages_reset'
 LANGUAGE C EXECUTE ON ALL SEGMENTS;
 
 CREATE FUNCTION yagpcc.stat_messages_reset()
-RETURNS void
+RETURNS SETOF void
 AS
 $$
   SELECT yagpcc.__stat_messages_reset_f_on_master();
@@ -57,12 +57,12 @@ CREATE VIEW yagpcc.stat_messages AS
 ORDER BY segid;
 
 CREATE FUNCTION yagpcc.__init_log_on_master()
-RETURNS void
+RETURNS SETOF void
 AS 'MODULE_PATHNAME', 'yagp_init_log'
 LANGUAGE C STRICT VOLATILE EXECUTE ON MASTER;
 
 CREATE FUNCTION yagpcc.__init_log_on_segments()
-RETURNS void
+RETURNS SETOF void
 AS 'MODULE_PATHNAME', 'yagp_init_log'
 LANGUAGE C STRICT VOLATILE EXECUTE ON ALL SEGMENTS;
 
@@ -77,17 +77,17 @@ CREATE VIEW yagpcc.log AS
 ORDER BY tmid, ssid, ccnt;
 
 CREATE FUNCTION yagpcc.__truncate_log_on_master()
-RETURNS void
+RETURNS SETOF void
 AS 'MODULE_PATHNAME', 'yagp_truncate_log'
 LANGUAGE C STRICT VOLATILE EXECUTE ON MASTER;
 
 CREATE FUNCTION yagpcc.__truncate_log_on_segments()
-RETURNS void
+RETURNS SETOF void
 AS 'MODULE_PATHNAME', 'yagp_truncate_log'
 LANGUAGE C STRICT VOLATILE EXECUTE ON ALL SEGMENTS;
 
 CREATE FUNCTION yagpcc.truncate_log()
-RETURNS void AS $$
+RETURNS SETOF void AS $$
 BEGIN
     PERFORM yagpcc.__truncate_log_on_master();
     PERFORM yagpcc.__truncate_log_on_segments();


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to