esper how to use table data created by epl - esper

I'm new to esper, I want to get data stored in tbl_config. Here are some esper config file:
config.epl
module rms.config;
create table tbl_config(
id java.math.BigDecimal primary key,
time java.math.BigDecimal
);
create schema ConfigListEvent as (
id java.math.BigDecimal,
time java.math.BigDecimal
);
#Audit
#Name("LoadConfigDataFromDBRule")
insert into ConfigListEvent
select tbl.ID as id, tbl.time as time
from ImportDataEvent,
sql: rms ['select * from T_CONFIG'] as tbl;
#Audit
#Priority(1)
#Name("DeleteConfigDataRule")
on ConfigListEvent as evt
delete from tbl_config as tbl where evt.id = tbl.id;
#Audit
#Name("InsertConfigDataRule")
on ConfigListEvent
insert into tbl_config select *;
stat.epl
module rms.stat;
uses rms.config;
#Name("Create-PaymentContext")
create window PaymentWindow.win:time(2 hour) as PaymentRequest;
#Audit
#Name("insertPaymentRequest ")
#Priority(1)
insert into PaymentWindow select * from PaymentRequest;
rule.epl
module rms.rule;
uses rms.config;
uses rms.stat;
#Audit
#Name("xxx")
#Description("check max times per IntervalTime")
on PaymentRequest as pay
select CustomUtil.getEndTime(pay.createTime,tbl_config["time"]) as startTime from PaymentWindow as payWindow;
then system launch with errors:
com.espertech.esper.epl.expression.core.ExprValidationException: Failed to validate method-chain parameter expression 'tbl_config["time"]': Incompatible type returned by a key expression for use with table 'tbl_config', the key expression '"time"' returns 'java.lang.String' but the table expects 'java.math.BigDecimal'
It has confused me for a few days, Thanks for any help!

The table has a key field "id" that is type BigDecimal.
The expression tbl_config["time"] however provides the string value "time" as a key and not a BigDecimal value. Try tbl_config[id] assuming there is a field named 'id' in payment request that has a type BigDecimal.
The on-delete and on-insert in config.epl look a little awkward and on-merge would make this one easy to read statement.

Related

bigquery sql table function with string interpolation

I am trying to write a BigQuery SQL function / stored procedure / table function that accepts as input:
a INT64 filter for the WHERE clause,
a table name (STRING type) as fully qualified name e.g. project_id.dataset_name.table_name
The idea is to dynamically figure out the table name and provide a filter to slice the data to return as a table.
However if try to write a Table Function (TVF) and I use SET to start dynamically writing the SQL to execute, then I see this error:
Syntax error: Expected "(" or keyword SELECT or keyword WITH but got keyword SET at [4:5]
If I try to write a stored procedure, then it expects BEGIN and END and throws this error:
Syntax error: Expected keyword BEGIN or keyword LANGUAGE but got keyword AS at [3:1]
If I try to add those, then I get various validation errors basically because I need to remove the WITH using CTEs (Common Table Expression), and semicolons ; etc.
But what I am really trying to do is using a table function:
to combine some CTEs dynamically with those inputs above (e.g. the input table name),
to PIVOT that data,
to then eventually return a table as a result of a SELECT.
A bit like producing a View that could be used in other SQL queries, but without creating the view (because the slice of data can be decided dynamically with the other INT64 input filter).
Once I dynamically build the SQL string I would like to EXECUTE IMMEDIATE that SQL and provide a SELECT as a final step of the table function to return the "dynamic table".
The thing is that:
I don't know before runtime the name of this table.
But I have all these tables with the same structure, so the SQL should apply to all of them.
Is this possible at all?
This is the not-so-working SQL I am trying to work around. See what I am trying to inject with %s and num_days:
CREATE OR REPLACE TABLE FUNCTION `my_dataset.my_table_func_name`(num_days INT64, fqn_org_table STRING)
AS (
-- this SET breaks !!!
SET f_query = """
WITH report_cst_t AS (
SELECT
DATE(start) as day,
entity_id,
conn_sub_type,
FROM `%s` AS oa
CROSS JOIN UNNEST(oa.connection_sub_type) AS conn_sub_type
WHERE
DATE(start) > DATE_SUB(CURRENT_DATE(), INTERVAL num_days DAY)
AND oa.entity_id IN ('my-very-long-id')
ORDER BY 1, 2 ASC
),
cst AS (
SELECT * FROM
(SELECT day, entity_id, report_cst_t FROM report_cst_t)
PIVOT (COUNT(*) AS connection_sub_type FOR report_cst_t.conn_sub_type IN ('cat1', 'cat2','cat3' ))
)
""";
-- here I would like to EXECUTE IMMEDIATE !!!
SELECT
cst.day,
cst.entity_id,
cst.connection_sub_type_cat1 AS cst_cat1,
cst.connection_sub_type_cat2 AS cst_cat2,
cst.connection_sub_type_cat3 AS cst_cat3,
FROM cst
ORDER BY 1, 2 ASC
);
This might not be satisfying but since Procedural language or DDL are not allowed inside Table functions currently, one possible way around would be simply using PROCEDURE like below.
CREATE OR REPLACE PROCEDURE my_dataset.temp_procedure(filter_value INT64, table_name STRING)
BEGIN
EXECUTE IMMEDIATE FORMAT(CONCAT(
"SELECT year, COUNT(1) as record_count, ",
"FROM %s ",
"WHERE year = %d ",
"GROUP BY year ",
"; "
), table_name, filter_value);
END;
CALL my_dataset.temp_procedure(2002, 'bigquery-public-data.usa_names.usa_1910_current');

Calculated time of day field in Postgres from timestamp

I have a timestamp with time zone field named statdate and the entry looks like this 2021-11-17 12:47:54-08. I want to create a field with just the time of day expressed locally, so it would look like 12:47:54. (This data was recorded on an iPhone and it's 12:28 PST). (Go to bottom of post for solution using views from #AdrianKalver)
select *,statdate :: timestamp :: time as stattime from table
works in PGAdmin and an example result is 12:47:54 as desired. How do I make this an alter table
ALTER TABLE tablename add COLUMN stattime timestamp generated always AS (select *,statdate :: timestamp :: time as stattime from tablename) stored;
is the wrong syntax.
ALTER TABLE tablename add COLUMN stattime timestamp generated always AS ( EXTRACT(HOUR FROM statdate) || ':' || EXTRACT(MINUTE FROM statdate) || ':' || EXTRACT(SECOND FROM statdate)) stored;
ERROR: generation expression is not immutable which I'm presuming is a type problem, although postgres can concatenate strings and numbers with this syntax.
Just tried something else
ALTER TABLE tablename add COLUMN stattime timestamp generated always AS ( Cast(EXTRACT(HOUR FROM statdate) as text) || ':' || cast(EXTRACT(MINUTE FROM statdate) as text) || ':' || cast(EXTRACT(SECOND FROM statdate) as text) ) stored; -- ERROR: generation expression is not immutable
I'm using the hours and minutes for a graph and I can't get in the middle of the Chartkick. Could do it in High Charts, but think it will be simpler to create the view chart and use that. The Rails/Chartkick looks like
<%= line_chart TableName.where(statdate: start..current_date).pluck(:statdate, :y_axis) %>
and can't break that apart. So will go with creating a View Table.
What's the right way to do this? I've looked here and at the postgresql docs and not having much luck.
Following comments, the solution
CREATE OR REPLACE VIEW public.view_bp_with_time AS
SELECT
id,
statdate,
statdate :: time AS stattime,
y-axis
FROM table_name
ORDER BY statdate
Now to bring into Rails. Not as straightforward as I thought. And I'm off the computer for the next week.
Per here:
https://www.postgresql.org/docs/current/sql-createtable.html
GENERATED ALWAYS AS ( generation_expr ) STORED
This clause creates the column as a generated column. The column cannot be written to, and when read the result of the specified expression will be returned.
The keyword STORED is required to signify that the column will be computed on write and will be stored on disk.
The generation expression can refer to other columns in the table, but not other generated columns. Any functions and operators used must be immutable. References to other tables are not allowed.
Basically the cast from timestamptz to timestamp is not immutable as there are time zones involved.
For more information see:
https://www.postgresql.org/docs/14/xfunc-volatility.html
Either:
Create a view that does the conversion.
Include it in your query as you show for the pgAdmin4 example.
Create a timestamp field on the table and either add the value to that field as part of INSERT\UPDATE or add a trigger that does that.

how to get the integer column to integer list in informix

To read an integer column into integer list
create function somedum()
returning int
define s LIST(INTEGER NOT NULL);
select id into s from informix.emptest;
end function
create table emptest(id int)
insert into emptest(id)values(7)
when I execute the above function
iam getting error as attached image
The Informix documentation on inserting elements into a LIST seems misleading to me, as my first impression of the example ( Insert into a LIST ) also led me to use the SELECT INTO syntax and get the same error:
-9634 No cast from integer to set(integer not null)
The SELECT INTO syntax can be used to copy/insert an entire LIST, not elements into the LIST.
To insert an element into the LIST ( or generally manipulate it's elements ) we need to use the Informix virtual table interface, in this case using the TABLE syntax to create a virtual table from the LIST which then can be used to do the usual insert/select/update/delete operations ( Collection-Derived Table ).
CREATE FUNCTION somedum()
RETURNING LIST( INTEGER NOT NULL ) AS alist;
DEFINE my_list LIST( INTEGER NOT NULL );
INSERT INTO TABLE( my_list ) SELECT id FROM emptest;
RETURN my_list;
END FUNCTION;
Executing the function we get:
EXECUTE FUNCTION somedum();
alist LIST{7 }

Postgres function returns custom data set

Is there a way to create postgres stored function (using plpgsql to be able to set input parameters) that returns a custom data set?
I've tried to do something like this according to official manual:
CREATE FUNCTION extended_sales(p_itemno int)
RETURNS TABLE(quantity int, total numeric) AS $$
BEGIN
RETURN QUERY SELECT quantity, quantity * price FROM sales
WHERE itemno = p_itemno;
END;
$$ LANGUAGE plpgsql;
but result is an array with only one column which contains type (quantity, total), but I need to get two column array with 'quantity' column and 'total' column.
At a guess you're running:
SELECT extended_sales(1);
This will return a composite type column. If you want it expanded, you must instead run:
SELECT * FROM extended_sales(1);
Also, as #a_horse_with_no_name notes, a PL/pgSQL function is completely unnecessary here. Presumably this is a simplified example?
In future please include:
Your PostgreSQL version; and
The exact SQL you ran and the exact output you got

Getting invalid identifier and SQL ignored errors in stored procedure in Oracle

I am trying to create a stored procedure in order to insert some data into some table in Oracle 11g.
For this purpose, I need to read the last amount from the latest insert for that user, and then add it to my new value and save the changes as a new row and if any kind of exception is occurred just rollback. This is what I have come up with so far:
CREATE OR REPLACE PROCEDURE MYTESTDB.INSERT_INTO_TESTBANK
(
ID IN TBLTESTBANK.ID%TYPE,
USERID IN TBLTESTBANK.USERID%TYPE,
TYPE IN TBLTESTBANK.TYPE%TYPE,
AMOUNT IN TBLTESTBANK.AMOUNT%TYPE,
DATETIMESTAMP IN TBLTESTBANK.DATETIMESTAMP%TYPE,
TRANSACTION_ID IN TBLTESTBANK.IDTRANS%TYPE,
TOTAL_MONEY IN TBLTESTBANK.TOTALMONEY%TYPE,
COMPUTED_HASH IN TBLTESTBANK.HASH%TYPE
)
IS
BEGIN
DECLARE
LastAmount TBLTESTBANK.TOTALMONEY%TYPE;
BEGIN
SELECT TBLTESTBANK.TOTALMONEY INTO LASTAMOUNT
FROM
(
SELECT TBLTESTBANK.ID
FROM TBLTESTBANK tblbnk
WHERE tblbnk.USERID = USERID
order by max(tblbnk.DATETIMESTAMP)
)
where ROWNUM<2;
EXCEPTION WHEN NO_DATA_FOUND
THEN LastAmount := 0;
END;
LastAmount := LastAmount+ AMOUNT;
INSERT INTO TBLTESTBANK (ID, USERID, TYPE, LastAmount,
DATETIMESTAMP, IDTRANS, TOTALMONEY, HASH
)
VALUES (ID, USERID, TYPE, AMOUNT, DATETIMESTAMP, TRANSACTION_ID, TOTAL_MONEY, COMPUTED_HASH);
COMMIT;
EXCEPTION WHEN OTHERS
THEN
ROLLBACK;
END;
/
Whenever I try to test it, I get a red wiggly line under the first SELECT , and then he TESTBANK.ID in the inner select statements. For the select command it says, sql statement is ignored, and for the TESTBANK.ID it says invalid identifier!
It also doesn't let me add two variables, and keeps saying LastAmount must be declared.
And these are the errors I get :
Error(19,7): PL/SQL: SQL Statement ignored
Error(22,16): PL/SQL: ORA-00904: "TBLTESTBANK"."ID": invalid identifier
Error(32,3): PLS-00201: identifier 'LASTAMOUNT' must be declared
Error(32,3): PL/SQL: Statement ignored
Error(34,3): PL/SQL: SQL Statement ignored
Error(34,47): PL/SQL: ORA-00904: "LASTAMOUNT": invalid identifier
You have two problems:
In your select statement:
SELECT TBLTESTBANK.ID
FROM TBLTESTBANK tblbnk
WHERE tblbnk.USERID = USERID
order by max(tblbnk.DATETIMESTAMP)
You have given the table TBLTESTBANK the alias tblbnk therefor you must use the alias throughout the statement:
SELECT tblbnk.ID -- use the correct alias here
FROM TBLTESTBANK tblbnk
WHERE tblbnk.USERID = USERID
order by max(tblbnk.DATETIMESTAMP)
Second:
in the INSERT statement you have to list columns not values.
INSERT INTO TBLTESTBANK (ID, USERID, TYPE, LastAmount,
DATETIMESTAMP, IDTRANS, TOTALMONEY, HASH
)
should be:
INSERT INTO TBLTESTBANK (ID, USERID, TYPE, AMOUNT, --- column name instead of variable name
DATETIMESTAMP, IDTRANS, TOTALMONEY, HASH
)
And then of course you need to use LastAmount in the values part, not AMOUNT
In general it's not a good idea to have variables with the same name as columns of tables that you use in the procedure. It's easy to shadow a variable with a column. You should rename the variables to avoid any problems there.
Edit (I didn't notice this at first).
You also have an error in the structure of the code. A stored procedure (or function) does not have a DECLARE section:
Your declaration needs to look like this:
CREATE OR REPLACE PROCEDURE MYTESTDB.INSERT_INTO_TESTBANK
(
....
)
IS
-- no DECLARE
-- variables right after the IS keyword
LastAmount TBLTESTBANK.TOTALMONEY%TYPE;
BEGIN
...
END;
You can try below select query to get latest record.
SELECT TB.TOTALMONEY INTO LASTAMOUNT
FROM
TESTBANK TB
WHERE
TB.USERID=USERID
AND
DATETIMESTAMP= (SELECT MAX (TB2.DATETIMESTAMP) FROM TESTBANK TB2
WHERE TB2.USERID=USERID);

Resources