Skip to content

Commit 46ad159

Browse files
committed
Refactor Postgres type string output code
Often we need to get the output string representation of a given value for certain Postgres type doing something like this: bool isvarlena; Oid outfuncid; getTypeOutputInfo(type, &outfuncid, &isvarlena); Assert(OidIsValid(outfuncid)); valstr = OidOutputFunctionCall(outfuncid, datum); So encapsulated this pattern into a new accessor function `ts_datum_to_string` and also use the `ts_internal_to_time_string` when necessary instead of repeat a lot of code.
1 parent e054291 commit 46ad159

15 files changed

Lines changed: 83 additions & 181 deletions

File tree

src/chunk.c

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1015,24 +1015,17 @@ chunk_create_from_hypercube_after_lock(const Hypertable *ht, Hypercube *cube,
10151015

10161016
if (chunk_exists)
10171017
{
1018-
Oid outfuncid = InvalidOid;
1019-
bool isvarlena;
1020-
1021-
Datum start_ts =
1022-
ts_internal_to_time_value(cube->slices[0]->fd.range_start, dim->fd.column_type);
1023-
Datum end_ts =
1024-
ts_internal_to_time_value(cube->slices[0]->fd.range_end, dim->fd.column_type);
1025-
getTypeOutputInfo(dim->fd.column_type, &outfuncid, &isvarlena);
1026-
Assert(!isvarlena);
10271018
ereport(ERROR,
10281019
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
10291020
errmsg("Cannot insert into tiered chunk range of %s.%s - attempt to create "
10301021
"new chunk "
10311022
"with range [%s %s] failed",
10321023
NameStr(ht->fd.schema_name),
10331024
NameStr(ht->fd.table_name),
1034-
DatumGetCString(OidFunctionCall1(outfuncid, start_ts)),
1035-
DatumGetCString(OidFunctionCall1(outfuncid, end_ts))),
1025+
ts_internal_to_time_string(cube->slices[0]->fd.range_start,
1026+
dim->fd.column_type),
1027+
ts_internal_to_time_string(cube->slices[0]->fd.range_end,
1028+
dim->fd.column_type)),
10361029
errhint(
10371030
"Hypertable has tiered data with time range that overlaps the insert")));
10381031
}

src/chunk_constraint.c

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -278,12 +278,10 @@ ts_chunk_constraint_dimensional_create(const Dimension *dim, const DimensionSlic
278278
const char *name)
279279
{
280280
Constraint *constr = NULL;
281-
bool isvarlena;
282281
Node *dimdef;
283282
ColumnRef *colref;
284-
Datum startdat, enddat;
285283
List *compexprs = NIL;
286-
Oid outfuncid;
284+
Oid type;
287285

288286
if (slice->fd.range_start == PG_INT64_MIN && slice->fd.range_end == PG_INT64_MAX)
289287
return NULL;
@@ -308,16 +306,12 @@ ts_chunk_constraint_dimensional_create(const Dimension *dim, const DimensionSlic
308306
/* The dimension has a time function to compute the time value so
309307
* need to convert the range values to the time type returned by
310308
* the partitioning function. */
311-
getTypeOutputInfo(partinfo->partfunc.rettype, &outfuncid, &isvarlena);
312-
startdat = ts_internal_to_time_value(slice->fd.range_start, partinfo->partfunc.rettype);
313-
enddat = ts_internal_to_time_value(slice->fd.range_end, partinfo->partfunc.rettype);
309+
type = partinfo->partfunc.rettype;
314310
}
315311
else
316312
{
317-
/* Closed dimension, just use the integer output function */
318-
getTypeOutputInfo(INT8OID, &outfuncid, &isvarlena);
319-
startdat = Int64GetDatum(slice->fd.range_start);
320-
enddat = Int64GetDatum(slice->fd.range_end);
313+
/* Closed dimension, just use the INT8 type */
314+
type = INT8OID;
321315
}
322316
}
323317
else
@@ -326,28 +320,24 @@ ts_chunk_constraint_dimensional_create(const Dimension *dim, const DimensionSlic
326320
Assert(IS_OPEN_DIMENSION(dim));
327321

328322
dimdef = (Node *) colref;
329-
getTypeOutputInfo(dim->fd.column_type, &outfuncid, &isvarlena);
330-
startdat = ts_internal_to_time_value(slice->fd.range_start, dim->fd.column_type);
331-
enddat = ts_internal_to_time_value(slice->fd.range_end, dim->fd.column_type);
323+
type = dim->fd.column_type;
332324
}
333325

334326
/*
335-
* Convert internal format datums to string (output) datums.
336-
*
337327
* We are forcing ISO datestyle here to prevent parsing errors with
338328
* certain timezone/datestyle combinations.
339329
*/
340330
int current_datestyle = DateStyle;
341331
DateStyle = USE_ISO_DATES;
342-
startdat = OidFunctionCall1(outfuncid, startdat);
343-
enddat = OidFunctionCall1(outfuncid, enddat);
332+
char *start_str = ts_internal_to_time_string(slice->fd.range_start, type);
333+
char *end_str = ts_internal_to_time_string(slice->fd.range_end, type);
344334
DateStyle = current_datestyle;
345335

346336
/* Elide range constraint for +INF or -INF */
347337
if (slice->fd.range_start != PG_INT64_MIN)
348338
{
349339
A_Const *start_const = makeNode(A_Const);
350-
memcpy(&start_const->val, makeString(DatumGetCString(startdat)), sizeof(start_const->val));
340+
memcpy(&start_const->val, makeString(start_str), sizeof(start_const->val));
351341
start_const->location = -1;
352342
A_Expr *ge_expr = makeSimpleA_Expr(AEXPR_OP, ">=", dimdef, (Node *) start_const, -1);
353343
compexprs = lappend(compexprs, ge_expr);
@@ -356,7 +346,7 @@ ts_chunk_constraint_dimensional_create(const Dimension *dim, const DimensionSlic
356346
if (slice->fd.range_end != PG_INT64_MAX)
357347
{
358348
A_Const *end_const = makeNode(A_Const);
359-
memcpy(&end_const->val, makeString(DatumGetCString(enddat)), sizeof(end_const->val));
349+
memcpy(&end_const->val, makeString(end_str), sizeof(end_const->val));
360350
end_const->location = -1;
361351
A_Expr *lt_expr = makeSimpleA_Expr(AEXPR_OP, "<", dimdef, (Node *) end_const, -1);
362352
compexprs = lappend(compexprs, lt_expr);

src/chunk_tuple_routing.c

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -100,23 +100,17 @@ ts_chunk_tuple_routing_find_chunk(ChunkTupleRouting *ctr, Point *point)
100100
const Dimension *time_dim = hyperspace_get_open_dimension(ctr->hypertable->space, 0);
101101
Assert(time_dim != NULL);
102102

103-
Oid outfuncid = InvalidOid;
104-
bool isvarlena;
105-
getTypeOutputInfo(time_dim->fd.column_type, &outfuncid, &isvarlena);
106-
Assert(!isvarlena);
107-
Datum start_ts = ts_internal_to_time_value(chunk->cube->slices[0]->fd.range_start,
108-
time_dim->fd.column_type);
109-
Datum end_ts = ts_internal_to_time_value(chunk->cube->slices[0]->fd.range_end,
110-
time_dim->fd.column_type);
111103
ereport(ERROR,
112104
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
113105
errmsg("Cannot insert into tiered chunk range of %s.%s - attempt to create "
114106
"new chunk "
115107
"with range [%s %s] failed",
116108
NameStr(ctr->hypertable->fd.schema_name),
117109
NameStr(ctr->hypertable->fd.table_name),
118-
DatumGetCString(OidFunctionCall1(outfuncid, start_ts)),
119-
DatumGetCString(OidFunctionCall1(outfuncid, end_ts))),
110+
ts_internal_to_time_string(chunk->cube->slices[0]->fd.range_start,
111+
time_dim->fd.column_type),
112+
ts_internal_to_time_string(chunk->cube->slices[0]->fd.range_end,
113+
time_dim->fd.column_type)),
120114
errhint(
121115
"Hypertable has tiered data with time range that overlaps the insert")));
122116
}

src/dimension.c

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1714,11 +1714,7 @@ ts_dimension_info_out(PG_FUNCTION_ARGS)
17141714

17151715
if (OidIsValid(info->interval_type))
17161716
{
1717-
bool isvarlena;
1718-
Oid outfuncid;
1719-
getTypeOutputInfo(info->interval_type, &outfuncid, &isvarlena);
1720-
Assert(OidIsValid(outfuncid));
1721-
argvalstr = OidOutputFunctionCall(outfuncid, info->interval_datum);
1717+
argvalstr = ts_datum_to_string(info->interval_datum, info->interval_type);
17221718
}
17231719

17241720
appendStringInfo(&str,

src/jsonb_utils.c

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "compat/compat.h"
1515
#include "export.h"
1616
#include "jsonb_utils.h"
17+
#include "utils.h"
1718

1819
static void ts_jsonb_add_pair(JsonbParseState *state, JsonbValue *key, JsonbValue *value);
1920

@@ -75,27 +76,24 @@ ts_jsonb_set_value_by_type(JsonbValue *value, Oid typeid, Datum datum)
7576
{
7677
switch (typeid)
7778
{
78-
Oid typeOut;
79-
bool isvarlena;
80-
char *str;
81-
PGFunction func;
82-
8379
case INT2OID:
8480
case INT4OID:
8581
case INT8OID:
8682
case NUMERICOID:
87-
func = get_convert_func(typeid);
83+
{
84+
PGFunction func = get_convert_func(typeid);
8885
value->type = jbvNumeric;
8986
value->val.numeric = DatumGetNumeric(func ? DirectFunctionCall1(func, datum) : datum);
9087
break;
91-
88+
}
9289
default:
93-
getTypeOutputInfo(typeid, &typeOut, &isvarlena);
94-
str = OidOutputFunctionCall(typeOut, datum);
90+
{
91+
char *str = ts_datum_to_string(datum, typeid);
9592
value->type = jbvString;
9693
value->val.string.val = str;
9794
value->val.string.len = strlen(str);
9895
break;
96+
}
9997
}
10098
}
10199

src/nodes/chunk_dispatch/chunk_dispatch.c

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -105,23 +105,17 @@ ts_chunk_dispatch_get_chunk_insert_state(ChunkDispatch *dispatch, Point *point,
105105
hyperspace_get_open_dimension(dispatch->hypertable->space, 0);
106106
Assert(time_dim != NULL);
107107

108-
Oid outfuncid = InvalidOid;
109-
bool isvarlena;
110-
getTypeOutputInfo(time_dim->fd.column_type, &outfuncid, &isvarlena);
111-
Assert(!isvarlena);
112-
Datum start_ts = ts_internal_to_time_value(chunk->cube->slices[0]->fd.range_start,
113-
time_dim->fd.column_type);
114-
Datum end_ts = ts_internal_to_time_value(chunk->cube->slices[0]->fd.range_end,
115-
time_dim->fd.column_type);
116108
ereport(ERROR,
117109
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
118110
errmsg("Cannot insert into tiered chunk range of %s.%s - attempt to create "
119111
"new chunk "
120112
"with range [%s %s] failed",
121113
NameStr(dispatch->hypertable->fd.schema_name),
122114
NameStr(dispatch->hypertable->fd.table_name),
123-
DatumGetCString(OidFunctionCall1(outfuncid, start_ts)),
124-
DatumGetCString(OidFunctionCall1(outfuncid, end_ts))),
115+
ts_internal_to_time_string(chunk->cube->slices[0]->fd.range_start,
116+
time_dim->fd.column_type),
117+
ts_internal_to_time_string(chunk->cube->slices[0]->fd.range_end,
118+
time_dim->fd.column_type)),
125119
errhint(
126120
"Hypertable has tiered data with time range that overlaps the insert")));
127121
}

src/ts_catalog/chunk_column_stats.c

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -547,12 +547,9 @@ create_col_stats_check_constraint(const Form_chunk_column_stats info, Oid main_t
547547
Oid chunk_relid, const char *name)
548548
{
549549
Constraint *constr = NULL;
550-
bool isvarlena;
551550
Node *rangedef;
552551
ColumnRef *colref;
553-
Datum startdat, enddat;
554552
List *compexprs = NIL;
555-
Oid outfuncid;
556553
Oid col_type;
557554
int attno;
558555

@@ -564,8 +561,8 @@ create_col_stats_check_constraint(const Form_chunk_column_stats info, Oid main_t
564561
colref->location = -1;
565562

566563
/*
567-
* Convert the ranges to the appropriate text/string representation for the
568-
* specific type. But first get this column type.
564+
* Get the column type for later converting the internal format
565+
* to string.
569566
*
570567
* Get the attribute number in the HT for this column, and map to the chunk
571568
*/
@@ -574,19 +571,14 @@ create_col_stats_check_constraint(const Form_chunk_column_stats info, Oid main_t
574571
col_type = get_atttype(main_table_relid, attno);
575572

576573
rangedef = (Node *) colref;
577-
getTypeOutputInfo(col_type, &outfuncid, &isvarlena);
578-
startdat = ts_internal_to_time_value(info->range_start, col_type);
579-
enddat = ts_internal_to_time_value(info->range_end, col_type);
580-
581-
/* Convert internal format datums to string (output) datums */
582-
startdat = OidFunctionCall1(outfuncid, startdat);
583-
enddat = OidFunctionCall1(outfuncid, enddat);
584574

585575
/* Elide range constraint for +INF or -INF */
586576
if (info->range_start != PG_INT64_MIN)
587577
{
588578
A_Const *start_const = makeNode(A_Const);
589-
memcpy(&start_const->val, makeString(DatumGetCString(startdat)), sizeof(start_const->val));
579+
memcpy(&start_const->val,
580+
makeString(ts_internal_to_time_string(info->range_start, col_type)),
581+
sizeof(start_const->val));
590582
start_const->location = -1;
591583
A_Expr *ge_expr = makeSimpleA_Expr(AEXPR_OP, ">=", rangedef, (Node *) start_const, -1);
592584
compexprs = lappend(compexprs, ge_expr);
@@ -595,7 +587,9 @@ create_col_stats_check_constraint(const Form_chunk_column_stats info, Oid main_t
595587
if (info->range_end != PG_INT64_MAX)
596588
{
597589
A_Const *end_const = makeNode(A_Const);
598-
memcpy(&end_const->val, makeString(DatumGetCString(enddat)), sizeof(end_const->val));
590+
memcpy(&end_const->val,
591+
makeString(ts_internal_to_time_string(info->range_end, col_type)),
592+
sizeof(end_const->val));
599593
end_const->location = -1;
600594
A_Expr *lt_expr = makeSimpleA_Expr(AEXPR_OP, "<", rangedef, (Node *) end_const, -1);
601595
compexprs = lappend(compexprs, lt_expr);

src/utils.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -381,16 +381,23 @@ ts_internal_to_time_int64(int64 value, Oid type)
381381
}
382382

383383
TSDLLEXPORT char *
384-
ts_internal_to_time_string(int64 value, Oid type)
384+
ts_datum_to_string(Datum value, Oid type)
385385
{
386-
Datum time_datum = ts_internal_to_time_value(value, type);
387386
Oid typoutputfunc;
388387
bool typIsVarlena;
389388
FmgrInfo typoutputinfo;
390389

391390
getTypeOutputInfo(type, &typoutputfunc, &typIsVarlena);
392391
fmgr_info(typoutputfunc, &typoutputinfo);
393-
return OutputFunctionCall(&typoutputinfo, time_datum);
392+
return OutputFunctionCall(&typoutputinfo, value);
393+
}
394+
395+
TSDLLEXPORT char *
396+
ts_internal_to_time_string(int64 value, Oid type)
397+
{
398+
Datum time_datum = ts_internal_to_time_value(value, type);
399+
400+
return ts_datum_to_string(time_datum, type);
394401
}
395402

396403
TS_FUNCTION_INFO_V1(ts_pg_unix_microseconds_to_interval);

src/utils.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ extern TSDLLEXPORT int64 ts_interval_value_to_internal(Datum time_val, Oid type_
146146
extern TSDLLEXPORT Datum ts_internal_to_time_value(int64 value, Oid type);
147147
extern TSDLLEXPORT int64 ts_internal_to_time_int64(int64 value, Oid type);
148148
extern TSDLLEXPORT Datum ts_internal_to_interval_value(int64 value, Oid type);
149+
extern TSDLLEXPORT char *ts_datum_to_string(Datum value, Oid type);
149150
extern TSDLLEXPORT char *ts_internal_to_time_string(int64 value, Oid type);
150151

151152
/*

src/with_clause/with_clause_parser.c

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -120,17 +120,11 @@ ts_with_clauses_parse(const List *def_elems, const WithClauseDefinition *args, S
120120
extern TSDLLEXPORT char *
121121
ts_with_clause_result_deparse_value(const WithClauseResult *result)
122122
{
123-
Oid oid = result->definition->type_id;
124-
Ensure(OidIsValid(oid), "argument \"%d\" has invalid OID", oid);
123+
Ensure(OidIsValid(result->definition->type_id),
124+
"argument \"%d\" has invalid OID",
125+
result->definition->type_id);
125126

126-
Oid in_fn;
127-
bool typIsVarlena pg_attribute_unused();
128-
129-
getTypeOutputInfo(oid, &in_fn, &typIsVarlena);
130-
Ensure(OidIsValid(in_fn), "no output function for type with OID %d", oid);
131-
132-
char *val = OidOutputFunctionCall(in_fn, result->parsed);
133-
return val;
127+
return ts_datum_to_string(result->parsed, result->definition->type_id);
134128
}
135129

136130
static Datum

0 commit comments

Comments
 (0)