timescaledb/extension/sql/main/ioql_sql_gen.sql
2017-01-05 12:35:08 -05:00

202 lines
6.9 KiB
PL/PgSQL

CREATE OR REPLACE FUNCTION get_time_clause(time_col_name NAME, time_col_type regtype, group_time BIGINT)
RETURNS TEXT LANGUAGE SQL IMMUTABLE AS
$BODY$
SELECT CASE
WHEN group_time IS NULL THEN
format('%I', time_col_name)
WHEN time_col_type IN ('BIGINT', 'INTEGER', 'SMALLINT') THEN
format('(%1$I - (%1$I %% %2$L::%3$s))::%3$s', time_col_name, group_time, time_col_type)
WHEN time_col_type IN ('TIMESTAMP', 'TIMESTAMPTZ') THEN
--NOTE: note the conversion at the end. important for timestamp without timezone. right conversion?
format('to_timestamp( (
(EXTRACT(EPOCH from %1$I)*1e6)::bigint -
( (EXTRACT(EPOCH from %1$I)*1e6)::bigint %% %2$L::bigint )
)::double precision / 1e6
)::%3$s', time_col_name, group_time, time_col_type) --group time is given in us
END;
$BODY$;
CREATE OR REPLACE FUNCTION get_full_select_clause_nonagg(query ioql_query)
RETURNS TEXT LANGUAGE SQL STABLE AS
$BODY$
SELECT format('SELECT %s', get_result_column_list_nonagg(query));
$BODY$;
CREATE OR REPLACE FUNCTION get_from_clause(crn chunk_replica_node)
RETURNS TEXT LANGUAGE SQL IMMUTABLE AS
$BODY$
SELECT format('FROM %I.%I', crn.schema_name, crn.table_name);
$BODY$;
/* predicates */
CREATE OR REPLACE FUNCTION combine_predicates(VARIADIC clauses TEXT [])
RETURNS TEXT LANGUAGE SQL IMMUTABLE AS
$BODY$
SELECT string_agg(format('( %s )', clause.val), ' AND ')
FROM unnest(clauses) AS clause(val)
WHERE val IS NOT NULL;
$BODY$;
CREATE OR REPLACE FUNCTION get_time_predicate(time_col_name NAME, time_col_type regtype, cond time_condition_type)
RETURNS TEXT LANGUAGE SQL IMMUTABLE AS
$BODY$
SELECT string_agg(clauses.val, ' AND ')
FROM (
VALUES (format('%I >= ', time_col_name) || NULLIF(_sysinternal.time_literal_sql(cond.from_time, time_col_type), 'NULL')),
(format('%I < ', time_col_name) || NULLIF(_sysinternal.time_literal_sql(cond.to_time, time_col_type), 'NULL'))
) AS clauses(val);
$BODY$;
--TODO: Review this
CREATE OR REPLACE FUNCTION get_select_field_predicate(items select_item [])
RETURNS TEXT LANGUAGE SQL IMMUTABLE STRICT AS
$BODY$
SELECT string_agg(format('%I IS NOT NULL', field), ' AND ')
FROM unnest(items);
$BODY$;
CREATE OR REPLACE FUNCTION get_one_field_predicate_clause(field_pred field_predicate)
RETURNS TEXT LANGUAGE SQL STABLE STRICT AS
$BODY$
SELECT format('(%1$I%2$s%3$L AND %1$I IS NOT NULL)', field_pred.field, field_pred.op, field_pred.constant)
$BODY$;
CREATE OR REPLACE FUNCTION get_field_predicate_clause(cond field_condition_type)
RETURNS TEXT LANGUAGE SQL STABLE STRICT AS
$BODY$
SELECT '( ' || string_agg(get_one_field_predicate_clause(p), format(' %s ', cond.conjunctive)) || ' )'
FROM unnest(cond.predicates) AS p
$BODY$;
CREATE OR REPLACE FUNCTION get_constrained_partitioning_field_value(partitioning_field_name NAME,
cond field_condition_type)
RETURNS TEXT LANGUAGE SQL STABLE STRICT AS
$BODY$
SELECT p.constant
FROM unnest(cond.predicates) AS p
WHERE p.field = partitioning_field_name AND cond.conjunctive = 'AND' AND p.op = '='
$BODY$;
CREATE OR REPLACE FUNCTION get_partitioning_predicate(
query ioql_query,
epoch partition_epoch
)
RETURNS TEXT LANGUAGE PLPGSQL IMMUTABLE STRICT AS
$BODY$
DECLARE
keyspace_value SMALLINT;
field_value TEXT;
BEGIN
field_value := get_constrained_partitioning_field_value(epoch.partitioning_field, query.field_condition);
EXECUTE format($$ SELECT %s(%L, %L) $$, epoch.partitioning_func, field_value, epoch.partitioning_mod)
INTO keyspace_value;
IF field_value IS NOT NULL THEN
RETURN format('%s(%I, %L) = %L',
epoch.partitioning_func,
epoch.partitioning_field,
epoch.partitioning_mod,
keyspace_value);
END IF;
RETURN NULL;
END
$BODY$;
CREATE OR REPLACE FUNCTION default_predicates(query ioql_query, epoch partition_epoch)
RETURNS TEXT LANGUAGE SQL STABLE AS
$BODY$
SELECT combine_predicates(
get_time_predicate(get_time_field(query.namespace_name), get_time_field_type(query.namespace_name), query.time_condition),
get_field_predicate_clause(query.field_condition),
get_select_field_predicate(query.select_items),
get_partitioning_predicate(query, epoch)
);
$BODY$;
CREATE OR REPLACE FUNCTION get_where_clause(VARIADIC clauses TEXT [])
RETURNS TEXT LANGUAGE SQL IMMUTABLE AS
$BODY$
SELECT coalesce('WHERE ' || combine_predicates(VARIADIC clauses), '');
$BODY$;
CREATE OR REPLACE FUNCTION get_time_periods_limit_for_max(max_time BIGINT, period_length BIGINT, num_periods INT)
RETURNS time_range LANGUAGE SQL STABLE AS
$BODY$
--todo unit test;
-- start and end inclusive
SELECT ROW (
(max_time - (max_time % period_length)) - (period_length :: BIGINT * (num_periods - 1) :: BIGINT),
max_time
) :: time_range;
$BODY$;
CREATE OR REPLACE FUNCTION get_groupby_clause(agg aggregate_type)
RETURNS TEXT LANGUAGE SQL IMMUTABLE STRICT AS
$BODY$
SELECT CASE
WHEN agg IS NULL THEN
NULL
WHEN agg.group_field IS NOT NULL THEN
format('GROUP BY %s, group_time', agg.group_field)
ELSE
'GROUP BY group_time'
END;
$BODY$;
CREATE OR REPLACE FUNCTION get_orderby_clause_nonagg(query ioql_query)
RETURNS TEXT LANGUAGE SQL IMMUTABLE AS
$BODY$
SELECT CASE
WHEN query.limit_by_field IS NOT NULL THEN
format('ORDER BY %I DESC NULLS LAST, %s', get_time_field(query.namespace_name), (query.limit_by_field).field)
ELSE
format('ORDER BY %I DESC NULLS LAST', get_time_field(query.namespace_name))
END;
$BODY$;
CREATE OR REPLACE FUNCTION get_orderby_clause_agg(query ioql_query, time_col TEXT = 'group_time')
RETURNS TEXT LANGUAGE SQL IMMUTABLE AS
$BODY$
SELECT CASE
WHEN query.limit_rows IS NULL THEN
NULL --no need to order if not gonna limit
WHEN (query.aggregate).group_field IS NOT NULL THEN
format('ORDER BY %s DESC NULLS LAST, %s',
time_col,
(query.aggregate).group_field) --group field needs to be included so that 5 aggregates across partitions overlap
ELSE
format('ORDER BY %s DESC NULLS LAST', time_col)
END;
$BODY$;
CREATE OR REPLACE FUNCTION get_limit_clause(limit_count INT)
RETURNS TEXT LANGUAGE SQL IMMUTABLE AS
$BODY$
SELECT 'LIMIT ' || limit_count
$BODY$;
CREATE OR REPLACE FUNCTION base_query_raw(select_clause TEXT, from_clause TEXT, where_clause TEXT,
group_by_clause TEXT, order_by_clause TEXT, limit_clause TEXT)
RETURNS TEXT LANGUAGE SQL IMMUTABLE AS
$BODY$
SELECT format(
$$
%s
%s
%s
%s
%s
%s
$$,
select_clause,
from_clause,
where_clause,
group_by_clause,
order_by_clause,
limit_clause
);
$BODY$;