Skip to content
This repository was archived by the owner on May 9, 2024. It is now read-only.

Commit 88f570b

Browse files
ienkovichkurapov-peter
authored andcommitted
Support POWER in query builder.
Signed-off-by: ienkovich <[email protected]>
1 parent 32ea192 commit 88f570b

File tree

6 files changed

+90
-0
lines changed

6 files changed

+90
-0
lines changed

omniscidb/QueryBuilder/QueryBuilder.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1153,6 +1153,36 @@ BuilderExpr BuilderExpr::floor() const {
11531153
<< expr_->type()->toString();
11541154
}
11551155

1156+
BuilderExpr BuilderExpr::pow(const BuilderExpr& rhs) const {
1157+
if (!expr_->type()->isNumber() || !rhs.type()->isNumber()) {
1158+
throw InvalidQueryError() << "Cannot apply POW operation for operand types: "
1159+
<< type()->toString() << " and " << rhs.type()->toString();
1160+
}
1161+
ExprPtrVector args;
1162+
args.push_back(cast(ctx().fp64(type()->nullable())).expr());
1163+
args.push_back(rhs.cast(ctx().fp64(rhs.type()->nullable())).expr());
1164+
auto res_type = ctx().fp64(type()->nullable() || rhs.type()->nullable());
1165+
auto pow_expr =
1166+
hdk::ir::makeExpr<hdk::ir::FunctionOper>(res_type, "POWER", std::move(args));
1167+
return {builder_, pow_expr, "", true};
1168+
}
1169+
1170+
BuilderExpr BuilderExpr::pow(int val) const {
1171+
return pow(builder_->cst(val, builder_->ctx_.int32(false)));
1172+
}
1173+
1174+
BuilderExpr BuilderExpr::pow(int64_t val) const {
1175+
return pow(builder_->cst(val, builder_->ctx_.int64(false)));
1176+
}
1177+
1178+
BuilderExpr BuilderExpr::pow(float val) const {
1179+
return pow(builder_->cst(val, builder_->ctx_.fp32(false)));
1180+
}
1181+
1182+
BuilderExpr BuilderExpr::pow(double val) const {
1183+
return pow(builder_->cst(val, builder_->ctx_.fp64(false)));
1184+
}
1185+
11561186
BuilderExpr BuilderExpr::logicalAnd(const BuilderExpr& rhs) const {
11571187
try {
11581188
auto bin_oper = Analyzer::normalizeOperExpr(

omniscidb/QueryBuilder/QueryBuilder.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ class BuilderExpr {
3737
bool isAutoNamed() const { return auto_name_; }
3838

3939
ExprPtr expr() const { return expr_; }
40+
const Type* type() const { return expr_->type(); }
4041

4142
BuilderExpr avg() const;
4243
BuilderExpr min() const;
@@ -108,6 +109,12 @@ class BuilderExpr {
108109
BuilderExpr ceil() const;
109110
BuilderExpr floor() const;
110111

112+
BuilderExpr pow(const BuilderExpr& rhs) const;
113+
BuilderExpr pow(int val) const;
114+
BuilderExpr pow(int64_t val) const;
115+
BuilderExpr pow(float val) const;
116+
BuilderExpr pow(double val) const;
117+
111118
BuilderExpr logicalAnd(const BuilderExpr& rhs) const;
112119
BuilderExpr logicalOr(const BuilderExpr& rhs) const;
113120

omniscidb/Tests/QueryBuilderTest.cpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3952,6 +3952,34 @@ TEST_F(QueryBuilderTest, Floor) {
39523952
EXPECT_THROW(scan.ref("col_arr_i32").floor(), InvalidQueryError);
39533953
}
39543954

3955+
TEST_F(QueryBuilderTest, Pow) {
3956+
QueryBuilder builder(ctx(), schema_mgr_, configPtr());
3957+
auto scan = builder.scan("test3");
3958+
checkFunctionOper(scan.ref("col_bi").pow(2), "POWER", 2, ctx().fp64());
3959+
checkFunctionOper(scan.ref("col_i").pow((int64_t)3), "POWER", 2, ctx().fp64());
3960+
checkFunctionOper(scan.ref("col_f").pow(2.3f), "POWER", 2, ctx().fp64());
3961+
checkFunctionOper(scan.ref("col_d").pow(2.0), "POWER", 2, ctx().fp64());
3962+
checkFunctionOper(scan.ref("col_dec").pow(scan.ref("col_d")), "POWER", 2, ctx().fp64());
3963+
checkFunctionOper(scan.ref("col_d").pow(scan.ref("col_bi")), "POWER", 2, ctx().fp64());
3964+
checkFunctionOper(scan.ref("col_d").pow(scan.ref("col_i")), "POWER", 2, ctx().fp64());
3965+
checkFunctionOper(scan.ref("col_d").pow(scan.ref("col_f")), "POWER", 2, ctx().fp64());
3966+
checkFunctionOper(scan.ref("col_d").pow(scan.ref("col_dec")), "POWER", 2, ctx().fp64());
3967+
EXPECT_THROW(scan.ref("col_b").pow(2), InvalidQueryError);
3968+
EXPECT_THROW(scan.ref("col_str").pow(2), InvalidQueryError);
3969+
EXPECT_THROW(scan.ref("col_dict").pow(2), InvalidQueryError);
3970+
EXPECT_THROW(scan.ref("col_date").pow(2), InvalidQueryError);
3971+
EXPECT_THROW(scan.ref("col_time").pow(2), InvalidQueryError);
3972+
EXPECT_THROW(scan.ref("col_timestamp").pow(2), InvalidQueryError);
3973+
EXPECT_THROW(scan.ref("col_arr_i32").pow(2), InvalidQueryError);
3974+
EXPECT_THROW(scan.ref("col_d").pow(scan.ref("col_b")), InvalidQueryError);
3975+
EXPECT_THROW(scan.ref("col_d").pow(scan.ref("col_str")), InvalidQueryError);
3976+
EXPECT_THROW(scan.ref("col_d").pow(scan.ref("col_dict")), InvalidQueryError);
3977+
EXPECT_THROW(scan.ref("col_d").pow(scan.ref("col_date")), InvalidQueryError);
3978+
EXPECT_THROW(scan.ref("col_d").pow(scan.ref("col_time")), InvalidQueryError);
3979+
EXPECT_THROW(scan.ref("col_d").pow(scan.ref("col_timestamp")), InvalidQueryError);
3980+
EXPECT_THROW(scan.ref("col_d").pow(scan.ref("col_arr_i32")), InvalidQueryError);
3981+
}
3982+
39553983
TEST_F(QueryBuilderTest, SimpleProjection) {
39563984
QueryBuilder builder(ctx(), schema_mgr_, configPtr());
39573985
compare_test1_data(builder.scan("test1").proj({0, 1, 2, 3}));

python/pyhdk/_builder.pxd

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ cdef extern from "omniscidb/QueryBuilder/QueryBuilder.h":
5050
CBuilderExpr ceil() except +
5151
CBuilderExpr floor() except +
5252

53+
CBuilderExpr pow(const CBuilderExpr&) except +
54+
5355
CBuilderExpr add(const CBuilderExpr&) except +
5456
CBuilderExpr sub(const CBuilderExpr&) except +
5557
CBuilderExpr mul(const CBuilderExpr&) except +

python/pyhdk/_builder.pyx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,12 @@ cdef class QueryExpr:
241241
res.c_expr = self.c_expr.unnest()
242242
return res
243243

244+
def pow(self, value):
245+
value = self._process_op_expr(value)
246+
res = QueryExpr()
247+
res.c_expr = self.c_expr.pow((<QueryExpr>value).c_expr)
248+
return res
249+
244250
def at(self, value):
245251
value = self._process_op_expr(value)
246252
res = QueryExpr()

python/tests/test_pyhdk_api.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -836,6 +836,23 @@ def test_unnest(self):
836836

837837
hdk.drop_table(ht)
838838

839+
def test_pow(self):
840+
hdk = pyhdk.init()
841+
ht = hdk.import_pydict({"a": [1, 2, 3, 4, 5], "b": [1.0, 2.0, 3.0, 4.0, 5.0]})
842+
843+
self.check_res(
844+
ht.proj(
845+
a1=ht["a"].pow(2), a2=ht["a"].pow(ht["b"]), b=ht["b"].pow(2.0)
846+
).run(),
847+
{
848+
"a1": [1.0, 4.0, 9.0, 16.0, 25.0],
849+
"a2": [1.0, 4.0, 27.0, 256.0, 3125.0],
850+
"b": [1.0, 4.0, 9.0, 16.0, 25.0],
851+
},
852+
)
853+
854+
hdk.drop_table(ht)
855+
839856
def test_at(self):
840857
hdk = pyhdk.init()
841858
ht = hdk.create_table("test1", [("a", "array(int)"), ("b", "int")])

0 commit comments

Comments
 (0)