diff --git a/PLEX.pkb b/PLEX.pkb index a81d49d..0e635f5 100755 --- a/PLEX.pkb +++ b/PLEX.pkb @@ -12,8 +12,8 @@ c_at CONSTANT VARCHAR2(1) := '@'; c_hash CONSTANT VARCHAR2(1) := '#'; c_slash CONSTANT VARCHAR2(1) := '/'; c_vc2_max_size CONSTANT PLS_INTEGER := 32767; -c_zip_local_file_header CONSTANT RAW(4) := hextoraw('504B0304'); -- local file header signature -c_zip_end_of_central_directory CONSTANT RAW(4) := hextoraw('504B0506'); -- end of central directory signature +c_zip_local_file_header CONSTANT RAW(4) := hextoraw('504B0304'); +c_zip_end_of_central_directory CONSTANT RAW(4) := hextoraw('504B0506'); TYPE tab_errlog IS TABLE OF rec_error_log INDEX BY BINARY_INTEGER; @@ -110,35 +110,24 @@ ZIP UTILS - Copyright (c) 2010, 2011 by Anton Scheffer (MIT license) - Thank you for sharing this Anton :-) */ - FUNCTION util_zip_blob_to_num ( p_blob IN BLOB, p_len IN INTEGER, p_pos IN INTEGER ) RETURN NUMBER; - FUNCTION util_zip_little_endian ( p_big IN NUMBER, p_bytes IN PLS_INTEGER := 4 ) RETURN RAW; - PROCEDURE util_zip_add_file ( p_zipped_blob IN OUT BLOB, p_name IN VARCHAR2, p_content IN BLOB ); - PROCEDURE util_zip_finish ( p_zipped_blob IN OUT BLOB ); -/* FIXME: implement this -FUNCTION util_multireplace ( - p_source_string IN VARCHAR2, - p_replacements IN tab_varchar2 -) RETURN VARCHAR2; -*/ - FUNCTION util_multi_replace ( p_source_string VARCHAR2, p_01_find VARCHAR2 DEFAULT NULL, p_01_replace VARCHAR2 DEFAULT NULL, @@ -203,9 +192,17 @@ PROCEDURE util_clob_query_to_csv ( p_header_prefix IN VARCHAR2 DEFAULT NULL ); -PROCEDURE util_clob_create_runtime_log (p_export_files IN OUT NOCOPY tab_export_files); +PROCEDURE util_clob_create_runtime_log ( + p_export_files IN OUT NOCOPY tab_export_files +); -PROCEDURE util_clob_create_error_log (p_export_files IN OUT NOCOPY tab_export_files); +PROCEDURE util_clob_create_error_log ( + p_export_files IN OUT NOCOPY tab_export_files +); + +PROCEDURE util_ensure_unique_file_names ( + p_export_files IN OUT tab_export_files +); PROCEDURE util_log_init ( p_module IN VARCHAR2 @@ -339,8 +336,7 @@ BEGIN src_offset => v_src_offset, blob_csid => nls_charset_id('AL32UTF8'), lang_context => v_lang_context, - warning => v_warning - ); + warning => v_warning); END IF; RETURN v_blob; END util_clob_to_blob; @@ -356,8 +352,7 @@ FUNCTION util_zip_blob_to_num (-- copyright by Anton Scheffer (MIT license, see BEGIN rv := utl_raw.cast_to_binary_integer( dbms_lob.substr(p_blob, p_len, p_pos), - utl_raw.little_endian - ); + utl_raw.little_endian); IF rv < 0 THEN rv := rv + 4294967296; END IF; @@ -366,9 +361,10 @@ END util_zip_blob_to_num; -------------------------------------------------------------------------------------------------------------------------------- -FUNCTION util_zip_little_endian (-- copyright by Anton Scheffer (MIT license, see https://technology.amis.nl/2010/03/13/utl_compress-gzip-and-zlib/) - p_big IN NUMBER, - p_bytes IN PLS_INTEGER := 4 +-- copyright by Anton Scheffer (MIT license, see https://technology.amis.nl/2010/03/13/utl_compress-gzip-and-zlib/) +FUNCTION util_zip_little_endian ( + p_big IN NUMBER, + p_bytes IN PLS_INTEGER := 4 ) RETURN RAW IS t_big NUMBER := p_big; BEGIN @@ -380,10 +376,11 @@ END util_zip_little_endian; -------------------------------------------------------------------------------------------------------------------------------- -PROCEDURE util_zip_add_file (-- copyright by Anton Scheffer (MIT license, see https://technology.amis.nl/2010/03/13/utl_compress-gzip-and-zlib/) - p_zipped_blob IN OUT BLOB, - p_name IN VARCHAR2, - p_content IN BLOB +-- copyright by Anton Scheffer (MIT license, see https://technology.amis.nl/2010/03/13/utl_compress-gzip-and-zlib/) +PROCEDURE util_zip_add_file ( + p_zipped_blob IN OUT BLOB, + p_name IN VARCHAR2, + p_content IN BLOB ) IS t_now DATE; t_blob BLOB; @@ -402,13 +399,13 @@ BEGIN t_crc32 := dbms_lob.substr(t_blob, 4, t_clen + 11); END IF; IF NOT t_compressed THEN - t_clen := t_len; - t_blob := p_content; + t_clen := t_len; + t_blob := p_content; END IF; -- We create our temporary BLOB in to_zip and do not need it here: - --IF p_zipped_blob IS NULL THEN - -- dbms_lob.createtemporary(p_zipped_blob, true); - --END IF; + -- IF p_zipped_blob IS NULL THEN + -- dbms_lob.createtemporary(p_zipped_blob, true); + -- END IF; t_name := utl_i18n.string_to_raw(p_name, 'AL32UTF8'); dbms_lob.append( p_zipped_blob, @@ -427,39 +424,32 @@ BEGIN to_number(TO_CHAR(t_now, 'ss')) / 2 + to_number(TO_CHAR(t_now, 'mi')) * 32 + to_number(TO_CHAR(t_now, 'hh24')) * 2048, - 2 - ), -- file last modification time + 2), -- file last modification time util_zip_little_endian( to_number(TO_CHAR(t_now, 'dd')) + to_number(TO_CHAR(t_now, 'mm')) * 32 + (to_number(TO_CHAR(t_now, 'yyyy')) - 1980) * 512, - 2 - ), -- file last modification date + 2), -- file last modification date t_crc32, -- CRC-32 util_zip_little_endian(t_clen), -- compressed size util_zip_little_endian(t_len), -- uncompressed size util_zip_little_endian(utl_raw.length(t_name), 2), -- file name length hextoraw('0000'), -- extra field length - t_name -- file name - ) - ); - + t_name)); -- file name IF t_compressed THEN dbms_lob.copy(p_zipped_blob, t_blob, t_clen, dbms_lob.getlength(p_zipped_blob) + 1, 11); -- compressed content ELSIF t_clen > 0 THEN dbms_lob.copy(p_zipped_blob, t_blob, t_clen, dbms_lob.getlength(p_zipped_blob) + 1, 1); -- content END IF; - - IF dbms_lob.istemporary(t_blob) = 1 - THEN + IF dbms_lob.istemporary(t_blob) = 1 THEN dbms_lob.freetemporary(t_blob); END IF; - END util_zip_add_file; -------------------------------------------------------------------------------------------------------------------------------- -PROCEDURE util_zip_finish (-- copyright by Anton Scheffer (MIT license, see https://technology.amis.nl/2010/03/13/utl_compress-gzip-and-zlib/) +-- copyright by Anton Scheffer (MIT license, see https://technology.amis.nl/2010/03/13/utl_compress-gzip-and-zlib/) +PROCEDURE util_zip_finish ( p_zipped_blob IN OUT BLOB ) IS t_cnt PLS_INTEGER := 0; @@ -481,27 +471,26 @@ BEGIN dbms_lob.substr(p_zipped_blob, 26, t_offs + 4), hextoraw('0000'), -- file comment length hextoraw('0000'), -- disk number where file starts - hextoraw('0000'), -- internal file attributes => - -- 0000 binary file - -- 0100 (ascii)text file + hextoraw('0000'), -- internal file attributes: 0000 = binary file, 0100 = (ascii)text file CASE - WHEN dbms_lob.substr(p_zipped_blob, 1, t_offs + 30 + util_zip_blob_to_num(p_zipped_blob, 2, t_offs + 26) - 1) - IN ( - hextoraw('2F'), -- / - hextoraw('5C') -- \ - ) + WHEN dbms_lob.substr( + p_zipped_blob, + 1, + t_offs + 30 + util_zip_blob_to_num(p_zipped_blob, 2, t_offs + 26) - 1) + IN (hextoraw('2F')/*slash*/, hextoraw('5C')/*backslash*/) THEN hextoraw('10000000') -- a directory/folder ELSE hextoraw('2000B681') -- a file END, -- external file attributes util_zip_little_endian(t_offs - 1), -- relative offset of local file header - dbms_lob.substr(p_zipped_blob, util_zip_blob_to_num(p_zipped_blob, 2, t_offs + 26), t_offs + 30) -- File name - )); + dbms_lob.substr( + p_zipped_blob, + util_zip_blob_to_num(p_zipped_blob, 2, t_offs + 26), + t_offs + 30))); -- File name t_offs := t_offs + 30 + util_zip_blob_to_num(p_zipped_blob, 4, t_offs + 18) -- compressed size + util_zip_blob_to_num(p_zipped_blob, 2, t_offs + 26) -- file name length + util_zip_blob_to_num(p_zipped_blob, 2, t_offs + 28); -- extra field length END LOOP; - t_offs_end_header := dbms_lob.getlength(p_zipped_blob); dbms_lob.append( p_zipped_blob, @@ -514,26 +503,11 @@ BEGIN util_zip_little_endian(t_offs_end_header - t_offs_dir_header), -- size of central directory util_zip_little_endian(t_offs_dir_header), -- offset of start of central directory, relative to start of archive util_zip_little_endian(nvl(utl_raw.length(t_comment), 0), 2), -- ZIP file comment length - t_comment - ) - ); - + t_comment)); END util_zip_finish; -------------------------------------------------------------------------------------------------------------------------------- -/* FIXME: implement this -FUNCTION util_multireplace ( - p_source_string VARCHAR2, - p_replacements tab_varchar2 -) RETURN VARCHAR2 IS -BEGIN - NULL; -END; -*/ - --------------------------------------------------------------------------------------------------------------------------------- - FUNCTION util_multi_replace ( p_source_string VARCHAR2, p_01_find VARCHAR2 DEFAULT NULL, p_01_replace VARCHAR2 DEFAULT NULL, @@ -579,7 +553,6 @@ BEGIN || ',p_build_status=>''RUN_ONLY''' || c_lf || substr(p_app_export_sql, v_position); - END util_set_build_status_run_only; -------------------------------------------------------------------------------------------------------------------------------- @@ -593,8 +566,7 @@ BEGIN replace( q'[SELECT systimestamp - INTERVAL '{{MINUTES}}' MINUTE FROM dual]', '{{MINUTES}}', - TO_CHAR(p_as_of_minutes_ago) - ) + TO_CHAR(p_as_of_minutes_ago)) INTO v_return; RETURN v_return; END util_calc_data_timestamp; @@ -639,21 +611,20 @@ PROCEDURE util_ensure_unique_file_names ( v_count PLS_INTEGER; BEGIN util_log_start('ensure unique file names in collection'); - -$if $$apex_installed $then + -- + $if $$apex_installed $then -- find apex install file FOR i IN 1..p_export_files.count LOOP IF p_export_files(i).name = 'scripts/install_frontend_generated_by_apex.sql' THEN v_apex_install_file_id := i; END IF; END LOOP; -$end - + $end + -- FOR i IN 1..p_export_files.count LOOP - v_file_name := p_export_files(i).name; v_count := 1; - + -- IF instr(v_file_name, '.') > 0 THEN v_base_name := substr(v_file_name, 1, instr(v_file_name, '.', -1) - 1); v_extension := substr(v_file_name, instr(v_file_name, '.', -1)); @@ -661,24 +632,20 @@ $end v_base_name := v_file_name; v_extension := NULL; END IF; - + -- WHILE v_file_list_lookup.EXISTS(v_file_name) LOOP v_count := v_count + 1; v_file_name := v_base_name || '_' || v_count || v_extension; END LOOP; - + -- v_file_list_lookup(v_file_name) := i; - -- correct data if needed IF p_export_files(i).name != v_file_name THEN - -- correct the prompt statement p_export_files(i).contents := replace( p_export_files(i).contents, v_base_name, - v_base_name || '_' || v_count - ); - + v_base_name || '_' || v_count); -- correct the apex install file IF v_apex_install_file_id IS NOT NULL THEN p_export_files(v_apex_install_file_id).contents := regexp_replace( @@ -687,19 +654,13 @@ $end v_file_name, 1, 2, - 'm' - ); + 'm'); END IF; - -- correct the file name itself p_export_files(i).name := v_file_name; - END IF; - END LOOP; - util_log_stop; - END util_ensure_unique_file_names; -------------------------------------------------------------------------------------------------------------------------------- @@ -727,8 +688,7 @@ PROCEDURE util_log_start ( BEGIN dbms_application_info.set_module( module_name => g_runlog.module, - action_name => p_action - ); + action_name => p_action); v_index := g_runlog.data.count + 1; g_runlog.data(v_index).action := substr(p_action, 1, plex.c_app_info_length); g_runlog.data(v_index).start_time := systimestamp; @@ -767,8 +727,7 @@ BEGIN v_index := g_runlog.data.count; dbms_application_info.set_module( module_name => NULL, - action_name => NULL - ); + action_name => NULL); g_runlog.data(v_index).stop_time := systimestamp; g_runlog.data(v_index).elapsed := util_log_get_runtime(g_runlog.start_time, g_runlog.data(v_index).stop_time); g_runlog.data(v_index).execution := util_log_get_runtime(g_runlog.data(v_index).start_time, g_runlog.data(v_index).stop_time); @@ -787,6 +746,8 @@ BEGIN --https://stackoverflow.com/questions/10092032/extracting-the-total-number-of-seconds-from-an-interval-data-type END util_log_get_runtime; +-------------------------------------------------------------------------------------------------------------------------------- + PROCEDURE util_log_calc_runtimes IS BEGIN g_runlog.stop_time := systimestamp; @@ -854,8 +815,7 @@ BEGIN p_export_files.extend; p_export_files(v_index) := rec_export_file( name => p_name, - contents => g_clob - ); + contents => g_clob); g_clob := null; END util_clob_add_to_export_files; @@ -871,7 +831,7 @@ PROCEDURE util_clob_query_to_csv ( -- inspired by Tim Hall: https://oracle-base.com/dba/script?category=miscellaneous&file=csv.sql v_line_terminator VARCHAR2(2) := c_crlf; -- to be compatible with Excel we need to use crlf here (multiline text uses lf and is wrapped in quotes) v_cursor PLS_INTEGER; - v_ignore PLS_INTEGER; + v_ignore_me PLS_INTEGER; v_data_count PLS_INTEGER := 0; v_col_cnt PLS_INTEGER; v_desc_tab dbms_sql.desc_tab3; @@ -917,8 +877,7 @@ PROCEDURE util_clob_query_to_csv ( v_buffer_varchar2 := replace( replace(v_buffer_varchar2, c_crlf, c_lf), c_cr, - c_lf - ); + c_lf); -- if we have the parameter p_force_quotes set to true or the delimiter character or -- line feeds in the string then we have to wrap the text in quotes marks and escape @@ -937,16 +896,16 @@ PROCEDURE util_clob_query_to_csv ( BEGIN IF p_query IS NOT NULL THEN - v_cursor := dbms_sql.open_cursor; + v_cursor := dbms_sql.open_cursor; dbms_sql.parse( v_cursor, regexp_replace(p_query, ';\s*$', NULL), - dbms_sql.native - ); + dbms_sql.native); -- https://support.esri.com/en/technical-article/000010110 -- http://bluefrog-oracle.blogspot.com/2011/11/describing-ref-cursor-using-dbmssql-api.html dbms_sql.describe_columns3(v_cursor, v_col_cnt, v_desc_tab); + FOR i IN 1..v_col_cnt LOOP IF v_desc_tab(i).col_type = c_clob THEN dbms_sql.define_column(v_cursor, i, v_buffer_clob); @@ -961,7 +920,7 @@ BEGIN END IF; END LOOP; - v_ignore := dbms_sql.execute(v_cursor); + v_ignore_me := dbms_sql.execute(v_cursor); -- create header util_clob_append(p_header_prefix); @@ -979,11 +938,11 @@ BEGIN -- create data LOOP EXIT WHEN dbms_sql.fetch_rows(v_cursor) = 0 OR v_data_count = p_max_rows; + FOR i IN 1..v_col_cnt LOOP IF i > 1 THEN util_clob_append(p_delimiter); END IF; - -- IF v_desc_tab(i).col_type = c_clob THEN dbms_sql.column_value(v_cursor, i, v_buffer_clob); IF length(v_buffer_clob) <= c_vc2_max_size THEN @@ -994,7 +953,6 @@ BEGIN v_buffer_varchar2 := 'CLOB value skipped - larger then ' || c_vc2_max_size || ' characters'; util_clob_append(v_buffer_varchar2); END IF; - ELSIF v_desc_tab(i).col_type = c_xmltype THEN dbms_sql.column_value(v_cursor, i, v_buffer_xmltype); v_buffer_clob := v_buffer_xmltype.getclobval(); @@ -1006,7 +964,6 @@ BEGIN v_buffer_varchar2 := 'XML value skipped - larger then ' || c_vc2_max_size || ' characters'; util_clob_append(v_buffer_varchar2); END IF; - ELSIF v_desc_tab(i).col_type = c_long THEN dbms_sql.column_value_long(v_cursor, i, c_vc2_max_size, 0, v_buffer_varchar2, v_buffer_long_length); IF v_buffer_long_length <= c_vc2_max_size THEN @@ -1015,16 +972,13 @@ BEGIN ELSE util_clob_append('LONG value skipped - larger then ' || c_vc2_max_size || ' characters'); END IF; - ELSIF v_desc_tab(i).col_type IN (c_raw, c_long_raw, c_blob, c_bfile) THEN util_clob_append('Binary data type skipped - not supported for CSV'); - ELSE dbms_sql.column_value(v_cursor, i, v_buffer_varchar2); escape_varchar2_buffer_for_csv; util_clob_append(v_buffer_varchar2); END IF; - END LOOP; util_clob_append(v_line_terminator); @@ -1037,21 +991,17 @@ END util_clob_query_to_csv; -------------------------------------------------------------------------------------------------------------------------------- -PROCEDURE util_clob_create_error_log (p_export_files IN OUT NOCOPY tab_export_files) IS +PROCEDURE util_clob_create_error_log ( + p_export_files IN OUT NOCOPY tab_export_files +) IS BEGIN IF g_errlog.count > 0 THEN util_log_start(g_errlog.count || ' error' || CASE WHEN g_errlog.count != 1 THEN 's' END || ' occurred: create error log'); -- prepend header util_clob_append( - util_multi_replace( - '{{HASH}} {{MAIN_FUNCTION}} - Error Log', - '{{HASH}}', - c_hash, - '{{MAIN_FUNCTION}}', - upper(g_runlog.module) - ) || c_crlf || c_crlf || c_crlf - ); + replace('# {{MAIN_FUNCTION}} - Error Log', '{{MAIN_FUNCTION}}', upper(g_runlog.module)) + || c_crlf || c_crlf || c_crlf); FOR i IN 1..g_errlog.count LOOP util_clob_append('## ' || g_errlog(i).file_name || c_crlf || c_crlf); @@ -1062,79 +1012,52 @@ BEGIN -- add error log to file collection util_clob_add_to_export_files( p_export_files => p_export_files, - p_name => 'plex_error_log.md' - ); + p_name => 'plex_error_log.md'); util_log_stop; - END IF; - END util_clob_create_error_log; -------------------------------------------------------------------------------------------------------------------------------- -PROCEDURE util_clob_create_runtime_log (p_export_files IN OUT NOCOPY tab_export_files) IS +PROCEDURE util_clob_create_runtime_log ( + p_export_files IN OUT NOCOPY tab_export_files +) IS BEGIN util_log_calc_runtimes; - util_clob_append(util_multi_replace( - '{{HASH}} {{MAIN_FUNCTION}} - Runtime Log + util_clob_append(util_multi_replace('# {{MAIN_FUNCTION}} - Runtime Log -- Export started at {{START_TIME}} and took {{RUN_TIME}} seconds to finish +- Export started at {{START_TIME}} and took {{RUN_TIME}} seconds to finish with {{ERRORCOUNT}} errors - Unmeasured execution time because of system waits, missing log calls or log overhead was {{UNMEASURED_TIME}} seconds - The used PLEX version was {{PLEX_VERSION}} - More infos here: [PLEX on GitHub]({{PLEX_URL}}) -' , - '{{HASH}}', - c_hash, - '{{MAIN_FUNCTION}}', - upper(g_runlog.module), - '{{START_TIME}}', - TO_CHAR( - g_runlog.start_time, - 'yyyy-mm-dd hh24:mi:ss' - ), - '{{RUN_TIME}}', - trim(TO_CHAR( - g_runlog.run_time, - '999G990D000' - )), - '{{UNMEASURED_TIME}}', - trim(TO_CHAR( - g_runlog.unmeasured_time, - '999G990D000000' - )), - '{{PLEX_VERSION}}', - c_plex_version, - '{{PLEX_URL}}', - c_plex_url +' , + '{{MAIN_FUNCTION}}', upper(g_runlog.module), + '{{START_TIME}}', TO_CHAR(g_runlog.start_time, 'yyyy-mm-dd hh24:mi:ss'), + '{{RUN_TIME}}', trim(TO_CHAR(g_runlog.run_time, '999G990D000')), + '{{UNMEASURED_TIME}}', trim(TO_CHAR(g_runlog.unmeasured_time, '999G990D000')), + '{{PLEX_VERSION}}', c_plex_version, + '{{PLEX_URL}}', c_plex_url, + '{{ERRORCOUNT}}', g_errlog.count )); util_clob_append(' | Step | Elapsed | Execution | Action | |------:|----------:|------------:|:-----------------------------------------------------------------| -' +' ); - ); FOR i IN 1..g_runlog.data.count LOOP util_clob_append(util_multi_replace( '| {{STEP}} | {{ELAPSED}} | {{EXECUTION}} | {{ACTION}} |' || c_lf, - '{{STEP}}', - lpad(TO_CHAR(i), 5), - '{{ELAPSED}}', - lpad(trim(TO_CHAR(g_runlog.data(i).elapsed, '99990D000')), 9), - '{{EXECUTION}}', - lpad(trim(TO_CHAR(g_runlog.data(i).execution, '9990D000000')), 11), - '{{ACTION}}', - rpad(g_runlog.data(i).action, 64) - )); + '{{STEP}}', lpad(TO_CHAR(i), 5), + '{{ELAPSED}}', lpad(trim(TO_CHAR(g_runlog.data(i).elapsed, '99990D000')), 9), + '{{EXECUTION}}', lpad(trim(TO_CHAR(g_runlog.data(i).execution, '9990D000000')), 11), + '{{ACTION}}', rpad(g_runlog.data(i).action, 64))); END LOOP; - util_clob_add_to_export_files( - p_export_files => p_export_files, - p_name => 'plex_runtime_log.md' - ); - + p_export_files => p_export_files, + p_name => 'plex_runtime_log.md'); END util_clob_create_runtime_log; @@ -1144,7 +1067,7 @@ END util_clob_create_runtime_log; ------------------------------------------------------------------------------------------------------------------------------ FUNCTION backapp ( -$if $$apex_installed $then + $if $$apex_installed $then p_app_id IN NUMBER DEFAULT NULL, p_app_date IN BOOLEAN DEFAULT true, p_app_public_reports IN BOOLEAN DEFAULT true, @@ -1158,7 +1081,7 @@ $if $$apex_installed $then p_app_supporting_objects IN VARCHAR2 DEFAULT NULL, p_app_include_single_file IN BOOLEAN DEFAULT false, p_app_build_status_run_only IN BOOLEAN DEFAULT false, -$end + $end p_include_object_ddl IN BOOLEAN DEFAULT false, p_object_type_like IN VARCHAR2 DEFAULT NULL, p_object_type_not_like IN VARCHAR2 DEFAULT NULL, @@ -1197,23 +1120,23 @@ $end BEGIN util_log_init( p_module => 'plex.backapp' - $if $$apex_installed $then || CASE WHEN p_app_id IS NOT NULL THEN '(' || TO_CHAR(p_app_id) || ')' END $end - ); + $if $$apex_installed $then + || CASE WHEN p_app_id IS NOT NULL THEN '(' || TO_CHAR(p_app_id) || ')' END + $end); util_log_start('init'); - v_export_files := NEW tab_export_files(); - v_current_user := sys_context('USERENV', 'CURRENT_USER'); + v_export_files := NEW tab_export_files(); + v_current_user := sys_context('USERENV', 'CURRENT_USER'); util_log_stop; END init; -$if $$apex_installed $then + $if $$apex_installed $then PROCEDURE check_owner IS CURSOR cur_owner IS - SELECT workspace, - owner, - alias - FROM apex_applications t - WHERE t.application_id = p_app_id; - + SELECT workspace, + owner, + alias + FROM apex_applications t + WHERE t.application_id = p_app_id; BEGIN util_log_start('check_owner'); IF p_app_id IS NOT NULL THEN @@ -1228,80 +1151,68 @@ $if $$apex_installed $then IF p_app_id IS NOT NULL AND v_app_owner IS NULL THEN raise_application_error( -20101, - 'Could not find owner for application - are you sure you provided the right app_id?' - ); + 'Could not find owner for application - are you sure you provided the right app_id?'); ELSIF p_app_id IS NOT NULL AND v_app_owner != v_current_user THEN raise_application_error( -20102, - 'You are not the owner of the app - please login as the owner.' - ); + 'You are not the owner of the app - please login as the owner.'); END IF; - util_log_stop; END check_owner; -$end + $end -$if $$apex_installed $then + $if $$apex_installed $then PROCEDURE process_apex_app IS v_apex_files apex_t_export_files; BEGIN - -- save as individual files util_log_start(p_base_path_frontend || '/APEX_EXPORT:individual_files'); v_apex_files := apex_export.get_application( - p_application_id => p_app_id, - p_split => true, - p_with_date => p_app_date, - p_with_ir_public_reports => p_app_public_reports, - p_with_ir_private_reports => p_app_private_reports, - p_with_ir_notifications => p_app_notifications, - p_with_translations => p_app_translations, - p_with_pkg_app_mapping => p_app_pkg_app_mapping, - p_with_original_ids => p_app_original_ids, - p_with_no_subscriptions => CASE WHEN p_app_subscriptions THEN false ELSE true END, - p_with_comments => p_app_comments, - p_with_supporting_objects => p_app_supporting_objects - ); + p_application_id => p_app_id, + p_split => true, + p_with_date => p_app_date, + p_with_ir_public_reports => p_app_public_reports, + p_with_ir_private_reports => p_app_private_reports, + p_with_ir_notifications => p_app_notifications, + p_with_translations => p_app_translations, + p_with_pkg_app_mapping => p_app_pkg_app_mapping, + p_with_original_ids => p_app_original_ids, + p_with_no_subscriptions => CASE WHEN p_app_subscriptions THEN false ELSE true END, + p_with_comments => p_app_comments, + p_with_supporting_objects => p_app_supporting_objects); FOR i IN 1..v_apex_files.count LOOP v_export_files.extend; -- relocate files to own project structure - v_export_files(i).name := replace( + v_export_files(i).name := replace( v_apex_files(i).name, 'f' || p_app_id || '/application/', - p_base_path_frontend || '/' - ); + p_base_path_frontend || '/'); -- correct prompts for relocation - v_export_files(i).contents := replace( + v_export_files(i).contents := replace( v_apex_files(i).contents, 'prompt --application/', - 'prompt --' || p_base_path_frontend || '/' - ); + 'prompt --' || p_base_path_frontend || '/'); v_apex_files.DELETE(i); -- special handling for install file IF v_export_files(i).name = 'f' || p_app_id || '/install.sql' THEN - v_export_files(i).name := 'scripts/install_frontend_generated_by_apex.sql'; - v_export_files(i).contents := '-- DO NOT TOUCH THIS FILE - IT WILL BE OVERWRITTEN ON NEXT PLEX BACKAPP CALL' || c_lf || c_lf - || replace( - replace( - v_export_files(i).contents, - '@application/', - '@../' || p_base_path_frontend || '/' - ), - 'prompt --install', - 'prompt --install_frontend_generated_by_apex' - ); + v_export_files(i).name := 'scripts/install_frontend_generated_by_apex.sql'; + v_export_files(i).contents := '-- DO NOT TOUCH THIS FILE - IT WILL BE OVERWRITTEN ON NEXT PLEX BACKAPP CALL' + || c_lf || c_lf + || util_multi_replace( + v_export_files(i).contents, + '@application/', '@../' || p_base_path_frontend || '/', + 'prompt --install', 'prompt --install_frontend_generated_by_apex'); END IF; -- handle build status RUN_ONLY IF v_export_files(i).name = p_base_path_frontend || '/create_application.sql' AND p_app_build_status_run_only THEN v_export_files(i).contents := util_set_build_status_run_only(v_export_files(i).contents); END IF; - END LOOP; util_log_stop; @@ -1310,32 +1221,30 @@ $if $$apex_installed $then v_apex_files.DELETE; util_log_start(p_base_path_frontend || '/APEX_EXPORT:single_file'); v_apex_files := apex_export.get_application( - p_application_id => p_app_id, - p_split => false, - p_with_date => p_app_date, - p_with_ir_public_reports => p_app_public_reports, - p_with_ir_private_reports => p_app_private_reports, - p_with_ir_notifications => p_app_notifications, - p_with_translations => p_app_translations, - p_with_pkg_app_mapping => p_app_pkg_app_mapping, - p_with_original_ids => p_app_original_ids, - p_with_no_subscriptions => CASE WHEN p_app_subscriptions THEN false ELSE true END, - p_with_comments => p_app_comments, - p_with_supporting_objects => p_app_supporting_objects - ); + p_application_id => p_app_id, + p_split => false, + p_with_date => p_app_date, + p_with_ir_public_reports => p_app_public_reports, + p_with_ir_private_reports => p_app_private_reports, + p_with_ir_notifications => p_app_notifications, + p_with_translations => p_app_translations, + p_with_pkg_app_mapping => p_app_pkg_app_mapping, + p_with_original_ids => p_app_original_ids, + p_with_no_subscriptions => CASE WHEN p_app_subscriptions THEN false ELSE true END, + p_with_comments => p_app_comments, + p_with_supporting_objects => p_app_supporting_objects); IF p_app_build_status_run_only THEN v_apex_files(1).contents := util_set_build_status_run_only(v_apex_files(1).contents); END IF; util_clob_append(v_apex_files(1).contents); util_clob_add_to_export_files( p_export_files => v_export_files, - p_name => p_base_path_frontend || '/' || v_apex_files(1).name - ); + p_name => p_base_path_frontend || '/' || v_apex_files(1).name); v_apex_files.DELETE; util_log_stop; END IF; END process_apex_app; -$end + $end PROCEDURE replace_query_like_expressions ( p_like_list VARCHAR2, @@ -1345,53 +1254,34 @@ $end ) IS v_expression_table tab_varchar2; BEGIN - - -- process filter "like" - v_expression_table := util_split( - p_like_list, - ',' - ); - FOR i IN 1..v_expression_table.count LOOP v_expression_table(i) := p_column_name || ' like ''' || trim(v_expression_table(i - )) || ''' escape ''\'''; + -- process filter "like" + v_expression_table := util_split(p_like_list, ','); + FOR i IN 1..v_expression_table.count LOOP + v_expression_table(i) := p_column_name + || ' like ''' + || trim(v_expression_table(i)) + || ''' escape ''\'''; END LOOP; - v_query := replace( v_query, '#' || p_placeholder_prefix || '_LIKE_EXPRESSIONS#', - nvl( - util_join( - v_expression_table, - ' or ' - ), - '1 = 1' - ) - ); + nvl(util_join(v_expression_table, ' or '), '1 = 1')); -- process filter "not like" - v_expression_table := util_split( - p_not_like_list, - ',' - ); - FOR i IN 1..v_expression_table.count LOOP v_expression_table(i) := p_column_name || ' not like ''' || trim(v_expression_table - (i)) || ''' escape ''\'''; + v_expression_table := util_split(p_not_like_list, ','); + FOR i IN 1..v_expression_table.count LOOP + v_expression_table(i) := p_column_name + || ' not like ''' + || trim(v_expression_table (i)) + || ''' escape ''\'''; END LOOP; - v_query := replace( v_query, '#' || p_placeholder_prefix || '_NOT_LIKE_EXPRESSIONS#', - nvl( - util_join( - v_expression_table, - ' and ' - ), - '1 = 1' - ) - ); - + nvl( util_join( v_expression_table, ' and ' ), '1 = 1')); $if $$debug_on $then dbms_output.put_line(v_query); $end - END replace_query_like_expressions; PROCEDURE process_user_ddl IS @@ -1404,7 +1294,7 @@ $end util_clob_append(util_multi_replace(q'^ BEGIN FOR i IN (SELECT '{{CURRENT_USER}}' AS username FROM dual - MINUS + MINUS SELECT username FROM dba_users) LOOP EXECUTE IMMEDIATE q'[ -------------------------------------------------------------------------------- @@ -1413,17 +1303,15 @@ BEGIN ]' END LOOP; END; -{{SLASH}} -^', +{{/}} +^' , '{{CURRENT_USER}}', v_current_user, - '{{DDL}}', dbms_metadata.get_ddl('USER', v_current_user), - '{{SLASH}}', c_slash + '{{DDL}}', dbms_metadata.get_ddl('USER', v_current_user), + '{{/}}', c_slash )); - util_clob_add_to_export_files( - p_export_files => v_export_files, - p_name => v_file_path - ); + p_export_files => v_export_files, + p_name => v_file_path); util_setup_dbms_metadata; util_log_stop; EXCEPTION @@ -1433,24 +1321,17 @@ END; END; -- roles - BEGIN v_file_path := p_base_path_backend || '/_user/' || v_current_user || '_roles.sql'; util_log_start(v_file_path); - FOR i IN ( - -- ensure we get no dbms_metadata error when no role privs exists - SELECT DISTINCT username - FROM user_role_privs - ) LOOP util_clob_append(dbms_metadata.get_granted_ddl( - 'ROLE_GRANT', - v_current_user - )); + FOR i IN (SELECT DISTINCT username FROM user_role_privs) LOOP + util_clob_append(dbms_metadata.get_granted_ddl( + 'ROLE_GRANT', + v_current_user)); END LOOP; - util_clob_add_to_export_files( - p_export_files => v_export_files, - p_name => v_file_path - ); + p_export_files => v_export_files, + p_name => v_file_path); util_log_stop; EXCEPTION WHEN OTHERS THEN @@ -1458,24 +1339,17 @@ END; END; -- system privileges - BEGIN v_file_path := p_base_path_backend || '/_user/' || v_current_user || '_system_privileges.sql'; util_log_start(v_file_path); - FOR i IN ( - -- ensure we get no dbms_metadata error when no sys privs exists - SELECT DISTINCT username - FROM user_sys_privs - ) LOOP util_clob_append(dbms_metadata.get_granted_ddl( - 'SYSTEM_GRANT', - v_current_user - )); + FOR i IN (SELECT DISTINCT username FROM user_sys_privs) LOOP + util_clob_append(dbms_metadata.get_granted_ddl( + 'SYSTEM_GRANT', + v_current_user)); END LOOP; - util_clob_add_to_export_files( - p_export_files => v_export_files, - p_name => v_file_path - ); + p_export_files => v_export_files, + p_name => v_file_path); util_log_stop; EXCEPTION WHEN OTHERS THEN @@ -1483,40 +1357,29 @@ END; END; -- object privileges - BEGIN v_file_path := p_base_path_backend || '/_user/' || v_current_user || '_object_privileges.sql'; util_log_start(v_file_path); - FOR i IN ( - -- ensure we get no dbms_metadata error when no object grants exists - SELECT DISTINCT grantee - FROM user_tab_privs - WHERE grantee = v_current_user - ) LOOP util_clob_append(dbms_metadata.get_granted_ddl( - 'OBJECT_GRANT', - v_current_user - )); + FOR i IN (SELECT DISTINCT grantee FROM user_tab_privs WHERE grantee = v_current_user) LOOP + util_clob_append(dbms_metadata.get_granted_ddl( + 'OBJECT_GRANT', + v_current_user)); END LOOP; - util_clob_add_to_export_files( - p_export_files => v_export_files, - p_name => v_file_path - ); + p_export_files => v_export_files, + p_name => v_file_path); util_log_stop; EXCEPTION WHEN OTHERS THEN util_log_error(v_file_path); END; - END process_user_ddl; PROCEDURE process_object_ddl IS - TYPE obj_rec_typ IS RECORD ( object_type VARCHAR2(128), object_name VARCHAR2(256), - file_path VARCHAR2(512) - ); + file_path VARCHAR2(512)); v_rec obj_rec_typ; BEGIN util_log_start(p_base_path_backend || '/open_objects_cursor'); @@ -1524,104 +1387,93 @@ END; --https://stackoverflow.com/questions/10886450/how-to-generate-entire-ddl-of-an-oracle-schema-scriptable --https://stackoverflow.com/questions/3235300/oracles-dbms-metadata-get-ddl-for-object-type-job SELECT CASE object_type - --http://psoug.org/reference/dbms_metadata.html - WHEN 'UNIFIED AUDIT POLICY' THEN 'AUDIT_OBJ' - WHEN 'CONSUMER GROUP' THEN 'RMGR_CONSUMER_GROUP' - WHEN 'DATABASE LINK' THEN 'DB_LINK' - WHEN 'EVALUATION CONTEXT' THEN 'PROCOBJ' - WHEN 'JAVA CLASS' THEN 'JAVA_CLASS' - WHEN 'JAVA RESOURCE' THEN 'JAVA_RESOURCE' - WHEN 'JAVA SOURCE' THEN 'JAVA_SOURCE' - WHEN 'JAVA TYPE' THEN 'JAVA_TYPE' - WHEN 'JOB' THEN 'PROCOBJ' - WHEN 'JOB CLASS' THEN 'PROCOBJ' - WHEN 'MATERIALIZED VIEW' THEN 'MATERIALIZED_VIEW' - WHEN 'PACKAGE BODY' THEN 'PACKAGE_BODY' - WHEN 'PACKAGE' THEN 'PACKAGE_SPEC' - WHEN 'PROGRAM' THEN 'PROCOBJ' - WHEN 'QUEUE' THEN 'AQ_QUEUE' - WHEN 'RESOURCE PLAN' THEN 'RMGR_PLAN' - WHEN 'RULE SET' THEN 'PROCOBJ' - WHEN 'RULE' THEN 'PROCOBJ' - WHEN 'SCHEDULE' THEN 'PROCOBJ' - WHEN 'SCHEDULER GROUP' THEN 'PROCOBJ' - WHEN 'TYPE BODY' THEN 'TYPE_BODY' - WHEN 'TYPE' THEN 'TYPE_SPEC' - ELSE object_type - END AS object_type, - object_name, - '{{BASE_PATH_APP_BACKEND}}/' || - replace( - lower( + --http://psoug.org/reference/dbms_metadata.html + WHEN 'UNIFIED AUDIT POLICY' THEN 'AUDIT_OBJ' + WHEN 'CONSUMER GROUP' THEN 'RMGR_CONSUMER_GROUP' + WHEN 'DATABASE LINK' THEN 'DB_LINK' + WHEN 'EVALUATION CONTEXT' THEN 'PROCOBJ' + WHEN 'JAVA CLASS' THEN 'JAVA_CLASS' + WHEN 'JAVA RESOURCE' THEN 'JAVA_RESOURCE' + WHEN 'JAVA SOURCE' THEN 'JAVA_SOURCE' + WHEN 'JAVA TYPE' THEN 'JAVA_TYPE' + WHEN 'JOB' THEN 'PROCOBJ' + WHEN 'JOB CLASS' THEN 'PROCOBJ' + WHEN 'MATERIALIZED VIEW' THEN 'MATERIALIZED_VIEW' + WHEN 'PACKAGE BODY' THEN 'PACKAGE_BODY' + WHEN 'PACKAGE' THEN 'PACKAGE_SPEC' + WHEN 'PROGRAM' THEN 'PROCOBJ' + WHEN 'QUEUE' THEN 'AQ_QUEUE' + WHEN 'RESOURCE PLAN' THEN 'RMGR_PLAN' + WHEN 'RULE SET' THEN 'PROCOBJ' + WHEN 'RULE' THEN 'PROCOBJ' + WHEN 'SCHEDULE' THEN 'PROCOBJ' + WHEN 'SCHEDULER GROUP' THEN 'PROCOBJ' + WHEN 'TYPE BODY' THEN 'TYPE_BODY' + WHEN 'TYPE' THEN 'TYPE_SPEC' + ELSE object_type + END AS object_type, + object_name, + '{{BASE_PATH_APP_BACKEND}}/' + || replace(lower( CASE WHEN object_type LIKE '%S' THEN object_type || 'ES' WHEN object_type LIKE '%EX' THEN regexp_replace(object_type, 'EX$', 'ICES', 1, 0, 'i') WHEN object_type LIKE '%Y' THEN regexp_replace(object_type, 'Y$', 'IES', 1, 0, 'i') ELSE object_type || 'S' - END - ), - ' ', - '_' - ) || '/' || object_name || - CASE object_type - WHEN 'FUNCTION' THEN '.fnc' - WHEN 'PACKAGE BODY' THEN '.pkb' - WHEN 'PACKAGE' THEN '.pks' - WHEN 'PROCEDURE' THEN '.prc' - WHEN 'TRIGGER' THEN '.trg' - WHEN 'TYPE BODY' THEN '.tpb' - WHEN 'TYPE' THEN '.tps' - ELSE '.sql' - END AS file_path -FROM ^' + END), ' ', '_') + || '/' || object_name + || CASE object_type + WHEN 'FUNCTION' THEN '.fnc' + WHEN 'PACKAGE BODY' THEN '.pkb' + WHEN 'PACKAGE' THEN '.pks' + WHEN 'PROCEDURE' THEN '.prc' + WHEN 'TRIGGER' THEN '.trg' + WHEN 'TYPE BODY' THEN '.tpb' + WHEN 'TYPE' THEN '.tps' + ELSE '.sql' + END AS file_path + FROM ^' $if NOT $$debug_on $then || 'user_objects' $else || '(SELECT MIN(object_name) AS object_name, object_type FROM user_objects GROUP BY object_type)' $end || q'^ -WHERE -- ignore invalid object types - object_type NOT IN ('UNDEFINED','DESTINATION','EDITION','JAVA DATA','WINDOW') - --These objects are included within other object types: - AND object_type NOT IN ('INDEX PARTITION','INDEX SUBPARTITION','LOB','LOB PARTITION','TABLE PARTITION','TABLE SUBPARTITION') - --Ignore system-generated types for collection processing: - AND NOT (object_type = 'TYPE' AND object_name LIKE 'SYS_PLSQL_%') - --Ignore system-generated sequences for identity columns: - AND NOT (object_type = 'SEQUENCE' AND object_name LIKE 'ISEQ$$_%') - --Ignore LOB indices, their DDL is part of the table: - AND object_name NOT IN (SELECT index_name FROM user_lobs) - --Ignore nested tables, their DDL is part of their parent table: - AND object_name NOT IN (SELECT table_name FROM user_nested_tables) - --Set user specific like filters: - AND (#TYPE_LIKE_EXPRESSIONS#) - AND (#TYPE_NOT_LIKE_EXPRESSIONS#) - AND (#NAME_LIKE_EXPRESSIONS#) - AND (#NAME_NOT_LIKE_EXPRESSIONS#) -ORDER BY - object_type, - object_name -^' - ; - v_query := replace( + WHERE -- ignore invalid object types + object_type NOT IN ('UNDEFINED','DESTINATION','EDITION','JAVA DATA','WINDOW') + --These objects are included within other object types: + AND object_type NOT IN ('INDEX PARTITION','INDEX SUBPARTITION','LOB','LOB PARTITION','TABLE PARTITION','TABLE SUBPARTITION') + --Ignore system-generated types for collection processing: + AND NOT (object_type = 'TYPE' AND object_name LIKE 'SYS_PLSQL_%') + --Ignore system-generated sequences for identity columns: + AND NOT (object_type = 'SEQUENCE' AND object_name LIKE 'ISEQ$$_%') + --Ignore LOB indices, their DDL is part of the table: + AND object_name NOT IN (SELECT index_name FROM user_lobs) + --Ignore nested tables, their DDL is part of their parent table: + AND object_name NOT IN (SELECT table_name FROM user_nested_tables) + --Set user specific like filters: + AND (#TYPE_LIKE_EXPRESSIONS#) + AND (#TYPE_NOT_LIKE_EXPRESSIONS#) + AND (#NAME_LIKE_EXPRESSIONS#) + AND (#NAME_NOT_LIKE_EXPRESSIONS#) + ORDER BY + object_type, + object_name +^' ; + v_query := replace( v_query, '{{BASE_PATH_APP_BACKEND}}', - p_base_path_backend - ); + p_base_path_backend); replace_query_like_expressions( - p_like_list => p_object_type_like, - p_not_like_list => p_object_type_not_like, - p_placeholder_prefix => 'TYPE', - p_column_name => 'object_type' - ); - + p_like_list => p_object_type_like, + p_not_like_list => p_object_type_not_like, + p_placeholder_prefix => 'TYPE', + p_column_name => 'object_type'); replace_query_like_expressions( - p_like_list => p_object_name_like, - p_not_like_list => p_object_name_not_like, - p_placeholder_prefix => 'NAME', - p_column_name => 'object_name' - ); - + p_like_list => p_object_name_like, + p_not_like_list => p_object_name_not_like, + p_placeholder_prefix => 'NAME', + p_column_name => 'object_name'); util_setup_dbms_metadata; OPEN v_cur FOR v_query; - util_log_stop; LOOP FETCH v_cur INTO v_rec; @@ -1654,108 +1506,74 @@ ORDER BY ELSE v_ddl_files.other_objects_(v_ddl_files.other_objects_.count + 1) := v_rec.file_path; END CASE; - CASE WHEN v_rec.object_type = 'VIEW' THEN - util_clob_append(ltrim( - regexp_replace( - regexp_replace( - dbms_metadata.get_ddl( - object_type => v_rec.object_type, - name => v_rec.object_name, - schema => v_current_user - ), - '\(.*\) ', - -- remove additional column list from the compiler - NULL, - 1, - 1 - ), - '^\s*SELECT', - -- remove additional whitespace from the compiler - 'SELECT', - 1, - 1, - 'im' - ), - ' ' || c_lf - )); - + util_clob_append(ltrim(regexp_replace(regexp_replace( + -- source string + dbms_metadata.get_ddl( + object_type => v_rec.object_type, + name => v_rec.object_name, + schema => v_current_user), + -- regex replace: remove additional column list from the compiler + '\(.*\) ', NULL, 1, 1), + -- regex replace: remove additional whitespace from the compiler + '^\s*SELECT', 'SELECT', 1, 1, 'im'), + -- ltrim: remove leading whitspace + ' ' || c_lf)); util_clob_add_to_export_files( - p_export_files => v_export_files, - p_name => v_rec.file_path - ); - WHEN v_rec.object_type IN ( - 'TABLE', - 'INDEX', - 'SEQUENCE' - ) THEN + p_export_files => v_export_files, + p_name => v_rec.file_path); + WHEN v_rec.object_type IN ('TABLE', 'INDEX', 'SEQUENCE') THEN util_setup_dbms_metadata(p_sqlterminator => false); - util_clob_append(replace( - q'^ + util_clob_append(replace(q'^ BEGIN -FOR i IN (SELECT '{{OBJECT_NAME}}' AS object_name FROM dual - MINUS - SELECT object_name FROM user_objects) LOOP - EXECUTE IMMEDIATE q'[ + FOR i IN (SELECT '{{OBJECT_NAME}}' AS object_name FROM dual + MINUS + SELECT object_name FROM user_objects) LOOP + EXECUTE IMMEDIATE q'[ -------------------------------------------------------------------------------- -^' - , +^' , '{{OBJECT_NAME}}', - v_rec.object_name - ) || dbms_metadata.get_ddl( - object_type => v_rec.object_type, - name => v_rec.object_name, - schema => v_current_user - ) || replace( - q'^ + v_rec.object_name) + || dbms_metadata.get_ddl( v_rec.object_type, v_rec.object_name, v_current_user ) + || replace(q'^ -------------------------------------------------------------------------------- - ]'; -END LOOP; + ]'; + END LOOP; END; -{{SLASH}} +{{/}} -- Put your ALTER statements below in the same style as before to ensure that -- the script is restartable. -^' - , - '{{SLASH}}', - c_slash - )); - +^' , + '{{/}}', + c_slash)); util_setup_dbms_metadata; ELSE util_clob_append(dbms_metadata.get_ddl( - object_type => v_rec.object_type, - name => v_rec.object_name, - schema => v_current_user - )); + object_type => v_rec.object_type, + name => v_rec.object_name, + schema => v_current_user)); END CASE; - util_clob_add_to_export_files( - p_export_files => v_export_files, - p_name => v_rec.file_path - ); + p_export_files => v_export_files, + p_name => v_rec.file_path); util_log_stop; EXCEPTION WHEN OTHERS THEN util_setup_dbms_metadata; util_log_error(v_rec.file_path); END; - END LOOP; - CLOSE v_cur; END process_object_ddl; PROCEDURE process_object_grants IS - TYPE obj_rec_typ IS RECORD ( - grantor VARCHAR2(128), - privilege VARCHAR2(128), - object_name VARCHAR2(256), - file_path VARCHAR2(512) - ); + grantor VARCHAR2(128), + privilege VARCHAR2(128), + object_name VARCHAR2(256), + file_path VARCHAR2(512)); v_rec obj_rec_typ; BEGIN util_log_start(p_base_path_backend || '/grants:open_cursor'); @@ -1772,22 +1590,17 @@ WHERE (#NAME_LIKE_EXPRESSIONS#) ORDER BY privilege, object_name -^' - ; - v_query := replace( +^' ; + v_query := replace( v_query, '{{BASE_PATH_APP_BACKEND}}', - p_base_path_backend - ); + p_base_path_backend); replace_query_like_expressions( - p_like_list => p_object_name_like, - p_not_like_list => p_object_name_not_like, - p_placeholder_prefix => 'NAME', - p_column_name => 'o.object_name' - ); - + p_like_list => p_object_name_like, + p_not_like_list => p_object_name_not_like, + p_placeholder_prefix => 'NAME', + p_column_name => 'o.object_name'); OPEN v_cur FOR v_query; - util_log_stop; LOOP FETCH v_cur INTO v_rec; @@ -1801,27 +1614,22 @@ ORDER BY )); v_ddl_files.grants_(v_ddl_files.grants_.count + 1) := v_rec.file_path; util_clob_add_to_export_files( - p_export_files => v_export_files, - p_name => v_rec.file_path - ); + p_export_files => v_export_files, + p_name => v_rec.file_path); util_log_stop; EXCEPTION WHEN OTHERS THEN util_log_error(v_rec.file_path); END; - END LOOP; - CLOSE v_cur; END process_object_grants; PROCEDURE process_ref_constraints IS - TYPE obj_rec_typ IS RECORD ( table_name VARCHAR2(256), constraint_name VARCHAR2(256), - file_path VARCHAR2(512) - ); + file_path VARCHAR2(512)); v_rec obj_rec_typ; BEGIN util_log_start(p_base_path_backend || '/ref_constraints:open_cursor'); @@ -1836,22 +1644,17 @@ WHERE constraint_type = 'R' ORDER BY table_name, constraint_name -^' - ; - v_query := replace( +^' ; + v_query := replace( v_query, '{{BASE_PATH_APP_BACKEND}}', - p_base_path_backend - ); + p_base_path_backend); replace_query_like_expressions( - p_like_list => p_object_name_like, - p_not_like_list => p_object_name_not_like, - p_placeholder_prefix => 'NAME', - p_column_name => 'table_name' - ); - + p_like_list => p_object_name_like, + p_not_like_list => p_object_name_not_like, + p_placeholder_prefix => 'NAME', + p_column_name => 'table_name'); OPEN v_cur FOR v_query; - util_log_stop; LOOP FETCH v_cur INTO v_rec; @@ -1859,54 +1662,42 @@ ORDER BY BEGIN util_log_start(v_rec.file_path); util_setup_dbms_metadata(p_sqlterminator => false); - util_clob_append(replace( - q'^ + util_clob_append(replace(q'^ BEGIN FOR i IN (SELECT '{{CONSTRAINT_NAME}}' AS constraint_name FROM dual MINUS SELECT constraint_name FROM user_constraints) LOOP EXECUTE IMMEDIATE q'[ -------------------------------------------------------------------------------- -^' - , +^' , '{{CONSTRAINT_NAME}}', - v_rec.constraint_name - ) || dbms_metadata.get_ddl( - 'REF_CONSTRAINT', - v_rec.constraint_name - ) || replace( - q'^ + v_rec.constraint_name) + || dbms_metadata.get_ddl('REF_CONSTRAINT', v_rec.constraint_name) + || replace(q'^ -------------------------------------------------------------------------------- ]'; END LOOP; END; -{{SLASH}} -^' - , - '{{SLASH}}', - c_slash - )); - +{{/}} +^' , + '{{/}}', + c_slash)); util_setup_dbms_metadata; v_ddl_files.ref_constraints_(v_ddl_files.ref_constraints_.count + 1) := v_rec.file_path; util_clob_add_to_export_files( - p_export_files => v_export_files, - p_name => v_rec.file_path - ); + p_export_files => v_export_files, + p_name => v_rec.file_path); util_log_stop; EXCEPTION WHEN OTHERS THEN util_setup_dbms_metadata; util_log_error(v_rec.file_path); END; - END LOOP; - CLOSE v_cur; END process_ref_constraints; PROCEDURE create_backend_install_file IS - FUNCTION get_script_line ( p_file_path VARCHAR2 ) RETURN VARCHAR2 IS @@ -1919,9 +1710,6 @@ END; END get_script_line; BEGIN - - - -- file one v_file_path := 'scripts/install_backend_generated_by_plex.sql'; util_log_start(v_file_path); util_clob_append('/* A T T E N T I O N @@ -1936,102 +1724,92 @@ whenever sqlerror exit sql.sqlcode rollback prompt --install_backend_generated_by_plex -' - ); - FOR i IN 1..v_ddl_files.sequences_.count LOOP util_clob_append(get_script_line(v_ddl_files.sequences_(i))); +' ); + FOR i IN 1..v_ddl_files.sequences_.count LOOP + util_clob_append(get_script_line(v_ddl_files.sequences_(i))); END LOOP; - - FOR i IN 1..v_ddl_files.tables_.count LOOP util_clob_append(get_script_line(v_ddl_files.tables_(i))); + FOR i IN 1..v_ddl_files.tables_.count LOOP + util_clob_append(get_script_line(v_ddl_files.tables_(i))); END LOOP; - - FOR i IN 1..v_ddl_files.ref_constraints_.count LOOP util_clob_append(get_script_line(v_ddl_files.ref_constraints_(i))); + FOR i IN 1..v_ddl_files.ref_constraints_.count LOOP + util_clob_append(get_script_line(v_ddl_files.ref_constraints_(i))); END LOOP; - - FOR i IN 1..v_ddl_files.indices_.count LOOP util_clob_append(get_script_line(v_ddl_files.indices_(i))); + FOR i IN 1..v_ddl_files.indices_.count LOOP + util_clob_append(get_script_line(v_ddl_files.indices_(i))); END LOOP; - - FOR i IN 1..v_ddl_files.views_.count LOOP util_clob_append(get_script_line(v_ddl_files.views_(i))); + FOR i IN 1..v_ddl_files.views_.count LOOP + util_clob_append(get_script_line(v_ddl_files.views_(i))); END LOOP; - - FOR i IN 1..v_ddl_files.types_.count LOOP util_clob_append(get_script_line(v_ddl_files.types_(i))); + FOR i IN 1..v_ddl_files.types_.count LOOP + util_clob_append(get_script_line(v_ddl_files.types_(i))); END LOOP; - - FOR i IN 1..v_ddl_files.type_bodies_.count LOOP util_clob_append(get_script_line(v_ddl_files.type_bodies_(i))); + FOR i IN 1..v_ddl_files.type_bodies_.count LOOP + util_clob_append(get_script_line(v_ddl_files.type_bodies_(i))); END LOOP; - - FOR i IN 1..v_ddl_files.triggers_.count LOOP util_clob_append(get_script_line(v_ddl_files.triggers_(i))); + FOR i IN 1..v_ddl_files.triggers_.count LOOP + util_clob_append(get_script_line(v_ddl_files.triggers_(i))); END LOOP; - - FOR i IN 1..v_ddl_files.functions_.count LOOP util_clob_append(get_script_line(v_ddl_files.functions_(i))); + FOR i IN 1..v_ddl_files.functions_.count LOOP + util_clob_append(get_script_line(v_ddl_files.functions_(i))); END LOOP; - - FOR i IN 1..v_ddl_files.procedures_.count LOOP util_clob_append(get_script_line(v_ddl_files.procedures_(i))); + FOR i IN 1..v_ddl_files.procedures_.count LOOP + util_clob_append(get_script_line(v_ddl_files.procedures_(i))); END LOOP; - - FOR i IN 1..v_ddl_files.packages_.count LOOP util_clob_append(get_script_line(v_ddl_files.packages_(i))); + FOR i IN 1..v_ddl_files.packages_.count LOOP + util_clob_append(get_script_line(v_ddl_files.packages_(i))); END LOOP; - - FOR i IN 1..v_ddl_files.package_bodies_.count LOOP util_clob_append(get_script_line(v_ddl_files.package_bodies_(i))); + FOR i IN 1..v_ddl_files.package_bodies_.count LOOP + util_clob_append(get_script_line(v_ddl_files.package_bodies_(i))); END LOOP; - - FOR i IN 1..v_ddl_files.grants_.count LOOP util_clob_append(get_script_line(v_ddl_files.grants_(i))); + FOR i IN 1..v_ddl_files.grants_.count LOOP + util_clob_append(get_script_line(v_ddl_files.grants_(i))); END LOOP; - - FOR i IN 1..v_ddl_files.other_objects_.count LOOP util_clob_append(get_script_line(v_ddl_files.other_objects_(i))); + FOR i IN 1..v_ddl_files.other_objects_.count LOOP + util_clob_append(get_script_line(v_ddl_files.other_objects_(i))); END LOOP; - util_clob_add_to_export_files( - p_export_files => v_export_files, - p_name => v_file_path - ); + p_export_files => v_export_files, + p_name => v_file_path); util_log_stop; END create_backend_install_file; PROCEDURE process_data IS - TYPE obj_rec_typ IS RECORD ( table_name VARCHAR2(256), - pk_columns VARCHAR2(4000) - ); + pk_columns VARCHAR2(4000)); v_rec obj_rec_typ; BEGIN util_log_start(p_base_path_data || '/open_tables_cursor'); v_query := q'^ SELECT table_name, - (SELECT LISTAGG(column_name, ', ') WITHIN GROUP(ORDER BY position) - FROM user_cons_columns - WHERE constraint_name = (SELECT constraint_name - FROM user_constraints c - WHERE constraint_type = 'P' - AND c.table_name = t.table_name) - ) AS pk_columns -FROM user_tables t -WHERE table_name IN (SELECT table_name FROM user_tables + (SELECT LISTAGG(column_name, ', ') WITHIN GROUP(ORDER BY position) + FROM user_cons_columns + WHERE constraint_name = (SELECT constraint_name + FROM user_constraints c + WHERE constraint_type = 'P' + AND c.table_name = t.table_name) + ) AS pk_columns + FROM user_tables t + WHERE table_name IN (SELECT table_name FROM user_tables MINUS SELECT table_name FROM user_external_tables) - AND (#NAME_LIKE_EXPRESSIONS#) - AND (#NAME_NOT_LIKE_EXPRESSIONS#) -ORDER BY - table_name -^' - ; + AND (#NAME_LIKE_EXPRESSIONS#) + AND (#NAME_NOT_LIKE_EXPRESSIONS#) + ORDER BY + table_name +^' ; replace_query_like_expressions( - p_like_list => p_data_table_name_like, - p_not_like_list => p_data_table_name_not_like, - p_placeholder_prefix => 'NAME', - p_column_name => 'table_name' - ); - + p_like_list => p_data_table_name_like, + p_not_like_list => p_data_table_name_not_like, + p_placeholder_prefix => 'NAME', + p_column_name => 'table_name'); OPEN v_cur FOR v_query; + util_log_stop; - util_log_stop; util_log_start(p_base_path_data || '/get_scn'); - v_data_timestamp := util_calc_data_timestamp(nvl( - p_data_as_of_minutes_ago, - 0 - )); - v_data_scn := timestamp_to_scn(v_data_timestamp); - util_log_stop; + v_data_timestamp := util_calc_data_timestamp(nvl(p_data_as_of_minutes_ago, 0)); + v_data_scn := timestamp_to_scn(v_data_timestamp); + util_log_stop; LOOP FETCH v_cur INTO v_rec; EXIT WHEN v_cur%notfound; @@ -2039,36 +1817,29 @@ ORDER BY v_file_path := p_base_path_data || '/' || v_rec.table_name || '.csv'; util_log_start(v_file_path); util_clob_query_to_csv( - p_query => 'SELECT * FROM ' || v_rec.table_name || ' AS OF SCN ' || v_data_scn || - CASE - WHEN v_rec.pk_columns IS NOT NULL THEN - ' ORDER BY ' || v_rec.pk_columns - ELSE - NULL - END, - p_max_rows => p_data_max_rows - ); - + p_query => 'SELECT * FROM ' || v_rec.table_name || ' AS OF SCN ' || v_data_scn || + CASE + WHEN v_rec.pk_columns IS NOT NULL + THEN ' ORDER BY ' || v_rec.pk_columns + ELSE NULL + END, + p_max_rows => p_data_max_rows); util_clob_add_to_export_files( - p_export_files => v_export_files, - p_name => v_file_path - ); + p_export_files => v_export_files, + p_name => v_file_path); util_log_stop; EXCEPTION WHEN OTHERS THEN util_log_error(v_file_path); END; - END LOOP; - CLOSE v_cur; END process_data; PROCEDURE create_template_files IS v_file_template VARCHAR2(32767 CHAR); BEGIN - v_file_template := q'^ -Your Global README File + v_file_template := q'^Your Global README File ======================= It is a good practice to have a README file in the root of your project with @@ -2106,25 +1877,21 @@ If you want to use these files please make a copy into the scripts directory and modify it to your needs. Doing it this way your changes are overwrite save. [Feedback is welcome]({{PLEX_URL}}/issues/new) -^' - ; - v_file_path := 'plex_README.md'; +^' ; + v_file_path := 'plex_README.md'; util_log_start(v_file_path); util_clob_append(replace( v_file_template, '{{PLEX_URL}}', - c_plex_url - )); + c_plex_url)); util_clob_add_to_export_files( - p_export_files => v_export_files, - p_name => v_file_path - ); + p_export_files => v_export_files, + p_name => v_file_path); util_log_stop; - v_file_template := q'^ -rem Template generated by PLEX version {{PLEX_VERSION}} + v_file_template := q'^rem Template generated by PLEX version {{PLEX_VERSION}} rem More infos here: {{PLEX_URL}} -{{AT}}echo off +{{@}}echo off setlocal set "areyousure=N" @@ -2151,7 +1918,7 @@ set NLS_LANG=AMERICAN_AMERICA.UTF8 set /p "password=Please enter password for %app_schema% [default = oracle]: " || set "password=oracle" echo This is the runlog for %scriptfile% on %app_schema%@%systemrole%(%connection%) > %logfile% echo exit | sqlplus -S %app_schema%/%password%@%connection% ^ -{{AT}}%scriptfile% ^ +{{@}}%scriptfile% ^ %logfile% ^ %app_id% ^ %app_alias% ^ @@ -2165,115 +1932,71 @@ if %errorlevel% neq 0 echo ERROR: SQL script finished with return code %errorlev rem Remove "pause" for fully automated setup: pause if %errorlevel% neq 0 exit /b %errorlevel% -^' - ; - v_file_path := 'scripts/templates/1_export_app_from_DEV.bat'; +^' ; + v_file_path := 'scripts/templates/1_export_app_from_DEV.bat'; util_log_start(v_file_path); util_clob_append(util_multi_replace( v_file_template, - '{{PLEX_VERSION}}', - c_plex_version, - '{{PLEX_URL}}', - c_plex_url, - '{{SYSTEMROLE}}', - 'DEV', + '{{PLEX_VERSION}}', c_plex_version, + '{{PLEX_URL}}', c_plex_url, + '{{SYSTEMROLE}}', 'DEV', $if $$apex_installed $then - '{{APP_ID}}', - p_app_id, - '{{APP_ALIAS}}', - v_app_alias, - '{{APP_OWNER}}', - v_app_owner, - '{{APP_WORKSPACE}}', - v_app_workspace, + '{{APP_ID}}', p_app_id, + '{{APP_ALIAS}}', v_app_alias, + '{{APP_OWNER}}', v_app_owner, + '{{APP_WORKSPACE}}', v_app_workspace, $end - '{{SCRIPTFILE}}', - 'export_app_custom_code.sql', - '{{LOGFILE}}', - 'logs/export_app_%app_id%_from_%app_schema%_at_%systemrole%_%mydate%_%mytime%.log', - '{{AT}}', - c_at - )); - + '{{SCRIPTFILE}}', 'export_app_custom_code.sql', + '{{LOGFILE}}', 'logs/export_app_%app_id%_from_%app_schema%_at_%systemrole%_%mydate%_%mytime%.log', + '{{@}}', c_at)); util_clob_add_to_export_files( - p_export_files => v_export_files, - p_name => v_file_path - ); + p_export_files => v_export_files, + p_name => v_file_path); util_log_stop; - -- - v_file_path := 'scripts/templates/2_install_app_into_TEST.bat'; + v_file_path := 'scripts/templates/2_install_app_into_TEST.bat'; util_log_start(v_file_path); util_clob_append(util_multi_replace( v_file_template, - '{{PLEX_VERSION}}', - c_plex_version, - '{{PLEX_URL}}', - c_plex_url, - '{{SYSTEMROLE}}', - 'TEST', + '{{PLEX_VERSION}}', c_plex_version, + '{{PLEX_URL}}', c_plex_url, + '{{SYSTEMROLE}}', 'TEST', $if $$apex_installed $then - '{{APP_ID}}', - p_app_id, - '{{APP_ALIAS}}', - v_app_alias, - '{{APP_OWNER}}', - v_app_owner, - '{{APP_WORKSPACE}}', - v_app_workspace, + '{{APP_ID}}', p_app_id, + '{{APP_ALIAS}}', v_app_alias, + '{{APP_OWNER}}', v_app_owner, + '{{APP_WORKSPACE}}', v_app_workspace, $end - '{{SCRIPTFILE}}', - 'install_app_custom_code.sql', - '{{LOGFILE}}', - 'logs/install_app_%app_id%_into_%app_schema%_at_%systemrole%_%mydate%_%mytime%.log', - '{{AT}}', - c_at - )); - + '{{SCRIPTFILE}}', 'install_app_custom_code.sql', + '{{LOGFILE}}', 'logs/install_app_%app_id%_into_%app_schema%_at_%systemrole%_%mydate%_%mytime%.log', + '{{@}}', c_at)); util_clob_add_to_export_files( - p_export_files => v_export_files, - p_name => v_file_path - ); + p_export_files => v_export_files, + p_name => v_file_path); util_log_stop; - -- - v_file_path := 'scripts/templates/3_install_app_into_PROD.bat'; + v_file_path := 'scripts/templates/3_install_app_into_PROD.bat'; util_log_start(v_file_path); util_clob_append(util_multi_replace( v_file_template, - '{{PLEX_VERSION}}', - c_plex_version, - '{{PLEX_URL}}', - c_plex_url, - '{{SYSTEMROLE}}', - 'PROD', + '{{PLEX_VERSION}}', c_plex_version, + '{{PLEX_URL}}', c_plex_url, + '{{SYSTEMROLE}}', 'PROD', $if $$apex_installed $then - '{{APP_ID}}', - p_app_id, - '{{APP_ALIAS}}', - v_app_alias, - '{{APP_OWNER}}', - v_app_owner, - '{{APP_WORKSPACE}}', - v_app_workspace, + '{{APP_ID}}', p_app_id, + '{{APP_ALIAS}}', v_app_alias, + '{{APP_OWNER}}', v_app_owner, + '{{APP_WORKSPACE}}', v_app_workspace, $end - '{{SCRIPTFILE}}', - 'install_app_custom_code.sql', - '{{LOGFILE}}', - 'logs/install_app_%app_id%_into_%app_schema%_at_%systemrole%_%mydate%_%mytime%.log', - '{{AT}}', - c_at - )); - + '{{SCRIPTFILE}}', 'install_app_custom_code.sql', + '{{LOGFILE}}', 'logs/install_app_%app_id%_into_%app_schema%_at_%systemrole%_%mydate%_%mytime%.log', + '{{@}}', c_at)); util_clob_add_to_export_files( - p_export_files => v_export_files, - p_name => v_file_path - ); + p_export_files => v_export_files, + p_name => v_file_path); util_log_stop; - -- - v_file_template := q'^ --- Template generated by PLEX version {{PLEX_VERSION}} + v_file_template := q'^-- Template generated by PLEX version {{PLEX_VERSION}} -- More infos here: {{PLEX_URL}} set verify off feedback off heading off @@ -2286,13 +2009,13 @@ variable app_id varchar2(100) variable app_alias varchar2(100) variable app_schema varchar2(100) variable app_workspace varchar2(100) -begin -:app_id := &2; -:app_alias := '&3'; -:app_schema := '&4'; -:app_workspace := '&5'; -end; -{{SLASH}} +BEGIN + :app_id := &2; + :app_alias := '&3'; + :app_schema := '&4'; + :app_workspace := '&5'; +END; +{{/}} prompt @@ -2300,78 +2023,76 @@ prompt Start Export prompt ========================================================================= prompt Create global temporary table temp_export_files if not exist BEGIN -FOR i IN (SELECT 'TEMP_EXPORT_FILES' AS object_name FROM dual - MINUS - SELECT object_name FROM user_objects) LOOP - EXECUTE IMMEDIATE ' + FOR i IN (SELECT 'TEMP_EXPORT_FILES' AS object_name FROM dual + MINUS + SELECT object_name FROM user_objects) LOOP + EXECUTE IMMEDIATE ' -------------------------------------------------------------------------------- CREATE GLOBAL TEMPORARY TABLE temp_export_files ( -name VARCHAR2(255), -contents CLOB + name VARCHAR2(255), + contents CLOB ) ON COMMIT DELETE ROWS -------------------------------------------------------------------------------- - '; -END LOOP; + '; + END LOOP; END; -{{SLASH}} +{{/}} prompt Do the app export, relocate files and save to temporary table prompt ATTENTION: Depending on your options this could take some time ... DECLARE -v_files tab_export_files; + v_files tab_export_files; BEGIN -v_files := plex.backapp ( --- These are the defaults - align it to your needs:^'; -$if $$apex_installed $then - v_file_template := v_file_template || q'^ - p_app_id => :app_id, - p_app_date => true, - p_app_public_reports => true, - p_app_private_reports => false, - p_app_notifications => false, - p_app_translations => true, - p_app_pkg_app_mapping => false, - p_app_original_ids => false, - p_app_subscriptions => true, - p_app_comments => true, - p_app_supporting_objects => null, - p_app_include_single_file => false, - p_app_build_status_run_only => false,^'; -$end - v_file_template := v_file_template || q'^ - p_include_object_ddl => true, - p_object_type_like => null, - p_object_type_not_like => null, - p_object_name_like => null, - p_object_name_not_like => null, + v_files := plex.backapp( + -- These are the defaults - align it to your needs:^'; + $if $$apex_installed $then + v_file_template := v_file_template || q'^ + p_app_id => :app_id, + p_app_date => true, + p_app_public_reports => true, + p_app_private_reports => false, + p_app_notifications => false, + p_app_translations => true, + p_app_pkg_app_mapping => false, + p_app_original_ids => false, + p_app_subscriptions => true, + p_app_comments => true, + p_app_supporting_objects => null, + p_app_include_single_file => false, + p_app_build_status_run_only => false,^'; + $end + v_file_template := v_file_template || q'^ + p_include_object_ddl => true, + p_object_type_like => null, + p_object_type_not_like => null, + p_object_name_like => null, + p_object_name_not_like => null, - p_include_data => false, - p_data_as_of_minutes_ago => 0, - p_data_max_rows => 1000, - p_data_table_name_like => null, - p_data_table_name_not_like => null, + p_include_data => false, + p_data_as_of_minutes_ago => 0, + p_data_max_rows => 1000, + p_data_table_name_like => null, + p_data_table_name_not_like => null, - p_include_templates => true, - p_include_runtime_log => true, - p_include_error_log => true, - p_base_path_backend => 'app_backend', - p_base_path_frontend => 'app_frontend', - p_base_path_data => 'app_data' -); + p_include_templates => true, + p_include_runtime_log => true, + p_include_error_log => true, + p_base_path_backend => 'app_backend', + p_base_path_frontend => 'app_frontend', + p_base_path_data => 'app_data'); --- relocate files to own project structure, we are inside the scripts folder -FOR i IN 1..v_files.count LOOP - v_files(i).name := '../' || v_files(i).name; -END LOOP; + -- relocate files to own project structure, we are inside the scripts folder + FOR i IN 1..v_files.count LOOP + v_files(i).name := '../' || v_files(i).name; + END LOOP; -FORALL i IN 1..v_files.count - INSERT INTO temp_export_files VALUES ( - v_files(i).name, - v_files(i).contents - ); + FORALL i IN 1..v_files.count + INSERT INTO temp_export_files VALUES ( + v_files(i).name, + v_files(i).contents); END; -{{SLASH}} +{{/}} prompt Create intermediate script file to unload the table contents into files @@ -2379,44 +2100,44 @@ spool off set termout off serveroutput on spool "logs/temp_export_files.sql" BEGIN --- create host commands for the needed directories (spool does not create missing directories) -FOR i IN ( - WITH t AS ( - SELECT regexp_substr(name, '^((\w|\.)+\/)+' /*path without file name*/) AS dir - FROM temp_export_files - ) - SELECT DISTINCT - dir, - -- This is for Windows to create a directory and suppress warning if it exist. - -- Align the command to your operating system: - 'host mkdir "' || replace(dir,'/','\') || '" 2>NUL' AS mkdir - FROM t - WHERE dir IS NOT NULL -) LOOP - dbms_output.put_line('set termout on'); - dbms_output.put_line('spool "&logfile." append'); - dbms_output.put_line('prompt --create directory if not exist: ' || i.dir); - dbms_output.put_line('spool off'); - dbms_output.put_line('set termout off'); - dbms_output.put_line(i.mkdir); - dbms_output.put_line('-----'); -END LOOP; + -- create host commands for the needed directories (spool does not create missing directories) + FOR i IN ( + WITH t AS ( + SELECT regexp_substr(name, '^((\w|\.)+\/)+' /*path without file name*/) AS dir + FROM temp_export_files + ) + SELECT DISTINCT + dir, + -- This is for Windows to create a directory and suppress warning if it exist. + -- Align the command to your operating system: + 'host mkdir "' || replace(dir,'/','\') || '" 2>NUL' AS mkdir + FROM t + WHERE dir IS NOT NULL + ) LOOP + dbms_output.put_line('set termout on'); + dbms_output.put_line('spool "&logfile." append'); + dbms_output.put_line('prompt --create directory if not exist: ' || i.dir); + dbms_output.put_line('spool off'); + dbms_output.put_line('set termout off'); + dbms_output.put_line(i.mkdir); + dbms_output.put_line('-----'); + END LOOP; --- create the spool calls for unload the files -FOR i IN (SELECT * FROM temp_export_files) LOOP - dbms_output.put_line('set termout on'); - dbms_output.put_line('spool "&logfile." append'); - dbms_output.put_line('prompt --' || i.name); - dbms_output.put_line('spool off'); - dbms_output.put_line('set termout off'); - dbms_output.put_line('spool "' || i.name || '"'); - dbms_output.put_line('select contents from temp_export_files where name = ''' || i.name || ''';'); - dbms_output.put_line('spool off'); - dbms_output.put_line('-----'); -END LOOP; + -- create the spool calls for unload the files + FOR i IN (SELECT * FROM temp_export_files) LOOP + dbms_output.put_line('set termout on'); + dbms_output.put_line('spool "&logfile." append'); + dbms_output.put_line('prompt --' || i.name); + dbms_output.put_line('spool off'); + dbms_output.put_line('set termout off'); + dbms_output.put_line('spool "' || i.name || '"'); + dbms_output.put_line('select contents from temp_export_files where name = ''' || i.name || ''';'); + dbms_output.put_line('spool off'); + dbms_output.put_line('-----'); + END LOOP; END; -{{SLASH}} +{{/}} spool off set termout on serveroutput off spool "&logfile." append @@ -2424,7 +2145,7 @@ spool "&logfile." append prompt Call the intermediate script file to save the files spool off -{{AT}}logs/temp_export_files.sql +{{@}}logs/temp_export_files.sql set termout on serveroutput off spool "&logfile." append @@ -2435,30 +2156,21 @@ COMMIT; prompt ========================================================================= prompt Export DONE :-) prompt -^' ; +^' ; v_file_path := 'scripts/templates/export_app_custom_code.sql'; util_log_start(v_file_path); util_clob_append(util_multi_replace( v_file_template, - '{{PLEX_VERSION}}', - c_plex_version, - '{{PLEX_URL}}', - c_plex_url, - '{{SLASH}}', - '/', - '{{AT}}', - c_at - )); - + '{{PLEX_VERSION}}', c_plex_version, + '{{PLEX_URL}}', c_plex_url, + '{{/}}', c_slash, + '{{@}}', c_at)); util_clob_add_to_export_files( p_export_files => v_export_files, - p_name => v_file_path - ); + p_name => v_file_path); util_log_stop; - -- - v_file_template := q'^ --- Template generated by PLEX version {{PLEX_VERSION}} + v_file_template := q'^-- Template generated by PLEX version {{PLEX_VERSION}} -- More infos here: {{PLEX_URL}} set define on verify off feedback off @@ -2470,13 +2182,13 @@ variable app_id varchar2(100) variable app_alias varchar2(100) variable app_schema varchar2(100) variable app_workspace varchar2(100) -begin -:app_id := &2; -:app_alias := '&3'; -:app_schema := '&4'; -:app_workspace := '&5'; -end; -{{SLASH}} +BEGIN + :app_id := &2; + :app_alias := '&3'; + :app_schema := '&4'; + :app_workspace := '&5'; +END; +{{/}} set define off @@ -2487,40 +2199,38 @@ prompt Start backend installation prompt Call PLEX backend install script -{{AT}}install_backend_generated_by_plex.sql +{{@}}install_backend_generated_by_plex.sql prompt Compile invalid objects BEGIN -dbms_utility.compile_schema( - schema => user, - compile_all => false, - reuse_settings => true -); + dbms_utility.compile_schema( + schema => user, + compile_all => false, + reuse_settings => true); END; -{{SLASH}} +{{/}} prompt Check invalid objects DECLARE -v_count PLS_INTEGER; -v_objects VARCHAR2(4000); + v_count PLS_INTEGER; + v_objects VARCHAR2(4000); BEGIN -SELECT COUNT(*), + SELECT COUNT(*), listagg(object_name, ', ') within GROUP(ORDER BY object_name) - INTO v_count, + INTO v_count, v_objects - FROM user_objects - WHERE status = 'INVALID'; -IF v_count > 0 -THEN - raise_application_error(-20000, - 'Found ' || v_count || ' invalid object' - || CASE WHEN v_count > 1 THEN 's' END - || ' :-( ' || v_objects); -END IF; + FROM user_objects + WHERE status = 'INVALID'; + IF v_count > 0 THEN + raise_application_error(-20000, + 'Found ' || v_count || ' invalid object' + || CASE WHEN v_count > 1 THEN 's' END + || ' :-( ' || v_objects); + END IF; END; -{{SLASH}} +{{/}} prompt Start frontend installation @@ -2531,70 +2241,56 @@ BEGIN apex_application_install.set_schema(:app_schema); apex_application_install.generate_offset; END; -{{SLASH}} +{{/}} prompt Call APEX frontend install script -{{AT}}install_frontend_generated_by_APEX.sql +{{@}}install_frontend_generated_by_APEX.sql prompt ========================================================================= prompt Installation DONE :-) prompt -^' ; - v_file_path := 'scripts/templates/install_app_custom_code.sql'; +^' ; + v_file_path := 'scripts/templates/install_app_custom_code.sql'; util_log_start(v_file_path); util_clob_append(util_multi_replace( v_file_template, - '{{PLEX_VERSION}}', - c_plex_version, - '{{PLEX_URL}}', - c_plex_url, - '{{SLASH}}', - '/', - '{{AT}}', - c_at - )); - + '{{PLEX_VERSION}}', c_plex_version, + '{{PLEX_URL}}', c_plex_url, + '{{/}}', c_slash, + '{{@}}', c_at)); util_clob_add_to_export_files( - p_export_files => v_export_files, - p_name => v_file_path - ); + p_export_files => v_export_files, + p_name => v_file_path); util_log_stop; END create_template_files; - -- - PROCEDURE create_directory_keepers IS v_the_point VARCHAR2(30) := '. < this is the point ;-)'; BEGIN - v_file_path := 'docs/_save_your_docs_here.txt'; + v_file_path := 'docs/_save_your_docs_here.txt'; util_log_start(v_file_path); util_clob_append(v_the_point); util_clob_add_to_export_files( - p_export_files => v_export_files, - p_name => v_file_path - ); + p_export_files => v_export_files, + p_name => v_file_path); util_log_stop; - -- v_file_path := 'scripts/logs/_spool_your_script_logs_here.txt'; util_log_start(v_file_path); util_clob_append(v_the_point); util_clob_add_to_export_files( - p_export_files => v_export_files, - p_name => v_file_path - ); + p_export_files => v_export_files, + p_name => v_file_path); util_log_stop; - -- v_file_path := 'tests/_save_your_tests_here.txt'; util_log_start(v_file_path); util_clob_append(v_the_point); util_clob_add_to_export_files( - p_export_files => v_export_files, - p_name => v_file_path - ); + p_export_files => v_export_files, + p_name => v_file_path); util_log_stop; END create_directory_keepers; @@ -2611,63 +2307,56 @@ prompt BEGIN init; -$if $$apex_installed $then + $if $$apex_installed $then check_owner; - IF p_app_id IS NOT NULL THEN process_apex_app; END IF; -$end - + $end IF p_include_object_ddl THEN process_user_ddl; process_object_ddl; -$if NOT $$debug_on $then - --> conditional compilation begin: excluded in debug mode (potential long running object types) + $if NOT $$debug_on $then + -- excluded in debug mode (potential long running object types) process_object_grants; process_ref_constraints; - --< conditional compilation end -$end + $end create_backend_install_file; END IF; - -- IF p_include_data THEN process_data; END IF; - -- IF p_include_templates THEN create_template_files; create_directory_keepers; END IF; - -- finish; - -- RETURN v_export_files; END backapp; -------------------------------------------------------------------------------------------------------------------------------- PROCEDURE add_query ( - p_query VARCHAR2, - p_file_name VARCHAR2, - p_max_rows NUMBER DEFAULT 1000 + p_query VARCHAR2, + p_file_name VARCHAR2, + p_max_rows NUMBER DEFAULT 1000 ) IS v_index PLS_INTEGER; BEGIN - v_index := g_queries.count + 1; - g_queries(v_index).query := p_query; - g_queries(v_index).file_name := p_file_name; - g_queries(v_index).max_rows := p_max_rows; + v_index := g_queries.count + 1; + g_queries(v_index).query := p_query; + g_queries(v_index).file_name := p_file_name; + g_queries(v_index).max_rows := p_max_rows; END add_query; -------------------------------------------------------------------------------------------------------------------------------- FUNCTION queries_to_csv ( - p_delimiter IN VARCHAR2 DEFAULT ',', - p_quote_mark IN VARCHAR2 DEFAULT '"', - p_header_prefix IN VARCHAR2 DEFAULT NULL, - p_include_runtime_log IN BOOLEAN DEFAULT true, - p_include_error_log IN BOOLEAN DEFAULT true + p_delimiter IN VARCHAR2 DEFAULT ',', + p_quote_mark IN VARCHAR2 DEFAULT '"', + p_header_prefix IN VARCHAR2 DEFAULT NULL, + p_include_runtime_log IN BOOLEAN DEFAULT true, + p_include_error_log IN BOOLEAN DEFAULT true ) RETURN tab_export_files IS v_export_files tab_export_files; @@ -2676,8 +2365,7 @@ FUNCTION queries_to_csv ( IF g_queries.count = 0 THEN raise_application_error( -20201, - 'You need first to add queries by using plex.add_query. Calling plex.queries_to_csv clears the global queries array for subsequent processing.' - ); + 'You need first to add queries by using plex.add_query. Calling plex.queries_to_csv clears the global queries array for subsequent processing.'); END IF; util_log_init(p_module => 'plex.queries_to_csv'); util_log_start('init'); @@ -2691,16 +2379,14 @@ FUNCTION queries_to_csv ( BEGIN util_log_start('process_query ' || TO_CHAR(i) || ': ' || g_queries(i).file_name); util_clob_query_to_csv( - p_query => g_queries(i).query, - p_max_rows => g_queries(i).max_rows, - p_delimiter => p_delimiter, - p_quote_mark => p_quote_mark, - p_header_prefix => p_header_prefix - ); + p_query => g_queries(i).query, + p_max_rows => g_queries(i).max_rows, + p_delimiter => p_delimiter, + p_quote_mark => p_quote_mark, + p_header_prefix => p_header_prefix); util_clob_add_to_export_files( - p_export_files => v_export_files, - p_name => g_queries(i).file_name || '.csv' - ); + p_export_files => v_export_files, + p_name => g_queries(i).file_name || '.csv'); util_log_stop; EXCEPTION WHEN OTHERS THEN @@ -2726,6 +2412,9 @@ BEGIN process_queries; finish; RETURN v_export_files; +EXCEPTION + WHEN others THEN + g_queries.DELETE; END queries_to_csv; -------------------------------------------------------------------------------------------------------------------------------- @@ -2740,9 +2429,8 @@ BEGIN FOR i IN 1..p_file_collection.count LOOP util_zip_add_file( p_zipped_blob => v_zip, - p_name => p_file_collection(i).name, - p_content => util_clob_to_blob(p_file_collection(i).contents) - ); + p_name => p_file_collection(i).name, + p_content => util_clob_to_blob(p_file_collection(i).contents)); END LOOP; util_zip_finish(v_zip); util_log_stop; @@ -2779,8 +2467,8 @@ END view_runtime_log; -------------------------------------------------------------------------------------------------------------------------------- BEGIN - IF dbms_lob.istemporary(g_clob) = 0 THEN - dbms_lob.createtemporary(g_clob, true); - END IF; + IF dbms_lob.istemporary(g_clob) = 0 THEN + dbms_lob.createtemporary(g_clob, true); + END IF; END plex; / \ No newline at end of file diff --git a/PLEX.pks b/PLEX.pks index 499f7d2..04b0825 100755 --- a/PLEX.pks +++ b/PLEX.pks @@ -59,8 +59,7 @@ CHANGELOG -- CONSTANTS, TYPES -------------------------------------------------------------------------------------------------------------------------------- -c_app_info_length CONSTANT PLS_INTEGER := 64; - +c_app_info_length CONSTANT PLS_INTEGER := 64; SUBTYPE app_info_text IS VARCHAR2(64 CHAR); TYPE rec_error_log IS RECORD ( @@ -69,7 +68,6 @@ TYPE rec_error_log IS RECORD ( error_text VARCHAR2(200), call_stack VARCHAR2(500) ); - TYPE tab_error_log IS TABLE OF rec_error_log; TYPE rec_runtime_log IS RECORD ( @@ -81,14 +79,12 @@ TYPE rec_runtime_log IS RECORD ( module app_info_text, action app_info_text ); - TYPE tab_runtime_log IS TABLE OF rec_runtime_log; TYPE rec_export_file IS RECORD ( name VARCHAR2(255), contents CLOB ); - TYPE tab_export_files IS TABLE OF rec_export_file; TYPE tab_varchar2 IS TABLE OF varchar2(32767); @@ -152,21 +148,16 @@ BEGIN l_file_collection := plex.backapp( p_app_id => 100, -- parameter only available when APEX installed p_include_object_ddl => false, - p_include_data => false - ); + p_include_data => false); -- do something with the file collection FOR i IN 1..l_file_collection.count LOOP - dbms_output.put_line( - i - || ' | ' - || lpad(round(length(l_file_collection(i).contents) / 1024), 3) || ' kB' - || ' | ' - || l_file_collection(i).name - ); + dbms_output.put_line(i || ' | ' + || lpad(round(length(l_file_collection(i).contents) / 1024), 3) || ' kB' || ' | ' + || l_file_collection(i).name); END LOOP; END; -{{SLASH}} +{{/}} ``` EXAMPLE ZIP FILE PL/SQL @@ -178,13 +169,12 @@ BEGIN l_zip_file := plex.to_zip(plex.backapp( p_app_id => 100, -- parameter only available when APEX installed p_include_object_ddl => true, - p_include_data => false - )); + p_include_data => false)); -- do something with the zip file -- Your code here... END; -{{SLASH}} +{{/}} ``` EXAMPLE ZIP FILE SQL @@ -229,20 +219,19 @@ WITH p_include_error_log => true, p_base_path_backend => 'app_backend', p_base_path_frontend => 'app_frontend', - p_base_path_data => 'app_data' - )); + p_base_path_data => 'app_data')); END backapp; SELECT backapp FROM dual; -{{SLASH}} +{{/}} ``` **/ PROCEDURE add_query ( - p_query IN VARCHAR2, -- The query itself - p_file_name IN VARCHAR2, -- File name like 'Path/to/your/file-without-extension'. - p_max_rows IN NUMBER DEFAULT 1000 -- The maximum number of rows to be included in your file. + p_query IN VARCHAR2, -- The query itself + p_file_name IN VARCHAR2, -- File name like 'Path/to/your/file-without-extension'. + p_max_rows IN NUMBER DEFAULT 1000 -- The maximum number of rows to be included in your file. ); /** Add a query to be processed by the method queries_to_csv. You can add as many queries as you like. @@ -253,10 +242,9 @@ EXAMPLE BEGIN plex.add_query( p_query => 'select * from user_tables', - p_file_name => 'user_tables' - ); + p_file_name => 'user_tables'); END; -{{SLASH}} +{{/}} ``` **/ @@ -282,29 +270,23 @@ BEGIN --fill the queries array plex.add_query( p_query => 'select * from user_tables', - p_file_name => 'user_tables' - ); + p_file_name => 'user_tables'); plex.add_query( p_query => 'select * from user_tab_columns', p_file_name => 'user_tab_columns', - p_max_rows => 10000 - ); + p_max_rows => 10000); -- process the queries l_file_collection := plex.queries_to_csv; -- do something with the file collection FOR i IN 1..l_file_collection.count LOOP - dbms_output.put_line( - i - || ' | ' - || lpad(round(length(l_file_collection(i).contents) / 1024), 3) || ' kB' - || ' | ' - || l_file_collection(i).name - ); + dbms_output.put_line(i || ' | ' + || lpad(round(length(l_file_collection(i).contents) / 1024), 3) || ' kB' || ' | ' + || l_file_collection(i).name); END LOOP; END; -{{SLASH}} +{{/}} ``` EXPORT EXPORT ZIP FILE PL/SQL @@ -317,13 +299,11 @@ BEGIN --fill the queries array plex.add_query( p_query => 'select * from user_tables', - p_file_name => 'user_tables' - ); + p_file_name => 'user_tables'); plex.add_query( p_query => 'select * from user_tab_columns', p_file_name => 'user_tab_columns', - p_max_rows => 10000 - ); + p_max_rows => 10000); -- process the queries l_zip_file := plex.to_zip(plex.queries_to_csv); @@ -331,7 +311,7 @@ BEGIN -- do something with the zip file -- Your code here... END; -{{SLASH}} +{{/}} ``` EXAMPLE EXPORT ZIP FILE SQL @@ -343,18 +323,16 @@ WITH BEGIN plex.add_query( p_query => 'select * from user_tables', - p_file_name => 'user_tables' - ); + p_file_name => 'user_tables'); plex.add_query( p_query => 'select * from user_tab_columns', p_file_name => 'user_tab_columns', - p_max_rows => 10000 - ); + p_max_rows => 10000); v_return := plex.to_zip(plex.queries_to_csv); RETURN v_return; END queries_to_csv_zip; SELECT queries_to_csv_zip FROM dual; -{{SLASH}} +{{/}} **/ @@ -373,8 +351,7 @@ DECLARE BEGIN l_zip := plex.to_zip(plex.backapp( p_app_id => 100, - p_include_object_ddl => true - )); + p_include_object_ddl => true)); -- do something with the zip file... END; @@ -446,29 +423,19 @@ FUNCTION util_zip_blob_to_num ( p_len IN INTEGER, p_pos IN INTEGER ) RETURN NUMBER; - FUNCTION util_zip_little_endian ( p_big IN NUMBER, p_bytes IN PLS_INTEGER := 4 ) RETURN RAW; - PROCEDURE util_zip_add_file ( p_zipped_blob IN OUT BLOB, p_name IN VARCHAR2, p_content IN BLOB ); - PROCEDURE util_zip_finish ( p_zipped_blob IN OUT BLOB ); -/* FIXME: implement this -FUNCTION util_multireplace ( - p_source_string IN VARCHAR2, - p_replacements IN tab_varchar2 -) RETURN VARCHAR2; -*/ - FUNCTION util_multi_replace ( p_source_string VARCHAR2, p_01_find VARCHAR2 DEFAULT NULL, p_01_replace VARCHAR2 DEFAULT NULL, @@ -506,7 +473,9 @@ PROCEDURE util_setup_dbms_metadata ( p_emit_schema IN BOOLEAN DEFAULT false ); -PROCEDURE util_ensure_unique_file_names; +PROCEDURE util_ensure_unique_file_names ( + p_export_files IN OUT tab_export_files +); -------------------------------------------------------------------------------------------------------------------------------- -- The following tools are working on global private package variables @@ -556,9 +525,13 @@ PROCEDURE util_clob_query_to_csv ( p_header_prefix IN VARCHAR2 DEFAULT NULL ); -PROCEDURE util_clob_create_error_log (p_export_files IN OUT NOCOPY tab_export_files); +PROCEDURE util_clob_create_error_log ( + p_export_files IN OUT NOCOPY tab_export_files +); -PROCEDURE util_clob_create_runtime_log (p_export_files IN OUT NOCOPY tab_export_files); +PROCEDURE util_clob_create_runtime_log ( + p_export_files IN OUT NOCOPY tab_export_files +); $end diff --git a/README.md b/README.md index 909519f..8ab0b6f 100644 --- a/README.md +++ b/README.md @@ -92,21 +92,16 @@ BEGIN l_file_collection := plex.backapp( p_app_id => 100, -- parameter only available when APEX installed p_include_object_ddl => false, - p_include_data => false - ); + p_include_data => false); -- do something with the file collection FOR i IN 1..l_file_collection.count LOOP - dbms_output.put_line( - i - || ' | ' - || lpad(round(length(l_file_collection(i).contents) / 1024), 3) || ' kB' - || ' | ' - || l_file_collection(i).name - ); + dbms_output.put_line(i || ' | ' + || lpad(round(length(l_file_collection(i).contents) / 1024), 3) || ' kB' || ' | ' + || l_file_collection(i).name); END LOOP; END; -{{SLASH}} +{{/}} ``` EXAMPLE ZIP FILE PL/SQL @@ -118,13 +113,12 @@ BEGIN l_zip_file := plex.to_zip(plex.backapp( p_app_id => 100, -- parameter only available when APEX installed p_include_object_ddl => true, - p_include_data => false - )); + p_include_data => false)); -- do something with the zip file -- Your code here... END; -{{SLASH}} +{{/}} ``` EXAMPLE ZIP FILE SQL @@ -169,11 +163,10 @@ WITH p_include_error_log => true, p_base_path_backend => 'app_backend', p_base_path_frontend => 'app_frontend', - p_base_path_data => 'app_data' - )); + p_base_path_data => 'app_data')); END backapp; SELECT backapp FROM dual; -{{SLASH}} +{{/}} ``` SIGNATURE @@ -230,19 +223,18 @@ EXAMPLE BEGIN plex.add_query( p_query => 'select * from user_tables', - p_file_name => 'user_tables' - ); + p_file_name => 'user_tables'); END; -{{SLASH}} +{{/}} ``` SIGNATURE ```sql PROCEDURE add_query ( - p_query IN VARCHAR2, -- The query itself - p_file_name IN VARCHAR2, -- File name like 'Path/to/your/file-without-extension'. - p_max_rows IN NUMBER DEFAULT 1000 -- The maximum number of rows to be included in your file. + p_query IN VARCHAR2, -- The query itself + p_file_name IN VARCHAR2, -- File name like 'Path/to/your/file-without-extension'. + p_max_rows IN NUMBER DEFAULT 1000 -- The maximum number of rows to be included in your file. ); ``` @@ -262,29 +254,23 @@ BEGIN --fill the queries array plex.add_query( p_query => 'select * from user_tables', - p_file_name => 'user_tables' - ); + p_file_name => 'user_tables'); plex.add_query( p_query => 'select * from user_tab_columns', p_file_name => 'user_tab_columns', - p_max_rows => 10000 - ); + p_max_rows => 10000); -- process the queries l_file_collection := plex.queries_to_csv; -- do something with the file collection FOR i IN 1..l_file_collection.count LOOP - dbms_output.put_line( - i - || ' | ' - || lpad(round(length(l_file_collection(i).contents) / 1024), 3) || ' kB' - || ' | ' - || l_file_collection(i).name - ); + dbms_output.put_line(i || ' | ' + || lpad(round(length(l_file_collection(i).contents) / 1024), 3) || ' kB' || ' | ' + || l_file_collection(i).name); END LOOP; END; -{{SLASH}} +{{/}} ``` EXPORT EXPORT ZIP FILE PL/SQL @@ -297,13 +283,11 @@ BEGIN --fill the queries array plex.add_query( p_query => 'select * from user_tables', - p_file_name => 'user_tables' - ); + p_file_name => 'user_tables'); plex.add_query( p_query => 'select * from user_tab_columns', p_file_name => 'user_tab_columns', - p_max_rows => 10000 - ); + p_max_rows => 10000); -- process the queries l_zip_file := plex.to_zip(plex.queries_to_csv); @@ -311,7 +295,7 @@ BEGIN -- do something with the zip file -- Your code here... END; -{{SLASH}} +{{/}} ``` EXAMPLE EXPORT ZIP FILE SQL @@ -323,18 +307,16 @@ WITH BEGIN plex.add_query( p_query => 'select * from user_tables', - p_file_name => 'user_tables' - ); + p_file_name => 'user_tables'); plex.add_query( p_query => 'select * from user_tab_columns', p_file_name => 'user_tab_columns', - p_max_rows => 10000 - ); + p_max_rows => 10000); v_return := plex.to_zip(plex.queries_to_csv); RETURN v_return; END queries_to_csv_zip; SELECT queries_to_csv_zip FROM dual; -{{SLASH}} +{{/}} SIGNATURE @@ -362,8 +344,7 @@ DECLARE BEGIN l_zip := plex.to_zip(plex.backapp( p_app_id => 100, - p_include_object_ddl => true - )); + p_include_object_ddl => true)); -- do something with the zip file... END; diff --git a/plex_install.sql b/plex_install.sql index 56b1b07..8c73520 100644 --- a/plex_install.sql +++ b/plex_install.sql @@ -5,10 +5,10 @@ prompt Installing PL/SQL Export Utilities prompt ================================== prompt Set compiler flags DECLARE - v_apex_installed VARCHAR2(5) := 'FALSE'; -- Do not change (is set dynamically). - v_ords_installed VARCHAR2(5) := 'FALSE'; -- Do not change (is set dynamically). - v_utils_public VARCHAR2(5) := 'FALSE'; -- Make utilities public available (for testing or other usages). - v_debug_on VARCHAR2(5) := 'TRUE'; -- Object DDL: extract only one object per type to find problematic ones and save time in big schemas like APEX_XXX. + v_apex_installed VARCHAR2(5) := 'FALSE'; -- Do not change (is set dynamically). + v_ords_installed VARCHAR2(5) := 'FALSE'; -- Do not change (is set dynamically). + v_utils_public VARCHAR2(5) := 'FALSE'; -- Make utilities public available (for testing or other usages). + v_debug_on VARCHAR2(5) := 'FALSE'; -- Object DDL: extract only one object per type to find problematic ones and save time in big schemas like APEX_XXX. BEGIN FOR i IN ( SELECT *