Skip to content

Commit

Permalink
add device only function for text->int* cast
Browse files Browse the repository at this point in the history
  • Loading branch information
kaigai committed Jan 27, 2025
1 parent 58d07c4 commit eb5dee9
Show file tree
Hide file tree
Showing 3 changed files with 169 additions and 24 deletions.
123 changes: 99 additions & 24 deletions src/codegen.c
Original file line number Diff line number Diff line change
Expand Up @@ -2076,9 +2076,9 @@ codegen_booleantest_expression(codegen_context *context,
* So, we add a special optimization for the numeric jsonb key references.
*/
static int
codegen_coerceviaio_expression(codegen_context *context,
StringInfo buf, int curr_depth,
CoerceViaIO *cvio)
__codegen_coerceviaio_jsonbref_expression(codegen_context *context,
StringInfo buf, int curr_depth,
CoerceViaIO *cvio)
{
static struct {
Oid func_oid;
Expand Down Expand Up @@ -2141,7 +2141,6 @@ codegen_coerceviaio_expression(codegen_context *context,
Oid func_oid = InvalidOid;
List *func_args = NIL;
devtype_info *dtype;
kern_expression kexp;

/* check special case if jsonb key reference */
if (IsA(cvio->arg, FuncExpr))
Expand All @@ -2158,30 +2157,31 @@ codegen_coerceviaio_expression(codegen_context *context,
func_oid = get_opcode(op->opno);
func_args = op->args;
}
if (func_oid == F_JSONB_OBJECT_FIELD_TEXT)
{
/* sanity checks */
if (list_length(func_args) != 2 ||
exprType(linitial(func_args)) != JSONBOID ||
exprType(lsecond(func_args)) != TEXTOID)
__Elog("Not expected arguments of %s", format_procedure(func_oid));
}
else if (func_oid == F_JSONB_ARRAY_ELEMENT_TEXT)
else
return -1;

switch (func_oid)
{
/* sanity checks */
if (list_length(func_args) != 2 ||
exprType(linitial(func_args)) != JSONBOID ||
exprType(lsecond(func_args)) != INT4OID)
__Elog("Not expected arguments of %s", format_procedure(func_oid));
case F_JSONB_OBJECT_FIELD_TEXT:
if (list_length(func_args) == 2 &&
exprType(linitial(func_args)) == JSONBOID &&
exprType(lsecond(func_args)) == TEXTOID)
break;
return -1;
case F_JSONB_ARRAY_ELEMENT_TEXT:
if (list_length(func_args) == 2 &&
exprType(linitial(func_args)) == JSONBOID &&
exprType(lsecond(func_args)) == INT4OID)
break;
return -1;
default:
return -1;
}
else
__Elog("Not a supported CoerceViaIO: %s", nodeToString(cvio));

dtype = pgstrom_devtype_lookup(cvio->resulttype);
if (!dtype)
__Elog("Not a supported CoerceViaIO: %s", nodeToString(cvio));
return -1;

memset(&kexp, 0, sizeof(kexp));
for (int i=0; jsonref_catalog[i].type_name != NULL; i++)
{
if (func_oid == jsonref_catalog[i].func_oid &&
Expand All @@ -2192,11 +2192,13 @@ codegen_coerceviaio_expression(codegen_context *context,
: (dtype->type_extension == NULL &&
dtype->type_namespace == PG_CATALOG_NAMESPACE)))
{
ListCell *lc;
kern_expression kexp;
uint32_t stack_usage_saved = context->stack_usage;
uint32_t stack_usage_max = stack_usage_saved;
ListCell *lc;
int pos = -1;

memset(&kexp, 0, sizeof(kexp));
kexp.opcode = jsonref_catalog[i].opcode;
kexp.exptype = dtype->type_code;
kexp.expflags = context->kexp_flags;
Expand All @@ -2209,7 +2211,11 @@ codegen_coerceviaio_expression(codegen_context *context,
Expr *arg = lfirst(lc);

if (codegen_expression_walker(context, buf, curr_depth, arg) < 0)
{
if (buf)
buf->len = pos;
return -1;
}
stack_usage_max = Max(stack_usage_max, context->stack_usage);
context->stack_usage = stack_usage_saved;
}
Expand All @@ -2219,10 +2225,79 @@ codegen_coerceviaio_expression(codegen_context *context,
return 0;
}
}
__Elog("Not a supported CoerceViaIO: %s", nodeToString(cvio));
return -1;
}

static int
codegen_coerceviaio_expression(codegen_context *context,
StringInfo buf, int curr_depth,
CoerceViaIO *cvio)
{
static struct
{
FuncOpCode opcode;
const char *source_name;
const char *source_extension;
const char *dest_name;
const char *dest_extension;
} coerce_viaio_catalog[] = {
{FuncOpCode__devcast_text_to_int1, "text", NULL, "int1", "pg_strom"},
{FuncOpCode__devcast_text_to_int2, "text", NULL, "int2", NULL},
{FuncOpCode__devcast_text_to_int4, "text", NULL, "int4", NULL},
{FuncOpCode__devcast_text_to_int8, "text", NULL, "int8", NULL},
{FuncOpCode__Invalid, NULL, NULL, NULL, NULL},
};
devtype_info *stype;
devtype_info *dtype;

if (__codegen_coerceviaio_jsonbref_expression(context, buf,
curr_depth,
cvio) == 0)
return 0; /* OK, cvio is JSONB field reference */

dtype = pgstrom_devtype_lookup(cvio->resulttype);
if (!dtype)
__Elog("Not a supported CoerceViaIO: %s", nodeToString(cvio));
stype = pgstrom_devtype_lookup(exprType((Node *)cvio->arg));
if (!stype)
__Elog("Not a supported CoerceViaIO: %s", nodeToString(cvio));

for (int i=0; coerce_viaio_catalog[i].opcode != FuncOpCode__Invalid; i++)
{
if (strcmp(coerce_viaio_catalog[i].source_name, stype->type_name) == 0 &&
((coerce_viaio_catalog[i].source_extension != NULL &&
stype->type_extension != NULL &&
strcmp(coerce_viaio_catalog[i].source_extension,
stype->type_extension) == 0) ||
(!coerce_viaio_catalog[i].source_extension && !stype->type_extension)) &&
strcmp(coerce_viaio_catalog[i].dest_name, dtype->type_name) == 0 &&
((coerce_viaio_catalog[i].dest_extension != NULL &&
dtype->type_extension != NULL &&
strcmp(coerce_viaio_catalog[i].dest_extension,
dtype->type_extension) == 0) ||
(!coerce_viaio_catalog[i].dest_extension && !dtype->type_extension)))
{
kern_expression kexp;
int pos = -1;

memset(&kexp, 0, sizeof(kexp));
kexp.opcode = coerce_viaio_catalog[i].opcode;
kexp.exptype = dtype->type_code;
kexp.expflags = context->kexp_flags;
kexp.nr_args = 1;
kexp.args_offset = SizeOfKernExpr(0);
if (buf)
pos = __appendBinaryStringInfo(buf, &kexp, SizeOfKernExpr(0));
if (codegen_expression_walker(context, buf, curr_depth, cvio->arg) < 0)
return -1;
if (buf)
__appendKernExpMagicAndLength(buf, pos);
return 0;
}
}
__Elog("Not a supported CoerceViaIO: %s", nodeToString(cvio));
}

/*
* codegen_coalesce_expression
*/
Expand Down
60 changes: 60 additions & 0 deletions src/xpu_basetype.cu
Original file line number Diff line number Diff line change
Expand Up @@ -864,3 +864,63 @@ PG_BITWISE_OPERATOR_TEMPLATE(int1shl,int1,int1,int4,<<)
PG_BITWISE_OPERATOR_TEMPLATE(int2shl,int2,int2,int4,<<)
PG_BITWISE_OPERATOR_TEMPLATE(int4shl,int4,int4,int4,<<)
PG_BITWISE_OPERATOR_TEMPLATE(int8shl,int8,int8,int4,<<)

/*
* Device only type cast functions instead of CoerceViaIO
*/
#define PG_DEVCAST_TEXT_TO_INT_TEMPLATE(XTYPE,BTYPE,__MIN,__MAX) \
PUBLIC_FUNCTION(bool) \
pgfn_devcast_text_to_##XTYPE(XPU_PGFUNCTION_ARGS) \
{ \
KEXP_PROCESS_ARGS1(XTYPE,text,arg); \
\
if (XPU_DATUM_ISNULL(&arg)) \
result->expr_ops = NULL; \
else if (!xpu_text_is_valid(kcxt, &arg)) \
return false; \
else \
{ \
const char *str = arg.value; \
int len = arg.length; \
BTYPE ival = 0; \
bool negative = false; \
\
if (*str == '-') \
{ \
str++; \
len--; \
negative = true; \
} \
while (len-- > 0) \
{ \
int c = *str++; \
\
if (c < '0' || c > '9') \
{ \
STROM_ELOG(kcxt, "invalid input for int1"); \
return false; \
} \
if (ival > (__MAX/10) || \
(ival == (__MAX/10) && c > (negative ? '8' : '7'))) \
{ \
STROM_ELOG(kcxt, #XTYPE ": out of range"); \
return false; \
} \
ival = 10 * ival + (c - '0'); \
} \
if (negative) \
ival = -ival; \
assert(ival >= __MIN && ival <= __MAX); \
result->expr_ops = &xpu_##XTYPE##_ops; \
result->value = ival; \
} \
return true; \
}
PG_DEVCAST_TEXT_TO_INT_TEMPLATE(int1,int32_t,SCHAR_MIN,SCHAR_MAX)
PG_DEVCAST_TEXT_TO_INT_TEMPLATE(int2,int32_t,SHRT_MIN,SHRT_MAX)
PG_DEVCAST_TEXT_TO_INT_TEMPLATE(int4,int32_t,INT_MIN,INT_MAX)
PG_DEVCAST_TEXT_TO_INT_TEMPLATE(int8,int64_t,LONG_MIN,LONG_MAX)

//DEVONLY_FUNC_OPCODE(float2, devcast_text_to_float2, text, DEVKIND__ANY, 12)
//DEVONLY_FUNC_OPCODE(float4, devcast_text_to_float4, text, DEVKIND__ANY, 12)
//DEVONLY_FUNC_OPCODE(float8, devcast_text_to_float8, text, DEVKIND__ANY, 12)
10 changes: 10 additions & 0 deletions src/xpu_opcodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,16 @@ FUNC_OPCODE(float8, int8, DEVKIND__ANY, int8_to_float8, 1, NULL)
FUNC_OPCODE(float8, float2, DEVKIND__ANY, float2_to_float8, 1, "pg_strom")
FUNC_OPCODE(float8, float4, DEVKIND__ANY, float4_to_float8, 1, NULL)

/* device only functions instead of CoerceViaIO */
DEVONLY_FUNC_OPCODE(int1, devcast_text_to_int1, text, DEVKIND__ANY, 10)
DEVONLY_FUNC_OPCODE(int2, devcast_text_to_int2, text, DEVKIND__ANY, 10)
DEVONLY_FUNC_OPCODE(int4, devcast_text_to_int4, text, DEVKIND__ANY, 10)
DEVONLY_FUNC_OPCODE(int8, devcast_text_to_int8, text, DEVKIND__ANY, 10)
//DEVONLY_FUNC_OPCODE(float2, devcast_text_to_float2, text, DEVKIND__ANY, 12)
//DEVONLY_FUNC_OPCODE(float4, devcast_text_to_float4, text, DEVKIND__ANY, 12)
//DEVONLY_FUNC_OPCODE(float8, devcast_text_to_float8, text, DEVKIND__ANY, 12)
//DEVONLY_FUNC_OPCODE(numeric, devcast_text_to_numeric, text, DEVKIND__ANY, 15)

/* '+' : add operators */
__FUNC_OPCODE(int1pl, int1/int1, 1, "pg_strom")
__FUNC_OPCODE(int12pl, int1/int2, 1, "pg_strom")
Expand Down

0 comments on commit eb5dee9

Please sign in to comment.