Exemple #1
0
def test_short_ints(cql, test_keyspace, table1, scylla_with_wasm_only):
    table = table1
    plus_name = "plus_" + unique_name()
    plus_source = f"""
(module
  (type (;0;) (func (param i32 i32) (result i32)))
  (func ${plus_name} (type 0) (param i32 i32) (result i32)
    local.get 1
    local.get 0
    i32.add)
  (table (;0;) 1 1 funcref)
  (table (;1;) 32 externref)
  (memory (;0;) 17)
  (export "{plus_name}" (func ${plus_name}))
  (elem (;0;) (i32.const 0) func))
"""
    src = f"(input tinyint, input2 tinyint) RETURNS NULL ON NULL INPUT RETURNS tinyint LANGUAGE xwasm AS '{plus_source}'"
    with new_function(cql, test_keyspace, src, plus_name):
        cql.execute(f"INSERT INTO {table} (p, t, t2, s, s2) VALUES (42, 42, 24, 33, 55)")
        cql.execute(f"INSERT INTO {table} (p, t, t2, s, s2) VALUES (43, 120, 112, 32000, 24001)")
        res = [row for row in cql.execute(f"SELECT {test_keyspace}.{plus_name}(t, t2) AS result FROM {table} WHERE p = 42")]
        assert len(res) == 1 and res[0].result == 66
        # Overflow is fine
        res = [row for row in cql.execute(f"SELECT {test_keyspace}.{plus_name}(t, t2) AS result FROM {table} WHERE p = 43")]
        assert len(res) == 1 and res[0].result == -24
    # A similar run for 16bit ints - note that the exact same source code is used
    src = f"(input smallint, input2 smallint) RETURNS NULL ON NULL INPUT RETURNS smallint LANGUAGE xwasm AS '{plus_source}'"
    with new_function(cql, test_keyspace, src, plus_name):
        res = [row for row in cql.execute(f"SELECT {test_keyspace}.{plus_name}(s, s2) AS result FROM {table} WHERE p = 42")]
        assert len(res) == 1 and res[0].result == 88
        # Overflow is fine
        res = [row for row in cql.execute(f"SELECT {test_keyspace}.{plus_name}(s, s2) AS result FROM {table} WHERE p = 43")]
        assert len(res) == 1 and res[0].result == -9535
Exemple #2
0
def test_validate_params(cql, test_keyspace, table1, scylla_with_wasm_only):
    table = table1
    inc_float_name = "inc_float_" + unique_name()
    inc_float_source = f"""
(module
  (type (;0;) (func (param f32) (result f32)))
  (func ${inc_float_name} (type 0) (param f32) (result f32)
    local.get 0
    f32.const 0x1p+0 (;=1;)
    f32.add)
  (table (;0;) 1 1 funcref)
  (table (;1;) 32 externref)
  (memory (;0;) 17)
  (export "memory" (memory 0))
  (export "{inc_float_name}" (func ${inc_float_name}))
  (elem (;0;) (i32.const 0) func))
"""
    src = f"(input int) RETURNS NULL ON NULL INPUT RETURNS float LANGUAGE xwasm AS '{inc_float_source}'"
    with new_function(cql, test_keyspace, src, inc_float_name):
        cql.execute(f"INSERT INTO {table} (p, i, f, txt) VALUES (700, 7, 7., 'oi')")
        with pytest.raises(InvalidRequest, match="type mismatch"):
            cql.execute(f"SELECT {test_keyspace}.{inc_float_name}(i) AS result FROM {table} WHERE p = 700")
    src = f"(input text) RETURNS NULL ON NULL INPUT RETURNS int LANGUAGE xwasm AS '{inc_float_source}'"
    with new_function(cql, test_keyspace, src, inc_float_name):
        with pytest.raises(InvalidRequest, match="failed"):
            cql.execute(f"SELECT {test_keyspace}.{inc_float_name}(txt) AS result FROM {table} WHERE p = 700")
    src = f"(input float) RETURNS NULL ON NULL INPUT RETURNS int LANGUAGE xwasm AS '{inc_float_source}'"
    with new_function(cql, test_keyspace, src, inc_float_name):
        with pytest.raises(InvalidRequest, match="Expected i32, got f32"):
            cql.execute(f"SELECT {test_keyspace}.{inc_float_name}(f) AS result FROM {table} WHERE p = 700")
        with pytest.raises(InvalidRequest, match="number.*arguments"):
            cql.execute(f"SELECT {test_keyspace}.{inc_float_name}(i, f) AS result FROM {table} WHERE p = 700")
Exemple #3
0
def test_wrong_sfunc_or_ffunc(scylla_only, cql, test_keyspace):
    avg_partial_body = "(state tuple<bigint, text>, val bigint) CALLED ON NULL INPUT RETURNS tuple<bigint, text> LANGUAGE lua AS 'return {state[1] + val, \"hello\"}'"
    div_body = "(state tuple<bigint, bigint>) CALLED ON NULL INPUT RETURNS bigint LANGUAGE lua AS 'return state[1]//state[2]'"
    div_body2 = "(state tuple<bigint, bigint>) CALLED ON NULL INPUT RETURNS float LANGUAGE lua AS 'return state[1]/state[2]'"
    with new_function(cql, test_keyspace,
                      avg_partial_body) as avg_partial, new_function(
                          cql, test_keyspace,
                          div_body) as div_fun, new_function(
                              cql, test_keyspace, div_body2) as div_fun2:
        custom_avg_body = f"(bigint) SFUNC {avg_partial} STYPE tuple<bigint, bigint> FINALFUNC {div_fun} INITCOND (0,0)"
        with pytest.raises(InvalidRequest, match="not found"):
            cql.execute(
                f"CREATE AGGREGATE {test_keyspace}.{unique_name()} {custom_avg_body}"
            )
        custom_avg_body = f"(bigint) SFUNC {avg_partial} STYPE tuple<bigint, bigint> FINALFUNC {div_fun2} INITCOND (0,0)"
        with pytest.raises(InvalidRequest, match="not found"):
            cql.execute(
                f"CREATE AGGREGATE {test_keyspace}.{unique_name()} {custom_avg_body}"
            )
        custom_avg_body = f"(bigint) SFUNC i_do_not_exist STYPE tuple<bigint, bigint> FINALFUNC {div_fun2} INITCOND (0,0)"
        with pytest.raises(InvalidRequest, match="not found"):
            cql.execute(
                f"CREATE AGGREGATE {test_keyspace}.{unique_name()} {custom_avg_body}"
            )
        custom_avg_body = f"(bigint) SFUNC {avg_partial} STYPE tuple<bigint, bigint> FINALFUNC i_do_not_exist_either INITCOND (0,0)"
        with pytest.raises(InvalidRequest, match="not found"):
            cql.execute(
                f"CREATE AGGREGATE {test_keyspace}.{unique_name()} {custom_avg_body}"
            )
Exemple #4
0
def test_drop_sfunc_or_ffunc(scylla_only, cql, test_keyspace):
    avg_partial_body = "(state tuple<bigint, bigint>, val bigint) CALLED ON NULL INPUT RETURNS tuple<bigint, bigint> LANGUAGE lua AS 'return {state[1] + val, state[2] + 1}'"
    div_body = "(state tuple<bigint, bigint>) CALLED ON NULL INPUT RETURNS bigint LANGUAGE lua AS 'return state[1]//state[2]'"
    with new_function(cql, test_keyspace,
                      avg_partial_body) as avg_partial, new_function(
                          cql, test_keyspace, div_body) as div_fun:
        custom_avg_body = f"(bigint) SFUNC {avg_partial} STYPE tuple<bigint, bigint> FINALFUNC {div_fun} INITCOND (0,0)"
        with new_aggregate(cql, test_keyspace, custom_avg_body) as custom_avg:
            with pytest.raises(InvalidRequest, match="it is used"):
                cql.execute(f"DROP FUNCTION {test_keyspace}.{avg_partial}")
            with pytest.raises(InvalidRequest, match="it is used"):
                cql.execute(f"DROP FUNCTION {test_keyspace}.{div_fun}")
Exemple #5
0
def test_bool_negate(cql, test_keyspace, table1, scylla_with_wasm_only):
    table = table1
    negate_name = "negate_" + unique_name()
    negate_source = f"""
(module
  (type (;0;) (func (param i32) (result i32)))
  (func ${negate_name} (type 0) (param i32) (result i32)
    local.get 0
    i32.eqz)
  (table (;0;) 1 1 funcref)
  (table (;1;) 32 externref)
  (memory (;0;) 17)
  (export "{negate_name}" (func ${negate_name}))
  (elem (;0;) (i32.const 0) func)
  (global (;0;) i32 (i32.const 1024))
  (export "_scylla_abi" (global 0))
  (data $.rodata (i32.const 1024) "\\01"))
"""
    src = f"(input boolean) RETURNS NULL ON NULL INPUT RETURNS boolean LANGUAGE xwasm AS '{negate_source}'"
    with new_function(cql, test_keyspace, src, negate_name):
        cql.execute(f"INSERT INTO {table} (p, bl) VALUES (19, true)")
        cql.execute(f"INSERT INTO {table} (p, bl) VALUES (21, false)")
        res = [
            row for row in cql.execute(
                f"SELECT {test_keyspace}.{negate_name}(bl) AS result FROM {table} WHERE p = 19"
            )
        ]
        assert len(res) == 1 and res[0].result == False
        res = [
            row for row in cql.execute(
                f"SELECT {test_keyspace}.{negate_name}(bl) AS result FROM {table} WHERE p = 21"
            )
        ]
        assert len(res) == 1 and res[0].result == True
Exemple #6
0
def test_f32_param(cql, test_keyspace, table1, scylla_with_wasm_only):
    table = table1
    inc_float_name = "inc_float_" + unique_name()
    inc_float_source = f"""
(module
  (type (;0;) (func (param f32) (result f32)))
  (func ${inc_float_name} (type 0) (param f32) (result f32)
    local.get 0
    f32.const 0x1p+0 (;=1;)
    f32.add)
  (table (;0;) 1 1 funcref)
  (table (;1;) 32 externref)
  (memory (;0;) 17)
  (export "{inc_float_name}" (func ${inc_float_name}))
  (elem (;0;) (i32.const 0) func)
  (global (;0;) i32 (i32.const 1024))
  (export "_scylla_abi" (global 0))
  (data $.rodata (i32.const 1024) "\\01"))
"""
    src = f"(input float) RETURNS NULL ON NULL INPUT RETURNS float LANGUAGE xwasm AS '{inc_float_source}'"
    with new_function(cql, test_keyspace, src, inc_float_name):
        cql.execute(f"INSERT INTO {table} (p, f) VALUES (121, 121.00390625)")
        res = [
            row for row in cql.execute(
                f"SELECT {test_keyspace}.{inc_float_name}(f) AS result FROM {table} WHERE p = 121"
            )
        ]
        assert len(res) == 1 and res[0].result == 122.00390625
Exemple #7
0
def test_f64_param(cql, test_keyspace, table1, scylla_with_wasm_only):
    table = table1
    dec_double_name = "dec_double_" + unique_name()
    dec_double_source = f"""
(module
  (type (;0;) (func (param f64) (result f64)))
  (func ${dec_double_name} (type 0) (param f64) (result f64)
    local.get 0
    f64.const -0x1p+0 (;=-1;)
    f64.add)
  (table (;0;) 1 1 funcref)
  (table (;1;) 32 externref)
  (memory (;0;) 17)
  (export "{dec_double_name}" (func ${dec_double_name}))
  (elem (;0;) (i32.const 0) func)
  (global (;0;) i32 (i32.const 1024))
  (export "_scylla_abi" (global 0))
  (data $.rodata (i32.const 1024) "\\01"))
"""
    src = f"(input double) RETURNS NULL ON NULL INPUT RETURNS double LANGUAGE xwasm AS '{dec_double_source}'"
    with new_function(cql, test_keyspace, src, dec_double_name):
        cql.execute(f"INSERT INTO {table} (p,d) VALUES (17,17.015625)")
        res = [
            row for row in cql.execute(
                f"SELECT {test_keyspace}.{dec_double_name}(d) AS result FROM {table} WHERE p = 17"
            )
        ]
        assert len(res) == 1 and res[0].result == 16.015625
Exemple #8
0
def test_infinite_loop(cql, test_keyspace, table1, scylla_with_wasm_only):
    table = table1
    inf_loop_name = "inf_loop_" + unique_name()
    inf_loop_source = f"""
(module
  (type (;0;) (func (param i32) (result i32)))
  (func ${inf_loop_name} (type 0) (param i32) (result i32)
    loop (result i32)  ;; label = @1
      br 0 (;@1;)
    end)
  (table (;0;) 1 1 funcref)
  (table (;1;) 32 externref)
  (memory (;0;) 17)
  (export "{inf_loop_name}" (func ${inf_loop_name}))
  (elem (;0;) (i32.const 0) func)
  (global (;0;) i32 (i32.const 1024))
  (export "_scylla_abi" (global 0))
  (data $.rodata (i32.const 1024) "\\01"))
"""
    src = f"(input int) RETURNS NULL ON NULL INPUT RETURNS int LANGUAGE xwasm AS '{inf_loop_source}'"
    with new_function(cql, test_keyspace, src, inf_loop_name):
        cql.execute(f"INSERT INTO {table} (p,i) VALUES (10, 10)")
        import time
        start = time.monotonic()
        with pytest.raises(InvalidRequest, match="fuel consumed"):
            cql.execute(
                f"SELECT {test_keyspace}.{inf_loop_name}(i) AS result FROM {table} WHERE p = 10"
            )
        elapsed_s = time.monotonic() - start
        print(f"Breaking the loop took {elapsed_s*1000:.2f}ms")
Exemple #9
0
def test_no_initcond(scylla_only, cql, test_keyspace):
    rows = 5
    schema = "id int primary key"
    # This aggregate will return `1000 - #rows` if there is no initcond and `initcond - #rows` otherwise
    state_body = "(acc int, val int) CALLED ON NULL INPUT RETURNS int LANGUAGE lua AS 'if acc == null then return 999 else return acc - 1 end'"
    final_body = "(acc int) CALLED ON NULL INPUT RETURNS int LANGUAGE lua AS 'return acc'"
    with new_test_table(cql, test_keyspace, schema) as table:
        for i in range(rows):
            cql.execute(f"INSERT INTO {table} (id) VALUES ({i})")
        with new_function(cql, test_keyspace,
                          state_body) as state_func, new_function(
                              cql, test_keyspace, final_body) as final_func:
            aggr_body = f"(int) SFUNC {state_func} STYPE int FINALFUNC {final_func}"
            with new_aggregate(cql, test_keyspace, aggr_body) as aggr_func:
                result = cql.execute(
                    f"SELECT {aggr_func}(id) AS result FROM {table}").one()
                assert result.result == (1000 - rows)
Exemple #10
0
def test_incorrect_state_func(scylla_only, cql, test_keyspace):
    avg_partial_body = "(state tuple<bigint, bigint>, val bigint, redundant int) CALLED ON NULL INPUT RETURNS tuple<bigint, bigint> LANGUAGE lua AS 'return {state[1] + val, state[2] + 1}'"
    div_body = "(state tuple<bigint, bigint>) CALLED ON NULL INPUT RETURNS bigint LANGUAGE lua AS 'return state[1]//state[2]'"
    with new_function(cql, test_keyspace,
                      avg_partial_body) as avg_partial, new_function(
                          cql, test_keyspace, div_body) as div_fun:
        custom_avg_body = f"(bigint) SFUNC {avg_partial} STYPE tuple<bigint, bigint> FINALFUNC {div_fun} INITCOND (0,0)"
        with pytest.raises(InvalidRequest, match="State function not found"):
            cql.execute(
                f"CREATE AGGREGATE {test_keyspace}.{unique_name()} {custom_avg_body}"
            )
    avg2_partial_body = "(state tuple<bigint, bigint>) CALLED ON NULL INPUT RETURNS tuple<bigint, bigint> LANGUAGE lua AS 'return {state[1] + 42, state[2] + 1}'"
    div_body = "(state tuple<bigint, bigint>) CALLED ON NULL INPUT RETURNS bigint LANGUAGE lua AS 'return state[1]//state[2]'"
    with new_function(cql, test_keyspace,
                      avg2_partial_body) as avg2_partial, new_function(
                          cql, test_keyspace, div_body) as div_fun:
        custom_avg_body = f"(bigint) SFUNC {avg2_partial} STYPE tuple<bigint, bigint> FINALFUNC {div_fun} INITCOND (0,0)"
        with pytest.raises(InvalidRequest, match="State function not found"):
            cql.execute(
                f"CREATE AGGREGATE {test_keyspace}.{unique_name()} {custom_avg_body}"
            )
Exemple #11
0
def test_map_literal_builder(scylla_only, cql, test_keyspace):
    schema = 'id int, k text, val int, primary key (id, k)'
    with new_test_table(cql, test_keyspace, schema) as table:
        for i in range(8):
            cql.execute(
                f"INSERT INTO {table} (id, k, val) VALUES (0, '{chr(ord('a') + i)}', {i})"
            )
        map_literal_partial_body = "(state text, id text, val int) RETURNS NULL ON NULL INPUT RETURNS text LANGUAGE lua AS 'return state..id..\":\"..tostring(val)..\",\"'"
        finish_body = "(state text) CALLED ON NULL INPUT RETURNS text LANGUAGE lua AS 'return state..\"}\"'"
        with new_function(
                cql, test_keyspace,
                map_literal_partial_body) as map_literal_partial, new_function(
                    cql, test_keyspace, finish_body) as finish_fun:
            map_literal_body = f"(text, int) SFUNC {map_literal_partial} STYPE text FINALFUNC {finish_fun} INITCOND '{{'"
            with new_aggregate(cql, test_keyspace,
                               map_literal_body) as map_literal:
                map_res = [
                    row for row in cql.execute(
                        f"SELECT {test_keyspace}.{map_literal}(k, val) AS result FROM {table}"
                    )
                ]
                assert len(map_res) == 1 and map_res[
                    0].result == '{a:0,b:1,c:2,d:3,e:4,f:5,g:6,h:7,}'
Exemple #12
0
def test_custom_avg(scylla_only, cql, test_keyspace):
    schema = 'id bigint primary key'
    with new_test_table(cql, test_keyspace, schema) as table:
        for i in range(8):
            cql.execute(f"INSERT INTO {table} (id) VALUES ({10**i})")
        avg_partial_body = "(state tuple<bigint, bigint>, val bigint) CALLED ON NULL INPUT RETURNS tuple<bigint, bigint> LANGUAGE lua AS 'return {state[1] + val, state[2] + 1}'"
        div_body = "(state tuple<bigint, bigint>) CALLED ON NULL INPUT RETURNS bigint LANGUAGE lua AS 'return state[1]//state[2]'"
        with new_function(cql, test_keyspace,
                          avg_partial_body) as avg_partial, new_function(
                              cql, test_keyspace, div_body) as div_fun:
            custom_avg_body = f"(bigint) SFUNC {avg_partial} STYPE tuple<bigint, bigint> FINALFUNC {div_fun} INITCOND (0,0)"
            with new_aggregate(cql, test_keyspace,
                               custom_avg_body) as custom_avg:
                custom_res = [
                    row for row in cql.execute(
                        f"SELECT {test_keyspace}.{custom_avg}(id) AS result FROM {table}"
                    )
                ]
                avg_res = [
                    row for row in cql.execute(
                        f"SELECT avg(id) AS result FROM {table}")
                ]
                assert custom_res == avg_res
Exemple #13
0
def test_fib(cql, test_keyspace, table1, scylla_with_wasm_only):
    table = table1
    fib_name = unique_name()
    fib_source = f"""
(module
  (func ${fib_name} (param $n i64) (result i64)
    (if
      (i64.lt_s (local.get $n) (i64.const 2))
      (return (local.get $n))
    )
    (i64.add
      (call ${fib_name} (i64.sub (local.get $n) (i64.const 1)))
      (call ${fib_name} (i64.sub (local.get $n) (i64.const 2)))
    )
  )
  (export "{fib_name}" (func ${fib_name}))
)
"""
    src = f"(input bigint) RETURNS NULL ON NULL INPUT RETURNS bigint LANGUAGE xwasm AS '{fib_source}'"
    with new_function(cql, test_keyspace, src, fib_name):
        cql.execute(f"INSERT INTO {table1} (p) VALUES (10)")
        res = [
            row for row in cql.execute(
                f"SELECT {test_keyspace}.{fib_name}(p) AS result FROM {table} WHERE p = 10"
            )
        ]
        assert len(res) == 1 and res[0].result == 55

        cql.execute(f"INSERT INTO {table} (p) VALUES (14)")
        res = [
            row for row in cql.execute(
                f"SELECT {test_keyspace}.{fib_name}(p) AS result FROM {table} WHERE p = 14"
            )
        ]
        assert len(res) == 1 and res[0].result == 377

        # This function returns null on null values
        res = [
            row for row in cql.execute(
                f"SELECT {test_keyspace}.{fib_name}(p2) AS result FROM {table} WHERE p = 14"
            )
        ]
        assert len(res) == 1 and res[0].result is None

        cql.execute(f"INSERT INTO {table} (p) VALUES (997)")
        # The call request takes too much time and resources, and should therefore fail
        with pytest.raises(InvalidRequest, match="wasm"):
            cql.execute(
                f"SELECT {test_keyspace}.{fib_name}(p) AS result FROM {table} WHERE p = 997"
            )
Exemple #14
0
def test_no_final_func(scylla_only, cql, test_keyspace):
    schema = "id int primary key"
    sum_partial_body = "(acc int, val int) RETURNS NULL ON NULL INPUT RETURNS int LANGUAGE lua AS 'return acc + val'"
    with new_test_table(cql, test_keyspace, schema) as table:
        for i in range(5):
            cql.execute(f"INSERT INTO {table} (id) VALUES ({i})")
        with new_function(cql, test_keyspace, sum_partial_body) as sum_partial:
            custom_sum_body = f"(int) SFUNC {sum_partial} STYPE int INITCOND 0"
            with new_aggregate(cql, test_keyspace,
                               custom_sum_body) as custom_sum:
                custom_res = cql.execute(
                    f"SELECT {custom_sum}(id) AS result FROM {table}").one()
                avg_res = cql.execute(
                    f"SELECT sum(id) AS result FROM {table}").one()
                assert custom_res == avg_res
Exemple #15
0
def test_9_params(cql, test_keyspace, table1, scylla_with_wasm_only):
    table = table1
    sum9_name = "sum9_" + unique_name()
    sum9_source = f"""
(module
  (type (;0;) (func (param i32 i32 i32 i32 i32 i32 i32 i32 i32) (result i32)))
  (func ${sum9_name} (type 0) (param i32 i32 i32 i32 i32 i32 i32 i32 i32) (result i32)
    local.get 1
    local.get 0
    i32.add
    local.get 2
    i32.add
    local.get 3
    i32.add
    local.get 4
    i32.add
    local.get 5
    i32.add
    local.get 6
    i32.add
    local.get 7
    i32.add
    local.get 8
    i32.add)
  (table (;0;) 1 1 funcref)
  (table (;1;) 32 externref)
  (memory (;0;) 17)
  (export "{sum9_name}" (func ${sum9_name}))
  (elem (;0;) (i32.const 0) func)
  (global (;0;) i32 (i32.const 1024))
  (export "_scylla_abi" (global 0))
  (data $.rodata (i32.const 1024) "\\01"))

"""
    src = f"(a int, b int, c int, d int, e int, f int, g int, h int, i int) RETURNS NULL ON NULL INPUT RETURNS int LANGUAGE xwasm AS '{sum9_source}'"
    with new_function(cql, test_keyspace, src, sum9_name):
        cql.execute(f"INSERT INTO {table} (p, i, i2) VALUES (777, 1,2)")
        res = [
            row for row in cql.execute(
                f"SELECT {test_keyspace}.{sum9_name}(i,i2,i2,i,i2,i,i2,i,i2) AS result FROM {table} WHERE p = 777"
            )
        ]
        assert len(res) == 1 and res[0].result == 14
Exemple #16
0
def test_fib_called_on_null(cql, test_keyspace, table1, scylla_with_wasm_only):
    table = table1
    fib_name = unique_name()
    fib_source = f"""
(module
  (type (;0;) (func))
  (type (;1;) (func (param i64) (result i64)))
  (type (;2;) (func (param i32) (result i32)))
  (func $__wasm_call_ctors (type 0))
  (func $fib_aux (type 1) (param i64) (result i64)
    (local i64 i32 i64)
    block  ;; label = @1
      local.get 0
      i64.const 2
      i64.ge_s
      br_if 0 (;@1;)
      local.get 0
      i64.const 0
      i64.add
      return
    end
    i64.const 0
    local.set 1
    loop  ;; label = @1
      local.get 0
      i64.const -1
      i64.add
      call $fib_aux
      local.get 1
      i64.add
      local.set 1
      local.get 0
      i64.const 3
      i64.gt_s
      local.set 2
      local.get 0
      i64.const -2
      i64.add
      local.tee 3
      local.set 0
      local.get 2
      br_if 0 (;@1;)
    end
    local.get 3
    local.get 1
    i64.add)
  (func $fib (type 2) (param i32) (result i32)
    (local i32 i64)
    memory.size
    local.set 1
    i32.const 12
    memory.grow
    drop
    local.get 1
    i32.const 8
    i32.store align=1
    block  ;; label = @1
      local.get 0
      i32.load align=1
      i32.const -1
      i32.ne
      br_if 0 (;@1;)
      local.get 1
      i64.const 3026418949592973312
      i64.store offset=4 align=1
      local.get 1
      return
    end
    local.get 1
    local.get 0
    i64.load offset=4 align=1
    local.tee 2
    i64.const 56
    i64.shl
    local.get 2
    i64.const 40
    i64.shl
    i64.const 71776119061217280
    i64.and
    i64.or
    local.get 2
    i64.const 24
    i64.shl
    i64.const 280375465082880
    i64.and
    local.get 2
    i64.const 8
    i64.shl
    i64.const 1095216660480
    i64.and
    i64.or
    i64.or
    local.get 2
    i64.const 8
    i64.shr_u
    i64.const 4278190080
    i64.and
    local.get 2
    i64.const 24
    i64.shr_u
    i64.const 16711680
    i64.and
    i64.or
    local.get 2
    i64.const 40
    i64.shr_u
    i64.const 65280
    i64.and
    local.get 2
    i64.const 56
    i64.shr_u
    i64.or
    i64.or
    i64.or
    call $fib_aux
    local.tee 2
    i64.const 56
    i64.shl
    local.get 2
    i64.const 40
    i64.shl
    i64.const 71776119061217280
    i64.and
    i64.or
    local.get 2
    i64.const 24
    i64.shl
    i64.const 280375465082880
    i64.and
    local.get 2
    i64.const 8
    i64.shl
    i64.const 1095216660480
    i64.and
    i64.or
    i64.or
    local.get 2
    i64.const 8
    i64.shr_u
    i64.const 4278190080
    i64.and
    local.get 2
    i64.const 24
    i64.shr_u
    i64.const 16711680
    i64.and
    i64.or
    local.get 2
    i64.const 40
    i64.shr_u
    i64.const 65280
    i64.and
    local.get 2
    i64.const 56
    i64.shr_u
    i64.or
    i64.or
    i64.or
    i64.store offset=4 align=1
    local.get 1)
  (memory (;0;) 2)
  (global (;0;) (mut i32) (i32.const 66560))
  (global (;1;) i32 (i32.const 1024))
  (global (;2;) i32 (i32.const 1024))
  (global (;3;) i32 (i32.const 1024))
  (global (;4;) i32 (i32.const 66560))
  (global (;5;) i32 (i32.const 0))
  (global (;6;) i32 (i32.const 1))
  (export "memory" (memory 0))
  (export "{fib_name}" (func $fib)))
"""
    src = f"(input bigint) CALLED ON NULL INPUT RETURNS bigint LANGUAGE xwasm AS '{fib_source}'"
    with new_function(cql, test_keyspace, src, fib_name):
        cql.execute(f"INSERT INTO {table1} (p) VALUES (3)")
        res = [row for row in cql.execute(f"SELECT {test_keyspace}.{fib_name}(p) AS result FROM {table} WHERE p = 3")]
        assert len(res) == 1 and res[0].result == 2

        cql.execute(f"INSERT INTO {table} (p) VALUES (7)")
        res = [row for row in cql.execute(f"SELECT {test_keyspace}.{fib_name}(p) AS result FROM {table} WHERE p = 7")]
        assert len(res) == 1 and res[0].result == 13

        # Special semantics defined for null input in our function is to return "42"
        res = [row for row in cql.execute(f"SELECT {test_keyspace}.{fib_name}(p2) AS result FROM {table} WHERE p = 7")]
        assert len(res) == 1 and res[0].result == 42

        cql.execute(f"INSERT INTO {table} (p) VALUES (997)")
        # The call request takes too much time and resources, and should therefore fail
        with pytest.raises(InvalidRequest, match="wasm"):
          cql.execute(f"SELECT {test_keyspace}.{fib_name}(p) AS result FROM {table} WHERE p = 997")
Exemple #17
0
def test_word_double(cql, test_keyspace, table1, scylla_with_wasm_only):
    table = table1
    dbl_name = unique_name()
    dbl_source = f"""
(module
  (type (;0;) (func (param i64) (result i64)))
  (func $dbl (type 0) (param i64) (result i64)
    (local i32 i32 i32 i64 i64 i64 i32 i64 i64 i64 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i64 i64 i64 i64 i64 i32 i32 i64 i64 i64)
    global.get $__stack_pointer
    local.set 1
    i32.const 48
    local.set 2
    local.get 1
    local.get 2
    i32.sub
    local.set 3
    local.get 3
    local.get 0
    i64.store offset=40
    local.get 3
    i64.load offset=40
    local.set 4
    i64.const 32
    local.set 5
    local.get 4
    local.get 5
    i64.shr_s
    local.set 6
    local.get 6
    i32.wrap_i64
    local.set 7
    local.get 3
    local.get 7
    i32.store offset=36
    local.get 3
    i64.load offset=40
    local.set 8
    i64.const 4294967295
    local.set 9
    local.get 8
    local.get 9
    i64.and
    local.set 10
    local.get 10
    i32.wrap_i64
    local.set 11
    local.get 3
    local.get 11
    i32.store offset=32
    memory.size
    local.set 12
    i32.const 16
    local.set 13
    local.get 12
    local.get 13
    i32.shl
    local.set 14
    local.get 3
    local.get 14
    i32.store offset=28
    local.get 3
    i32.load offset=36
    local.set 15
    i32.const 1
    local.set 16
    local.get 15
    local.get 16
    i32.shl
    local.set 17
    i32.const 1
    local.set 18
    local.get 17
    local.get 18
    i32.sub
    local.set 19
    i32.const 65536
    local.set 20
    local.get 19
    local.get 20
    i32.div_s
    local.set 21
    i32.const 1
    local.set 22
    local.get 21
    local.get 22
    i32.add
    local.set 23
    local.get 23
    memory.grow
    drop
    i32.const 0
    local.set 24
    local.get 3
    local.get 24
    i32.store offset=24
    i32.const 0
    local.set 25
    local.get 3
    local.get 25
    i32.store offset=20
    block  ;; label = @1
      loop  ;; label = @2
        local.get 3
        i32.load offset=20
        local.set 26
        local.get 3
        i32.load offset=36
        local.set 27
        local.get 26
        local.set 28
        local.get 27
        local.set 29
        local.get 28
        local.get 29
        i32.lt_s
        local.set 30
        i32.const 1
        local.set 31
        local.get 30
        local.get 31
        i32.and
        local.set 32
        local.get 32
        i32.eqz
        br_if 1 (;@1;)
        local.get 3
        i32.load offset=24
        local.set 33
        local.get 3
        i32.load offset=32
        local.set 34
        local.get 3
        i32.load offset=20
        local.set 35
        local.get 34
        local.get 35
        i32.add
        local.set 36
        local.get 33
        local.get 36
        i32.add
        local.set 37
        local.get 37
        i32.load8_u
        local.set 38
        local.get 3
        i32.load offset=24
        local.set 39
        local.get 3
        i32.load offset=28
        local.set 40
        local.get 3
        i32.load offset=20
        local.set 41
        local.get 40
        local.get 41
        i32.add
        local.set 42
        local.get 39
        local.get 42
        i32.add
        local.set 43
        local.get 43
        local.get 38
        i32.store8
        local.get 3
        i32.load offset=24
        local.set 44
        local.get 3
        i32.load offset=32
        local.set 45
        local.get 3
        i32.load offset=20
        local.set 46
        local.get 45
        local.get 46
        i32.add
        local.set 47
        local.get 44
        local.get 47
        i32.add
        local.set 48
        local.get 48
        i32.load8_u
        local.set 49
        local.get 3
        i32.load offset=24
        local.set 50
        local.get 3
        i32.load offset=28
        local.set 51
        local.get 3
        i32.load offset=36
        local.set 52
        local.get 51
        local.get 52
        i32.add
        local.set 53
        local.get 3
        i32.load offset=20
        local.set 54
        local.get 53
        local.get 54
        i32.add
        local.set 55
        local.get 50
        local.get 55
        i32.add
        local.set 56
        local.get 56
        local.get 49
        i32.store8
        local.get 3
        i32.load offset=20
        local.set 57
        i32.const 1
        local.set 58
        local.get 57
        local.get 58
        i32.add
        local.set 59
        local.get 3
        local.get 59
        i32.store offset=20
        br 0 (;@2;)
      end
    end
    local.get 3
    i32.load offset=36
    local.set 60
    local.get 60
    local.set 61
    local.get 61
    i64.extend_i32_s
    local.set 62
    i64.const 1
    local.set 63
    local.get 62
    local.get 63
    i64.shl
    local.set 64
    i64.const 32
    local.set 65
    local.get 64
    local.get 65
    i64.shl
    local.set 66
    local.get 3
    i32.load offset=28
    local.set 67
    local.get 67
    local.set 68
    local.get 68
    i64.extend_i32_s
    local.set 69
    local.get 66
    local.get 69
    i64.or
    local.set 70
    local.get 3
    local.get 70
    i64.store offset=8
    local.get 3
    i64.load offset=8
    local.set 71
    local.get 71
    return)
  (memory (;0;) 2)
  (global $__stack_pointer (mut i32) (i32.const 66576))
  (global (;1;) i32 (i32.const 1024))
  (export "memory" (memory 0))
  (export "{dbl_name}" (func $dbl))
  (export "_scylla_abi" (global 1))
  (data $.rodata (i32.const 1024) "\\01"))
"""
    src = f"(input text) RETURNS NULL ON NULL INPUT RETURNS text LANGUAGE xwasm AS '{dbl_source}'"
    with new_function(cql, test_keyspace, src, dbl_name):
        cql.execute(f"INSERT INTO {table1} (p, txt) VALUES (1000, 'doggo')")
        res = [
            row for row in cql.execute(
                f"SELECT {test_keyspace}.{dbl_name}(txt) AS result FROM {table} WHERE p = 1000"
            )
        ]
        assert len(res) == 1 and res[0].result == 'doggodoggo'

        cql.execute(f"INSERT INTO {table} (p, txt) VALUES (1001, 'cat42')")
        res = [
            row for row in cql.execute(
                f"SELECT {test_keyspace}.{dbl_name}(txt) AS result FROM {table} WHERE p = 1001"
            )
        ]
        assert len(res) == 1 and res[0].result == 'cat42cat42'
Exemple #18
0
def test_pow(cql, test_keyspace, table1, scylla_with_wasm_only):
    table = table1
    pow_name = "pow_" + unique_name()
    pow_source = f"""
(module
  (type (;0;) (func (param i32 i32) (result i32)))
  (func ${pow_name} (type 0) (param i32 i32) (result i32)
    (local i32 i32)
    i32.const 1
    local.set 2
    block  ;; label = @1
      block  ;; label = @2
        block  ;; label = @3
          local.get 1
          br_table 2 (;@1;) 1 (;@2;) 0 (;@3;)
        end
        local.get 1
        local.set 2
        i32.const 1
        local.set 1
        loop  ;; label = @3
          local.get 0
          i32.const 1
          local.get 2
          i32.const 1
          i32.and
          select
          local.get 1
          i32.mul
          local.set 1
          local.get 2
          i32.const 3
          i32.gt_u
          local.set 3
          local.get 0
          local.get 0
          i32.mul
          local.set 0
          local.get 2
          i32.const 1
          i32.shr_u
          local.set 2
          local.get 3
          br_if 0 (;@3;)
        end
      end
      local.get 0
      local.get 1
      i32.mul
      local.set 2
    end
    local.get 2)
  (table (;0;) 1 1 funcref)
  (table (;1;) 32 externref)
  (memory (;0;) 17)
  (global (;0;) i32 (i32.const 1024))
  (export "{pow_name}" (func ${pow_name}))
  (elem (;0;) (i32.const 0) func)
  (export "_scylla_abi" (global 0))
  (data $.rodata (i32.const 1024) "\\01"))
"""
    src = f"(base int, pow int) RETURNS NULL ON NULL INPUT RETURNS int LANGUAGE xwasm AS '{pow_source}'"
    with new_function(cql, test_keyspace, src, pow_name):
        cql.execute(f"INSERT INTO {table} (p, i, i2) VALUES (311, 3, 11)")
        res = [
            row for row in cql.execute(
                f"SELECT {test_keyspace}.{pow_name}(i, i2) AS result FROM {table} WHERE p = 311"
            )
        ]
        assert len(res) == 1 and res[0].result == 177147
Exemple #19
0
def test_fib_called_on_null(cql, test_keyspace, table1, scylla_with_wasm_only):
    table = table1
    fib_name = unique_name()
    fib_source = f"""
(module
  (type (;0;) (func (param i64) (result i64)))
  (func (;0;) (type 0) (param i64) (result i64)
    (local i64 i32)
    local.get 0
    i64.const 2
    i64.lt_s
    if  ;; label = @1
      local.get 0
      return
    end
    loop  ;; label = @1
      local.get 0
      i64.const 1
      i64.sub
      call 0
      local.get 1
      i64.add
      local.set 1
      local.get 0
      i64.const 3
      i64.gt_s
      local.set 2
      local.get 0
      i64.const 2
      i64.sub
      local.set 0
      local.get 2
      br_if 0 (;@1;)
    end
    local.get 0
    local.get 1
    i64.add)
  (func (;1;) (type 0) (param i64) (result i64)
    (local i32 i64)
    memory.size
    local.set 1
    i32.const 1
    memory.grow
    drop
    i64.const 3026418949592973312
    local.set 2
    local.get 1
    i32.const 16
    i32.shl
    local.tee 1
    local.get 0
    i64.const -4294967297
    i64.le_u
    if (result i64)  ;; label = @1
      local.get 0
      i32.wrap_i64
      i64.load
      local.tee 0
      i64.const 56
      i64.shl
      local.get 0
      i64.const 40
      i64.shl
      i64.const 71776119061217280
      i64.and
      i64.or
      local.get 0
      i64.const 24
      i64.shl
      i64.const 280375465082880
      i64.and
      local.get 0
      i64.const 8
      i64.shl
      i64.const 1095216660480
      i64.and
      i64.or
      i64.or
      local.get 0
      i64.const 8
      i64.shr_u
      i64.const 4278190080
      i64.and
      local.get 0
      i64.const 24
      i64.shr_u
      i64.const 16711680
      i64.and
      i64.or
      local.get 0
      i64.const 40
      i64.shr_u
      i64.const 65280
      i64.and
      local.get 0
      i64.const 56
      i64.shr_u
      i64.or
      i64.or
      i64.or
      call 0
      local.tee 0
      i64.const 56
      i64.shl
      local.get 0
      i64.const 40
      i64.shl
      i64.const 71776119061217280
      i64.and
      i64.or
      local.get 0
      i64.const 24
      i64.shl
      i64.const 280375465082880
      i64.and
      local.get 0
      i64.const 8
      i64.shl
      i64.const 1095216660480
      i64.and
      i64.or
      i64.or
      local.get 0
      i64.const 8
      i64.shr_u
      i64.const 4278190080
      i64.and
      local.get 0
      i64.const 24
      i64.shr_u
      i64.const 16711680
      i64.and
      i64.or
      local.get 0
      i64.const 40
      i64.shr_u
      i64.const 65280
      i64.and
      local.get 0
      i64.const 56
      i64.shr_u
      i64.or
      i64.or
      i64.or
    else
      local.get 2
    end
    i64.store
    local.get 1
    i64.extend_i32_u
    i64.const 34359738368
    i64.or)
  (memory (;0;) 2)
  (global (;0;) i32 (i32.const 1024))
  (export "memory" (memory 0))
  (export "{fib_name}" (func 1))
  (export "_scylla_abi" (global 0))
  (data (;0;) (i32.const 1024) "\\01"))
"""
    src = f"(input bigint) CALLED ON NULL INPUT RETURNS bigint LANGUAGE xwasm AS '{fib_source}'"
    with new_function(cql, test_keyspace, src, fib_name):
        cql.execute(f"INSERT INTO {table1} (p) VALUES (3)")
        res = [
            row for row in cql.execute(
                f"SELECT {test_keyspace}.{fib_name}(p) AS result FROM {table} WHERE p = 3"
            )
        ]
        assert len(res) == 1 and res[0].result == 2

        cql.execute(f"INSERT INTO {table} (p) VALUES (7)")
        res = [
            row for row in cql.execute(
                f"SELECT {test_keyspace}.{fib_name}(p) AS result FROM {table} WHERE p = 7"
            )
        ]
        assert len(res) == 1 and res[0].result == 13

        # Special semantics defined for null input in our function is to return "42"
        res = [
            row for row in cql.execute(
                f"SELECT {test_keyspace}.{fib_name}(p2) AS result FROM {table} WHERE p = 7"
            )
        ]
        assert len(res) == 1 and res[0].result == 42

        cql.execute(f"INSERT INTO {table} (p) VALUES (997)")
        # The call request takes too much time and resources, and should therefore fail
        with pytest.raises(InvalidRequest, match="wasm"):
            cql.execute(
                f"SELECT {test_keyspace}.{fib_name}(p) AS result FROM {table} WHERE p = 997"
            )
Exemple #20
0
def test_word_double(cql, test_keyspace, table1, scylla_with_wasm_only):
    table = table1
    dbl_name = unique_name()
    dbl_source = f"""
(module
  (type (;0;) (func))
  (type (;1;) (func (param i32) (result i32)))
  (func $__wasm_call_ctors (type 0))
  (func $dbl (type 1) (param i32) (result i32)
    (local i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32 i32)
    global.get 0
    local.set 1
    i32.const 48
    local.set 2
    local.get 1
    local.get 2
    i32.sub
    local.set 3
    local.get 3
    local.get 0
    i32.store offset=44
    local.get 3
    i32.load offset=44
    local.set 4
    local.get 4
    i32.load
    local.set 5
    local.get 3
    local.get 5
    i32.store offset=40
    local.get 3
    i32.load offset=44
    local.set 6
    i32.const 4
    local.set 7
    local.get 6
    local.get 7
    i32.add
    local.set 8
    local.get 3
    local.get 8
    i32.store offset=36
    memory.size
    local.set 9
    local.get 3
    local.get 9
    i32.store offset=32
    local.get 3
    i32.load offset=32
    local.set 10
    i32.const 4
    local.set 11
    local.get 10
    local.get 11
    i32.add
    local.set 12
    local.get 3
    local.get 12
    i32.store offset=28
    local.get 3
    i32.load offset=40
    local.set 13
    i32.const 1
    local.set 14
    local.get 13
    local.get 14
    i32.shl
    local.set 15
    i32.const 4
    local.set 16
    local.get 15
    local.get 16
    i32.add
    local.set 17
    local.get 17
    memory.grow
    drop
    i32.const 0
    local.set 18
    local.get 3
    local.get 18
    i32.store offset=24
    i32.const 0
    local.set 19
    local.get 3
    local.get 19
    i32.store offset=20
    block  ;; label = @1
      loop  ;; label = @2
        local.get 3
        i32.load offset=20
        local.set 20
        local.get 3
        i32.load offset=40
        local.set 21
        local.get 20
        local.set 22
        local.get 21
        local.set 23
        local.get 22
        local.get 23
        i32.lt_s
        local.set 24
        i32.const 1
        local.set 25
        local.get 24
        local.get 25
        i32.and
        local.set 26
        local.get 26
        i32.eqz
        br_if 1 (;@1;)
        local.get 3
        i32.load offset=24
        local.set 27
        local.get 3
        i32.load offset=36
        local.set 28
        local.get 3
        i32.load offset=20
        local.set 29
        local.get 28
        local.get 29
        i32.add
        local.set 30
        local.get 27
        local.get 30
        i32.add
        local.set 31
        local.get 31
        i32.load8_u
        local.set 32
        local.get 3
        i32.load offset=24
        local.set 33
        local.get 3
        i32.load offset=28
        local.set 34
        local.get 3
        i32.load offset=20
        local.set 35
        local.get 34
        local.get 35
        i32.add
        local.set 36
        local.get 33
        local.get 36
        i32.add
        local.set 37
        local.get 37
        local.get 32
        i32.store8
        local.get 3
        i32.load offset=24
        local.set 38
        local.get 3
        i32.load offset=36
        local.set 39
        local.get 3
        i32.load offset=20
        local.set 40
        local.get 39
        local.get 40
        i32.add
        local.set 41
        local.get 38
        local.get 41
        i32.add
        local.set 42
        local.get 42
        i32.load8_u
        local.set 43
        local.get 3
        i32.load offset=24
        local.set 44
        local.get 3
        i32.load offset=28
        local.set 45
        local.get 3
        i32.load offset=40
        local.set 46
        local.get 45
        local.get 46
        i32.add
        local.set 47
        local.get 3
        i32.load offset=20
        local.set 48
        local.get 47
        local.get 48
        i32.add
        local.set 49
        local.get 44
        local.get 49
        i32.add
        local.set 50
        local.get 50
        local.get 43
        i32.store8
        local.get 3
        i32.load offset=20
        local.set 51
        i32.const 1
        local.set 52
        local.get 51
        local.get 52
        i32.add
        local.set 53
        local.get 3
        local.get 53
        i32.store offset=20
        br 0 (;@2;)
      end
    end
    local.get 3
    i32.load offset=40
    local.set 54
    i32.const 1
    local.set 55
    local.get 54
    local.get 55
    i32.shl
    local.set 56
    local.get 3
    local.get 56
    i32.store offset=16
    local.get 3
    i32.load offset=32
    local.set 57
    local.get 3
    local.get 57
    i32.store offset=12
    i32.const 0
    local.set 58
    local.get 3
    local.get 58
    i32.store offset=8
    block  ;; label = @1
      loop  ;; label = @2
        local.get 3
        i32.load offset=8
        local.set 59
        i32.const 4
        local.set 60
        local.get 59
        local.set 61
        local.get 60
        local.set 62
        local.get 61
        local.get 62
        i32.lt_s
        local.set 63
        i32.const 1
        local.set 64
        local.get 63
        local.get 64
        i32.and
        local.set 65
        local.get 65
        i32.eqz
        br_if 1 (;@1;)
        local.get 3
        i32.load offset=16
        local.set 66
        local.get 3
        i32.load offset=8
        local.set 67
        i32.const 3
        local.set 68
        local.get 68
        local.get 67
        i32.sub
        local.set 69
        i32.const 3
        local.set 70
        local.get 69
        local.get 70
        i32.shl
        local.set 71
        local.get 66
        local.get 71
        i32.shr_s
        local.set 72
        local.get 3
        i32.load offset=12
        local.set 73
        local.get 73
        local.get 72
        i32.store8
        local.get 3
        i32.load offset=8
        local.set 74
        i32.const 1
        local.set 75
        local.get 74
        local.get 75
        i32.add
        local.set 76
        local.get 3
        local.get 76
        i32.store offset=8
        br 0 (;@2;)
      end
    end
    local.get 3
    i32.load offset=32
    local.set 77
    local.get 77
    return)
  (memory (;0;) 2)
  (global (;0;) (mut i32) (i32.const 66560))
  (global (;1;) i32 (i32.const 1024))
  (global (;2;) i32 (i32.const 1024))
  (global (;3;) i32 (i32.const 1024))
  (global (;4;) i32 (i32.const 66560))
  (global (;5;) i32 (i32.const 0))
  (global (;6;) i32 (i32.const 1))
  (export "memory" (memory 0))
  (export "{dbl_name}" (func $dbl)))
"""
    src = f"(input text) RETURNS NULL ON NULL INPUT RETURNS text LANGUAGE xwasm AS '{dbl_source}'"
    with new_function(cql, test_keyspace, src, dbl_name):
        cql.execute(f"INSERT INTO {table1} (p, txt) VALUES (1000, 'doggo')")
        res = [row for row in cql.execute(f"SELECT {test_keyspace}.{dbl_name}(txt) AS result FROM {table} WHERE p = 1000")]
        assert len(res) == 1 and res[0].result == 'doggodoggo'

        cql.execute(f"INSERT INTO {table} (p, txt) VALUES (1001, 'cat42')")
        res = [row for row in cql.execute(f"SELECT {test_keyspace}.{dbl_name}(txt) AS result FROM {table} WHERE p = 1001")]
        assert len(res) == 1 and res[0].result == 'cat42cat42'