Skip to content

Commit

Permalink
Move functions to appropriate files
Browse files Browse the repository at this point in the history
  • Loading branch information
konskov committed Sep 13, 2023
1 parent ba8fdd5 commit 2a1259b
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 121 deletions.
9 changes: 9 additions & 0 deletions src/chunk.c
Original file line number Diff line number Diff line change
Expand Up @@ -4869,3 +4869,12 @@ ts_osm_chunk_range_is_invalid(Oid dimtype, int64 range_start, int64 range_end)
{
return ((range_end == PG_INT64_MAX) && (range_start == range_end - 1));
}

int32
ts_chunk_get_osm_slice_id(int32 chunk_id, int32 time_dim_id)
{
Chunk *chunk = ts_chunk_get_by_id(chunk_id, true);
const DimensionSlice *ds = ts_hypercube_get_slice_by_dimension_id(chunk->cube, time_dim_id);
const int slice_id = ds->fd.id;
return slice_id;
}
3 changes: 2 additions & 1 deletion src/chunk.h
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,8 @@ extern TSDLLEXPORT void ts_chunk_merge_on_dimension(const Hypertable *ht, Chunk
#define CHUNK_STATUS_COMPRESSED_PARTIAL 8

extern TSDLLEXPORT bool ts_chunk_clear_status(Chunk *chunk, int32 status);
extern TSDLLEXPORT bool ts_osm_chunk_range_is_invalid(Oid dimtype, int64 range_start,
extern bool ts_osm_chunk_range_is_invalid(Oid dimtype, int64 range_start,
int64 range_end);
extern int32 ts_chunk_get_osm_slice_id(int32 chunk_id, int32 time_dim_id);

#endif /* TIMESCALEDB_CHUNK_H */
123 changes: 3 additions & 120 deletions src/dimension_slice.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
#include "dimension_vector.h"
#include "hypertable.h"
#include "scanner.h"
#include "hypercube.h"

#include "compat/compat.h"

Expand Down Expand Up @@ -1154,7 +1153,7 @@ ts_dimension_slice_get_chunkids_to_compress(int32 dimension_id, StrategyNumber s
/* This function checks for overlap between the range we want to update
for the OSM chunk and the chunks currently in timescaledb (not managed by OSM)
*/
static bool
bool
ts_osm_chunk_range_overlaps(int32 osm_dimension_slice_id, int32 dimension_id, int64 range_start,
int64 range_end)
{
Expand Down Expand Up @@ -1203,8 +1202,8 @@ dimension_slice_tuple_update(TupleInfo *ti, void *data)
return SCAN_DONE;
}

static int
dimension_slice_update_by_id(int32 dimension_slice_id, FormData_dimension_slice *fd_slice)
int
ts_dimension_slice_update_by_id(int32 dimension_slice_id, FormData_dimension_slice *fd_slice)
{
ScanKeyData scankey[1];

Expand All @@ -1224,119 +1223,3 @@ dimension_slice_update_by_id(int32 dimension_slice_id, FormData_dimension_slice
NULL,
CurrentMemoryContext);
}

static int32
ts_chunk_get_osm_slice_id(int32 chunk_id, int32 time_dim_id)
{
Chunk *chunk = ts_chunk_get_by_id(chunk_id, true);
const DimensionSlice *ds = ts_hypercube_get_slice_by_dimension_id(chunk->cube, time_dim_id);
const int slice_id = ds->fd.id;
return slice_id;
}

/*
* hypertable_update_range_for_osm
* 0 hypertable REGCLASS,
* 1 range_start,
* 2 range_end,
* 3 empty=false
* If empty is set to true then the range will be set to invalid range
* but the overlap flag will be unset, indicating that no data is managed
* by OSM and therefore timescaledb optimizations can be applied.
*/
TS_FUNCTION_INFO_V1(ts_hypertable_update_range_for_osm);
Datum
ts_hypertable_update_range_for_osm(PG_FUNCTION_ARGS)
{
Oid relid = PG_ARGISNULL(0) ? InvalidOid : PG_GETARG_OID(0);
Hypertable *ht;
const Dimension *time_dim;
Cache *hcache;

Oid time_type; /* required for resolving the argument types, should match the hypertable
partitioning column type */

hcache = ts_hypertable_cache_pin();
ht = ts_resolve_hypertable_from_table_or_cagg(hcache, relid, true);
Assert(ht != NULL);
time_dim = hyperspace_get_open_dimension(ht->space, 0);

Ensure(time_dim != NULL,
"could not find time dimension for hypertable %s.%s",
quote_identifier(NameStr(ht->fd.schema_name)),
quote_identifier(NameStr(ht->fd.table_name)));

time_type = ts_dimension_get_partition_type(time_dim);

int32 osm_chunk_id = ts_chunk_get_osm_chunk_id(ht->fd.id);
if (osm_chunk_id == INVALID_CHUNK_ID)
elog(ERROR,
"no OSM chunk found for hypertable %s.%s",
quote_identifier(NameStr(ht->fd.schema_name)),
quote_identifier(NameStr(ht->fd.table_name)));

int32 dimension_slice_id = ts_chunk_get_osm_slice_id(osm_chunk_id, time_dim->fd.id);

/*
* range_start, range_end arguments must be converted to internal representation
* a NULL start value is interpreted as INT64_MAX - 1 and a NULL end value is
* interpreted as infinity.
* Passing both start and end NULL values will reset the range to the default range an
* OSM chunk is given upon creation, which is [INT64_MAX - 1, INT64_MAX]
*/
int64 range_start_internal, range_end_internal;
if (PG_ARGISNULL(1))
range_start_internal = PG_INT64_MAX - 1;
else
range_start_internal = ts_time_value_to_internal(PG_GETARG_DATUM(1), time_type);
if (PG_ARGISNULL(2))
range_end_internal = PG_INT64_MAX;
else
range_end_internal = ts_time_value_to_internal(PG_GETARG_DATUM(2), time_type);

if (range_start_internal > range_end_internal)
ereport(ERROR, errmsg("dimension slice range_end cannot be less than range_start"));

bool osm_chunk_empty = PG_GETARG_BOOL(3);

bool overlap = false, range_invalid = false;

ScanTupLock tuplock = {
.lockmode = LockTupleExclusive,
.waitpolicy = LockWaitBlock,
};
DimensionSlice *slice =
ts_dimension_slice_scan_by_id_and_lock(dimension_slice_id, &tuplock, CurrentMemoryContext);

if (!slice)
ereport(ERROR, errmsg("could not find slice with id %d", dimension_slice_id));
overlap = ts_osm_chunk_range_overlaps(dimension_slice_id,
slice->fd.dimension_id,
range_start_internal,
range_end_internal);
range_invalid =
ts_osm_chunk_range_is_invalid(time_type, range_start_internal, range_end_internal);
/* Update the hypertable flags regarding the validity of the OSM range */
if (overlap || range_invalid)
{
if (!osm_chunk_empty)
ht->fd.status = ts_set_flags_32(ht->fd.status, HYPERTABLE_STATUS_OSM_CHUNKS_OVERLAP);
else
{
/* range is also set to infinity so the OSM chunk is considered last */
range_start_internal = PG_INT64_MAX - 1;
range_end_internal = PG_INT64_MAX;
ht->fd.status = ts_clear_flags_32(ht->fd.status, HYPERTABLE_STATUS_OSM_CHUNKS_OVERLAP);
}
}
else
ht->fd.status = ts_clear_flags_32(ht->fd.status, HYPERTABLE_STATUS_OSM_CHUNKS_OVERLAP);
ts_hypertable_update(ht);
ts_cache_release(hcache);

slice->fd.range_start = range_start_internal;
slice->fd.range_end = range_end_internal;
dimension_slice_update_by_id(dimension_slice_id, &slice->fd);

PG_RETURN_BOOL(overlap);
}
6 changes: 6 additions & 0 deletions src/dimension_slice.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,12 @@ extern int ts_dimension_slice_scan_iterator_set_range(ScanIterator *it, int32 di
int64 start_value,
StrategyNumber end_strategy, int64 end_value);

extern bool ts_osm_chunk_range_overlaps(int32 osm_dimension_slice_id, int32 dimension_id,
int64 range_start, int64 range_end);

extern int ts_dimension_slice_update_by_id(int32 dimension_slice_id,
FormData_dimension_slice *fd_slice);

#define dimension_slice_insert(slice) ts_dimension_slice_insert_multi(&(slice), 1)

#define dimension_slice_scan(dimension_id, coordinate, tuplock) \
Expand Down
107 changes: 107 additions & 0 deletions src/hypertable.c
Original file line number Diff line number Diff line change
Expand Up @@ -3020,3 +3020,110 @@ ts_hypertable_update_dimension_partitions(const Hypertable *ht)

return false;
}

/*
* hypertable_update_range_for_osm
* 0 hypertable REGCLASS,
* 1 range_start,
* 2 range_end,
* 3 empty=false
* If empty is set to true then the range will be set to invalid range
* but the overlap flag will be unset, indicating that no data is managed
* by OSM and therefore timescaledb optimizations can be applied.
*/
TS_FUNCTION_INFO_V1(ts_hypertable_update_range_for_osm);
Datum
ts_hypertable_update_range_for_osm(PG_FUNCTION_ARGS)
{
Oid relid = PG_ARGISNULL(0) ? InvalidOid : PG_GETARG_OID(0);
Hypertable *ht;
const Dimension *time_dim;
Cache *hcache;

Oid time_type; /* required for resolving the argument types, should match the hypertable
partitioning column type */

hcache = ts_hypertable_cache_pin();
ht = ts_resolve_hypertable_from_table_or_cagg(hcache, relid, true);
Assert(ht != NULL);
time_dim = hyperspace_get_open_dimension(ht->space, 0);

Ensure(time_dim != NULL,
"could not find time dimension for hypertable %s.%s",
quote_identifier(NameStr(ht->fd.schema_name)),
quote_identifier(NameStr(ht->fd.table_name)));

time_type = ts_dimension_get_partition_type(time_dim);

int32 osm_chunk_id = ts_chunk_get_osm_chunk_id(ht->fd.id);
if (osm_chunk_id == INVALID_CHUNK_ID)
elog(ERROR,
"no OSM chunk found for hypertable %s.%s",
quote_identifier(NameStr(ht->fd.schema_name)),
quote_identifier(NameStr(ht->fd.table_name)));

int32 dimension_slice_id = ts_chunk_get_osm_slice_id(osm_chunk_id, time_dim->fd.id);

/*
* range_start, range_end arguments must be converted to internal representation
* a NULL start value is interpreted as INT64_MAX - 1 and a NULL end value is
* interpreted as infinity.
* Passing both start and end NULL values will reset the range to the default range an
* OSM chunk is given upon creation, which is [INT64_MAX - 1, INT64_MAX]
*/
int64 range_start_internal, range_end_internal;
if (PG_ARGISNULL(1))
range_start_internal = PG_INT64_MAX - 1;
else
range_start_internal = ts_time_value_to_internal(PG_GETARG_DATUM(1), time_type);
if (PG_ARGISNULL(2))
range_end_internal = PG_INT64_MAX;
else
range_end_internal = ts_time_value_to_internal(PG_GETARG_DATUM(2), time_type);

if (range_start_internal > range_end_internal)
ereport(ERROR, errmsg("dimension slice range_end cannot be less than range_start"));

bool osm_chunk_empty = PG_GETARG_BOOL(3);

bool overlap = false, range_invalid = false;

ScanTupLock tuplock = {
.lockmode = LockTupleExclusive,
.waitpolicy = LockWaitBlock,
};
DimensionSlice *slice =
ts_dimension_slice_scan_by_id_and_lock(dimension_slice_id, &tuplock, CurrentMemoryContext);

if (!slice)
ereport(ERROR, errmsg("could not find slice with id %d", dimension_slice_id));
overlap = ts_osm_chunk_range_overlaps(dimension_slice_id,
slice->fd.dimension_id,
range_start_internal,
range_end_internal);
range_invalid =
ts_osm_chunk_range_is_invalid(time_type, range_start_internal, range_end_internal);
/* Update the hypertable flags regarding the validity of the OSM range */
if (overlap || range_invalid)
{
if (!osm_chunk_empty)
ht->fd.status = ts_set_flags_32(ht->fd.status, HYPERTABLE_STATUS_OSM_CHUNKS_OVERLAP);
else
{
/* range is also set to infinity so the OSM chunk is considered last */
range_start_internal = PG_INT64_MAX - 1;
range_end_internal = PG_INT64_MAX;
ht->fd.status = ts_clear_flags_32(ht->fd.status, HYPERTABLE_STATUS_OSM_CHUNKS_OVERLAP);
}
}
else
ht->fd.status = ts_clear_flags_32(ht->fd.status, HYPERTABLE_STATUS_OSM_CHUNKS_OVERLAP);
ts_hypertable_update(ht);
ts_cache_release(hcache);

slice->fd.range_start = range_start_internal;
slice->fd.range_end = range_end_internal;
ts_dimension_slice_update_by_id(dimension_slice_id, &slice->fd);

PG_RETURN_BOOL(overlap);
}

0 comments on commit 2a1259b

Please sign in to comment.