v00 just the counter
Cette révision appartient à :
révision
0b9b6aa124
9 fichiers modifiés avec 629 ajouts et 0 suppressions
21
Makefile
Fichier normal
21
Makefile
Fichier normal
|
@ -0,0 +1,21 @@
|
|||
EXTENSION = pacs
|
||||
DATA = pacs--0.0.1.sql
|
||||
REGRESS = pacs
|
||||
MODULES = pacs
|
||||
|
||||
TAP_TESTS = 1
|
||||
|
||||
PG_CONFIG = pg_config
|
||||
PGXS := $(shell $(PG_CONFIG) --pgxs)
|
||||
include $(PGXS)
|
||||
|
||||
%.man.1: README.%.md
|
||||
pandoc -s $< -o $@
|
||||
@echo man -l $@
|
||||
|
||||
pgbench: NPROCS=$(shell nproc)
|
||||
pgbench: NJOBS=$(shell nproc)
|
||||
pgbench: sql/pgbench.sql
|
||||
pgbench -f $< -T 10 --progress 1 --no-vacuum \
|
||||
-c $$(( $(NPROCS) * 4 )) \
|
||||
-j $$(( $(NJOBS) * 4 ))
|
0
README.pacs.md
Fichier normal
0
README.pacs.md
Fichier normal
152
expected/pacs.out
Fichier normal
152
expected/pacs.out
Fichier normal
|
@ -0,0 +1,152 @@
|
|||
CREATE EXTENSION slim;
|
||||
CREATE EXTENSION pacs;
|
||||
SELECT pacs_reset_all_measures();
|
||||
pacs_reset_all_measures
|
||||
-------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
-- create a measure
|
||||
SELECT pacs_create_measure('A');
|
||||
pacs_create_measure
|
||||
---------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
-- increment it 3 times
|
||||
SELECT pacs_increment_measure('A');
|
||||
pacs_increment_measure
|
||||
------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT pacs_increment_measure('A');
|
||||
pacs_increment_measure
|
||||
------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT pacs_increment_measure('A');
|
||||
pacs_increment_measure
|
||||
------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
-- check measure value is 3
|
||||
SELECT pacs_get_measure('A');
|
||||
pacs_get_measure
|
||||
------------------
|
||||
3
|
||||
(1 row)
|
||||
|
||||
-- reset the measure
|
||||
SELECT pacs_reset_measure('A');
|
||||
pacs_reset_measure
|
||||
--------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
-- should be 0 now
|
||||
SELECT pacs_get_measure('A');
|
||||
pacs_get_measure
|
||||
------------------
|
||||
0
|
||||
(1 row)
|
||||
|
||||
-- increment again
|
||||
SELECT pacs_increment_measure('A');
|
||||
pacs_increment_measure
|
||||
------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
-- should be 1
|
||||
SELECT pacs_get_measure('A');
|
||||
pacs_get_measure
|
||||
------------------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
-- and drop the measure
|
||||
SELECT pacs_drop_measure('A');
|
||||
pacs_drop_measure
|
||||
-------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
-- get stats from pacs (empty)
|
||||
-- SELECT * FROM pacs_get_stats();
|
||||
-- create 2 measures
|
||||
SELECT pacs_create_measure('B');
|
||||
pacs_create_measure
|
||||
---------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
SELECT pacs_create_measure('C');
|
||||
pacs_create_measure
|
||||
---------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
-- expect 2 measures
|
||||
-- SELECT * FROM pacs_get_stats();
|
||||
-- drop one
|
||||
SELECT pacs_drop_measure('B');
|
||||
pacs_drop_measure
|
||||
-------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
-- so result now is 1
|
||||
-- SELECT * FROM pacs_get_stats();
|
||||
--
|
||||
-- SPECIAL CASES
|
||||
--
|
||||
-- measure A has been dropped already.
|
||||
-- but it's not erroing, as expected.
|
||||
SELECT pacs_drop_measure('A');
|
||||
pacs_drop_measure
|
||||
-------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
-- trying to get value for an inexisting measure
|
||||
-- should ERROR
|
||||
SELECT pacs_get_measure('absent');
|
||||
ERROR: measure "absent" does not exist
|
||||
HINT: ensure the measure name is correct or $$ select create_measure('absent')$$ to create it
|
||||
-- reseting an inexsting measure
|
||||
-- but it's not erroing, as expected
|
||||
SELECT pacs_reset_measure('absent');
|
||||
pacs_reset_measure
|
||||
--------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
-- the measure still does not exist
|
||||
-- so we have an error
|
||||
SELECT pacs_get_measure('absent');
|
||||
ERROR: measure "absent" does not exist
|
||||
HINT: ensure the measure name is correct or $$ select create_measure('absent')$$ to create it
|
||||
-- however increment always create the measure if it does not exists
|
||||
SELECT pacs_increment_measure('absent');
|
||||
pacs_increment_measure
|
||||
------------------------
|
||||
|
||||
(1 row)
|
||||
|
||||
-- and now we can fetch value (should be 1)
|
||||
SELECT pacs_get_measure('absent');
|
||||
pacs_get_measure
|
||||
------------------
|
||||
1
|
||||
(1 row)
|
||||
|
||||
-- and we drop the "absent" measure (yeah, it's confusing)
|
||||
SELECT pacs_drop_measure('absent');
|
||||
pacs_drop_measure
|
||||
-------------------
|
||||
|
||||
(1 row)
|
||||
|
30
pacs--0.0.1.sql
Fichier normal
30
pacs--0.0.1.sql
Fichier normal
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* measures
|
||||
*/
|
||||
CREATE FUNCTION pacs_reset_all_measures()
|
||||
RETURNS void
|
||||
AS 'MODULE_PATHNAME', 'pacs_reset_all_measures'
|
||||
LANGUAGE C STRICT;
|
||||
|
||||
CREATE FUNCTION pacs_reset_measure(measure_name Name)
|
||||
RETURNS void
|
||||
AS 'MODULE_PATHNAME', 'pacs_reset_measure'
|
||||
LANGUAGE C STRICT;
|
||||
|
||||
CREATE FUNCTION pacs_create_measure(measure_name Name)
|
||||
RETURNS void
|
||||
AS 'MODULE_PATHNAME', 'pacs_create_measure'
|
||||
LANGUAGE C STRICT;
|
||||
CREATE FUNCTION pacs_drop_measure(measure_name Name)
|
||||
RETURNS void
|
||||
AS 'MODULE_PATHNAME', 'pacs_drop_measure'
|
||||
LANGUAGE C STRICT;
|
||||
|
||||
CREATE FUNCTION pacs_increment_measure(measure_name Name)
|
||||
RETURNS void
|
||||
AS 'MODULE_PATHNAME', 'pacs_increment_measure'
|
||||
LANGUAGE C STRICT;
|
||||
CREATE FUNCTION pacs_get_measure(measure_name Name)
|
||||
RETURNS bigint
|
||||
AS 'MODULE_PATHNAME', 'pacs_get_measure'
|
||||
LANGUAGE C STRICT;
|
333
pacs.c
Fichier normal
333
pacs.c
Fichier normal
|
@ -0,0 +1,333 @@
|
|||
/*--------------------------------------------------------------------------
|
||||
*
|
||||
* pacs.c
|
||||
* Code for easier management of "measures".
|
||||
*
|
||||
* Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "postgres.h"
|
||||
#include "fmgr.h"
|
||||
|
||||
#include "common/hashfn.h"
|
||||
#include "pgstat.h"
|
||||
#include "utils/builtins.h"
|
||||
#include "utils/pgstat_internal.h"
|
||||
|
||||
#include "pacs.h"
|
||||
|
||||
PG_MODULE_MAGIC;
|
||||
|
||||
/* structure for measure */
|
||||
typedef struct MeasureStatEntry
|
||||
{
|
||||
PgStat_Counter measure;
|
||||
} MeasureStatEntry;
|
||||
|
||||
/* boilerplace structure for all measures */
|
||||
typedef struct MeasuresStatShared
|
||||
{
|
||||
PgStatShared_Common header;
|
||||
MeasureStatEntry stats;
|
||||
} MeasuresStatShared;
|
||||
|
||||
/* boilerplate declaration */
|
||||
static bool measure_flush_cb(PgStat_EntryRef *entry_ref, bool nowait);
|
||||
|
||||
/* declare our measures stats */
|
||||
static const PgStat_KindInfo measures = {
|
||||
.name = "measures",
|
||||
.fixed_amount = false,
|
||||
|
||||
/* Measures are system-wide */
|
||||
.accessed_across_databases = true,
|
||||
|
||||
.shared_size = sizeof(MeasuresStatShared),
|
||||
.shared_data_off = offsetof(MeasuresStatShared, stats),
|
||||
.shared_data_len = sizeof(((MeasuresStatShared *) 0)->stats),
|
||||
.pending_size = sizeof(MeasureStatEntry),
|
||||
.flush_pending_cb = measure_flush_cb,
|
||||
};
|
||||
|
||||
/*
|
||||
* Compute stats entry idx from measure name with an 8-byte hash.
|
||||
*/
|
||||
#define PGSTAT_MEASURE_IDX(name) hash_bytes_extended((const unsigned char *) name, strlen(name), 0)
|
||||
|
||||
/*
|
||||
* Kind ID reserved for statistics of measures.
|
||||
*/
|
||||
#define PGSTAT_KIND_MEASURE (PGSTAT_KIND_CUSTOM_MIN + 1)
|
||||
|
||||
/* Track if stats are loaded */
|
||||
static bool measures_loaded = false;
|
||||
|
||||
void
|
||||
_PG_init(void)
|
||||
{
|
||||
if (!process_shared_preload_libraries_in_progress)
|
||||
return;
|
||||
|
||||
ereport(LOG,
|
||||
(errmsg("Module pacs is starting"),
|
||||
errdetail("providing advanced stats structures.")));
|
||||
pgstat_register_kind(PGSTAT_KIND_MEASURE, &measures);
|
||||
|
||||
/* mark stats as loaded */
|
||||
measures_loaded = true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Callback for flushing a measure
|
||||
*/
|
||||
static bool
|
||||
measure_flush_cb(PgStat_EntryRef *entry_ref, bool nowait)
|
||||
{
|
||||
MeasureStatEntry *localent;
|
||||
MeasuresStatShared *shfuncent;
|
||||
|
||||
localent = (MeasureStatEntry *) entry_ref->pending;
|
||||
shfuncent = (MeasuresStatShared *) entry_ref->shared_stats;
|
||||
|
||||
if (!pgstat_lock_entry(entry_ref, nowait))
|
||||
return false;
|
||||
|
||||
shfuncent->stats.measure += localent->measure;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
check_loaded()
|
||||
{
|
||||
if (!measures_loaded)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("measures module not loaded"),
|
||||
errhint("check shared_preload_libraries")));
|
||||
}
|
||||
|
||||
/*
|
||||
* The following code contains:
|
||||
* - the exported C functions
|
||||
* - the SQL API
|
||||
*/
|
||||
/*
|
||||
* Create a measure
|
||||
*/
|
||||
PGDLLEXPORT void
|
||||
pacsCreateMeasure(const char *name)
|
||||
{
|
||||
PgStat_EntryRef *entry_ref;
|
||||
MeasuresStatShared *shstatent;
|
||||
|
||||
/* error if disabled */
|
||||
check_loaded();
|
||||
|
||||
entry_ref = pgstat_get_entry_ref_locked(PGSTAT_KIND_MEASURE, InvalidOid,
|
||||
PGSTAT_MEASURE_IDX(name), false);
|
||||
shstatent = (MeasuresStatShared *) entry_ref->shared_stats;
|
||||
|
||||
/* initialize shared memory data */
|
||||
memset(&shstatent->stats, 0, sizeof(shstatent->stats));
|
||||
pgstat_unlock_entry(entry_ref);
|
||||
}
|
||||
|
||||
/*
|
||||
* SQL API
|
||||
*/
|
||||
PG_FUNCTION_INFO_V1(pacs_create_measure);
|
||||
Datum
|
||||
pacs_create_measure(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Name name;
|
||||
|
||||
name = PG_GETARG_NAME(0);
|
||||
pacsCreateMeasure(NameStr(*name));
|
||||
PG_RETURN_VOID();
|
||||
}
|
||||
|
||||
/*
|
||||
* Drop a measure
|
||||
*
|
||||
* XXX register to create, drop to unregister...
|
||||
*/
|
||||
PGDLLEXPORT void
|
||||
pacsDropMeasure(const char *name)
|
||||
{
|
||||
/* error if disabled */
|
||||
check_loaded();
|
||||
|
||||
/* drop and on faillure inform for later garbage collection */
|
||||
if (!pgstat_drop_entry(PGSTAT_KIND_MEASURE, InvalidOid,
|
||||
PGSTAT_MEASURE_IDX(name)))
|
||||
pgstat_request_entry_refs_gc();
|
||||
}
|
||||
|
||||
PG_FUNCTION_INFO_V1(pacs_drop_measure);
|
||||
Datum
|
||||
pacs_drop_measure(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Name name;
|
||||
|
||||
name = PG_GETARG_NAME(0);
|
||||
pacsDropMeasure(NameStr(*name));
|
||||
PG_RETURN_VOID();
|
||||
}
|
||||
|
||||
/*
|
||||
* Increment a measure
|
||||
*
|
||||
* By design, PostgreSQL does create the measure if absent!
|
||||
*
|
||||
* we do not manage ereport() here to not add overhead.
|
||||
* XXX is it accurate ?
|
||||
*/
|
||||
PGDLLEXPORT void
|
||||
pacsIncrementMeasure(const char *name)
|
||||
{
|
||||
PgStat_EntryRef *entry_ref;
|
||||
MeasuresStatShared *shstatent;
|
||||
MeasureStatEntry *statent;
|
||||
|
||||
/* quick leave if disabled */
|
||||
if (!measures_loaded)
|
||||
return;
|
||||
|
||||
entry_ref = pgstat_get_entry_ref_locked(PGSTAT_KIND_MEASURE, InvalidOid,
|
||||
PGSTAT_MEASURE_IDX(name), false);
|
||||
|
||||
shstatent = (MeasuresStatShared *) entry_ref->shared_stats;
|
||||
statent = &shstatent->stats;
|
||||
|
||||
/* Update the measure */
|
||||
statent->measure++;
|
||||
|
||||
pgstat_unlock_entry(entry_ref);
|
||||
}
|
||||
|
||||
PG_FUNCTION_INFO_V1(pacs_increment_measure);
|
||||
Datum
|
||||
pacs_increment_measure(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Name name;
|
||||
|
||||
name = PG_GETARG_NAME(0);
|
||||
pacsIncrementMeasure(NameStr(*name));
|
||||
PG_RETURN_VOID();
|
||||
}
|
||||
|
||||
/*
|
||||
* Support function for the SQL-callable functions. Returns
|
||||
* a pointer to the measure struct.
|
||||
*/
|
||||
static MeasureStatEntry *
|
||||
pacsGetMeasure(const char *name)
|
||||
{
|
||||
MeasureStatEntry *entry = NULL;
|
||||
|
||||
/* error if disabled */
|
||||
check_loaded();
|
||||
|
||||
/* Compile the lookup key as a hash of the measure name */
|
||||
entry = (MeasureStatEntry *) pgstat_fetch_entry(PGSTAT_KIND_MEASURE,
|
||||
InvalidOid,
|
||||
PGSTAT_MEASURE_IDX(name));
|
||||
return entry;
|
||||
}
|
||||
|
||||
/*
|
||||
* SQL function returning the measure current value.
|
||||
*/
|
||||
PG_FUNCTION_INFO_V1(pacs_get_measure);
|
||||
Datum
|
||||
pacs_get_measure(PG_FUNCTION_ARGS)
|
||||
{
|
||||
MeasureStatEntry *entry;
|
||||
Name name;
|
||||
|
||||
name = PG_GETARG_NAME(0);
|
||||
|
||||
entry = pacsGetMeasure(NameStr(*name));
|
||||
if (entry == NULL)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_OBJECT),
|
||||
errmsg("measure \"%s\" does not exist",
|
||||
NameStr(*name)),
|
||||
errhint("ensure the measure name is correct or "
|
||||
"$$ select create_measure('%s')$$ to create it",
|
||||
NameStr(*name))));
|
||||
|
||||
PG_RETURN_INT64(entry->measure);
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset a measure
|
||||
*/
|
||||
PGDLLEXPORT void
|
||||
pacsResetMeasure(const char *name)
|
||||
{
|
||||
/* error if disabled */
|
||||
check_loaded();
|
||||
pgstat_reset_entry(PGSTAT_KIND_MEASURE, InvalidOid,
|
||||
PGSTAT_MEASURE_IDX(name), 0);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* SQL function reseting the measure(s)
|
||||
*/
|
||||
PG_FUNCTION_INFO_V1(pacs_reset_measure);
|
||||
Datum
|
||||
pacs_reset_measure(PG_FUNCTION_ARGS)
|
||||
{
|
||||
Name name;
|
||||
name = PG_GETARG_NAME(0);
|
||||
pacsResetMeasure(NameStr(*name));
|
||||
PG_RETURN_VOID();
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset a measure
|
||||
*/
|
||||
PGDLLEXPORT void
|
||||
pacsResetAllMeasures(void)
|
||||
{
|
||||
/* error if disabled */
|
||||
check_loaded();
|
||||
pgstat_reset_of_kind(PGSTAT_KIND_MEASURE);
|
||||
return;
|
||||
}
|
||||
|
||||
PG_FUNCTION_INFO_V1(pacs_reset_all_measures);
|
||||
Datum
|
||||
pacs_reset_all_measures(PG_FUNCTION_ARGS)
|
||||
{
|
||||
pacsResetAllMeasures();
|
||||
PG_RETURN_VOID();
|
||||
}
|
||||
|
||||
// PG_FUNCTION_INFO_V1(pacs_list_all_measures);
|
||||
// PGDLLEXPORT void
|
||||
// pacs_list_all_measures(PgStat_Kind kind)
|
||||
// {
|
||||
// HASH_SEQ_STATUS status;
|
||||
// PgStat_EntryRef *entry_ref;
|
||||
//
|
||||
// const PgStat_KindInfo *kind_info = pgstat_get_kind_info(kind);
|
||||
// if (!kind_info || !kind_info->hash_table)
|
||||
// {
|
||||
// elog(ERROR, "Invalid or unsupported statistics kind.");
|
||||
// return;
|
||||
// }
|
||||
//
|
||||
// hash_seq_init(&status, kind_info->hash_table);
|
||||
//
|
||||
// while ((entry_ref = hash_seq_search(&status)) != NULL)
|
||||
// {
|
||||
// elog(INFO, "Key for kind %d: %u/%llu", kind,
|
||||
// entry_ref->key.dboid, (unsigned long long)entry_ref->key.objid);
|
||||
// }
|
||||
// }
|
5
pacs.control
Fichier normal
5
pacs.control
Fichier normal
|
@ -0,0 +1,5 @@
|
|||
comment = 'Provides PostgresSQL Advanced Cumulative Statistics'
|
||||
default_version = '0.0.1'
|
||||
relocatable = true
|
||||
module_pathname = '$libdir/pacs'
|
||||
requires = 'slim'
|
29
pacs.h
Fichier normal
29
pacs.h
Fichier normal
|
@ -0,0 +1,29 @@
|
|||
/*--------------------------------------------------------------------------
|
||||
*
|
||||
* pacs.h
|
||||
* Definitions for easier statistics management.
|
||||
*
|
||||
* Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* -------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef PACS
|
||||
#define PACS
|
||||
|
||||
extern void RegisterMeasuresInPgStat(void);
|
||||
|
||||
/* creating/dropping stats */
|
||||
extern void pacsCreateMeasure(const char *name);
|
||||
extern void pacsDropMeasure(const char *name);
|
||||
|
||||
/* working with stats content */
|
||||
extern void pacsIncrementMeasure(const char *name);
|
||||
extern void pacsResetAllMeasures(void);
|
||||
extern void pacsResetMeasure(const char *name);
|
||||
|
||||
/* statsmgr_stats.c */
|
||||
extern void RegisterPacsInPgStat(void);
|
||||
|
||||
#endif
|
59
sql/pacs.sql
Fichier normal
59
sql/pacs.sql
Fichier normal
|
@ -0,0 +1,59 @@
|
|||
CREATE EXTENSION slim;
|
||||
CREATE EXTENSION pacs;
|
||||
|
||||
SELECT pacs_reset_all_measures();
|
||||
|
||||
-- create a measure
|
||||
SELECT pacs_create_measure('A');
|
||||
-- increment it 3 times
|
||||
SELECT pacs_increment_measure('A');
|
||||
SELECT pacs_increment_measure('A');
|
||||
SELECT pacs_increment_measure('A');
|
||||
-- check measure value is 3
|
||||
SELECT pacs_get_measure('A');
|
||||
-- reset the measure
|
||||
SELECT pacs_reset_measure('A');
|
||||
-- should be 0 now
|
||||
SELECT pacs_get_measure('A');
|
||||
-- increment again
|
||||
SELECT pacs_increment_measure('A');
|
||||
-- should be 1
|
||||
SELECT pacs_get_measure('A');
|
||||
-- and drop the measure
|
||||
SELECT pacs_drop_measure('A');
|
||||
|
||||
-- get stats from pacs (empty)
|
||||
-- SELECT * FROM pacs_get_stats();
|
||||
-- create 2 measures
|
||||
SELECT pacs_create_measure('B');
|
||||
SELECT pacs_create_measure('C');
|
||||
-- expect 2 measures
|
||||
-- SELECT * FROM pacs_get_stats();
|
||||
-- drop one
|
||||
SELECT pacs_drop_measure('B');
|
||||
-- so result now is 1
|
||||
-- SELECT * FROM pacs_get_stats();
|
||||
|
||||
--
|
||||
-- SPECIAL CASES
|
||||
--
|
||||
-- measure A has been dropped already.
|
||||
-- but it's not erroing, as expected.
|
||||
SELECT pacs_drop_measure('A');
|
||||
|
||||
-- trying to get value for an inexisting measure
|
||||
-- should ERROR
|
||||
SELECT pacs_get_measure('absent');
|
||||
|
||||
-- reseting an inexsting measure
|
||||
-- but it's not erroing, as expected
|
||||
SELECT pacs_reset_measure('absent');
|
||||
-- the measure still does not exist
|
||||
-- so we have an error
|
||||
SELECT pacs_get_measure('absent');
|
||||
-- however increment always create the measure if it does not exists
|
||||
SELECT pacs_increment_measure('absent');
|
||||
-- and now we can fetch value (should be 1)
|
||||
SELECT pacs_get_measure('absent');
|
||||
-- and we drop the "absent" measure (yeah, it's confusing)
|
||||
SELECT pacs_drop_measure('absent');
|
0
sql/pgbench.sql
Fichier normal
0
sql/pgbench.sql
Fichier normal
Chargement…
Référencer dans un nouveau ticket