mirror of
https://github.com/postgres/postgres.git
synced 2025-07-31 22:04:40 +03:00
pgindent run for 9.5
This commit is contained in:
@ -113,12 +113,12 @@ gin_btree_compare_prefix(FunctionCallInfo fcinfo)
|
||||
cmp;
|
||||
|
||||
cmp = DatumGetInt32(DirectFunctionCall2Coll(
|
||||
data->typecmp,
|
||||
PG_GET_COLLATION(),
|
||||
(data->strategy == BTLessStrategyNumber ||
|
||||
data->strategy == BTLessEqualStrategyNumber)
|
||||
? data->datum : a,
|
||||
b));
|
||||
data->typecmp,
|
||||
PG_GET_COLLATION(),
|
||||
(data->strategy == BTLessStrategyNumber ||
|
||||
data->strategy == BTLessEqualStrategyNumber)
|
||||
? data->datum : a,
|
||||
b));
|
||||
|
||||
switch (data->strategy)
|
||||
{
|
||||
@ -186,14 +186,14 @@ Datum \
|
||||
gin_extract_value_##type(PG_FUNCTION_ARGS) \
|
||||
{ \
|
||||
return gin_btree_extract_value(fcinfo, is_varlena); \
|
||||
} \
|
||||
} \
|
||||
PG_FUNCTION_INFO_V1(gin_extract_query_##type); \
|
||||
Datum \
|
||||
gin_extract_query_##type(PG_FUNCTION_ARGS) \
|
||||
{ \
|
||||
return gin_btree_extract_query(fcinfo, \
|
||||
is_varlena, leftmostvalue, typecmp); \
|
||||
} \
|
||||
} \
|
||||
PG_FUNCTION_INFO_V1(gin_compare_prefix_##type); \
|
||||
Datum \
|
||||
gin_compare_prefix_##type(PG_FUNCTION_ARGS) \
|
||||
@ -209,6 +209,7 @@ leftmostvalue_int2(void)
|
||||
{
|
||||
return Int16GetDatum(SHRT_MIN);
|
||||
}
|
||||
|
||||
GIN_SUPPORT(int2, false, leftmostvalue_int2, btint2cmp)
|
||||
|
||||
static Datum
|
||||
@ -216,6 +217,7 @@ leftmostvalue_int4(void)
|
||||
{
|
||||
return Int32GetDatum(INT_MIN);
|
||||
}
|
||||
|
||||
GIN_SUPPORT(int4, false, leftmostvalue_int4, btint4cmp)
|
||||
|
||||
static Datum
|
||||
@ -226,6 +228,7 @@ leftmostvalue_int8(void)
|
||||
*/
|
||||
return Int64GetDatum(SEQ_MINVALUE);
|
||||
}
|
||||
|
||||
GIN_SUPPORT(int8, false, leftmostvalue_int8, btint8cmp)
|
||||
|
||||
static Datum
|
||||
@ -233,6 +236,7 @@ leftmostvalue_float4(void)
|
||||
{
|
||||
return Float4GetDatum(-get_float4_infinity());
|
||||
}
|
||||
|
||||
GIN_SUPPORT(float4, false, leftmostvalue_float4, btfloat4cmp)
|
||||
|
||||
static Datum
|
||||
@ -240,6 +244,7 @@ leftmostvalue_float8(void)
|
||||
{
|
||||
return Float8GetDatum(-get_float8_infinity());
|
||||
}
|
||||
|
||||
GIN_SUPPORT(float8, false, leftmostvalue_float8, btfloat8cmp)
|
||||
|
||||
static Datum
|
||||
@ -250,6 +255,7 @@ leftmostvalue_money(void)
|
||||
*/
|
||||
return Int64GetDatum(SEQ_MINVALUE);
|
||||
}
|
||||
|
||||
GIN_SUPPORT(money, false, leftmostvalue_money, cash_cmp)
|
||||
|
||||
static Datum
|
||||
@ -257,6 +263,7 @@ leftmostvalue_oid(void)
|
||||
{
|
||||
return ObjectIdGetDatum(0);
|
||||
}
|
||||
|
||||
GIN_SUPPORT(oid, false, leftmostvalue_oid, btoidcmp)
|
||||
|
||||
static Datum
|
||||
@ -264,6 +271,7 @@ leftmostvalue_timestamp(void)
|
||||
{
|
||||
return TimestampGetDatum(DT_NOBEGIN);
|
||||
}
|
||||
|
||||
GIN_SUPPORT(timestamp, false, leftmostvalue_timestamp, timestamp_cmp)
|
||||
|
||||
GIN_SUPPORT(timestamptz, false, leftmostvalue_timestamp, timestamp_cmp)
|
||||
@ -273,6 +281,7 @@ leftmostvalue_time(void)
|
||||
{
|
||||
return TimeADTGetDatum(0);
|
||||
}
|
||||
|
||||
GIN_SUPPORT(time, false, leftmostvalue_time, time_cmp)
|
||||
|
||||
static Datum
|
||||
@ -285,6 +294,7 @@ leftmostvalue_timetz(void)
|
||||
|
||||
return TimeTzADTPGetDatum(v);
|
||||
}
|
||||
|
||||
GIN_SUPPORT(timetz, false, leftmostvalue_timetz, timetz_cmp)
|
||||
|
||||
static Datum
|
||||
@ -292,6 +302,7 @@ leftmostvalue_date(void)
|
||||
{
|
||||
return DateADTGetDatum(DATEVAL_NOBEGIN);
|
||||
}
|
||||
|
||||
GIN_SUPPORT(date, false, leftmostvalue_date, date_cmp)
|
||||
|
||||
static Datum
|
||||
@ -304,6 +315,7 @@ leftmostvalue_interval(void)
|
||||
v->month = 0;
|
||||
return IntervalPGetDatum(v);
|
||||
}
|
||||
|
||||
GIN_SUPPORT(interval, false, leftmostvalue_interval, interval_cmp)
|
||||
|
||||
static Datum
|
||||
@ -313,6 +325,7 @@ leftmostvalue_macaddr(void)
|
||||
|
||||
return MacaddrPGetDatum(v);
|
||||
}
|
||||
|
||||
GIN_SUPPORT(macaddr, false, leftmostvalue_macaddr, macaddr_cmp)
|
||||
|
||||
static Datum
|
||||
@ -320,6 +333,7 @@ leftmostvalue_inet(void)
|
||||
{
|
||||
return DirectFunctionCall1(inet_in, CStringGetDatum("0.0.0.0/0"));
|
||||
}
|
||||
|
||||
GIN_SUPPORT(inet, true, leftmostvalue_inet, network_cmp)
|
||||
|
||||
GIN_SUPPORT(cidr, true, leftmostvalue_inet, network_cmp)
|
||||
@ -329,6 +343,7 @@ leftmostvalue_text(void)
|
||||
{
|
||||
return PointerGetDatum(cstring_to_text_with_len("", 0));
|
||||
}
|
||||
|
||||
GIN_SUPPORT(text, true, leftmostvalue_text, bttextcmp)
|
||||
|
||||
static Datum
|
||||
@ -336,6 +351,7 @@ leftmostvalue_char(void)
|
||||
{
|
||||
return CharGetDatum(SCHAR_MIN);
|
||||
}
|
||||
|
||||
GIN_SUPPORT(char, false, leftmostvalue_char, btcharcmp)
|
||||
|
||||
GIN_SUPPORT(bytea, true, leftmostvalue_text, byteacmp)
|
||||
@ -348,6 +364,7 @@ leftmostvalue_bit(void)
|
||||
ObjectIdGetDatum(0),
|
||||
Int32GetDatum(-1));
|
||||
}
|
||||
|
||||
GIN_SUPPORT(bit, true, leftmostvalue_bit, bitcmp)
|
||||
|
||||
static Datum
|
||||
@ -358,6 +375,7 @@ leftmostvalue_varbit(void)
|
||||
ObjectIdGetDatum(0),
|
||||
Int32GetDatum(-1));
|
||||
}
|
||||
|
||||
GIN_SUPPORT(varbit, true, leftmostvalue_varbit, bitcmp)
|
||||
|
||||
/*
|
||||
@ -402,4 +420,5 @@ leftmostvalue_numeric(void)
|
||||
{
|
||||
return PointerGetDatum(NULL);
|
||||
}
|
||||
|
||||
GIN_SUPPORT(numeric, true, leftmostvalue_numeric, gin_numeric_cmp)
|
||||
|
@ -13,7 +13,7 @@
|
||||
GISTENTRY *
|
||||
gbt_num_compress(GISTENTRY *entry, const gbtree_ninfo *tinfo)
|
||||
{
|
||||
GISTENTRY *retval;
|
||||
GISTENTRY *retval;
|
||||
|
||||
if (entry->leafkey)
|
||||
{
|
||||
|
@ -71,7 +71,7 @@ gbt_var_key_readable(const GBT_VARKEY *k)
|
||||
* Create a leaf-entry to store in the index, from a single Datum.
|
||||
*/
|
||||
static GBT_VARKEY *
|
||||
gbt_var_key_from_datum(const struct varlena *u)
|
||||
gbt_var_key_from_datum(const struct varlena * u)
|
||||
{
|
||||
int32 lowersize = VARSIZE(u);
|
||||
GBT_VARKEY *r;
|
||||
|
@ -195,7 +195,7 @@ dmetaphone_alt(PG_FUNCTION_ARGS)
|
||||
* in a case like this.
|
||||
*/
|
||||
|
||||
#define META_FREE(x) ((void)true) /* pfree((x)) */
|
||||
#define META_FREE(x) ((void)true) /* pfree((x)) */
|
||||
#else /* not defined DMETAPHONE_MAIN */
|
||||
|
||||
/* use the standard malloc library when not running in PostgreSQL */
|
||||
|
@ -72,7 +72,7 @@ typedef struct
|
||||
static pg_crc32
|
||||
crc32_sz(char *buf, int size)
|
||||
{
|
||||
pg_crc32 crc;
|
||||
pg_crc32 crc;
|
||||
|
||||
INIT_TRADITIONAL_CRC32(crc);
|
||||
COMP_TRADITIONAL_CRC32(crc, buf, size);
|
||||
|
@ -9,7 +9,7 @@ PG_MODULE_MAGIC;
|
||||
|
||||
|
||||
PG_FUNCTION_INFO_V1(hstore_to_plperl);
|
||||
Datum hstore_to_plperl(PG_FUNCTION_ARGS);
|
||||
Datum hstore_to_plperl(PG_FUNCTION_ARGS);
|
||||
|
||||
Datum
|
||||
hstore_to_plperl(PG_FUNCTION_ARGS)
|
||||
@ -26,10 +26,10 @@ hstore_to_plperl(PG_FUNCTION_ARGS)
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
const char *key;
|
||||
SV *value;
|
||||
SV *value;
|
||||
|
||||
key = pnstrdup(HS_KEY(entries, base, i), HS_KEYLEN(entries, i));
|
||||
value = HS_VALISNULL(entries, i) ? newSV(0) : cstr2sv(pnstrdup(HS_VAL(entries, base,i), HS_VALLEN(entries, i)));
|
||||
value = HS_VALISNULL(entries, i) ? newSV(0) : cstr2sv(pnstrdup(HS_VAL(entries, base, i), HS_VALLEN(entries, i)));
|
||||
|
||||
(void) hv_store(hv, key, strlen(key), value, 0);
|
||||
}
|
||||
@ -39,7 +39,7 @@ hstore_to_plperl(PG_FUNCTION_ARGS)
|
||||
|
||||
|
||||
PG_FUNCTION_INFO_V1(plperl_to_hstore);
|
||||
Datum plperl_to_hstore(PG_FUNCTION_ARGS);
|
||||
Datum plperl_to_hstore(PG_FUNCTION_ARGS);
|
||||
|
||||
Datum
|
||||
plperl_to_hstore(PG_FUNCTION_ARGS)
|
||||
@ -61,8 +61,8 @@ plperl_to_hstore(PG_FUNCTION_ARGS)
|
||||
i = 0;
|
||||
while ((he = hv_iternext(hv)))
|
||||
{
|
||||
char *key = sv2cstr(HeSVKEY_force(he));
|
||||
SV *value = HeVAL(he);
|
||||
char *key = sv2cstr(HeSVKEY_force(he));
|
||||
SV *value = HeVAL(he);
|
||||
|
||||
pairs[i].key = pstrdup(key);
|
||||
pairs[i].keylen = hstoreCheckKeyLen(strlen(pairs[i].key));
|
||||
|
@ -8,7 +8,7 @@ PG_MODULE_MAGIC;
|
||||
|
||||
|
||||
PG_FUNCTION_INFO_V1(hstore_to_plpython);
|
||||
Datum hstore_to_plpython(PG_FUNCTION_ARGS);
|
||||
Datum hstore_to_plpython(PG_FUNCTION_ARGS);
|
||||
|
||||
Datum
|
||||
hstore_to_plpython(PG_FUNCTION_ARGS)
|
||||
@ -31,9 +31,9 @@ hstore_to_plpython(PG_FUNCTION_ARGS)
|
||||
PyDict_SetItem(dict, key, Py_None);
|
||||
else
|
||||
{
|
||||
PyObject *value;
|
||||
PyObject *value;
|
||||
|
||||
value = PyString_FromStringAndSize(HS_VAL(entries, base,i), HS_VALLEN(entries, i));
|
||||
value = PyString_FromStringAndSize(HS_VAL(entries, base, i), HS_VALLEN(entries, i));
|
||||
PyDict_SetItem(dict, key, value);
|
||||
Py_XDECREF(value);
|
||||
}
|
||||
@ -45,7 +45,7 @@ hstore_to_plpython(PG_FUNCTION_ARGS)
|
||||
|
||||
|
||||
PG_FUNCTION_INFO_V1(plpython_to_hstore);
|
||||
Datum plpython_to_hstore(PG_FUNCTION_ARGS);
|
||||
Datum plpython_to_hstore(PG_FUNCTION_ARGS);
|
||||
|
||||
Datum
|
||||
plpython_to_hstore(PG_FUNCTION_ARGS)
|
||||
@ -75,9 +75,9 @@ plpython_to_hstore(PG_FUNCTION_ARGS)
|
||||
|
||||
for (i = 0; i < pcount; i++)
|
||||
{
|
||||
PyObject *tuple;
|
||||
PyObject *key;
|
||||
PyObject *value;
|
||||
PyObject *tuple;
|
||||
PyObject *key;
|
||||
PyObject *value;
|
||||
|
||||
tuple = PyList_GetItem(items, i);
|
||||
key = PyTuple_GetItem(tuple, 0);
|
||||
|
@ -26,13 +26,14 @@
|
||||
unsigned int
|
||||
ltree_crc32_sz(char *buf, int size)
|
||||
{
|
||||
pg_crc32 crc;
|
||||
pg_crc32 crc;
|
||||
char *p = buf;
|
||||
|
||||
INIT_TRADITIONAL_CRC32(crc);
|
||||
while (size > 0)
|
||||
{
|
||||
char c = (char) TOLOWER(*p);
|
||||
char c = (char) TOLOWER(*p);
|
||||
|
||||
COMP_TRADITIONAL_CRC32(crc, &c, 1);
|
||||
size--;
|
||||
p++;
|
||||
|
@ -7,7 +7,7 @@ PG_MODULE_MAGIC;
|
||||
|
||||
|
||||
PG_FUNCTION_INFO_V1(ltree_to_plpython);
|
||||
Datum ltree_to_plpython(PG_FUNCTION_ARGS);
|
||||
Datum ltree_to_plpython(PG_FUNCTION_ARGS);
|
||||
|
||||
Datum
|
||||
ltree_to_plpython(PG_FUNCTION_ARGS)
|
||||
|
@ -58,7 +58,7 @@ brin_page_type(PG_FUNCTION_ARGS)
|
||||
{
|
||||
bytea *raw_page = PG_GETARG_BYTEA_P(0);
|
||||
Page page = VARDATA(raw_page);
|
||||
char *type;
|
||||
char *type;
|
||||
|
||||
switch (BrinPageType(page))
|
||||
{
|
||||
@ -86,8 +86,8 @@ brin_page_type(PG_FUNCTION_ARGS)
|
||||
static Page
|
||||
verify_brin_page(bytea *raw_page, uint16 type, const char *strtype)
|
||||
{
|
||||
Page page;
|
||||
int raw_page_size;
|
||||
Page page;
|
||||
int raw_page_size;
|
||||
|
||||
raw_page_size = VARSIZE(raw_page) - VARHDRSZ;
|
||||
|
||||
@ -95,7 +95,7 @@ verify_brin_page(bytea *raw_page, uint16 type, const char *strtype)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("input page too small"),
|
||||
errdetail("Expected size %d, got %d", raw_page_size, BLCKSZ)));
|
||||
errdetail("Expected size %d, got %d", raw_page_size, BLCKSZ)));
|
||||
|
||||
page = VARDATA(raw_page);
|
||||
|
||||
@ -153,7 +153,7 @@ brin_page_items(PG_FUNCTION_ARGS)
|
||||
indexRel = index_open(indexRelid, AccessShareLock);
|
||||
|
||||
state = palloc(offsetof(brin_page_state, columns) +
|
||||
sizeof(brin_column_state) * RelationGetDescr(indexRel)->natts);
|
||||
sizeof(brin_column_state) * RelationGetDescr(indexRel)->natts);
|
||||
|
||||
state->bdesc = brin_build_desc(indexRel);
|
||||
state->page = page;
|
||||
@ -168,10 +168,10 @@ brin_page_items(PG_FUNCTION_ARGS)
|
||||
*/
|
||||
for (attno = 1; attno <= state->bdesc->bd_tupdesc->natts; attno++)
|
||||
{
|
||||
Oid output;
|
||||
bool isVarlena;
|
||||
Oid output;
|
||||
bool isVarlena;
|
||||
BrinOpcInfo *opcinfo;
|
||||
int i;
|
||||
int i;
|
||||
brin_column_state *column;
|
||||
|
||||
opcinfo = state->bdesc->bd_info[attno - 1];
|
||||
@ -213,7 +213,7 @@ brin_page_items(PG_FUNCTION_ARGS)
|
||||
*/
|
||||
if (state->dtup == NULL)
|
||||
{
|
||||
BrinTuple *tup;
|
||||
BrinTuple *tup;
|
||||
MemoryContext mctx;
|
||||
ItemId itemId;
|
||||
|
||||
@ -225,8 +225,8 @@ brin_page_items(PG_FUNCTION_ARGS)
|
||||
if (ItemIdIsUsed(itemId))
|
||||
{
|
||||
tup = (BrinTuple *) PageGetItem(state->page,
|
||||
PageGetItemId(state->page,
|
||||
state->offset));
|
||||
PageGetItemId(state->page,
|
||||
state->offset));
|
||||
state->dtup = brin_deform_tuple(state->bdesc, tup);
|
||||
state->attno = 1;
|
||||
state->unusedItem = false;
|
||||
@ -253,7 +253,7 @@ brin_page_items(PG_FUNCTION_ARGS)
|
||||
}
|
||||
else
|
||||
{
|
||||
int att = state->attno - 1;
|
||||
int att = state->attno - 1;
|
||||
|
||||
values[0] = UInt16GetDatum(state->offset);
|
||||
values[1] = UInt32GetDatum(state->dtup->bt_blkno);
|
||||
@ -263,8 +263,8 @@ brin_page_items(PG_FUNCTION_ARGS)
|
||||
values[5] = BoolGetDatum(state->dtup->bt_placeholder);
|
||||
if (!state->dtup->bt_columns[att].bv_allnulls)
|
||||
{
|
||||
BrinValues *bvalues = &state->dtup->bt_columns[att];
|
||||
StringInfoData s;
|
||||
BrinValues *bvalues = &state->dtup->bt_columns[att];
|
||||
StringInfoData s;
|
||||
bool first;
|
||||
int i;
|
||||
|
||||
@ -274,7 +274,7 @@ brin_page_items(PG_FUNCTION_ARGS)
|
||||
first = true;
|
||||
for (i = 0; i < state->columns[att]->nstored; i++)
|
||||
{
|
||||
char *val;
|
||||
char *val;
|
||||
|
||||
if (!first)
|
||||
appendStringInfoString(&s, " .. ");
|
||||
@ -312,8 +312,8 @@ brin_page_items(PG_FUNCTION_ARGS)
|
||||
}
|
||||
|
||||
/*
|
||||
* If we're beyond the end of the page, set flag to end the function in
|
||||
* the following iteration.
|
||||
* If we're beyond the end of the page, set flag to end the function
|
||||
* in the following iteration.
|
||||
*/
|
||||
if (state->offset > PageGetMaxOffsetNumber(state->page))
|
||||
state->done = true;
|
||||
@ -366,8 +366,8 @@ brin_revmap_data(PG_FUNCTION_ARGS)
|
||||
struct
|
||||
{
|
||||
ItemPointerData *tids;
|
||||
int idx;
|
||||
} *state;
|
||||
int idx;
|
||||
} *state;
|
||||
FuncCallContext *fctx;
|
||||
|
||||
if (!superuser())
|
||||
|
@ -167,7 +167,7 @@ typedef struct gin_leafpage_items_state
|
||||
TupleDesc tupd;
|
||||
GinPostingList *seg;
|
||||
GinPostingList *lastseg;
|
||||
} gin_leafpage_items_state;
|
||||
} gin_leafpage_items_state;
|
||||
|
||||
Datum
|
||||
gin_leafpage_items(PG_FUNCTION_ARGS)
|
||||
|
@ -40,11 +40,11 @@
|
||||
|
||||
PG_MODULE_MAGIC;
|
||||
|
||||
void _PG_init(void);
|
||||
void _PG_init(void);
|
||||
|
||||
/* Prototypes for functions used with event triggers */
|
||||
Datum pg_audit_ddl_command_end(PG_FUNCTION_ARGS);
|
||||
Datum pg_audit_sql_drop(PG_FUNCTION_ARGS);
|
||||
Datum pg_audit_ddl_command_end(PG_FUNCTION_ARGS);
|
||||
Datum pg_audit_sql_drop(PG_FUNCTION_ARGS);
|
||||
|
||||
PG_FUNCTION_INFO_V1(pg_audit_ddl_command_end);
|
||||
PG_FUNCTION_INFO_V1(pg_audit_sql_drop);
|
||||
@ -67,14 +67,14 @@ PG_FUNCTION_INFO_V1(pg_audit_sql_drop);
|
||||
#define LOG_ROLE (1 << 4) /* GRANT/REVOKE, CREATE/ALTER/DROP ROLE */
|
||||
#define LOG_WRITE (1 << 5) /* INSERT, UPDATE, DELETE, TRUNCATE */
|
||||
|
||||
#define LOG_NONE 0 /* nothing */
|
||||
#define LOG_NONE 0 /* nothing */
|
||||
#define LOG_ALL (0xFFFFFFFF) /* All */
|
||||
|
||||
/* GUC variable for pg_audit.log, which defines the classes to log. */
|
||||
char *auditLog = NULL;
|
||||
char *auditLog = NULL;
|
||||
|
||||
/* Bitmap of classes selected */
|
||||
static int auditLogBitmap = LOG_NONE;
|
||||
static int auditLogBitmap = LOG_NONE;
|
||||
|
||||
/*
|
||||
* String constants for log classes - used when processing tokens in the
|
||||
@ -97,7 +97,7 @@ static int auditLogBitmap = LOG_NONE;
|
||||
* the query are in pg_catalog. Interactive sessions (eg: psql) can cause
|
||||
* a lot of noise in the logs which might be uninteresting.
|
||||
*/
|
||||
bool auditLogCatalog = true;
|
||||
bool auditLogCatalog = true;
|
||||
|
||||
/*
|
||||
* GUC variable for pg_audit.log_level
|
||||
@ -106,8 +106,8 @@ bool auditLogCatalog = true;
|
||||
* at. The default level is LOG, which goes into the server log but does
|
||||
* not go to the client. Set to NOTICE in the regression tests.
|
||||
*/
|
||||
char *auditLogLevelString = NULL;
|
||||
int auditLogLevel = LOG;
|
||||
char *auditLogLevelString = NULL;
|
||||
int auditLogLevel = LOG;
|
||||
|
||||
/*
|
||||
* GUC variable for pg_audit.log_parameter
|
||||
@ -115,7 +115,7 @@ int auditLogLevel = LOG;
|
||||
* Administrators can choose if parameters passed into a statement are
|
||||
* included in the audit log.
|
||||
*/
|
||||
bool auditLogParameter = false;
|
||||
bool auditLogParameter = false;
|
||||
|
||||
/*
|
||||
* GUC variable for pg_audit.log_relation
|
||||
@ -124,7 +124,7 @@ bool auditLogParameter = false;
|
||||
* in READ/WRITE class queries. By default, SESSION logs include the query but
|
||||
* do not have a log entry for each relation.
|
||||
*/
|
||||
bool auditLogRelation = false;
|
||||
bool auditLogRelation = false;
|
||||
|
||||
/*
|
||||
* GUC variable for pg_audit.log_statement_once
|
||||
@ -134,7 +134,7 @@ bool auditLogRelation = false;
|
||||
* the audit log to facilitate searching, but this can cause the log to be
|
||||
* unnecessairly bloated in some environments.
|
||||
*/
|
||||
bool auditLogStatementOnce = false;
|
||||
bool auditLogStatementOnce = false;
|
||||
|
||||
/*
|
||||
* GUC variable for pg_audit.role
|
||||
@ -143,7 +143,7 @@ bool auditLogStatementOnce = false;
|
||||
* Object-level auditing uses the privileges which are granted to this role to
|
||||
* determine if a statement should be logged.
|
||||
*/
|
||||
char *auditRole = NULL;
|
||||
char *auditRole = NULL;
|
||||
|
||||
/*
|
||||
* String constants for the audit log fields.
|
||||
@ -213,23 +213,23 @@ char *auditRole = NULL;
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
int64 statementId; /* Simple counter */
|
||||
int64 substatementId; /* Simple counter */
|
||||
int64 statementId; /* Simple counter */
|
||||
int64 substatementId; /* Simple counter */
|
||||
|
||||
LogStmtLevel logStmtLevel; /* From GetCommandLogLevel when possible, */
|
||||
/* generated when not. */
|
||||
NodeTag commandTag; /* same here */
|
||||
/* generated when not. */
|
||||
NodeTag commandTag; /* same here */
|
||||
const char *command; /* same here */
|
||||
const char *objectType; /* From event trigger when possible */
|
||||
/* generated when not. */
|
||||
char *objectName; /* Fully qualified object identification */
|
||||
/* generated when not. */
|
||||
char *objectName; /* Fully qualified object identification */
|
||||
const char *commandText; /* sourceText / queryString */
|
||||
ParamListInfo paramList; /* QueryDesc/ProcessUtility parameters */
|
||||
|
||||
bool granted; /* Audit role has object permissions? */
|
||||
bool logged; /* Track if we have logged this event, used */
|
||||
/* post-ProcessUtility to make sure we log */
|
||||
bool statementLogged; /* Track if we have logged the statement */
|
||||
bool granted; /* Audit role has object permissions? */
|
||||
bool logged; /* Track if we have logged this event, used */
|
||||
/* post-ProcessUtility to make sure we log */
|
||||
bool statementLogged; /* Track if we have logged the statement */
|
||||
} AuditEvent;
|
||||
|
||||
/*
|
||||
@ -239,9 +239,9 @@ typedef struct AuditEventStackItem
|
||||
{
|
||||
struct AuditEventStackItem *next;
|
||||
|
||||
AuditEvent auditEvent;
|
||||
AuditEvent auditEvent;
|
||||
|
||||
int64 stackId;
|
||||
int64 stackId;
|
||||
|
||||
MemoryContext contextAudit;
|
||||
MemoryContextCallback contextCallback;
|
||||
@ -288,7 +288,7 @@ stack_free(void *stackFree)
|
||||
while (nextItem != NULL)
|
||||
{
|
||||
/* Check if this item matches the item to be freed */
|
||||
if (nextItem == (AuditEventStackItem *)stackFree)
|
||||
if (nextItem == (AuditEventStackItem *) stackFree)
|
||||
{
|
||||
/* Move top of stack to the item after the freed item */
|
||||
auditEventStack = nextItem->next;
|
||||
@ -309,7 +309,8 @@ stack_free(void *stackFree)
|
||||
substatementTotal = 0;
|
||||
|
||||
/*
|
||||
* Reset statement logged so that next statement will be logged.
|
||||
* Reset statement logged so that next statement will be
|
||||
* logged.
|
||||
*/
|
||||
statementLogged = false;
|
||||
}
|
||||
@ -356,7 +357,7 @@ stack_push()
|
||||
* the stack at this item.
|
||||
*/
|
||||
stackItem->contextCallback.func = stack_free;
|
||||
stackItem->contextCallback.arg = (void *)stackItem;
|
||||
stackItem->contextCallback.arg = (void *) stackItem;
|
||||
MemoryContextRegisterResetCallback(contextAudit,
|
||||
&stackItem->contextCallback);
|
||||
|
||||
@ -431,7 +432,7 @@ append_valid_csv(StringInfoData *buffer, const char *appendStr)
|
||||
|
||||
for (pChar = appendStr; *pChar; pChar++)
|
||||
{
|
||||
if (*pChar == '"') /* double single quotes */
|
||||
if (*pChar == '"') /* double single quotes */
|
||||
appendStringInfoCharMacro(buffer, *pChar);
|
||||
|
||||
appendStringInfoCharMacro(buffer, *pChar);
|
||||
@ -461,23 +462,23 @@ static void
|
||||
log_audit_event(AuditEventStackItem *stackItem)
|
||||
{
|
||||
/* By default, put everything in the MISC class. */
|
||||
int class = LOG_MISC;
|
||||
const char *className = CLASS_MISC;
|
||||
MemoryContext contextOld;
|
||||
StringInfoData auditStr;
|
||||
int class = LOG_MISC;
|
||||
const char *className = CLASS_MISC;
|
||||
MemoryContext contextOld;
|
||||
StringInfoData auditStr;
|
||||
|
||||
|
||||
/* Classify the statement using log stmt level and the command tag */
|
||||
switch (stackItem->auditEvent.logStmtLevel)
|
||||
{
|
||||
/* All mods go in WRITE class, execpt EXECUTE */
|
||||
/* All mods go in WRITE class, execpt EXECUTE */
|
||||
case LOGSTMT_MOD:
|
||||
className = CLASS_WRITE;
|
||||
class = LOG_WRITE;
|
||||
|
||||
switch (stackItem->auditEvent.commandTag)
|
||||
{
|
||||
/* Currently, only EXECUTE is different */
|
||||
/* Currently, only EXECUTE is different */
|
||||
case T_ExecuteStmt:
|
||||
className = CLASS_MISC;
|
||||
class = LOG_MISC;
|
||||
@ -487,7 +488,7 @@ log_audit_event(AuditEventStackItem *stackItem)
|
||||
}
|
||||
break;
|
||||
|
||||
/* These are DDL, unless they are ROLE */
|
||||
/* These are DDL, unless they are ROLE */
|
||||
case LOGSTMT_DDL:
|
||||
className = CLASS_DDL;
|
||||
class = LOG_DDL;
|
||||
@ -495,7 +496,7 @@ log_audit_event(AuditEventStackItem *stackItem)
|
||||
/* Identify role statements */
|
||||
switch (stackItem->auditEvent.commandTag)
|
||||
{
|
||||
/* We know these are all role statements */
|
||||
/* We know these are all role statements */
|
||||
case T_GrantStmt:
|
||||
case T_GrantRoleStmt:
|
||||
case T_CreateRoleStmt:
|
||||
@ -505,11 +506,12 @@ log_audit_event(AuditEventStackItem *stackItem)
|
||||
className = CLASS_ROLE;
|
||||
class = LOG_ROLE;
|
||||
break;
|
||||
/*
|
||||
* Rename and Drop are general and therefore we have to do an
|
||||
* additional check against the command string to see if they
|
||||
* are role or regular DDL.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Rename and Drop are general and therefore we have to do
|
||||
* an additional check against the command string to see
|
||||
* if they are role or regular DDL.
|
||||
*/
|
||||
case T_RenameStmt:
|
||||
case T_DropStmt:
|
||||
if (pg_strcasecmp(stackItem->auditEvent.command,
|
||||
@ -527,11 +529,11 @@ log_audit_event(AuditEventStackItem *stackItem)
|
||||
}
|
||||
break;
|
||||
|
||||
/* Classify the rest */
|
||||
/* Classify the rest */
|
||||
case LOGSTMT_ALL:
|
||||
switch (stackItem->auditEvent.commandTag)
|
||||
{
|
||||
/* READ statements */
|
||||
/* READ statements */
|
||||
case T_CopyStmt:
|
||||
case T_SelectStmt:
|
||||
case T_PrepareStmt:
|
||||
@ -540,7 +542,7 @@ log_audit_event(AuditEventStackItem *stackItem)
|
||||
class = LOG_READ;
|
||||
break;
|
||||
|
||||
/* FUNCTION statements */
|
||||
/* FUNCTION statements */
|
||||
case T_DoStmt:
|
||||
className = CLASS_FUNCTION;
|
||||
class = LOG_FUNCTION;
|
||||
@ -558,8 +560,8 @@ log_audit_event(AuditEventStackItem *stackItem)
|
||||
/*
|
||||
* Only log the statement if:
|
||||
*
|
||||
* 1. If object was selected for audit logging (granted)
|
||||
* 2. The statement belongs to a class that is being logged
|
||||
* 1. If object was selected for audit logging (granted) 2. The statement
|
||||
* belongs to a class that is being logged
|
||||
*
|
||||
* If neither of these is true, return.
|
||||
*/
|
||||
@ -615,10 +617,10 @@ log_audit_event(AuditEventStackItem *stackItem)
|
||||
/* Handle parameter logging, if enabled. */
|
||||
if (auditLogParameter)
|
||||
{
|
||||
int paramIdx;
|
||||
int numParams;
|
||||
StringInfoData paramStrResult;
|
||||
ParamListInfo paramList = stackItem->auditEvent.paramList;
|
||||
int paramIdx;
|
||||
int numParams;
|
||||
StringInfoData paramStrResult;
|
||||
ParamListInfo paramList = stackItem->auditEvent.paramList;
|
||||
|
||||
numParams = paramList == NULL ? 0 : paramList->numParams;
|
||||
|
||||
@ -630,9 +632,9 @@ log_audit_event(AuditEventStackItem *stackItem)
|
||||
paramIdx++)
|
||||
{
|
||||
ParamExternData *prm = ¶mList->params[paramIdx];
|
||||
Oid typeOutput;
|
||||
bool typeIsVarLena;
|
||||
char *paramStr;
|
||||
Oid typeOutput;
|
||||
bool typeIsVarLena;
|
||||
char *paramStr;
|
||||
|
||||
/* Add a comma for each param */
|
||||
if (paramIdx != 0)
|
||||
@ -663,7 +665,7 @@ log_audit_event(AuditEventStackItem *stackItem)
|
||||
else
|
||||
/* we were asked to not log it */
|
||||
appendStringInfoString(&auditStr,
|
||||
"<previously logged>,<previously logged>");
|
||||
"<previously logged>,<previously logged>");
|
||||
|
||||
/*
|
||||
* Log the audit entry. Note: use of INT64_FORMAT here is bad for
|
||||
@ -696,7 +698,7 @@ audit_on_acl(Datum aclDatum,
|
||||
{
|
||||
bool result = false;
|
||||
Acl *acl;
|
||||
AclItem *aclItemData;
|
||||
AclItem *aclItemData;
|
||||
int aclIndex;
|
||||
int aclTotal;
|
||||
|
||||
@ -710,7 +712,7 @@ audit_on_acl(Datum aclDatum,
|
||||
/* Check privileges granted directly to auditOid */
|
||||
for (aclIndex = 0; aclIndex < aclTotal; aclIndex++)
|
||||
{
|
||||
AclItem *aclItem = &aclItemData[aclIndex];
|
||||
AclItem *aclItem = &aclItemData[aclIndex];
|
||||
|
||||
if (aclItem->ai_grantee == auditOid &&
|
||||
aclItem->ai_privs & mask)
|
||||
@ -731,7 +733,7 @@ audit_on_acl(Datum aclDatum,
|
||||
{
|
||||
for (aclIndex = 0; aclIndex < aclTotal; aclIndex++)
|
||||
{
|
||||
AclItem *aclItem = &aclItemData[aclIndex];
|
||||
AclItem *aclItem = &aclItemData[aclIndex];
|
||||
|
||||
/* Don't test public or auditOid (it has been tested already) */
|
||||
if (aclItem->ai_grantee == ACL_ID_PUBLIC ||
|
||||
@ -838,9 +840,9 @@ audit_on_any_attribute(Oid relOid,
|
||||
Bitmapset *attributeSet,
|
||||
AclMode mode)
|
||||
{
|
||||
bool result = false;
|
||||
AttrNumber col;
|
||||
Bitmapset *tmpSet;
|
||||
bool result = false;
|
||||
AttrNumber col;
|
||||
Bitmapset *tmpSet;
|
||||
|
||||
/* If bms is empty then check for any column match */
|
||||
if (bms_is_empty(attributeSet))
|
||||
@ -891,9 +893,9 @@ audit_on_any_attribute(Oid relOid,
|
||||
static void
|
||||
log_select_dml(Oid auditOid, List *rangeTabls)
|
||||
{
|
||||
ListCell *lr;
|
||||
bool first = true;
|
||||
bool found = false;
|
||||
ListCell *lr;
|
||||
bool first = true;
|
||||
bool found = false;
|
||||
|
||||
/* Do not log if this is an internal statement */
|
||||
if (internalStatement)
|
||||
@ -901,8 +903,8 @@ log_select_dml(Oid auditOid, List *rangeTabls)
|
||||
|
||||
foreach(lr, rangeTabls)
|
||||
{
|
||||
Oid relOid;
|
||||
Relation rel;
|
||||
Oid relOid;
|
||||
Relation rel;
|
||||
RangeTblEntry *rte = lfirst(lr);
|
||||
|
||||
/* We only care about tables, and can ignore subqueries etc. */
|
||||
@ -912,8 +914,8 @@ log_select_dml(Oid auditOid, List *rangeTabls)
|
||||
found = true;
|
||||
|
||||
/*
|
||||
* If we are not logging all-catalog queries (auditLogCatalog is false)
|
||||
* then filter out any system relations here.
|
||||
* If we are not logging all-catalog queries (auditLogCatalog is
|
||||
* false) then filter out any system relations here.
|
||||
*/
|
||||
relOid = rte->relid;
|
||||
rel = relation_open(relOid, NoLock);
|
||||
@ -982,63 +984,72 @@ log_select_dml(Oid auditOid, List *rangeTabls)
|
||||
{
|
||||
case RELKIND_RELATION:
|
||||
auditEventStack->auditEvent.objectType =
|
||||
OBJECT_TYPE_TABLE;
|
||||
OBJECT_TYPE_TABLE;
|
||||
|
||||
break;
|
||||
|
||||
case RELKIND_INDEX:
|
||||
auditEventStack->auditEvent.objectType =
|
||||
OBJECT_TYPE_INDEX;
|
||||
OBJECT_TYPE_INDEX;
|
||||
|
||||
break;
|
||||
|
||||
case RELKIND_SEQUENCE:
|
||||
auditEventStack->auditEvent.objectType =
|
||||
OBJECT_TYPE_SEQUENCE;
|
||||
OBJECT_TYPE_SEQUENCE;
|
||||
|
||||
break;
|
||||
|
||||
case RELKIND_TOASTVALUE:
|
||||
auditEventStack->auditEvent.objectType =
|
||||
OBJECT_TYPE_TOASTVALUE;
|
||||
OBJECT_TYPE_TOASTVALUE;
|
||||
|
||||
break;
|
||||
|
||||
case RELKIND_VIEW:
|
||||
auditEventStack->auditEvent.objectType =
|
||||
OBJECT_TYPE_VIEW;
|
||||
OBJECT_TYPE_VIEW;
|
||||
|
||||
break;
|
||||
|
||||
case RELKIND_COMPOSITE_TYPE:
|
||||
auditEventStack->auditEvent.objectType =
|
||||
OBJECT_TYPE_COMPOSITE_TYPE;
|
||||
OBJECT_TYPE_COMPOSITE_TYPE;
|
||||
|
||||
break;
|
||||
|
||||
case RELKIND_FOREIGN_TABLE:
|
||||
auditEventStack->auditEvent.objectType =
|
||||
OBJECT_TYPE_FOREIGN_TABLE;
|
||||
OBJECT_TYPE_FOREIGN_TABLE;
|
||||
|
||||
break;
|
||||
|
||||
case RELKIND_MATVIEW:
|
||||
auditEventStack->auditEvent.objectType =
|
||||
OBJECT_TYPE_MATVIEW;
|
||||
OBJECT_TYPE_MATVIEW;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
auditEventStack->auditEvent.objectType =
|
||||
OBJECT_TYPE_UNKNOWN;
|
||||
OBJECT_TYPE_UNKNOWN;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
/* Get a copy of the relation name and assign it to object name */
|
||||
auditEventStack->auditEvent.objectName =
|
||||
quote_qualified_identifier(get_namespace_name(
|
||||
RelationGetNamespace(rel)),
|
||||
RelationGetNamespace(rel)),
|
||||
RelationGetRelationName(rel));
|
||||
relation_close(rel, NoLock);
|
||||
|
||||
/* Perform object auditing only if the audit role is valid */
|
||||
if (auditOid != InvalidOid)
|
||||
{
|
||||
AclMode auditPerms =
|
||||
(ACL_SELECT | ACL_UPDATE | ACL_INSERT | ACL_DELETE) &
|
||||
rte->requiredPerms;
|
||||
AclMode auditPerms =
|
||||
(ACL_SELECT | ACL_UPDATE | ACL_INSERT | ACL_DELETE) &
|
||||
rte->requiredPerms;
|
||||
|
||||
/*
|
||||
* If any of the required permissions for the relation are granted
|
||||
@ -1104,8 +1115,8 @@ log_select_dml(Oid auditOid, List *rangeTabls)
|
||||
|
||||
/*
|
||||
* If no tables were found that means that RangeTbls was empty or all
|
||||
* relations were in the system schema. In that case still log a
|
||||
* session record.
|
||||
* relations were in the system schema. In that case still log a session
|
||||
* record.
|
||||
*/
|
||||
if (!found)
|
||||
{
|
||||
@ -1123,7 +1134,7 @@ log_select_dml(Oid auditOid, List *rangeTabls)
|
||||
static void
|
||||
log_function_execute(Oid objectId)
|
||||
{
|
||||
HeapTuple proctup;
|
||||
HeapTuple proctup;
|
||||
Form_pg_proc proc;
|
||||
AuditEventStackItem *stackItem;
|
||||
|
||||
@ -1159,6 +1170,7 @@ log_function_execute(Oid objectId)
|
||||
stackItem->auditEvent.commandTag = T_DoStmt;
|
||||
stackItem->auditEvent.command = COMMAND_EXECUTE;
|
||||
stackItem->auditEvent.objectType = OBJECT_TYPE_FUNCTION;
|
||||
|
||||
stackItem->auditEvent.commandText = stackItem->next->auditEvent.commandText;
|
||||
|
||||
log_audit_event(stackItem);
|
||||
@ -1236,9 +1248,9 @@ pg_audit_ExecutorStart_hook(QueryDesc *queryDesc, int eflags)
|
||||
standard_ExecutorStart(queryDesc, eflags);
|
||||
|
||||
/*
|
||||
* Move the stack memory context to the query memory context. This needs to
|
||||
* be done here because the query context does not exist before the call
|
||||
* to standard_ExecutorStart() but the stack item is required by
|
||||
* Move the stack memory context to the query memory context. This needs
|
||||
* to be done here because the query context does not exist before the
|
||||
* call to standard_ExecutorStart() but the stack item is required by
|
||||
* pg_audit_ExecutorCheckPerms_hook() which is called during
|
||||
* standard_ExecutorStart().
|
||||
*/
|
||||
@ -1253,7 +1265,7 @@ pg_audit_ExecutorStart_hook(QueryDesc *queryDesc, int eflags)
|
||||
static bool
|
||||
pg_audit_ExecutorCheckPerms_hook(List *rangeTabls, bool abort)
|
||||
{
|
||||
Oid auditOid;
|
||||
Oid auditOid;
|
||||
|
||||
/* Get the audit oid if the role exists */
|
||||
auditOid = get_role_oid(auditRole, true);
|
||||
@ -1283,7 +1295,7 @@ pg_audit_ProcessUtility_hook(Node *parsetree,
|
||||
char *completionTag)
|
||||
{
|
||||
AuditEventStackItem *stackItem = NULL;
|
||||
int64 stackId = 0;
|
||||
int64 stackId = 0;
|
||||
|
||||
/*
|
||||
* Don't audit substatements. All the substatements we care about should
|
||||
@ -1328,19 +1340,22 @@ pg_audit_ProcessUtility_hook(Node *parsetree,
|
||||
params, dest, completionTag);
|
||||
|
||||
/*
|
||||
* Process the audit event if there is one. Also check that this event was
|
||||
* not popped off the stack by a memory context being free'd elsewhere.
|
||||
* Process the audit event if there is one. Also check that this event
|
||||
* was not popped off the stack by a memory context being free'd
|
||||
* elsewhere.
|
||||
*/
|
||||
if (stackItem && !IsAbortedTransactionBlockState())
|
||||
{
|
||||
/*
|
||||
* Make sure the item we want to log is still on the stack - if not then
|
||||
* something has gone wrong and an error will be raised.
|
||||
* Make sure the item we want to log is still on the stack - if not
|
||||
* then something has gone wrong and an error will be raised.
|
||||
*/
|
||||
stack_valid(stackId);
|
||||
|
||||
/* Log the utility command if logging is on, the command has not already
|
||||
* been logged by another hook, and the transaction is not aborted.
|
||||
/*
|
||||
* Log the utility command if logging is on, the command has not
|
||||
* already been logged by another hook, and the transaction is not
|
||||
* aborted.
|
||||
*/
|
||||
if (auditLogBitmap != 0 && !stackItem->auditEvent.logged)
|
||||
log_audit_event(stackItem);
|
||||
@ -1380,11 +1395,12 @@ Datum
|
||||
pg_audit_ddl_command_end(PG_FUNCTION_ARGS)
|
||||
{
|
||||
EventTriggerData *eventData;
|
||||
int result, row;
|
||||
TupleDesc spiTupDesc;
|
||||
const char *query;
|
||||
MemoryContext contextQuery;
|
||||
MemoryContext contextOld;
|
||||
int result,
|
||||
row;
|
||||
TupleDesc spiTupDesc;
|
||||
const char *query;
|
||||
MemoryContext contextQuery;
|
||||
MemoryContext contextOld;
|
||||
|
||||
/* Continue only if session DDL logging is enabled */
|
||||
if (~auditLogBitmap & LOG_DDL)
|
||||
@ -1393,7 +1409,7 @@ pg_audit_ddl_command_end(PG_FUNCTION_ARGS)
|
||||
/* Be sure the module was loaded */
|
||||
if (!auditEventStack)
|
||||
elog(ERROR, "pg_audit not loaded before call to "
|
||||
"pg_audit_ddl_command_end()");
|
||||
"pg_audit_ddl_command_end()");
|
||||
|
||||
/* This is an internal statement - do not log it */
|
||||
internalStatement = true;
|
||||
@ -1404,11 +1420,11 @@ pg_audit_ddl_command_end(PG_FUNCTION_ARGS)
|
||||
|
||||
/* Switch memory context for query */
|
||||
contextQuery = AllocSetContextCreate(
|
||||
CurrentMemoryContext,
|
||||
"pg_audit_func_ddl_command_end temporary context",
|
||||
ALLOCSET_DEFAULT_MINSIZE,
|
||||
ALLOCSET_DEFAULT_INITSIZE,
|
||||
ALLOCSET_DEFAULT_MAXSIZE);
|
||||
CurrentMemoryContext,
|
||||
"pg_audit_func_ddl_command_end temporary context",
|
||||
ALLOCSET_DEFAULT_MINSIZE,
|
||||
ALLOCSET_DEFAULT_INITSIZE,
|
||||
ALLOCSET_DEFAULT_MAXSIZE);
|
||||
contextOld = MemoryContextSwitchTo(contextQuery);
|
||||
|
||||
/* Get information about triggered events */
|
||||
@ -1423,31 +1439,32 @@ pg_audit_ddl_command_end(PG_FUNCTION_ARGS)
|
||||
|
||||
/* Return objects affected by the (non drop) DDL statement */
|
||||
query = "SELECT UPPER(object_type), object_identity\n"
|
||||
" FROM pg_event_trigger_ddl_commands()";
|
||||
" FROM pg_event_trigger_ddl_commands()";
|
||||
|
||||
/* Attempt to connect */
|
||||
result = SPI_connect();
|
||||
if (result < 0)
|
||||
elog(ERROR, "pg_audit_ddl_command_end: SPI_connect returned %d",
|
||||
result);
|
||||
result);
|
||||
|
||||
/* Execute the query */
|
||||
result = SPI_execute(query, true, 0);
|
||||
if (result != SPI_OK_SELECT)
|
||||
elog(ERROR, "pg_audit_ddl_command_end: SPI_execute returned %d",
|
||||
result);
|
||||
result);
|
||||
|
||||
/* Iterate returned rows */
|
||||
spiTupDesc = SPI_tuptable->tupdesc;
|
||||
for (row = 0; row < SPI_processed; row++)
|
||||
{
|
||||
HeapTuple spiTuple;
|
||||
HeapTuple spiTuple;
|
||||
|
||||
spiTuple = SPI_tuptable->vals[row];
|
||||
|
||||
/* Supply object name and type for audit event */
|
||||
auditEventStack->auditEvent.objectType =
|
||||
SPI_getvalue(spiTuple, spiTupDesc, 1);
|
||||
SPI_getvalue(spiTuple, spiTupDesc, 1);
|
||||
|
||||
auditEventStack->auditEvent.objectName =
|
||||
SPI_getvalue(spiTuple, spiTupDesc, 2);
|
||||
|
||||
@ -1473,11 +1490,12 @@ pg_audit_ddl_command_end(PG_FUNCTION_ARGS)
|
||||
Datum
|
||||
pg_audit_sql_drop(PG_FUNCTION_ARGS)
|
||||
{
|
||||
int result, row;
|
||||
TupleDesc spiTupDesc;
|
||||
const char *query;
|
||||
MemoryContext contextQuery;
|
||||
MemoryContext contextOld;
|
||||
int result,
|
||||
row;
|
||||
TupleDesc spiTupDesc;
|
||||
const char *query;
|
||||
MemoryContext contextQuery;
|
||||
MemoryContext contextOld;
|
||||
|
||||
if (~auditLogBitmap & LOG_DDL)
|
||||
PG_RETURN_NULL();
|
||||
@ -1485,7 +1503,7 @@ pg_audit_sql_drop(PG_FUNCTION_ARGS)
|
||||
/* Be sure the module was loaded */
|
||||
if (!auditEventStack)
|
||||
elog(ERROR, "pg_audit not loaded before call to "
|
||||
"pg_audit_sql_drop()");
|
||||
"pg_audit_sql_drop()");
|
||||
|
||||
/* This is an internal statement - do not log it */
|
||||
internalStatement = true;
|
||||
@ -1496,44 +1514,45 @@ pg_audit_sql_drop(PG_FUNCTION_ARGS)
|
||||
|
||||
/* Switch memory context for the query */
|
||||
contextQuery = AllocSetContextCreate(
|
||||
CurrentMemoryContext,
|
||||
"pg_audit_func_ddl_command_end temporary context",
|
||||
ALLOCSET_DEFAULT_MINSIZE,
|
||||
ALLOCSET_DEFAULT_INITSIZE,
|
||||
ALLOCSET_DEFAULT_MAXSIZE);
|
||||
CurrentMemoryContext,
|
||||
"pg_audit_func_ddl_command_end temporary context",
|
||||
ALLOCSET_DEFAULT_MINSIZE,
|
||||
ALLOCSET_DEFAULT_INITSIZE,
|
||||
ALLOCSET_DEFAULT_MAXSIZE);
|
||||
contextOld = MemoryContextSwitchTo(contextQuery);
|
||||
|
||||
/* Return objects affected by the drop statement */
|
||||
query = "SELECT UPPER(object_type),\n"
|
||||
" object_identity\n"
|
||||
" FROM pg_event_trigger_dropped_objects()\n"
|
||||
" WHERE lower(object_type) <> 'type'\n"
|
||||
" AND schema_name <> 'pg_toast'";
|
||||
" object_identity\n"
|
||||
" FROM pg_event_trigger_dropped_objects()\n"
|
||||
" WHERE lower(object_type) <> 'type'\n"
|
||||
" AND schema_name <> 'pg_toast'";
|
||||
|
||||
/* Attempt to connect */
|
||||
result = SPI_connect();
|
||||
if (result < 0)
|
||||
elog(ERROR, "pg_audit_ddl_drop: SPI_connect returned %d",
|
||||
result);
|
||||
result);
|
||||
|
||||
/* Execute the query */
|
||||
result = SPI_execute(query, true, 0);
|
||||
if (result != SPI_OK_SELECT)
|
||||
elog(ERROR, "pg_audit_ddl_drop: SPI_execute returned %d",
|
||||
result);
|
||||
result);
|
||||
|
||||
/* Iterate returned rows */
|
||||
spiTupDesc = SPI_tuptable->tupdesc;
|
||||
for (row = 0; row < SPI_processed; row++)
|
||||
{
|
||||
HeapTuple spiTuple;
|
||||
HeapTuple spiTuple;
|
||||
|
||||
spiTuple = SPI_tuptable->vals[row];
|
||||
|
||||
auditEventStack->auditEvent.objectType =
|
||||
SPI_getvalue(spiTuple, spiTupDesc, 1);
|
||||
SPI_getvalue(spiTuple, spiTupDesc, 1);
|
||||
|
||||
auditEventStack->auditEvent.objectName =
|
||||
SPI_getvalue(spiTuple, spiTupDesc, 2);
|
||||
SPI_getvalue(spiTuple, spiTupDesc, 2);
|
||||
|
||||
log_audit_event(auditEventStack);
|
||||
}
|
||||
@ -1562,10 +1581,10 @@ pg_audit_sql_drop(PG_FUNCTION_ARGS)
|
||||
static bool
|
||||
check_pg_audit_log(char **newVal, void **extra, GucSource source)
|
||||
{
|
||||
List *flagRawList;
|
||||
char *rawVal;
|
||||
ListCell *lt;
|
||||
int *flags;
|
||||
List *flagRawList;
|
||||
char *rawVal;
|
||||
ListCell *lt;
|
||||
int *flags;
|
||||
|
||||
/* Make sure newval is a comma-separated list of tokens. */
|
||||
rawVal = pstrdup(*newVal);
|
||||
@ -1581,18 +1600,18 @@ check_pg_audit_log(char **newVal, void **extra, GucSource source)
|
||||
* Check that we recognise each token, and add it to the bitmap we're
|
||||
* building up in a newly-allocated int *f.
|
||||
*/
|
||||
if (!(flags = (int *)malloc(sizeof(int))))
|
||||
if (!(flags = (int *) malloc(sizeof(int))))
|
||||
return false;
|
||||
|
||||
*flags = 0;
|
||||
|
||||
foreach(lt, flagRawList)
|
||||
{
|
||||
bool subtract = false;
|
||||
int class;
|
||||
bool subtract = false;
|
||||
int class;
|
||||
|
||||
/* Retrieve a token */
|
||||
char *token = (char *)lfirst(lt);
|
||||
char *token = (char *) lfirst(lt);
|
||||
|
||||
/* If token is preceded by -, then the token is subtractive */
|
||||
if (strstr(token, "-") == token)
|
||||
@ -1651,7 +1670,7 @@ static void
|
||||
assign_pg_audit_log(const char *newVal, void *extra)
|
||||
{
|
||||
if (extra)
|
||||
auditLogBitmap = *(int *)extra;
|
||||
auditLogBitmap = *(int *) extra;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1662,10 +1681,10 @@ assign_pg_audit_log(const char *newVal, void *extra)
|
||||
static bool
|
||||
check_pg_audit_log_level(char **newVal, void **extra, GucSource source)
|
||||
{
|
||||
int *logLevel;
|
||||
int *logLevel;
|
||||
|
||||
/* Allocate memory to store the log level */
|
||||
if (!(logLevel = (int *)malloc(sizeof(int))))
|
||||
if (!(logLevel = (int *) malloc(sizeof(int))))
|
||||
return false;
|
||||
|
||||
/* Find the log level enum */
|
||||
@ -1718,7 +1737,7 @@ static void
|
||||
assign_pg_audit_log_level(const char *newVal, void *extra)
|
||||
{
|
||||
if (extra)
|
||||
auditLogLevel = *(int *)extra;
|
||||
auditLogLevel = *(int *) extra;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1729,126 +1748,126 @@ _PG_init(void)
|
||||
{
|
||||
/* Define pg_audit.log */
|
||||
DefineCustomStringVariable(
|
||||
"pg_audit.log",
|
||||
"pg_audit.log",
|
||||
|
||||
"Specifies which classes of statements will be logged by session audit "
|
||||
"logging. Multiple classes can be provided using a comma-separated "
|
||||
"list and classes can be subtracted by prefacing the class with a "
|
||||
"- sign.",
|
||||
"Specifies which classes of statements will be logged by session audit "
|
||||
"logging. Multiple classes can be provided using a comma-separated "
|
||||
"list and classes can be subtracted by prefacing the class with a "
|
||||
"- sign.",
|
||||
|
||||
NULL,
|
||||
&auditLog,
|
||||
"none",
|
||||
PGC_SUSET,
|
||||
GUC_LIST_INPUT | GUC_NOT_IN_SAMPLE,
|
||||
check_pg_audit_log,
|
||||
assign_pg_audit_log,
|
||||
NULL);
|
||||
NULL,
|
||||
&auditLog,
|
||||
"none",
|
||||
PGC_SUSET,
|
||||
GUC_LIST_INPUT | GUC_NOT_IN_SAMPLE,
|
||||
check_pg_audit_log,
|
||||
assign_pg_audit_log,
|
||||
NULL);
|
||||
|
||||
/* Define pg_audit.log_catalog */
|
||||
DefineCustomBoolVariable(
|
||||
"pg_audit.log_catalog",
|
||||
"pg_audit.log_catalog",
|
||||
|
||||
"Specifies that session logging should be enabled in the case where "
|
||||
"all relations in a statement are in pg_catalog. Disabling this "
|
||||
"setting will reduce noise in the log from tools like psql and PgAdmin "
|
||||
"that query the catalog heavily.",
|
||||
"all relations in a statement are in pg_catalog. Disabling this "
|
||||
"setting will reduce noise in the log from tools like psql and PgAdmin "
|
||||
"that query the catalog heavily.",
|
||||
|
||||
NULL,
|
||||
&auditLogCatalog,
|
||||
true,
|
||||
PGC_SUSET,
|
||||
GUC_NOT_IN_SAMPLE,
|
||||
NULL, NULL, NULL);
|
||||
NULL,
|
||||
&auditLogCatalog,
|
||||
true,
|
||||
PGC_SUSET,
|
||||
GUC_NOT_IN_SAMPLE,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
/* Define pg_audit.log_level */
|
||||
DefineCustomStringVariable(
|
||||
"pg_audit.log_level",
|
||||
"pg_audit.log_level",
|
||||
|
||||
"Specifies the log level that will be used for log entries. This "
|
||||
"setting is used for regression testing and may also be useful to end "
|
||||
"users for testing or other purposes. It is not intended to be used "
|
||||
"in a production environment as it may leak which statements are being "
|
||||
"logged to the user.",
|
||||
"Specifies the log level that will be used for log entries. This "
|
||||
"setting is used for regression testing and may also be useful to end "
|
||||
"users for testing or other purposes. It is not intended to be used "
|
||||
"in a production environment as it may leak which statements are being "
|
||||
"logged to the user.",
|
||||
|
||||
NULL,
|
||||
&auditLogLevelString,
|
||||
"log",
|
||||
PGC_SUSET,
|
||||
GUC_LIST_INPUT | GUC_NOT_IN_SAMPLE,
|
||||
check_pg_audit_log_level,
|
||||
assign_pg_audit_log_level,
|
||||
NULL);
|
||||
NULL,
|
||||
&auditLogLevelString,
|
||||
"log",
|
||||
PGC_SUSET,
|
||||
GUC_LIST_INPUT | GUC_NOT_IN_SAMPLE,
|
||||
check_pg_audit_log_level,
|
||||
assign_pg_audit_log_level,
|
||||
NULL);
|
||||
|
||||
/* Define pg_audit.log_parameter */
|
||||
DefineCustomBoolVariable(
|
||||
"pg_audit.log_parameter",
|
||||
"pg_audit.log_parameter",
|
||||
|
||||
"Specifies that audit logging should include the parameters that were "
|
||||
"passed with the statement. When parameters are present they will be "
|
||||
"be included in CSV format after the statement text.",
|
||||
"Specifies that audit logging should include the parameters that were "
|
||||
"passed with the statement. When parameters are present they will be "
|
||||
"be included in CSV format after the statement text.",
|
||||
|
||||
NULL,
|
||||
&auditLogParameter,
|
||||
false,
|
||||
PGC_SUSET,
|
||||
GUC_NOT_IN_SAMPLE,
|
||||
NULL, NULL, NULL);
|
||||
NULL,
|
||||
&auditLogParameter,
|
||||
false,
|
||||
PGC_SUSET,
|
||||
GUC_NOT_IN_SAMPLE,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
/* Define pg_audit.log_relation */
|
||||
DefineCustomBoolVariable(
|
||||
"pg_audit.log_relation",
|
||||
"pg_audit.log_relation",
|
||||
|
||||
"Specifies whether session audit logging should create a separate log "
|
||||
"entry for each relation referenced in a SELECT or DML statement. "
|
||||
"This is a useful shortcut for exhaustive logging without using object "
|
||||
"audit logging.",
|
||||
"Specifies whether session audit logging should create a separate log "
|
||||
"entry for each relation referenced in a SELECT or DML statement. "
|
||||
"This is a useful shortcut for exhaustive logging without using object "
|
||||
"audit logging.",
|
||||
|
||||
NULL,
|
||||
&auditLogRelation,
|
||||
false,
|
||||
PGC_SUSET,
|
||||
GUC_NOT_IN_SAMPLE,
|
||||
NULL, NULL, NULL);
|
||||
NULL,
|
||||
&auditLogRelation,
|
||||
false,
|
||||
PGC_SUSET,
|
||||
GUC_NOT_IN_SAMPLE,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
/* Define pg_audit.log_statement_once */
|
||||
DefineCustomBoolVariable(
|
||||
"pg_audit.log_statement_once",
|
||||
"pg_audit.log_statement_once",
|
||||
|
||||
"Specifies whether logging will include the statement text and "
|
||||
"parameters with the first log entry for a statement/substatement "
|
||||
"combination or with every entry. Disabling this setting will result "
|
||||
"in less verbose logging but may make it more difficult to determine "
|
||||
"the statement that generated a log entry, though the "
|
||||
"statement/substatement pair along with the process id should suffice "
|
||||
"to identify the statement text logged with a previous entry.",
|
||||
"Specifies whether logging will include the statement text and "
|
||||
"parameters with the first log entry for a statement/substatement "
|
||||
"combination or with every entry. Disabling this setting will result "
|
||||
"in less verbose logging but may make it more difficult to determine "
|
||||
"the statement that generated a log entry, though the "
|
||||
"statement/substatement pair along with the process id should suffice "
|
||||
"to identify the statement text logged with a previous entry.",
|
||||
|
||||
NULL,
|
||||
&auditLogStatementOnce,
|
||||
false,
|
||||
PGC_SUSET,
|
||||
GUC_NOT_IN_SAMPLE,
|
||||
NULL, NULL, NULL);
|
||||
NULL,
|
||||
&auditLogStatementOnce,
|
||||
false,
|
||||
PGC_SUSET,
|
||||
GUC_NOT_IN_SAMPLE,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
/* Define pg_audit.role */
|
||||
DefineCustomStringVariable(
|
||||
"pg_audit.role",
|
||||
"pg_audit.role",
|
||||
|
||||
"Specifies the master role to use for object audit logging. Muliple "
|
||||
"audit roles can be defined by granting them to the master role. This "
|
||||
"allows multiple groups to be in charge of different aspects of audit "
|
||||
"logging.",
|
||||
"Specifies the master role to use for object audit logging. Muliple "
|
||||
"audit roles can be defined by granting them to the master role. This "
|
||||
"allows multiple groups to be in charge of different aspects of audit "
|
||||
"logging.",
|
||||
|
||||
NULL,
|
||||
&auditRole,
|
||||
"",
|
||||
PGC_SUSET,
|
||||
GUC_NOT_IN_SAMPLE,
|
||||
NULL, NULL, NULL);
|
||||
NULL,
|
||||
&auditRole,
|
||||
"",
|
||||
PGC_SUSET,
|
||||
GUC_NOT_IN_SAMPLE,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
/*
|
||||
* Install our hook functions after saving the existing pointers to preserve
|
||||
* the chains.
|
||||
* Install our hook functions after saving the existing pointers to
|
||||
* preserve the chains.
|
||||
*/
|
||||
next_ExecutorStart_hook = ExecutorStart_hook;
|
||||
ExecutorStart_hook = pg_audit_ExecutorStart_hook;
|
||||
|
@ -34,6 +34,7 @@ typedef struct
|
||||
bool isvalid;
|
||||
bool isdirty;
|
||||
uint16 usagecount;
|
||||
|
||||
/*
|
||||
* An int32 is sufficiently large, as MAX_BACKENDS prevents a buffer from
|
||||
* being pinned by too many backends and each backend will only pin once
|
||||
|
@ -138,10 +138,10 @@ typedef struct Counters
|
||||
{
|
||||
int64 calls; /* # of times executed */
|
||||
double total_time; /* total execution time, in msec */
|
||||
double min_time; /* minimim execution time in msec */
|
||||
double max_time; /* maximum execution time in msec */
|
||||
double mean_time; /* mean execution time in msec */
|
||||
double sum_var_time; /* sum of variances in execution time in msec */
|
||||
double min_time; /* minimim execution time in msec */
|
||||
double max_time; /* maximum execution time in msec */
|
||||
double mean_time; /* mean execution time in msec */
|
||||
double sum_var_time; /* sum of variances in execution time in msec */
|
||||
int64 rows; /* total # of retrieved or affected rows */
|
||||
int64 shared_blks_hit; /* # of shared buffer hits */
|
||||
int64 shared_blks_read; /* # of shared disk blocks read */
|
||||
@ -1231,10 +1231,10 @@ pgss_store(const char *query, uint32 queryId,
|
||||
else
|
||||
{
|
||||
/*
|
||||
* Welford's method for accurately computing variance.
|
||||
* See <http://www.johndcook.com/blog/standard_deviation/>
|
||||
* Welford's method for accurately computing variance. See
|
||||
* <http://www.johndcook.com/blog/standard_deviation/>
|
||||
*/
|
||||
double old_mean = e->counters.mean_time;
|
||||
double old_mean = e->counters.mean_time;
|
||||
|
||||
e->counters.mean_time +=
|
||||
(total_time - old_mean) / e->counters.calls;
|
||||
@ -1572,10 +1572,11 @@ pg_stat_statements_internal(FunctionCallInfo fcinfo,
|
||||
values[i++] = Float8GetDatumFast(tmp.min_time);
|
||||
values[i++] = Float8GetDatumFast(tmp.max_time);
|
||||
values[i++] = Float8GetDatumFast(tmp.mean_time);
|
||||
|
||||
/*
|
||||
* Note we are calculating the population variance here, not the
|
||||
* sample variance, as we have data for the whole population,
|
||||
* so Bessel's correction is not used, and we don't divide by
|
||||
* sample variance, as we have data for the whole population, so
|
||||
* Bessel's correction is not used, and we don't divide by
|
||||
* tmp.calls - 1.
|
||||
*/
|
||||
if (tmp.calls > 1)
|
||||
@ -2687,16 +2688,16 @@ JumbleExpr(pgssJumbleState *jstate, Node *node)
|
||||
break;
|
||||
case T_OnConflictExpr:
|
||||
{
|
||||
OnConflictExpr *conf = (OnConflictExpr *) node;
|
||||
OnConflictExpr *conf = (OnConflictExpr *) node;
|
||||
|
||||
APP_JUMB(conf->action);
|
||||
JumbleExpr(jstate, (Node *) conf->arbiterElems);
|
||||
JumbleExpr(jstate, conf->arbiterWhere);
|
||||
JumbleExpr(jstate, (Node *) conf->onConflictSet);
|
||||
JumbleExpr(jstate, (Node *) conf->onConflictSet);
|
||||
JumbleExpr(jstate, conf->onConflictWhere);
|
||||
APP_JUMB(conf->constraint);
|
||||
APP_JUMB(conf->exclRelIndex);
|
||||
JumbleExpr(jstate, (Node *) conf->exclRelTlist);
|
||||
JumbleExpr(jstate, (Node *) conf->exclRelTlist);
|
||||
}
|
||||
break;
|
||||
case T_List:
|
||||
|
@ -399,7 +399,7 @@ pgp_extract_armor_headers(const uint8 *src, unsigned len,
|
||||
char *line;
|
||||
char *nextline;
|
||||
char *eol,
|
||||
*colon;
|
||||
*colon;
|
||||
int hlen;
|
||||
char *buf;
|
||||
int hdrlines;
|
||||
|
@ -259,6 +259,7 @@ set_arg(PGP_Context *ctx, char *key, char *val,
|
||||
res = pgp_set_convert_crlf(ctx, atoi(val));
|
||||
else if (strcmp(key, "unicode-mode") == 0)
|
||||
res = pgp_set_unicode_mode(ctx, atoi(val));
|
||||
|
||||
/*
|
||||
* The remaining options are for debugging/testing and are therefore not
|
||||
* documented in the user-facing docs.
|
||||
@ -834,22 +835,22 @@ static int
|
||||
parse_key_value_arrays(ArrayType *key_array, ArrayType *val_array,
|
||||
char ***p_keys, char ***p_values)
|
||||
{
|
||||
int nkdims = ARR_NDIM(key_array);
|
||||
int nvdims = ARR_NDIM(val_array);
|
||||
char **keys,
|
||||
**values;
|
||||
Datum *key_datums,
|
||||
*val_datums;
|
||||
bool *key_nulls,
|
||||
*val_nulls;
|
||||
int key_count,
|
||||
val_count;
|
||||
int i;
|
||||
int nkdims = ARR_NDIM(key_array);
|
||||
int nvdims = ARR_NDIM(val_array);
|
||||
char **keys,
|
||||
**values;
|
||||
Datum *key_datums,
|
||||
*val_datums;
|
||||
bool *key_nulls,
|
||||
*val_nulls;
|
||||
int key_count,
|
||||
val_count;
|
||||
int i;
|
||||
|
||||
if (nkdims > 1 || nkdims != nvdims)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_ARRAY_SUBSCRIPT_ERROR),
|
||||
errmsg("wrong number of array subscripts")));
|
||||
errmsg("wrong number of array subscripts")));
|
||||
if (nkdims == 0)
|
||||
return 0;
|
||||
|
||||
@ -871,7 +872,7 @@ parse_key_value_arrays(ArrayType *key_array, ArrayType *val_array,
|
||||
|
||||
for (i = 0; i < key_count; i++)
|
||||
{
|
||||
char *v;
|
||||
char *v;
|
||||
|
||||
/* Check that the key doesn't contain anything funny */
|
||||
if (key_nulls[i])
|
||||
@ -884,7 +885,7 @@ parse_key_value_arrays(ArrayType *key_array, ArrayType *val_array,
|
||||
if (!string_is_ascii(v))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("header key must not contain non-ASCII characters")));
|
||||
errmsg("header key must not contain non-ASCII characters")));
|
||||
if (strstr(v, ": "))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
@ -906,7 +907,7 @@ parse_key_value_arrays(ArrayType *key_array, ArrayType *val_array,
|
||||
if (!string_is_ascii(v))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
errmsg("header value must not contain non-ASCII characters")));
|
||||
errmsg("header value must not contain non-ASCII characters")));
|
||||
if (strchr(v, '\n'))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
|
||||
@ -1045,7 +1046,7 @@ pgp_armor_headers(PG_FUNCTION_ARGS)
|
||||
SRF_RETURN_DONE(funcctx);
|
||||
else
|
||||
{
|
||||
char *values[2];
|
||||
char *values[2];
|
||||
|
||||
/* we assume that the keys (and values) are in UTF-8. */
|
||||
utf8key = state->keys[funcctx->call_cntr];
|
||||
|
@ -278,11 +278,11 @@ void pgp_cfb_free(PGP_CFB *ctx);
|
||||
int pgp_cfb_encrypt(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst);
|
||||
int pgp_cfb_decrypt(PGP_CFB *ctx, const uint8 *data, int len, uint8 *dst);
|
||||
|
||||
void pgp_armor_encode(const uint8 *src, unsigned len, StringInfo dst,
|
||||
int num_headers, char **keys, char **values);
|
||||
void pgp_armor_encode(const uint8 *src, unsigned len, StringInfo dst,
|
||||
int num_headers, char **keys, char **values);
|
||||
int pgp_armor_decode(const uint8 *src, int len, StringInfo dst);
|
||||
int pgp_extract_armor_headers(const uint8 *src, unsigned len,
|
||||
int *nheaders, char ***keys, char ***values);
|
||||
int pgp_extract_armor_headers(const uint8 *src, unsigned len,
|
||||
int *nheaders, char ***keys, char ***values);
|
||||
|
||||
int pgp_compress_filter(PushFilter **res, PGP_Context *ctx, PushFilter *dst);
|
||||
int pgp_decompress_filter(PullFilter **res, PGP_Context *ctx, PullFilter *src);
|
||||
|
@ -84,8 +84,8 @@ statapprox_heap(Relation rel, output_type *stat)
|
||||
CHECK_FOR_INTERRUPTS();
|
||||
|
||||
/*
|
||||
* If the page has only visible tuples, then we can find out the
|
||||
* free space from the FSM and move on.
|
||||
* If the page has only visible tuples, then we can find out the free
|
||||
* space from the FSM and move on.
|
||||
*/
|
||||
if (visibilitymap_test(rel, blkno, &vmbuffer))
|
||||
{
|
||||
@ -103,8 +103,8 @@ statapprox_heap(Relation rel, output_type *stat)
|
||||
page = BufferGetPage(buf);
|
||||
|
||||
/*
|
||||
* It's not safe to call PageGetHeapFreeSpace() on new pages, so
|
||||
* we treat them as being free space for our purposes.
|
||||
* It's not safe to call PageGetHeapFreeSpace() on new pages, so we
|
||||
* treat them as being free space for our purposes.
|
||||
*/
|
||||
if (!PageIsNew(page))
|
||||
stat->free_space += PageGetHeapFreeSpace(page);
|
||||
@ -120,9 +120,9 @@ statapprox_heap(Relation rel, output_type *stat)
|
||||
scanned++;
|
||||
|
||||
/*
|
||||
* Look at each tuple on the page and decide whether it's live
|
||||
* or dead, then count it and its size. Unlike lazy_scan_heap,
|
||||
* we can afford to ignore problems and special cases.
|
||||
* Look at each tuple on the page and decide whether it's live or
|
||||
* dead, then count it and its size. Unlike lazy_scan_heap, we can
|
||||
* afford to ignore problems and special cases.
|
||||
*/
|
||||
maxoff = PageGetMaxOffsetNumber(page);
|
||||
|
||||
@ -179,9 +179,10 @@ statapprox_heap(Relation rel, output_type *stat)
|
||||
UnlockReleaseBuffer(buf);
|
||||
}
|
||||
|
||||
stat->table_len = (uint64) nblocks * BLCKSZ;
|
||||
stat->table_len = (uint64) nblocks *BLCKSZ;
|
||||
|
||||
stat->tuple_count = vac_estimate_reltuples(rel, false, nblocks, scanned,
|
||||
stat->tuple_count+misc_count);
|
||||
stat->tuple_count + misc_count);
|
||||
|
||||
/*
|
||||
* Calculate percentages if the relation has one or more pages.
|
||||
@ -240,9 +241,9 @@ pgstattuple_approx(PG_FUNCTION_ARGS)
|
||||
errmsg("cannot access temporary tables of other sessions")));
|
||||
|
||||
/*
|
||||
* We support only ordinary relations and materialised views,
|
||||
* because we depend on the visibility map and free space map
|
||||
* for our estimates about unscanned pages.
|
||||
* We support only ordinary relations and materialised views, because we
|
||||
* depend on the visibility map and free space map for our estimates about
|
||||
* unscanned pages.
|
||||
*/
|
||||
if (!(rel->rd_rel->relkind == RELKIND_RELATION ||
|
||||
rel->rd_rel->relkind == RELKIND_MATVIEW))
|
||||
@ -268,6 +269,6 @@ pgstattuple_approx(PG_FUNCTION_ARGS)
|
||||
values[i++] = Int64GetDatum(stat.free_space);
|
||||
values[i++] = Float8GetDatum(stat.free_percent);
|
||||
|
||||
ret = heap_form_tuple(tupdesc, values, nulls);
|
||||
ret = heap_form_tuple(tupdesc, values, nulls);
|
||||
return HeapTupleGetDatum(ret);
|
||||
}
|
||||
|
@ -203,7 +203,7 @@ typedef struct PgFdwAnalyzeState
|
||||
/* for random sampling */
|
||||
double samplerows; /* # of rows fetched */
|
||||
double rowstoskip; /* # of rows to skip before next sample */
|
||||
ReservoirStateData rstate; /* state for reservoir sampling*/
|
||||
ReservoirStateData rstate; /* state for reservoir sampling */
|
||||
|
||||
/* working memory contexts */
|
||||
MemoryContext anl_cxt; /* context for per-analyze lifespan data */
|
||||
|
@ -53,16 +53,16 @@ static void pg_decode_shutdown(LogicalDecodingContext *ctx);
|
||||
static void pg_decode_begin_txn(LogicalDecodingContext *ctx,
|
||||
ReorderBufferTXN *txn);
|
||||
static void pg_output_begin(LogicalDecodingContext *ctx,
|
||||
TestDecodingData *data,
|
||||
ReorderBufferTXN *txn,
|
||||
bool last_write);
|
||||
TestDecodingData *data,
|
||||
ReorderBufferTXN *txn,
|
||||
bool last_write);
|
||||
static void pg_decode_commit_txn(LogicalDecodingContext *ctx,
|
||||
ReorderBufferTXN *txn, XLogRecPtr commit_lsn);
|
||||
static void pg_decode_change(LogicalDecodingContext *ctx,
|
||||
ReorderBufferTXN *txn, Relation rel,
|
||||
ReorderBufferChange *change);
|
||||
static bool pg_decode_filter(LogicalDecodingContext *ctx,
|
||||
RepOriginId origin_id);
|
||||
RepOriginId origin_id);
|
||||
|
||||
void
|
||||
_PG_init(void)
|
||||
|
@ -33,14 +33,14 @@ PG_MODULE_MAGIC;
|
||||
typedef struct
|
||||
{
|
||||
SamplerRandomState randstate;
|
||||
uint32 seed; /* random seed */
|
||||
BlockNumber nblocks; /* number of block in relation */
|
||||
int32 ntuples; /* number of tuples to return */
|
||||
int32 donetuples; /* tuples already returned */
|
||||
OffsetNumber lt; /* last tuple returned from current block */
|
||||
BlockNumber step; /* step size */
|
||||
BlockNumber lb; /* last block visited */
|
||||
BlockNumber doneblocks; /* number of already returned blocks */
|
||||
uint32 seed; /* random seed */
|
||||
BlockNumber nblocks; /* number of block in relation */
|
||||
int32 ntuples; /* number of tuples to return */
|
||||
int32 donetuples; /* tuples already returned */
|
||||
OffsetNumber lt; /* last tuple returned from current block */
|
||||
BlockNumber step; /* step size */
|
||||
BlockNumber lb; /* last block visited */
|
||||
BlockNumber doneblocks; /* number of already returned blocks */
|
||||
} SystemSamplerData;
|
||||
|
||||
|
||||
@ -60,11 +60,11 @@ static uint32 random_relative_prime(uint32 n, SamplerRandomState randstate);
|
||||
Datum
|
||||
tsm_system_rows_init(PG_FUNCTION_ARGS)
|
||||
{
|
||||
TableSampleDesc *tsdesc = (TableSampleDesc *) PG_GETARG_POINTER(0);
|
||||
uint32 seed = PG_GETARG_UINT32(1);
|
||||
int32 ntuples = PG_ARGISNULL(2) ? -1 : PG_GETARG_INT32(2);
|
||||
HeapScanDesc scan = tsdesc->heapScan;
|
||||
SystemSamplerData *sampler;
|
||||
TableSampleDesc *tsdesc = (TableSampleDesc *) PG_GETARG_POINTER(0);
|
||||
uint32 seed = PG_GETARG_UINT32(1);
|
||||
int32 ntuples = PG_ARGISNULL(2) ? -1 : PG_GETARG_INT32(2);
|
||||
HeapScanDesc scan = tsdesc->heapScan;
|
||||
SystemSamplerData *sampler;
|
||||
|
||||
if (ntuples < 1)
|
||||
ereport(ERROR,
|
||||
@ -86,6 +86,7 @@ tsm_system_rows_init(PG_FUNCTION_ARGS)
|
||||
|
||||
/* Find relative prime as step size for linear probing. */
|
||||
sampler->step = random_relative_prime(sampler->nblocks, sampler->randstate);
|
||||
|
||||
/*
|
||||
* Randomize start position so that blocks close to step size don't have
|
||||
* higher probability of being chosen on very short scan.
|
||||
@ -106,8 +107,8 @@ tsm_system_rows_init(PG_FUNCTION_ARGS)
|
||||
Datum
|
||||
tsm_system_rows_nextblock(PG_FUNCTION_ARGS)
|
||||
{
|
||||
TableSampleDesc *tsdesc = (TableSampleDesc *) PG_GETARG_POINTER(0);
|
||||
SystemSamplerData *sampler = (SystemSamplerData *) tsdesc->tsmdata;
|
||||
TableSampleDesc *tsdesc = (TableSampleDesc *) PG_GETARG_POINTER(0);
|
||||
SystemSamplerData *sampler = (SystemSamplerData *) tsdesc->tsmdata;
|
||||
|
||||
sampler->lb = (sampler->lb + sampler->step) % sampler->nblocks;
|
||||
sampler->doneblocks++;
|
||||
@ -127,10 +128,10 @@ tsm_system_rows_nextblock(PG_FUNCTION_ARGS)
|
||||
Datum
|
||||
tsm_system_rows_nexttuple(PG_FUNCTION_ARGS)
|
||||
{
|
||||
TableSampleDesc *tsdesc = (TableSampleDesc *) PG_GETARG_POINTER(0);
|
||||
OffsetNumber maxoffset = PG_GETARG_UINT16(2);
|
||||
SystemSamplerData *sampler = (SystemSamplerData *) tsdesc->tsmdata;
|
||||
OffsetNumber tupoffset = sampler->lt;
|
||||
TableSampleDesc *tsdesc = (TableSampleDesc *) PG_GETARG_POINTER(0);
|
||||
OffsetNumber maxoffset = PG_GETARG_UINT16(2);
|
||||
SystemSamplerData *sampler = (SystemSamplerData *) tsdesc->tsmdata;
|
||||
OffsetNumber tupoffset = sampler->lt;
|
||||
|
||||
if (tupoffset == InvalidOffsetNumber)
|
||||
tupoffset = FirstOffsetNumber;
|
||||
@ -152,9 +153,9 @@ tsm_system_rows_nexttuple(PG_FUNCTION_ARGS)
|
||||
Datum
|
||||
tsm_system_rows_examinetuple(PG_FUNCTION_ARGS)
|
||||
{
|
||||
TableSampleDesc *tsdesc = (TableSampleDesc *) PG_GETARG_POINTER(0);
|
||||
bool visible = PG_GETARG_BOOL(3);
|
||||
SystemSamplerData *sampler = (SystemSamplerData *) tsdesc->tsmdata;
|
||||
TableSampleDesc *tsdesc = (TableSampleDesc *) PG_GETARG_POINTER(0);
|
||||
bool visible = PG_GETARG_BOOL(3);
|
||||
SystemSamplerData *sampler = (SystemSamplerData *) tsdesc->tsmdata;
|
||||
|
||||
if (!visible)
|
||||
PG_RETURN_BOOL(false);
|
||||
@ -183,8 +184,8 @@ tsm_system_rows_end(PG_FUNCTION_ARGS)
|
||||
Datum
|
||||
tsm_system_rows_reset(PG_FUNCTION_ARGS)
|
||||
{
|
||||
TableSampleDesc *tsdesc = (TableSampleDesc *) PG_GETARG_POINTER(0);
|
||||
SystemSamplerData *sampler = (SystemSamplerData *) tsdesc->tsmdata;
|
||||
TableSampleDesc *tsdesc = (TableSampleDesc *) PG_GETARG_POINTER(0);
|
||||
SystemSamplerData *sampler = (SystemSamplerData *) tsdesc->tsmdata;
|
||||
|
||||
sampler->lt = InvalidOffsetNumber;
|
||||
sampler->donetuples = 0;
|
||||
@ -203,14 +204,14 @@ tsm_system_rows_reset(PG_FUNCTION_ARGS)
|
||||
Datum
|
||||
tsm_system_rows_cost(PG_FUNCTION_ARGS)
|
||||
{
|
||||
PlannerInfo *root = (PlannerInfo *) PG_GETARG_POINTER(0);
|
||||
Path *path = (Path *) PG_GETARG_POINTER(1);
|
||||
RelOptInfo *baserel = (RelOptInfo *) PG_GETARG_POINTER(2);
|
||||
List *args = (List *) PG_GETARG_POINTER(3);
|
||||
BlockNumber *pages = (BlockNumber *) PG_GETARG_POINTER(4);
|
||||
double *tuples = (double *) PG_GETARG_POINTER(5);
|
||||
Node *limitnode;
|
||||
int32 ntuples;
|
||||
PlannerInfo *root = (PlannerInfo *) PG_GETARG_POINTER(0);
|
||||
Path *path = (Path *) PG_GETARG_POINTER(1);
|
||||
RelOptInfo *baserel = (RelOptInfo *) PG_GETARG_POINTER(2);
|
||||
List *args = (List *) PG_GETARG_POINTER(3);
|
||||
BlockNumber *pages = (BlockNumber *) PG_GETARG_POINTER(4);
|
||||
double *tuples = (double *) PG_GETARG_POINTER(5);
|
||||
Node *limitnode;
|
||||
int32 ntuples;
|
||||
|
||||
limitnode = linitial(args);
|
||||
limitnode = estimate_expression_value(root, limitnode);
|
||||
@ -235,9 +236,9 @@ tsm_system_rows_cost(PG_FUNCTION_ARGS)
|
||||
|
||||
|
||||
static uint32
|
||||
gcd (uint32 a, uint32 b)
|
||||
gcd(uint32 a, uint32 b)
|
||||
{
|
||||
uint32 c;
|
||||
uint32 c;
|
||||
|
||||
while (a != 0)
|
||||
{
|
||||
@ -253,8 +254,8 @@ static uint32
|
||||
random_relative_prime(uint32 n, SamplerRandomState randstate)
|
||||
{
|
||||
/* Pick random starting number, with some limits on what it can be. */
|
||||
uint32 r = (uint32) sampler_random_fract(randstate) * n/2 + n/4,
|
||||
t;
|
||||
uint32 r = (uint32) sampler_random_fract(randstate) * n / 2 + n / 4,
|
||||
t;
|
||||
|
||||
/*
|
||||
* This should only take 2 or 3 iterations as the probability of 2 numbers
|
||||
|
@ -35,16 +35,17 @@ PG_MODULE_MAGIC;
|
||||
typedef struct
|
||||
{
|
||||
SamplerRandomState randstate;
|
||||
uint32 seed; /* random seed */
|
||||
BlockNumber nblocks; /* number of block in relation */
|
||||
int32 time; /* time limit for sampling */
|
||||
TimestampTz start_time; /* start time of sampling */
|
||||
TimestampTz end_time; /* end time of sampling */
|
||||
OffsetNumber lt; /* last tuple returned from current block */
|
||||
BlockNumber step; /* step size */
|
||||
BlockNumber lb; /* last block visited */
|
||||
BlockNumber estblocks; /* estimated number of returned blocks (moving) */
|
||||
BlockNumber doneblocks; /* number of already returned blocks */
|
||||
uint32 seed; /* random seed */
|
||||
BlockNumber nblocks; /* number of block in relation */
|
||||
int32 time; /* time limit for sampling */
|
||||
TimestampTz start_time; /* start time of sampling */
|
||||
TimestampTz end_time; /* end time of sampling */
|
||||
OffsetNumber lt; /* last tuple returned from current block */
|
||||
BlockNumber step; /* step size */
|
||||
BlockNumber lb; /* last block visited */
|
||||
BlockNumber estblocks; /* estimated number of returned blocks
|
||||
* (moving) */
|
||||
BlockNumber doneblocks; /* number of already returned blocks */
|
||||
} SystemSamplerData;
|
||||
|
||||
|
||||
@ -63,11 +64,11 @@ static uint32 random_relative_prime(uint32 n, SamplerRandomState randstate);
|
||||
Datum
|
||||
tsm_system_time_init(PG_FUNCTION_ARGS)
|
||||
{
|
||||
TableSampleDesc *tsdesc = (TableSampleDesc *) PG_GETARG_POINTER(0);
|
||||
uint32 seed = PG_GETARG_UINT32(1);
|
||||
int32 time = PG_ARGISNULL(2) ? -1 : PG_GETARG_INT32(2);
|
||||
HeapScanDesc scan = tsdesc->heapScan;
|
||||
SystemSamplerData *sampler;
|
||||
TableSampleDesc *tsdesc = (TableSampleDesc *) PG_GETARG_POINTER(0);
|
||||
uint32 seed = PG_GETARG_UINT32(1);
|
||||
int32 time = PG_ARGISNULL(2) ? -1 : PG_GETARG_INT32(2);
|
||||
HeapScanDesc scan = tsdesc->heapScan;
|
||||
SystemSamplerData *sampler;
|
||||
|
||||
if (time < 1)
|
||||
ereport(ERROR,
|
||||
@ -92,6 +93,7 @@ tsm_system_time_init(PG_FUNCTION_ARGS)
|
||||
|
||||
/* Find relative prime as step size for linear probing. */
|
||||
sampler->step = random_relative_prime(sampler->nblocks, sampler->randstate);
|
||||
|
||||
/*
|
||||
* Randomize start position so that blocks close to step size don't have
|
||||
* higher probability of being chosen on very short scan.
|
||||
@ -111,8 +113,8 @@ tsm_system_time_init(PG_FUNCTION_ARGS)
|
||||
Datum
|
||||
tsm_system_time_nextblock(PG_FUNCTION_ARGS)
|
||||
{
|
||||
TableSampleDesc *tsdesc = (TableSampleDesc *) PG_GETARG_POINTER(0);
|
||||
SystemSamplerData *sampler = (SystemSamplerData *) tsdesc->tsmdata;
|
||||
TableSampleDesc *tsdesc = (TableSampleDesc *) PG_GETARG_POINTER(0);
|
||||
SystemSamplerData *sampler = (SystemSamplerData *) tsdesc->tsmdata;
|
||||
|
||||
sampler->lb = (sampler->lb + sampler->step) % sampler->nblocks;
|
||||
sampler->doneblocks++;
|
||||
@ -125,16 +127,16 @@ tsm_system_time_nextblock(PG_FUNCTION_ARGS)
|
||||
* Update the estimations for time limit at least 10 times per estimated
|
||||
* number of returned blocks to handle variations in block read speed.
|
||||
*/
|
||||
if (sampler->doneblocks % Max(sampler->estblocks/10, 1) == 0)
|
||||
if (sampler->doneblocks % Max(sampler->estblocks / 10, 1) == 0)
|
||||
{
|
||||
TimestampTz now = GetCurrentTimestamp();
|
||||
long secs;
|
||||
int usecs;
|
||||
TimestampTz now = GetCurrentTimestamp();
|
||||
long secs;
|
||||
int usecs;
|
||||
int usecs_remaining;
|
||||
int time_per_block;
|
||||
|
||||
TimestampDifference(sampler->start_time, now, &secs, &usecs);
|
||||
usecs += (int) secs * 1000000;
|
||||
usecs += (int) secs *1000000;
|
||||
|
||||
time_per_block = usecs / sampler->doneblocks;
|
||||
|
||||
@ -144,7 +146,7 @@ tsm_system_time_nextblock(PG_FUNCTION_ARGS)
|
||||
PG_RETURN_UINT32(InvalidBlockNumber);
|
||||
|
||||
/* Remaining microseconds */
|
||||
usecs_remaining = usecs + (int) secs * 1000000;
|
||||
usecs_remaining = usecs + (int) secs *1000000;
|
||||
|
||||
/* Recalculate estimated returned number of blocks */
|
||||
if (time_per_block < usecs_remaining && time_per_block > 0)
|
||||
@ -161,10 +163,10 @@ tsm_system_time_nextblock(PG_FUNCTION_ARGS)
|
||||
Datum
|
||||
tsm_system_time_nexttuple(PG_FUNCTION_ARGS)
|
||||
{
|
||||
TableSampleDesc *tsdesc = (TableSampleDesc *) PG_GETARG_POINTER(0);
|
||||
OffsetNumber maxoffset = PG_GETARG_UINT16(2);
|
||||
SystemSamplerData *sampler = (SystemSamplerData *) tsdesc->tsmdata;
|
||||
OffsetNumber tupoffset = sampler->lt;
|
||||
TableSampleDesc *tsdesc = (TableSampleDesc *) PG_GETARG_POINTER(0);
|
||||
OffsetNumber maxoffset = PG_GETARG_UINT16(2);
|
||||
SystemSamplerData *sampler = (SystemSamplerData *) tsdesc->tsmdata;
|
||||
OffsetNumber tupoffset = sampler->lt;
|
||||
|
||||
if (tupoffset == InvalidOffsetNumber)
|
||||
tupoffset = FirstOffsetNumber;
|
||||
@ -198,8 +200,8 @@ tsm_system_time_end(PG_FUNCTION_ARGS)
|
||||
Datum
|
||||
tsm_system_time_reset(PG_FUNCTION_ARGS)
|
||||
{
|
||||
TableSampleDesc *tsdesc = (TableSampleDesc *) PG_GETARG_POINTER(0);
|
||||
SystemSamplerData *sampler = (SystemSamplerData *) tsdesc->tsmdata;
|
||||
TableSampleDesc *tsdesc = (TableSampleDesc *) PG_GETARG_POINTER(0);
|
||||
SystemSamplerData *sampler = (SystemSamplerData *) tsdesc->tsmdata;
|
||||
|
||||
sampler->lt = InvalidOffsetNumber;
|
||||
sampler->start_time = GetCurrentTimestamp();
|
||||
@ -221,18 +223,18 @@ tsm_system_time_reset(PG_FUNCTION_ARGS)
|
||||
Datum
|
||||
tsm_system_time_cost(PG_FUNCTION_ARGS)
|
||||
{
|
||||
PlannerInfo *root = (PlannerInfo *) PG_GETARG_POINTER(0);
|
||||
Path *path = (Path *) PG_GETARG_POINTER(1);
|
||||
RelOptInfo *baserel = (RelOptInfo *) PG_GETARG_POINTER(2);
|
||||
List *args = (List *) PG_GETARG_POINTER(3);
|
||||
BlockNumber *pages = (BlockNumber *) PG_GETARG_POINTER(4);
|
||||
double *tuples = (double *) PG_GETARG_POINTER(5);
|
||||
Node *limitnode;
|
||||
int32 time;
|
||||
BlockNumber relpages;
|
||||
double reltuples;
|
||||
double density;
|
||||
double spc_random_page_cost;
|
||||
PlannerInfo *root = (PlannerInfo *) PG_GETARG_POINTER(0);
|
||||
Path *path = (Path *) PG_GETARG_POINTER(1);
|
||||
RelOptInfo *baserel = (RelOptInfo *) PG_GETARG_POINTER(2);
|
||||
List *args = (List *) PG_GETARG_POINTER(3);
|
||||
BlockNumber *pages = (BlockNumber *) PG_GETARG_POINTER(4);
|
||||
double *tuples = (double *) PG_GETARG_POINTER(5);
|
||||
Node *limitnode;
|
||||
int32 time;
|
||||
BlockNumber relpages;
|
||||
double reltuples;
|
||||
double density;
|
||||
double spc_random_page_cost;
|
||||
|
||||
limitnode = linitial(args);
|
||||
limitnode = estimate_expression_value(root, limitnode);
|
||||
@ -269,10 +271,10 @@ tsm_system_time_cost(PG_FUNCTION_ARGS)
|
||||
/*
|
||||
* Assumption here is that we'll never read less than 1% of table pages,
|
||||
* this is here mainly because it is much less bad to overestimate than
|
||||
* underestimate and using just spc_random_page_cost will probably lead
|
||||
* to underestimations in general.
|
||||
* underestimate and using just spc_random_page_cost will probably lead to
|
||||
* underestimations in general.
|
||||
*/
|
||||
*pages = Min(baserel->pages, Max(time/spc_random_page_cost, baserel->pages/100));
|
||||
*pages = Min(baserel->pages, Max(time / spc_random_page_cost, baserel->pages / 100));
|
||||
*tuples = rint(density * (double) *pages * path->rows / baserel->tuples);
|
||||
path->rows = *tuples;
|
||||
|
||||
@ -280,9 +282,9 @@ tsm_system_time_cost(PG_FUNCTION_ARGS)
|
||||
}
|
||||
|
||||
static uint32
|
||||
gcd (uint32 a, uint32 b)
|
||||
gcd(uint32 a, uint32 b)
|
||||
{
|
||||
uint32 c;
|
||||
uint32 c;
|
||||
|
||||
while (a != 0)
|
||||
{
|
||||
@ -298,8 +300,8 @@ static uint32
|
||||
random_relative_prime(uint32 n, SamplerRandomState randstate)
|
||||
{
|
||||
/* Pick random starting number, with some limits on what it can be. */
|
||||
uint32 r = (uint32) sampler_random_fract(randstate) * n/2 + n/4,
|
||||
t;
|
||||
uint32 r = (uint32) sampler_random_fract(randstate) * n / 2 + n / 4,
|
||||
t;
|
||||
|
||||
/*
|
||||
* This should only take 2 or 3 iterations as the probability of 2 numbers
|
||||
|
Reference in New Issue
Block a user