mirror of
https://github.com/timescale/timescaledb.git
synced 2025-05-22 13:40:56 +08:00
formatting with pgindent
This commit is contained in:
parent
73f4dcaaf0
commit
32c45b75b2
12
src/cache.c
12
src/cache.c
@ -16,8 +16,10 @@ cache_init(Cache *cache)
|
||||
}
|
||||
|
||||
static void
|
||||
cache_destroy(Cache *cache) {
|
||||
if (cache->refcount > 0) {
|
||||
cache_destroy(Cache * cache)
|
||||
{
|
||||
if (cache->refcount > 0)
|
||||
{
|
||||
/* will be destroyed later */
|
||||
return;
|
||||
}
|
||||
@ -49,13 +51,15 @@ cache_invalidate(Cache *cache)
|
||||
* Each call to cache_pin MUST BE paired with a call to cache_release.
|
||||
*
|
||||
*/
|
||||
extern Cache *cache_pin(Cache *cache)
|
||||
extern Cache *
|
||||
cache_pin(Cache * cache)
|
||||
{
|
||||
cache->refcount++;
|
||||
return cache;
|
||||
}
|
||||
|
||||
extern void cache_release(Cache *cache)
|
||||
extern void
|
||||
cache_release(Cache * cache)
|
||||
{
|
||||
Assert(cache->refcount > 0);
|
||||
cache->refcount--;
|
||||
|
@ -26,7 +26,8 @@ static Catalog catalog = {
|
||||
.database_id = InvalidOid,
|
||||
};
|
||||
|
||||
Catalog *catalog_get(void)
|
||||
Catalog *
|
||||
catalog_get(void)
|
||||
{
|
||||
AclResult aclresult;
|
||||
int i;
|
||||
@ -34,8 +35,10 @@ Catalog *catalog_get(void)
|
||||
if (MyDatabaseId == InvalidOid)
|
||||
elog(ERROR, "Invalid database ID");
|
||||
|
||||
/* Check that the user has CREATE permissions on the database, since the
|
||||
operation may involve creating chunks and inserting into them. */
|
||||
/*
|
||||
* Check that the user has CREATE permissions on the database, since the
|
||||
* operation may involve creating chunks and inserting into them.
|
||||
*/
|
||||
aclresult = pg_database_aclcheck(MyDatabaseId, GetUserId(), ACL_CREATE);
|
||||
|
||||
if (aclresult != ACLCHECK_OK)
|
||||
|
@ -3,7 +3,8 @@
|
||||
|
||||
#include <postgres.h>
|
||||
|
||||
enum catalog_table {
|
||||
enum catalog_table
|
||||
{
|
||||
HYPERTABLE = 0,
|
||||
CHUNK,
|
||||
PARTITION,
|
||||
@ -32,11 +33,13 @@ enum catalog_table {
|
||||
#define CHUNK_INDEX_NAME "chunk_pkey"
|
||||
#define CHUNK_PARTITION_TIME_INDEX_NAME "chunk_partition_id_start_time_end_time_idx"
|
||||
|
||||
typedef struct Catalog {
|
||||
typedef struct Catalog
|
||||
{
|
||||
char database_name[NAMEDATALEN];
|
||||
Oid database_id;
|
||||
Oid schema_id;
|
||||
struct {
|
||||
struct
|
||||
{
|
||||
const char *name;
|
||||
Oid id;
|
||||
Oid index_id;
|
||||
|
@ -54,14 +54,19 @@ chunk_crn_set_cache_get_key(CacheQueryCtx *ctx)
|
||||
static void *chunk_crn_set_cache_create_entry(Cache * cache, CacheQueryCtx * ctx);
|
||||
static void *chunk_crn_set_cache_update_entry(Cache * cache, CacheQueryCtx * ctx);
|
||||
|
||||
static Cache *chunk_crn_set_cache_create() {
|
||||
static Cache *
|
||||
chunk_crn_set_cache_create()
|
||||
{
|
||||
MemoryContext ctx = AllocSetContextCreate(CacheMemoryContext,
|
||||
CHUNK_CACHE_INVAL_PROXY_TABLE,
|
||||
ALLOCSET_DEFAULT_SIZES);
|
||||
|
||||
Cache *cache = MemoryContextAlloc(ctx, sizeof(Cache));
|
||||
*cache = (Cache) {
|
||||
.hctl = {
|
||||
|
||||
Cache tmp = (Cache)
|
||||
{
|
||||
.hctl =
|
||||
{
|
||||
.keysize = sizeof(int32),
|
||||
.entrysize = sizeof(chunk_crn_set_htable_entry),
|
||||
.hcxt = ctx,
|
||||
@ -74,6 +79,8 @@ static Cache *chunk_crn_set_cache_create() {
|
||||
.update_entry = chunk_crn_set_cache_update_entry,
|
||||
};
|
||||
|
||||
*cache = tmp;
|
||||
|
||||
cache_init(cache);
|
||||
|
||||
return cache;
|
||||
@ -179,7 +186,9 @@ typedef struct ChunkScanCtx
|
||||
chunk_row *chunk;
|
||||
Oid chunk_tbl_id;
|
||||
int32 partition_id;
|
||||
int64 starttime, endtime, timepoint;
|
||||
int64 starttime,
|
||||
endtime,
|
||||
timepoint;
|
||||
bool should_lock;
|
||||
} ChunkScanCtx;
|
||||
|
||||
@ -187,7 +196,8 @@ static bool
|
||||
chunk_tuple_timepoint_filter(TupleInfo * ti, void *arg)
|
||||
{
|
||||
ChunkScanCtx *ctx = arg;
|
||||
bool starttime_is_null, endtime_is_null;
|
||||
bool starttime_is_null,
|
||||
endtime_is_null;
|
||||
Datum datum;
|
||||
|
||||
datum = heap_getattr(ti->tuple, CHUNK_TBL_COL_STARTTIME, ti->desc, &starttime_is_null);
|
||||
@ -242,8 +252,9 @@ chunk_scan(int32 partition_id, int64 timepoint, bool tuplock)
|
||||
.scandirection = ForwardScanDirection,
|
||||
};
|
||||
|
||||
/* Perform an index scan on epoch ID to find the partitions for the
|
||||
* epoch. */
|
||||
/*
|
||||
* Perform an index scan on epoch ID to find the partitions for the epoch.
|
||||
*/
|
||||
ScanKeyInit(&scankey[0], CHUNK_IDX_COL_PARTITION_ID, BTEqualStrategyNumber,
|
||||
F_INT4EQ, Int32GetDatum(partition_id));
|
||||
|
||||
|
@ -29,14 +29,19 @@ hypertable_cache_get_key(CacheQueryCtx *ctx)
|
||||
}
|
||||
|
||||
|
||||
static Cache *hypertable_cache_create() {
|
||||
static Cache *
|
||||
hypertable_cache_create()
|
||||
{
|
||||
MemoryContext ctx = AllocSetContextCreate(CacheMemoryContext,
|
||||
HYPERTABLE_CACHE_INVAL_PROXY_TABLE,
|
||||
ALLOCSET_DEFAULT_SIZES);
|
||||
|
||||
Cache *cache = MemoryContextAlloc(ctx, sizeof(Cache));
|
||||
*cache = (Cache) {
|
||||
.hctl = {
|
||||
|
||||
Cache tmp = (Cache)
|
||||
{
|
||||
.hctl =
|
||||
{
|
||||
.keysize = sizeof(int32),
|
||||
.entrysize = sizeof(hypertable_cache_entry),
|
||||
.hcxt = ctx,
|
||||
@ -48,6 +53,7 @@ static Cache *hypertable_cache_create() {
|
||||
.create_entry = hypertable_cache_create_entry,
|
||||
};
|
||||
|
||||
*cache = tmp;
|
||||
cache_init(cache);
|
||||
|
||||
return cache;
|
||||
@ -213,7 +219,8 @@ hypertable_cache_pin()
|
||||
}
|
||||
|
||||
|
||||
void _hypertable_cache_init(void)
|
||||
void
|
||||
_hypertable_cache_init(void)
|
||||
{
|
||||
CreateCacheMemoryContext();
|
||||
hypertable_cache_current = hypertable_cache_create();
|
||||
|
32
src/insert.c
32
src/insert.c
@ -103,7 +103,8 @@ typedef struct ChunkInsertCtxRel
|
||||
} ChunkInsertCtxRel;
|
||||
|
||||
static ChunkInsertCtxRel *
|
||||
chunk_insert_ctx_rel_new(Relation rel, ResultRelInfo *resultRelInfo, List *range_table) {
|
||||
chunk_insert_ctx_rel_new(Relation rel, ResultRelInfo *resultRelInfo, List *range_table)
|
||||
{
|
||||
TupleDesc tupDesc;
|
||||
ChunkInsertCtxRel *rel_ctx = palloc(sizeof(ChunkInsertCtxRel));
|
||||
|
||||
@ -260,6 +261,7 @@ chunk_insert_ctx_destroy(ChunkInsertCtx *ctx)
|
||||
foreach(lc, ctx->ctxs)
|
||||
{
|
||||
ChunkInsertCtxRel *rel_ctx = lfirst(lc);
|
||||
|
||||
chunk_insert_ctx_rel_destroy(rel_ctx);
|
||||
}
|
||||
}
|
||||
@ -272,11 +274,13 @@ chunk_insert_ctx_insert_tuple(ChunkInsertCtx *ctx, HeapTuple tup)
|
||||
foreach(lc, ctx->ctxs)
|
||||
{
|
||||
ChunkInsertCtxRel *rel_ctx = lfirst(lc);
|
||||
|
||||
chunk_insert_ctx_rel_insert_tuple(rel_ctx, tup);
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct CopyTableQueryCtx {
|
||||
typedef struct CopyTableQueryCtx
|
||||
{
|
||||
Partition *part;
|
||||
ChunkInsertCtx *chunk_ctx;
|
||||
epoch_and_partitions_set *pe;
|
||||
@ -293,7 +297,10 @@ copy_table_tuple_found(TupleInfo *ti, void *data)
|
||||
|
||||
if (ctx->pe->num_partitions > 1)
|
||||
{
|
||||
/* first element is partition index (used for sorting but not necessary here) */
|
||||
/*
|
||||
* first element is partition index (used for sorting but not
|
||||
* necessary here)
|
||||
*/
|
||||
Datum time_datum = index_getattr(ti->ituple, 2, ti->ituple_desc, &is_null);
|
||||
Datum keyspace_datum = index_getattr(ti->ituple, 3, ti->ituple_desc, &is_null);
|
||||
|
||||
@ -303,6 +310,7 @@ copy_table_tuple_found(TupleInfo *ti, void *data)
|
||||
else
|
||||
{
|
||||
Datum time_datum = index_getattr(ti->ituple, 1, ti->ituple_desc, &is_null);
|
||||
|
||||
time_pt = time_value_to_internal(time_datum, ctx->hci->time_column_type);
|
||||
keyspace_pt = KEYSPACE_PT_NO_PARTITIONING;
|
||||
}
|
||||
@ -333,13 +341,18 @@ copy_table_tuple_found(TupleInfo *ti, void *data)
|
||||
Datum was_closed_datum;
|
||||
chunk_cache_entry *chunk;
|
||||
Cache *pinned = chunk_crn_set_cache_pin();
|
||||
|
||||
/*
|
||||
* TODO: this first call should be non-locking and use a cache(for
|
||||
* performance)
|
||||
*/
|
||||
chunk = get_chunk_cache_entry(pinned, ctx->part, time_pt, false);
|
||||
was_closed_datum = FunctionCall1(get_close_if_needed_fn(), Int32GetDatum(chunk->id));
|
||||
/* chunk may have been closed and thus changed /or/ need to get share lock */
|
||||
|
||||
/*
|
||||
* chunk may have been closed and thus changed /or/ need to get share
|
||||
* lock
|
||||
*/
|
||||
chunk = get_chunk_cache_entry(pinned, ctx->part, time_pt, true);
|
||||
|
||||
ctx->chunk_ctx = chunk_insert_ctx_new(chunk, pinned);
|
||||
@ -351,14 +364,17 @@ copy_table_tuple_found(TupleInfo *ti, void *data)
|
||||
return true;
|
||||
}
|
||||
|
||||
static void scan_copy_table_and_insert_post(int num_tuples, void *data)
|
||||
static void
|
||||
scan_copy_table_and_insert_post(int num_tuples, void *data)
|
||||
{
|
||||
CopyTableQueryCtx *ctx = data;
|
||||
|
||||
if (ctx->chunk_ctx != NULL)
|
||||
chunk_insert_ctx_destroy(ctx->chunk_ctx);
|
||||
}
|
||||
|
||||
static void scan_copy_table_and_insert( hypertable_cache_entry *hci,
|
||||
static void
|
||||
scan_copy_table_and_insert(hypertable_cache_entry * hci,
|
||||
epoch_and_partitions_set * pe,
|
||||
Oid table, Oid index)
|
||||
{
|
||||
@ -537,10 +553,12 @@ create_copy_table(int32 hypertable_id, Oid root_oid)
|
||||
}
|
||||
|
||||
static IndexElem *
|
||||
makeIndexElem(char *name, Node *expr){
|
||||
makeIndexElem(char *name, Node *expr)
|
||||
{
|
||||
Assert((name == NULL || expr == NULL) && (name != NULL || expr != NULL));
|
||||
|
||||
IndexElem *time_elem = makeNode(IndexElem);
|
||||
|
||||
time_elem->name = name;
|
||||
time_elem->expr = expr;
|
||||
time_elem->indexcolname = NULL;
|
||||
|
@ -225,6 +225,8 @@ chunk_row_insert_new(int32 partition_id, int64 timepoint, bool lock)
|
||||
}
|
||||
|
||||
|
||||
bool chunk_row_timepoint_is_member(const chunk_row *row, const int64 time_pt){
|
||||
bool
|
||||
chunk_row_timepoint_is_member(const chunk_row * row, const int64 time_pt)
|
||||
{
|
||||
return row->start_time <= time_pt && row->end_time >= time_pt;
|
||||
}
|
||||
|
@ -1,36 +1,39 @@
|
||||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
||||
//-----------------------------------------------------------------------------
|
||||
// MurmurHash3 was written by Austin Appleby, and is placed in the public
|
||||
// domain. The author hereby disclaims copyright to this source code.
|
||||
/* ----------------------------------------------------------------------------- */
|
||||
/* MurmurHash3 was written by Austin Appleby, and is placed in the public */
|
||||
/* domain. The author hereby disclaims copyright to this source code. */
|
||||
|
||||
// Note - The x86 and x64 versions do _not_ produce the same results, as the
|
||||
// algorithms are optimized for their respective platforms. You can still
|
||||
// compile and run any of them on any platform, but your performance with the
|
||||
// non-native version will be less than optimal.
|
||||
/* Note - The x86 and x64 versions do _not_ produce the same results, as the */
|
||||
/* algorithms are optimized for their respective platforms. You can still */
|
||||
/* compile and run any of them on any platform, but your performance with the */
|
||||
/* non-native version will be less than optimal. */
|
||||
|
||||
#include "pgmurmur3.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Platform-specific functions and macros
|
||||
/* ----------------------------------------------------------------------------- */
|
||||
/* Platform-specific functions and macros */
|
||||
|
||||
static inline uint32_t rotl32(uint32_t x, int8_t r)
|
||||
static inline uint32_t
|
||||
rotl32(uint32_t x, int8_t r)
|
||||
{
|
||||
return (x << r) | (x >> (32 - r));
|
||||
}
|
||||
|
||||
#define ROTL32(x,y) rotl32(x,y)
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Block read - if your platform needs to do endian-swapping or can only
|
||||
// handle aligned reads, do the conversion here
|
||||
static inline uint32_t getblock(const uint32_t * p, int i)
|
||||
/* ----------------------------------------------------------------------------- */
|
||||
/* Block read - if your platform needs to do endian-swapping or can only */
|
||||
/* handle aligned reads, do the conversion here */
|
||||
static inline uint32_t
|
||||
getblock(const uint32_t *p, int i)
|
||||
{
|
||||
return p[i];
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Finalization mix - force all bits of a hash block to avalanche
|
||||
static inline uint32_t fmix(uint32_t h)
|
||||
/* ----------------------------------------------------------------------------- */
|
||||
/* Finalization mix - force all bits of a hash block to avalanche */
|
||||
static inline uint32_t
|
||||
fmix(uint32_t h)
|
||||
{
|
||||
h ^= h >> 16;
|
||||
h *= 0x85ebca6b;
|
||||
@ -40,8 +43,9 @@ static inline uint32_t fmix(uint32_t h)
|
||||
return h;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
void hlib_murmur3(const void *key, size_t len, uint64_t *io)
|
||||
/* ----------------------------------------------------------------------------- */
|
||||
void
|
||||
hlib_murmur3(const void *key, size_t len, uint64_t * io)
|
||||
{
|
||||
const uint8_t *data = (const uint8_t *) key;
|
||||
const int nblocks = len / 4;
|
||||
@ -53,10 +57,11 @@ void hlib_murmur3(const void *key, size_t len, uint64_t *io)
|
||||
int i;
|
||||
uint32_t k1;
|
||||
|
||||
//----------
|
||||
// body
|
||||
/* ---------- */
|
||||
/* body */
|
||||
blocks = (const uint32_t *) (data + nblocks * 4);
|
||||
for (i = -nblocks; i; i++) {
|
||||
for (i = -nblocks; i; i++)
|
||||
{
|
||||
k1 = getblock(blocks, i);
|
||||
k1 *= c1;
|
||||
k1 = ROTL32(k1, 15);
|
||||
@ -65,11 +70,12 @@ void hlib_murmur3(const void *key, size_t len, uint64_t *io)
|
||||
h1 = ROTL32(h1, 13);
|
||||
h1 = h1 * 5 + 0xe6546b64;
|
||||
}
|
||||
//----------
|
||||
// tail
|
||||
/* ---------- */
|
||||
/* tail */
|
||||
tail = (const uint8_t *) (data + nblocks * 4);
|
||||
k1 = 0;
|
||||
switch (len & 3) {
|
||||
switch (len & 3)
|
||||
{
|
||||
case 3:
|
||||
k1 ^= tail[2] << 16;
|
||||
case 2:
|
||||
@ -82,10 +88,9 @@ void hlib_murmur3(const void *key, size_t len, uint64_t *io)
|
||||
h1 ^= k1;
|
||||
};
|
||||
|
||||
//----------
|
||||
// finalization
|
||||
/* ---------- */
|
||||
/* finalization */
|
||||
h1 ^= len;
|
||||
h1 = fmix(h1);
|
||||
io[0] = h1;
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,8 @@
|
||||
#include "scanner.h"
|
||||
#include "catalog.h"
|
||||
|
||||
static void partitioning_func_set_func_fmgr(PartitioningFunc *pf)
|
||||
static void
|
||||
partitioning_func_set_func_fmgr(PartitioningFunc * pf)
|
||||
{
|
||||
FuncCandidateList funclist =
|
||||
FuncnameGetCandidates(list_make2(makeString(pf->schema), makeString(pf->name)),
|
||||
@ -20,10 +21,13 @@ static void partitioning_func_set_func_fmgr(PartitioningFunc *pf)
|
||||
fmgr_info_cxt(funclist->oid, &pf->func_fmgr, CurrentMemoryContext);
|
||||
}
|
||||
|
||||
static void partitioning_info_set_textfunc_fmgr(PartitioningInfo *pi, Oid relid)
|
||||
static void
|
||||
partitioning_info_set_textfunc_fmgr(PartitioningInfo * pi, Oid relid)
|
||||
{
|
||||
Oid type_id, func_id;
|
||||
Oid type_id,
|
||||
func_id;
|
||||
bool isVarlena;
|
||||
|
||||
pi->column_attnum = get_attnum(relid, pi->column);
|
||||
type_id = get_atttype(relid, pi->column_attnum);
|
||||
getTypeOutputInfo(type_id, &func_id, &isVarlena);
|
||||
@ -56,13 +60,15 @@ partitioning_info_create(int num_partitions,
|
||||
return pi;
|
||||
}
|
||||
|
||||
int16 partitioning_func_apply(PartitioningFunc *pf, Datum value)
|
||||
int16
|
||||
partitioning_func_apply(PartitioningFunc * pf, Datum value)
|
||||
{
|
||||
Datum text = FunctionCall1(&pf->textfunc_fmgr, value);
|
||||
char *partition_val = DatumGetCString(text);
|
||||
Datum keyspace_datum = FunctionCall2(&pf->func_fmgr,
|
||||
CStringGetTextDatum(partition_val),
|
||||
Int32GetDatum(pf->modulos));
|
||||
|
||||
return DatumGetInt16(keyspace_datum);
|
||||
}
|
||||
|
||||
@ -85,11 +91,14 @@ int16 partitioning_func_apply(PartitioningFunc *pf, Datum value)
|
||||
|
||||
/* PartitionEpochCtx is used to pass on information during a partition epoch and
|
||||
* partition scans. */
|
||||
typedef struct {
|
||||
typedef struct
|
||||
{
|
||||
epoch_and_partitions_set *pe;
|
||||
int16 num_partitions;
|
||||
int32 hypertable_id;
|
||||
int64 starttime, endtime, timepoint;
|
||||
int64 starttime,
|
||||
endtime,
|
||||
timepoint;
|
||||
Oid relid;
|
||||
} PartitionEpochCtx;
|
||||
|
||||
@ -106,7 +115,8 @@ partition_epoch_filter(TupleInfo *ti, void *arg)
|
||||
|
||||
if (DatumGetInt32(id) == pctx->hypertable_id)
|
||||
{
|
||||
bool starttime_is_null, endtime_is_null;
|
||||
bool starttime_is_null,
|
||||
endtime_is_null;
|
||||
Datum starttime = heap_getattr(ti->tuple, PE_TBL_COL_STARTTIME, ti->desc, &starttime_is_null);
|
||||
Datum endtime = heap_getattr(ti->tuple, PE_TBL_COL_ENDTIME, ti->desc, &endtime_is_null);
|
||||
|
||||
@ -126,6 +136,7 @@ static epoch_and_partitions_set *
|
||||
partition_epoch_create(int32 epoch_id, PartitionEpochCtx * ctx)
|
||||
{
|
||||
epoch_and_partitions_set *pe;
|
||||
|
||||
pe = palloc(PARTITION_EPOCH_SIZE(ctx->num_partitions));
|
||||
pe->id = epoch_id;
|
||||
pe->num_partitions = ctx->num_partitions;
|
||||
@ -156,8 +167,13 @@ partition_epoch_tuple_found(TupleInfo *ti, void *arg)
|
||||
|
||||
if (pctx->num_partitions > 1)
|
||||
{
|
||||
Datum partfunc, partmod, partcol;
|
||||
bool partfunc_is_null, partmod_is_null, partcol_is_null;
|
||||
Datum partfunc,
|
||||
partmod,
|
||||
partcol;
|
||||
bool partfunc_is_null,
|
||||
partmod_is_null,
|
||||
partcol_is_null;
|
||||
|
||||
partfunc = heap_getattr(ti->tuple, PE_TBL_COL_PARTFUNC, ti->desc, &partfunc_is_null);
|
||||
partmod = heap_getattr(ti->tuple, PE_TBL_COL_PARTMOD, ti->desc, &partmod_is_null);
|
||||
partcol = heap_getattr(ti->tuple, PE_TBL_COL_PARTCOL, ti->desc, &partcol_is_null);
|
||||
@ -175,7 +191,9 @@ partition_epoch_tuple_found(TupleInfo *ti, void *arg)
|
||||
DatumGetCString(partcol),
|
||||
DatumGetInt16(partmod),
|
||||
pctx->relid);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
pe->partitioning = NULL;
|
||||
}
|
||||
|
||||
@ -236,15 +254,18 @@ partition_scan(PartitionEpochCtx *pctx)
|
||||
.scandirection = ForwardScanDirection,
|
||||
};
|
||||
|
||||
/* Perform an index scan on epoch ID to find the partitions for the
|
||||
* epoch. */
|
||||
/*
|
||||
* Perform an index scan on epoch ID to find the partitions for the epoch.
|
||||
*/
|
||||
ScanKeyInit(&scankey[0], PARTITION_IDX_COL_ID, BTEqualStrategyNumber,
|
||||
F_INT4EQ, Int32GetDatum(pctx->pe->id));
|
||||
|
||||
scanner_scan(&scanCtx);
|
||||
|
||||
/* The scan decremented the number of partitions in the context, so check
|
||||
that it is zero for correct number of partitions scanned. */
|
||||
/*
|
||||
* The scan decremented the number of partitions in the context, so check
|
||||
* that it is zero for correct number of partitions scanned.
|
||||
*/
|
||||
if (pctx->num_partitions != 0)
|
||||
{
|
||||
elog(ERROR, "%d partitions found for epoch %d, expected %d",
|
||||
@ -277,8 +298,10 @@ partition_epoch_scan(int32 hypertable_id, int64 timepoint, Oid relid)
|
||||
.scandirection = ForwardScanDirection,
|
||||
};
|
||||
|
||||
/* Perform an index scan on hypertable ID. We filter on start and end
|
||||
* time. */
|
||||
/*
|
||||
* Perform an index scan on hypertable ID. We filter on start and end
|
||||
* time.
|
||||
*/
|
||||
ScanKeyInit(&scankey[0], PE_IDX_COL_HTID, BTEqualStrategyNumber,
|
||||
F_INT4EQ, Int32GetDatum(hypertable_id));
|
||||
|
||||
@ -340,7 +363,8 @@ partition_epoch_get_partition(epoch_and_partitions_set *epoch, int16 keyspace_pt
|
||||
return part;
|
||||
}
|
||||
|
||||
bool partition_keyspace_pt_is_member(const Partition *part, const int16 keyspace_pt)
|
||||
bool
|
||||
partition_keyspace_pt_is_member(const Partition * part, const int16 keyspace_pt)
|
||||
{
|
||||
return keyspace_pt == KEYSPACE_PT_NO_PARTITIONING || (part->keyspace_start <= keyspace_pt && part->keyspace_end >= keyspace_pt);
|
||||
}
|
||||
|
@ -19,12 +19,16 @@ typedef struct PartitioningFunc
|
||||
char schema[NAMEDATALEN];
|
||||
char name[NAMEDATALEN];
|
||||
|
||||
/* Function manager info to call the function to convert a row's
|
||||
* partitioning column value to a text string */
|
||||
/*
|
||||
* Function manager info to call the function to convert a row's
|
||||
* partitioning column value to a text string
|
||||
*/
|
||||
FmgrInfo textfunc_fmgr;
|
||||
|
||||
/* Function manager info to call the partitioning function on the
|
||||
partitioning column's text representation */
|
||||
/*
|
||||
* Function manager info to call the partitioning function on the
|
||||
* partitioning column's text representation
|
||||
*/
|
||||
FmgrInfo func_fmgr;
|
||||
int32 modulos;
|
||||
} PartitioningFunc;
|
||||
|
@ -8,7 +8,8 @@
|
||||
|
||||
#include "scanner.h"
|
||||
|
||||
typedef union ScanDesc {
|
||||
typedef union ScanDesc
|
||||
{
|
||||
IndexScanDesc index_scan;
|
||||
HeapScanDesc heap_scan;
|
||||
} ScanDesc;
|
||||
@ -18,8 +19,10 @@ typedef union ScanDesc {
|
||||
* It holds a pointer to the user-given ScannerCtx as well as
|
||||
* internal state used during scanning.
|
||||
*/
|
||||
typedef struct InternalScannerCtx {
|
||||
Relation tablerel, indexrel;
|
||||
typedef struct InternalScannerCtx
|
||||
{
|
||||
Relation tablerel,
|
||||
indexrel;
|
||||
TupleInfo tinfo;
|
||||
ScanDesc scan;
|
||||
ScannerCtx *sctx;
|
||||
@ -28,7 +31,8 @@ typedef struct InternalScannerCtx {
|
||||
/*
|
||||
* Scanner can implement both index and heap scans in a single interface.
|
||||
*/
|
||||
typedef struct Scanner {
|
||||
typedef struct Scanner
|
||||
{
|
||||
Relation (*open) (InternalScannerCtx * ctx);
|
||||
ScanDesc(*beginscan) (InternalScannerCtx * ctx);
|
||||
bool (*getnext) (InternalScannerCtx * ctx);
|
||||
@ -37,47 +41,56 @@ typedef struct Scanner {
|
||||
} Scanner;
|
||||
|
||||
/* Functions implementing heap scans */
|
||||
static Relation heap_scanner_open(InternalScannerCtx *ctx)
|
||||
static Relation
|
||||
heap_scanner_open(InternalScannerCtx * ctx)
|
||||
{
|
||||
ctx->tablerel = heap_open(ctx->sctx->table, ctx->sctx->lockmode);
|
||||
return ctx->tablerel;
|
||||
}
|
||||
|
||||
static ScanDesc heap_scanner_beginscan(InternalScannerCtx *ctx)
|
||||
static ScanDesc
|
||||
heap_scanner_beginscan(InternalScannerCtx * ctx)
|
||||
{
|
||||
ScannerCtx *sctx = ctx->sctx;
|
||||
|
||||
ctx->scan.heap_scan = heap_beginscan(ctx->tablerel, SnapshotSelf,
|
||||
sctx->nkeys, sctx->scankey);
|
||||
return ctx->scan;
|
||||
}
|
||||
|
||||
static bool heap_scanner_getnext(InternalScannerCtx *ctx)
|
||||
static bool
|
||||
heap_scanner_getnext(InternalScannerCtx * ctx)
|
||||
{
|
||||
ctx->tinfo.tuple = heap_getnext(ctx->scan.heap_scan, ctx->sctx->scandirection);
|
||||
return HeapTupleIsValid(ctx->tinfo.tuple);
|
||||
}
|
||||
|
||||
static void heap_scanner_endscan(InternalScannerCtx *ctx)
|
||||
static void
|
||||
heap_scanner_endscan(InternalScannerCtx * ctx)
|
||||
{
|
||||
heap_endscan(ctx->scan.heap_scan);
|
||||
}
|
||||
|
||||
static void heap_scanner_close(InternalScannerCtx *ctx)
|
||||
static void
|
||||
heap_scanner_close(InternalScannerCtx * ctx)
|
||||
{
|
||||
heap_close(ctx->tablerel, ctx->sctx->lockmode);
|
||||
}
|
||||
|
||||
/* Functions implementing index scans */
|
||||
static Relation index_scanner_open(InternalScannerCtx *ctx)
|
||||
static Relation
|
||||
index_scanner_open(InternalScannerCtx * ctx)
|
||||
{
|
||||
ctx->tablerel = heap_open(ctx->sctx->table, ctx->sctx->lockmode);
|
||||
ctx->indexrel = index_open(ctx->sctx->index, ctx->sctx->lockmode);
|
||||
return ctx->indexrel;
|
||||
}
|
||||
|
||||
static ScanDesc index_scanner_beginscan(InternalScannerCtx *ctx)
|
||||
static ScanDesc
|
||||
index_scanner_beginscan(InternalScannerCtx * ctx)
|
||||
{
|
||||
ScannerCtx *sctx = ctx->sctx;
|
||||
|
||||
ctx->scan.index_scan = index_beginscan(ctx->tablerel, ctx->indexrel,
|
||||
SnapshotSelf, sctx->nkeys,
|
||||
sctx->norderbys);
|
||||
@ -87,7 +100,8 @@ static ScanDesc index_scanner_beginscan(InternalScannerCtx *ctx)
|
||||
return ctx->scan;
|
||||
}
|
||||
|
||||
static bool index_scanner_getnext(InternalScannerCtx *ctx)
|
||||
static bool
|
||||
index_scanner_getnext(InternalScannerCtx * ctx)
|
||||
{
|
||||
ctx->tinfo.tuple = index_getnext(ctx->scan.index_scan, ctx->sctx->scandirection);
|
||||
ctx->tinfo.ituple = ctx->scan.index_scan->xs_itup;
|
||||
@ -95,12 +109,14 @@ static bool index_scanner_getnext(InternalScannerCtx *ctx)
|
||||
return HeapTupleIsValid(ctx->tinfo.tuple);
|
||||
}
|
||||
|
||||
static void index_scanner_endscan(InternalScannerCtx *ctx)
|
||||
static void
|
||||
index_scanner_endscan(InternalScannerCtx * ctx)
|
||||
{
|
||||
index_endscan(ctx->scan.index_scan);
|
||||
}
|
||||
|
||||
static void index_scanner_close(InternalScannerCtx *ctx)
|
||||
static void
|
||||
index_scanner_close(InternalScannerCtx * ctx)
|
||||
{
|
||||
heap_close(ctx->tablerel, ctx->sctx->lockmode);
|
||||
index_close(ctx->indexrel, ctx->sctx->lockmode);
|
||||
@ -133,7 +149,8 @@ static Scanner scanners[] = {
|
||||
*
|
||||
* Return the number of tuples that where found.
|
||||
*/
|
||||
int scanner_scan(ScannerCtx *ctx)
|
||||
int
|
||||
scanner_scan(ScannerCtx * ctx)
|
||||
{
|
||||
TupleDesc tuple_desc;
|
||||
bool is_valid;
|
||||
@ -175,7 +192,10 @@ int scanner_scan(ScannerCtx *ctx)
|
||||
ctx->tuplock.waitpolicy,
|
||||
false, &buffer, &hufd);
|
||||
|
||||
/* A tuple lock pins the underlying buffer, so we need to unpin it. */
|
||||
/*
|
||||
* A tuple lock pins the underlying buffer, so we need to
|
||||
* unpin it.
|
||||
*/
|
||||
ReleaseBuffer(buffer);
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,8 @@
|
||||
#include <access/heapam.h>
|
||||
#include <nodes/lockoptions.h>
|
||||
|
||||
typedef enum ScannerType {
|
||||
typedef enum ScannerType
|
||||
{
|
||||
ScannerTypeHeap,
|
||||
ScannerTypeIndex,
|
||||
} ScannerType;
|
||||
@ -21,6 +22,7 @@ typedef struct TupleInfo
|
||||
/* return index tuple if it was requested -- only for index scans */
|
||||
IndexTuple ituple;
|
||||
TupleDesc ituple_desc;
|
||||
|
||||
/*
|
||||
* If the user requested a tuple lock, the result of the lock is passed on
|
||||
* in lockresult.
|
||||
@ -28,36 +30,48 @@ typedef struct TupleInfo
|
||||
HTSU_Result lockresult;
|
||||
} TupleInfo;
|
||||
|
||||
typedef struct ScannerCtx {
|
||||
typedef struct ScannerCtx
|
||||
{
|
||||
Oid table;
|
||||
Oid index;
|
||||
ScannerType scantype;
|
||||
ScanKey scankey;
|
||||
int nkeys, norderbys;
|
||||
int nkeys,
|
||||
norderbys;
|
||||
bool want_itup;
|
||||
LOCKMODE lockmode;
|
||||
struct {
|
||||
struct
|
||||
{
|
||||
LockTupleMode lockmode;
|
||||
LockWaitPolicy waitpolicy;
|
||||
bool enabled;
|
||||
} tuplock;
|
||||
ScanDirection scandirection;
|
||||
void *data; /* User-provided data passed on to filter() and tuple_found() */
|
||||
void *data; /* User-provided data passed on to filter()
|
||||
* and tuple_found() */
|
||||
|
||||
/* Optional handler called before a scan starts, but relation locks are
|
||||
* acquired. */
|
||||
/*
|
||||
* Optional handler called before a scan starts, but relation locks are
|
||||
* acquired.
|
||||
*/
|
||||
void (*prescan) (void *data);
|
||||
|
||||
/* Optional handler called after a scan finishes and before relation locks
|
||||
* are released. Passes on the number of tuples found. */
|
||||
/*
|
||||
* Optional handler called after a scan finishes and before relation locks
|
||||
* are released. Passes on the number of tuples found.
|
||||
*/
|
||||
void (*postscan) (int num_tuples, void *data);
|
||||
|
||||
/* Optional handler to filter tuples. Should return true for tuples that
|
||||
* should be passed on to tuple_found, or false otherwise. */
|
||||
/*
|
||||
* Optional handler to filter tuples. Should return true for tuples that
|
||||
* should be passed on to tuple_found, or false otherwise.
|
||||
*/
|
||||
bool (*filter) (TupleInfo * ti, void *data);
|
||||
|
||||
/* Handler for found tuples. Should return true to continue the scan or
|
||||
* false to abort. */
|
||||
/*
|
||||
* Handler for found tuples. Should return true to continue the scan or
|
||||
* false to abort.
|
||||
*/
|
||||
bool (*tuple_found) (TupleInfo * ti, void *data);
|
||||
} ScannerCtx;
|
||||
|
||||
|
@ -165,11 +165,13 @@ _PG_fini(void)
|
||||
_chunk_cache_fini();
|
||||
}
|
||||
|
||||
SPIPlanPtr get_hypertable_info_plan()
|
||||
SPIPlanPtr
|
||||
get_hypertable_info_plan()
|
||||
{
|
||||
Oid hypertable_info_plan_args[2] = {TEXTOID, TEXTOID};
|
||||
|
||||
if (hypertable_info_plan != NULL) {
|
||||
if (hypertable_info_plan != NULL)
|
||||
{
|
||||
return hypertable_info_plan;
|
||||
}
|
||||
|
||||
@ -194,7 +196,6 @@ SPIPlanPtr get_hypertable_info_plan()
|
||||
bool
|
||||
IobeamLoaded(void)
|
||||
{
|
||||
|
||||
if (!isLoaded)
|
||||
{
|
||||
Oid id;
|
||||
@ -232,16 +233,21 @@ change_table_name_walker(Node *node, void *context)
|
||||
{
|
||||
RangeTblEntry *rangeTableEntry = (RangeTblEntry *) node;
|
||||
change_table_name_context *ctx = (change_table_name_context *) context;
|
||||
|
||||
if (rangeTableEntry->rtekind == RTE_RELATION && rangeTableEntry->inh)
|
||||
{
|
||||
hypertable_info *hinfo = get_hypertable_info(rangeTableEntry->relid);
|
||||
|
||||
if (hinfo != NULL)
|
||||
{
|
||||
ctx->hypertable_info = lappend(ctx->hypertable_info, hinfo);
|
||||
rangeTableEntry->relid = hinfo->replica_oid;
|
||||
}
|
||||
} else if (rangeTableEntry->rtekind == RTE_RELATION && ctx->parse->commandType == CMD_INSERT){
|
||||
}
|
||||
else if (rangeTableEntry->rtekind == RTE_RELATION && ctx->parse->commandType == CMD_INSERT)
|
||||
{
|
||||
hypertable_info *hinfo = get_hypertable_info(rangeTableEntry->relid);
|
||||
|
||||
if (hinfo != NULL)
|
||||
{
|
||||
rangeTableEntry->relid = create_copy_table(hinfo->hypertable_id, hinfo->root_oid);
|
||||
@ -268,6 +274,7 @@ timescaledb_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
|
||||
{
|
||||
change_table_name_context context;
|
||||
char *printParse = GetConfigOptionByName("io.print_parse", NULL, true);
|
||||
|
||||
/* set to false to not print all internal actions */
|
||||
SetConfigOption("io.print_parse", "false", PGC_USERSET, PGC_S_SESSION);
|
||||
|
||||
@ -290,7 +297,8 @@ timescaledb_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
|
||||
{
|
||||
/* Call any earlier hooks */
|
||||
rv = (prev_planner_hook) (parse, cursorOptions, boundParams);
|
||||
} else
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Call the standard planner */
|
||||
rv = standard_planner(parse, cursorOptions, boundParams);
|
||||
@ -342,14 +350,20 @@ get_hypertable_info(Oid mainRelationOid)
|
||||
bool isnull;
|
||||
int total_rows = SPI_processed;
|
||||
int j;
|
||||
/* do not populate list until SPI_finish because the list cannot be populated in the SPI memory context */
|
||||
|
||||
/*
|
||||
* do not populate list until SPI_finish because the list cannot be
|
||||
* populated in the SPI memory context
|
||||
*/
|
||||
List *partitioning_info_list;
|
||||
|
||||
/* used to track list stuff til list can be populated */
|
||||
partitioning_info **partitioning_info_array = SPI_palloc(total_rows * sizeof(partitioning_info *));
|
||||
hypertable_info *hinfo = SPI_palloc(sizeof(hypertable_info));
|
||||
|
||||
TupleDesc tupdesc = SPI_tuptable->tupdesc;
|
||||
HeapTuple tuple = SPI_tuptable->vals[0];
|
||||
|
||||
hinfo->replica_oid = DatumGetObjectId(SPI_getbinval(tuple, tupdesc, 1, &isnull));
|
||||
hinfo->root_oid = DatumGetObjectId(SPI_getbinval(tuple, tupdesc, 6, &isnull));
|
||||
hinfo->hypertable_id = DatumGetInt32(SPI_getbinval(tuple, tupdesc, 7, &isnull));
|
||||
@ -357,7 +371,9 @@ get_hypertable_info(Oid mainRelationOid)
|
||||
for (j = 0; j < total_rows; j++)
|
||||
{
|
||||
HeapTuple tuple = SPI_tuptable->vals[j];
|
||||
Name partitioning_func_schema, partitioning_func, partitioning_column;
|
||||
Name partitioning_func_schema,
|
||||
partitioning_func,
|
||||
partitioning_column;
|
||||
int32 partitioning_mod;
|
||||
|
||||
partitioning_info *info = (partitioning_info *) SPI_palloc(sizeof(partitioning_info));
|
||||
@ -366,28 +382,32 @@ get_hypertable_info(Oid mainRelationOid)
|
||||
|
||||
partitioning_column = DatumGetName(SPI_getbinval(tuple, tupdesc, 2, &isnull));
|
||||
|
||||
if (!isnull) {
|
||||
if (!isnull)
|
||||
{
|
||||
info->partitioning_column = SPI_palloc(sizeof(NameData));
|
||||
memcpy(info->partitioning_column, partitioning_column, sizeof(NameData));
|
||||
}
|
||||
|
||||
partitioning_func_schema = DatumGetName(SPI_getbinval(tuple, tupdesc, 3, &isnull));
|
||||
|
||||
if (!isnull) {
|
||||
if (!isnull)
|
||||
{
|
||||
info->partitioning_func_schema = SPI_palloc(sizeof(NameData));
|
||||
memcpy(info->partitioning_func_schema, partitioning_func_schema, sizeof(NameData));
|
||||
}
|
||||
|
||||
partitioning_func = DatumGetName(SPI_getbinval(tuple, tupdesc, 4, &isnull));
|
||||
|
||||
if (!isnull) {
|
||||
if (!isnull)
|
||||
{
|
||||
info->partitioning_func = SPI_palloc(sizeof(NameData));
|
||||
memcpy(info->partitioning_func, partitioning_func, sizeof(NameData));
|
||||
}
|
||||
|
||||
partitioning_mod = DatumGetInt32(SPI_getbinval(tuple, tupdesc, 5, &isnull));
|
||||
|
||||
if (!isnull) {
|
||||
if (!isnull)
|
||||
{
|
||||
info->partitioning_mod = partitioning_mod;
|
||||
}
|
||||
|
||||
@ -414,8 +434,11 @@ get_hypertable_info(Oid mainRelationOid)
|
||||
|
||||
|
||||
|
||||
char * copy_table_name(int32 hypertable_id) {
|
||||
char *
|
||||
copy_table_name(int32 hypertable_id)
|
||||
{
|
||||
StringInfo temp_table_name = makeStringInfo();
|
||||
|
||||
appendStringInfo(temp_table_name, "_copy_temp_%d", hypertable_id);
|
||||
return temp_table_name->data;
|
||||
}
|
||||
@ -436,6 +459,7 @@ static void
|
||||
add_partitioning_func_qual(Query *parse, List *hypertable_info_list)
|
||||
{
|
||||
add_partitioning_func_qual_context context;
|
||||
|
||||
context.parse = parse;
|
||||
context.hypertable_info_list = hypertable_info_list;
|
||||
parse->jointree->quals = add_partitioning_func_qual_mutator(parse->jointree->quals, &context);
|
||||
@ -447,10 +471,11 @@ add_partitioning_func_qual_mutator(Node *node, add_partitioning_func_qual_contex
|
||||
if (node == NULL)
|
||||
return NULL;
|
||||
|
||||
/* Detect partitioning_column = const. If not fall-thru.
|
||||
* If detected, replace with
|
||||
* partitioning_column = const AND
|
||||
* partitioning_func(partition_column, partitioning_mod) = partitioning_func(const, partitioning_mod)
|
||||
/*
|
||||
* Detect partitioning_column = const. If not fall-thru. If detected,
|
||||
* replace with partitioning_column = const AND
|
||||
* partitioning_func(partition_column, partitioning_mod) =
|
||||
* partitioning_func(const, partitioning_mod)
|
||||
*/
|
||||
if (IsA(node, OpExpr))
|
||||
{
|
||||
@ -458,7 +483,7 @@ add_partitioning_func_qual_mutator(Node *node, add_partitioning_func_qual_contex
|
||||
|
||||
if (list_length(exp->args) == 2)
|
||||
{
|
||||
//only look at var op const or const op var;
|
||||
/* only look at var op const or const op var; */
|
||||
Node *left = (Node *) linitial(exp->args);
|
||||
Node *right = (Node *) lsecond(exp->args);
|
||||
Var *var_expr = NULL;
|
||||
@ -468,7 +493,8 @@ add_partitioning_func_qual_mutator(Node *node, add_partitioning_func_qual_contex
|
||||
{
|
||||
var_expr = (Var *) left;
|
||||
other_expr = right;
|
||||
} else if (IsA(right, Var))
|
||||
}
|
||||
else if (IsA(right, Var))
|
||||
{
|
||||
var_expr = (Var *) right;
|
||||
other_expr = left;
|
||||
@ -489,14 +515,18 @@ add_partitioning_func_qual_mutator(Node *node, add_partitioning_func_qual_contex
|
||||
|
||||
if (eq_oid == exp->opno)
|
||||
{
|
||||
/* I now have a var = const. Make sure var is a partitioning column */
|
||||
/*
|
||||
* I now have a var = const. Make sure var is a
|
||||
* partitioning column
|
||||
*/
|
||||
partitioning_info *pi = get_partitioning_info_for_partition_column_var(var_expr,
|
||||
context->parse,
|
||||
context->hypertable_info_list);
|
||||
|
||||
if (pi != NULL
|
||||
&& pi->partitioning_column != NULL
|
||||
&& pi->partitioning_func != NULL) {
|
||||
&& pi->partitioning_func != NULL)
|
||||
{
|
||||
/* The var is a partitioning column */
|
||||
Expr *partitioning_clause = create_partition_func_equals_const(var_expr, const_expr,
|
||||
pi->partitioning_func_schema,
|
||||
@ -519,7 +549,8 @@ add_partitioning_func_qual_mutator(Node *node, add_partitioning_func_qual_contex
|
||||
/* Returns the partitioning info for a var if the var is a partitioning column. If the var is not a partitioning
|
||||
* column return NULL */
|
||||
static partitioning_info *
|
||||
get_partitioning_info_for_partition_column_var(Var *var_expr, Query *parse, List * hypertable_info_list) {
|
||||
get_partitioning_info_for_partition_column_var(Var *var_expr, Query *parse, List *hypertable_info_list)
|
||||
{
|
||||
RangeTblEntry *rte = rt_fetch(var_expr->varno, parse->rtable);
|
||||
char *varname = get_rte_attribute_name(rte, var_expr->varattno);
|
||||
ListCell *hicell;
|
||||
@ -527,12 +558,15 @@ get_partitioning_info_for_partition_column_var(Var *var_expr, Query *parse, List
|
||||
foreach(hicell, hypertable_info_list)
|
||||
{
|
||||
hypertable_info *info = lfirst(hicell);
|
||||
|
||||
if (rte->relid == info->replica_oid)
|
||||
{
|
||||
ListCell *picell;
|
||||
|
||||
foreach(picell, info->partitioning_info)
|
||||
{
|
||||
partitioning_info *pi = lfirst(picell);
|
||||
|
||||
if (pi->partitioning_column != NULL &&
|
||||
strcmp(NameStr(*(pi->partitioning_column)), varname) == 0)
|
||||
{
|
||||
@ -601,10 +635,14 @@ PG_FUNCTION_INFO_V1(register_dblink_precommit_connection);
|
||||
Datum
|
||||
register_dblink_precommit_connection(PG_FUNCTION_ARGS)
|
||||
{
|
||||
/* allocate this stuff in top-level transaction context, so that it survives till commit */
|
||||
/*
|
||||
* allocate this stuff in top-level transaction context, so that it
|
||||
* survives till commit
|
||||
*/
|
||||
MemoryContext old = MemoryContextSwitchTo(TopTransactionContext);
|
||||
|
||||
char *connectionName = text_to_cstring(PG_GETARG_TEXT_PP(0));
|
||||
|
||||
callbackConnections = lappend(callbackConnections, connectionName);
|
||||
|
||||
MemoryContextSwitchTo(old);
|
||||
@ -617,7 +655,8 @@ register_dblink_precommit_connection(PG_FUNCTION_ARGS)
|
||||
* Look at meta_commands.sql for example usage. Remote commits happen in pre-commit.
|
||||
* Remote aborts happen on abort.
|
||||
* */
|
||||
static void io_xact_callback(XactEvent event, void *arg)
|
||||
static void
|
||||
io_xact_callback(XactEvent event, void *arg)
|
||||
{
|
||||
ListCell *cell;
|
||||
|
||||
@ -631,6 +670,7 @@ static void io_xact_callback(XactEvent event, void *arg)
|
||||
foreach(cell, callbackConnections)
|
||||
{
|
||||
char *connection = (char *) lfirst(cell);
|
||||
|
||||
DirectFunctionCall3(dblink_exec,
|
||||
PointerGetDatum(cstring_to_text(connection)),
|
||||
PointerGetDatum(cstring_to_text("COMMIT")),
|
||||
@ -640,11 +680,16 @@ static void io_xact_callback(XactEvent event, void *arg)
|
||||
break;
|
||||
case XACT_EVENT_PARALLEL_ABORT:
|
||||
case XACT_EVENT_ABORT:
|
||||
/* Be quite careful here. Cannot throw any errors (or infinite loop) and cannot use PG_TRY either.
|
||||
* Make sure to test with c-asserts on. */
|
||||
|
||||
/*
|
||||
* Be quite careful here. Cannot throw any errors (or infinite
|
||||
* loop) and cannot use PG_TRY either. Make sure to test with
|
||||
* c-asserts on.
|
||||
*/
|
||||
foreach(cell, callbackConnections)
|
||||
{
|
||||
char *connection = (char *) lfirst(cell);
|
||||
|
||||
DirectFunctionCall3(dblink_exec,
|
||||
PointerGetDatum(cstring_to_text(connection)),
|
||||
PointerGetDatum(cstring_to_text("ABORT")),
|
||||
@ -720,14 +765,16 @@ prev_ProcessUtility(Node *parsetree,
|
||||
|
||||
/* Hook-intercept for ProcessUtility. Used to make COPY use a temp copy table and */
|
||||
/* blocking renaming of hypertables. */
|
||||
void timescaledb_ProcessUtility(Node *parsetree,
|
||||
void
|
||||
timescaledb_ProcessUtility(Node *parsetree,
|
||||
const char *queryString,
|
||||
ProcessUtilityContext context,
|
||||
ParamListInfo params,
|
||||
DestReceiver *dest,
|
||||
char *completionTag)
|
||||
{
|
||||
if (!IobeamLoaded()){
|
||||
if (!IobeamLoaded())
|
||||
{
|
||||
prev_ProcessUtility(parsetree, queryString, context, params, dest, completionTag);
|
||||
return;
|
||||
}
|
||||
@ -736,8 +783,11 @@ void timescaledb_ProcessUtility(Node *parsetree,
|
||||
{
|
||||
CopyStmt *copystmt = (CopyStmt *) parsetree;
|
||||
Oid relId = RangeVarGetRelid(copystmt->relation, NoLock, true);
|
||||
if (OidIsValid(relId)) {
|
||||
|
||||
if (OidIsValid(relId))
|
||||
{
|
||||
hypertable_info *hinfo = get_hypertable_info(relId);
|
||||
|
||||
if (hinfo != NULL)
|
||||
{
|
||||
copystmt->relation = makeRangeVarFromRelid(create_copy_table(hinfo->hypertable_id, hinfo->root_oid));
|
||||
@ -752,8 +802,11 @@ void timescaledb_ProcessUtility(Node *parsetree,
|
||||
{
|
||||
RenameStmt *renamestmt = (RenameStmt *) parsetree;
|
||||
Oid relId = RangeVarGetRelid(renamestmt->relation, NoLock, true);
|
||||
if (OidIsValid(relId)) {
|
||||
|
||||
if (OidIsValid(relId))
|
||||
{
|
||||
hypertable_info *hinfo = get_hypertable_info(relId);
|
||||
|
||||
if (hinfo != NULL && renamestmt->renameType == OBJECT_TABLE)
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
|
||||
|
Loading…
x
Reference in New Issue
Block a user