CREATE OR REPLACE PACKAGE BODY column_sort_api IS
temporary_view_prefix_ CONSTANT VARCHAR2(30) := 'COLUMN_SORT_TEMP_VIEW_';
FUNCTION get_next_temporary_view_name_ RETURN VARCHAR2;
FUNCTION sort_query_columns(
sql_ IN VARCHAR2) RETURN VARCHAR2
IS
PRAGMA AUTONOMOUS_TRANSACTION;
temporary_view_name_ VARCHAR2(30) := get_next_temporary_view_name_;
modified_sql_ VARCHAR2(32767);
ddl_ VARCHAR2(32767);
column_concatenation_ VARCHAR2(32767);
BEGIN
modified_sql_ := RTRIM(TRIM(sql_), ';');
ddl_ := 'CREATE OR REPLACE VIEW ' || temporary_view_name_ || ' AS '
|| 'SELECT * FROM (' || modified_sql_ || ')';
EXECUTE IMMEDIATE ddl_;
SELECT LISTAGG(LOWER(column_name), ', ') WITHIN GROUP (ORDER BY column_name ASC)
INTO column_concatenation_
FROM user_tab_cols
WHERE table_name = temporary_view_name_;
ddl_ := 'DROP VIEW ' || temporary_view_name_;
EXECUTE IMMEDIATE ddl_;
RETURN 'SELECT ' || column_concatenation_ || ' FROM (' || modified_sql_ || ')';
COMMIT;
END sort_query_columns;
FUNCTION get_next_temporary_view_name_ RETURN VARCHAR2
IS
view_name_index_ NUMBER;
record_count_ NUMBER;
view_name_ VARCHAR2(30);
attempts_ NUMBER := 0;
BEGIN
LOOP
IF attempts_ > 10000 THEN
drop_all_temporary_views;
END IF;
view_name_index_ := column_sort_seq.NEXTVAL;
view_name_ := temporary_view_prefix_ || TO_CHAR(view_name_index_, 'FM0000');
SELECT COUNT(*)
INTO record_count_
FROM user_views
WHERE view_name = view_name_;
attempts_ := attempts_ + 1;
EXIT WHEN record_count_ = 0;
END LOOP;
RETURN view_name_;
END get_next_temporary_view_name_;
PROCEDURE drop_all_temporary_views
IS
BEGIN
FOR rec_ IN (
SELECT view_name
FROM user_views
WHERE view_name LIKE temporary_view_prefix_ || '%'
) LOOP
EXECUTE IMMEDIATE 'DROP VIEW ' || rec_.view_name;
END LOOP;
END drop_all_temporary_views;
END column_sort_api;