diff --git a/README.md b/README.md index 54554ac..ef509bb 100644 --- a/README.md +++ b/README.md @@ -87,7 +87,7 @@ SIGNATURE ```sql PACKAGE PLEX AUTHID current_user IS c_plex_name CONSTANT VARCHAR2(30 CHAR) := 'PLEX - PL/SQL Export Utilities'; -c_plex_version CONSTANT VARCHAR2(10 CHAR) := '2.2.0'; +c_plex_version CONSTANT VARCHAR2(10 CHAR) := '2.2.0.1'; c_plex_url CONSTANT VARCHAR2(40 CHAR) := 'https://github.com/ogobrecht/plex'; c_plex_license CONSTANT VARCHAR2(10 CHAR) := 'MIT'; c_plex_license_url CONSTANT VARCHAR2(60 CHAR) := 'https://github.com/ogobrecht/plex/blob/master/LICENSE.txt'; diff --git a/plex_install.sql b/plex_install.sql index 6e30137..7bd67ce 100644 --- a/plex_install.sql +++ b/plex_install.sql @@ -47,7 +47,7 @@ END; prompt Compile package plex (spec) CREATE OR REPLACE PACKAGE PLEX AUTHID current_user IS c_plex_name CONSTANT VARCHAR2(30 CHAR) := 'PLEX - PL/SQL Export Utilities'; -c_plex_version CONSTANT VARCHAR2(10 CHAR) := '2.2.0'; +c_plex_version CONSTANT VARCHAR2(10 CHAR) := '2.2.0.1'; c_plex_url CONSTANT VARCHAR2(40 CHAR) := 'https://github.com/ogobrecht/plex'; c_plex_license CONSTANT VARCHAR2(10 CHAR) := 'MIT'; c_plex_license_url CONSTANT VARCHAR2(60 CHAR) := 'https://github.com/ogobrecht/plex/blob/master/LICENSE.txt'; @@ -676,8 +676,8 @@ c_bfile CONSTANT PLS_INTEGER := 114; -- date type identfiers c_date CONSTANT PLS_INTEGER := 12; c_timestamp CONSTANT PLS_INTEGER := 180; -c_timestamp_with_time_zone CONSTANT PLS_INTEGER := 181; -c_timestamp_with_local_tz CONSTANT PLS_INTEGER := 231; +c_timestamp_tz CONSTANT PLS_INTEGER := 181; +c_timestamp_ltz CONSTANT PLS_INTEGER := 231; -- interval type identfiers c_interval_year_to_month CONSTANT PLS_INTEGER := 182; c_interval_day_to_second CONSTANT PLS_INTEGER := 183; @@ -1579,6 +1579,10 @@ IS v_col_cnt PLS_INTEGER; v_desc_tab dbms_sql.desc_tab3; v_buffer_varchar2 VARCHAR2(32767 CHAR); + v_buffer_date date; + v_buffer_timestamp timestamp; + v_buffer_timestamp_tz timestamp with time zone; + v_buffer_timestamp_ltz timestamp with local time zone; v_buffer_clob CLOB; v_buffer_xmltype XMLTYPE; v_buffer_long LONG; @@ -1664,7 +1668,15 @@ BEGIN -- 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 + IF v_desc_tab(i).col_type = c_date THEN + dbms_sql.define_column(v_cursor, i, v_buffer_date); + ELSIF v_desc_tab(i).col_type = c_timestamp THEN + dbms_sql.define_column(v_cursor, i, v_buffer_timestamp); + ELSIF v_desc_tab(i).col_type = c_timestamp_tz THEN + dbms_sql.define_column(v_cursor, i, v_buffer_timestamp_tz); + ELSIF v_desc_tab(i).col_type = c_timestamp_ltz THEN + dbms_sql.define_column(v_cursor, i, v_buffer_timestamp_ltz); + ELSIF v_desc_tab(i).col_type = c_clob THEN dbms_sql.define_column(v_cursor, i, v_buffer_clob); ELSIF v_desc_tab(i).col_type = c_xmltype THEN dbms_sql.define_column(v_cursor, i, v_buffer_xmltype); @@ -1701,27 +1713,35 @@ BEGIN -- start column util_clob_append(' t(' || v_data_count || ').' || v_desc_tab(i).col_name || ' := '); - IF v_desc_tab(i).col_type = c_clob THEN + IF v_desc_tab(i).col_type = c_date THEN + dbms_sql.column_value(v_cursor, i, v_buffer_date); + util_clob_append(q'^to_date('^' || to_char(v_buffer_date, 'yyyy-mm-dd hh24:mi:ss') || q'^','yyyy-mm-dd hh24:mi:ss')^'); + ELSIF v_desc_tab(i).col_type = c_timestamp THEN + dbms_sql.column_value(v_cursor, i, v_buffer_timestamp); + util_clob_append(q'^to_timestamp('^' || to_char(v_buffer_timestamp, 'yyyy-mm-dd hh24:mi:ss.ff6') || q'^','yyyy-mm-dd hh24:mi:ss.ff6')^'); + ELSIF v_desc_tab(i).col_type = c_timestamp_tz THEN + dbms_sql.column_value(v_cursor, i, v_buffer_timestamp_tz); + util_clob_append(q'^to_timestamp_tz('^' || to_char(v_buffer_timestamp_tz, 'yyyy-mm-dd hh24:mi:ss.ff6 tzr') || q'^','yyyy-mm-dd hh24:mi:ss.ff6 tzr')^'); + ELSIF v_desc_tab(i).col_type = c_timestamp_ltz THEN + dbms_sql.column_value(v_cursor, i, v_buffer_timestamp_ltz); + util_clob_append(q'^to_timestamp('^' || to_char(v_buffer_timestamp_ltz, 'yyyy-mm-dd hh24:mi:ss.ff6') || q'^','yyyy-mm-dd hh24:mi:ss.ff6')^'); + ELSIF 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 - v_buffer_varchar2 := substr(v_buffer_clob, 1, c_vc2_max_size); - prepare_varchar2_buffer_for_scripting; + IF length(v_buffer_clob) <= c_vc2_max_size - 11 THEN + v_buffer_varchar2 := q'^to_clob('^' || substr(v_buffer_clob, 1, c_vc2_max_size-11) || q'^')^'; util_clob_append(v_buffer_varchar2); ELSE - v_buffer_varchar2 := 'CLOB value skipped - larger then ' || c_vc2_max_size || ' characters'; - prepare_varchar2_buffer_for_scripting; + v_buffer_varchar2 := 'NULL; -- 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(); - IF length(v_buffer_clob) <= c_vc2_max_size THEN - v_buffer_varchar2 := substr(v_buffer_clob, 1, c_vc2_max_size); - prepare_varchar2_buffer_for_scripting; + IF length(v_buffer_clob) <= c_vc2_max_size - 11 THEN + v_buffer_varchar2 := q'^xmltype('^' || substr(v_buffer_clob, 1, c_vc2_max_size - 11) || q'^')^'; util_clob_append(v_buffer_varchar2); ELSE - v_buffer_varchar2 := 'XML value skipped - larger then ' || c_vc2_max_size || ' characters'; - prepare_varchar2_buffer_for_scripting; + v_buffer_varchar2 := 'NULL; -- 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 @@ -1730,13 +1750,11 @@ BEGIN prepare_varchar2_buffer_for_scripting; util_clob_append(v_buffer_varchar2); ELSE - v_buffer_varchar2 := 'LONG value skipped - larger then ' || c_vc2_max_size || ' characters'; - prepare_varchar2_buffer_for_scripting; + v_buffer_varchar2 := 'NULL; -- LONG value skipped - larger then ' || c_vc2_max_size || ' characters'; util_clob_append(v_buffer_varchar2); END IF; ELSIF v_desc_tab(i).col_type IN (c_raw, c_long_raw, c_blob, c_bfile) THEN - v_buffer_varchar2 := 'Binary data type skipped - currently not supported'; - prepare_varchar2_buffer_for_scripting; + v_buffer_varchar2 := 'NULL; -- Binary data type skipped - currently not supported'; util_clob_append(v_buffer_varchar2); ELSE dbms_sql.column_value(v_cursor, i, v_buffer_varchar2); diff --git a/src/PLEX.pkb b/src/PLEX.pkb index 615fabd..e34f679 100644 --- a/src/PLEX.pkb +++ b/src/PLEX.pkb @@ -35,8 +35,8 @@ c_bfile CONSTANT PLS_INTEGER := 114; -- date type identfiers c_date CONSTANT PLS_INTEGER := 12; c_timestamp CONSTANT PLS_INTEGER := 180; -c_timestamp_with_time_zone CONSTANT PLS_INTEGER := 181; -c_timestamp_with_local_tz CONSTANT PLS_INTEGER := 231; +c_timestamp_tz CONSTANT PLS_INTEGER := 181; +c_timestamp_ltz CONSTANT PLS_INTEGER := 231; -- interval type identfiers c_interval_year_to_month CONSTANT PLS_INTEGER := 182; c_interval_day_to_second CONSTANT PLS_INTEGER := 183; @@ -938,6 +938,10 @@ IS v_col_cnt PLS_INTEGER; v_desc_tab dbms_sql.desc_tab3; v_buffer_varchar2 VARCHAR2(32767 CHAR); + v_buffer_date date; + v_buffer_timestamp timestamp; + v_buffer_timestamp_tz timestamp with time zone; + v_buffer_timestamp_ltz timestamp with local time zone; v_buffer_clob CLOB; v_buffer_xmltype XMLTYPE; v_buffer_long LONG; @@ -1023,7 +1027,15 @@ BEGIN -- 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 + IF v_desc_tab(i).col_type = c_date THEN + dbms_sql.define_column(v_cursor, i, v_buffer_date); + ELSIF v_desc_tab(i).col_type = c_timestamp THEN + dbms_sql.define_column(v_cursor, i, v_buffer_timestamp); + ELSIF v_desc_tab(i).col_type = c_timestamp_tz THEN + dbms_sql.define_column(v_cursor, i, v_buffer_timestamp_tz); + ELSIF v_desc_tab(i).col_type = c_timestamp_ltz THEN + dbms_sql.define_column(v_cursor, i, v_buffer_timestamp_ltz); + ELSIF v_desc_tab(i).col_type = c_clob THEN dbms_sql.define_column(v_cursor, i, v_buffer_clob); ELSIF v_desc_tab(i).col_type = c_xmltype THEN dbms_sql.define_column(v_cursor, i, v_buffer_xmltype); @@ -1060,27 +1072,35 @@ BEGIN -- start column util_clob_append(' t(' || v_data_count || ').' || v_desc_tab(i).col_name || ' := '); - IF v_desc_tab(i).col_type = c_clob THEN + IF v_desc_tab(i).col_type = c_date THEN + dbms_sql.column_value(v_cursor, i, v_buffer_date); + util_clob_append(q'^to_date('^' || to_char(v_buffer_date, 'yyyy-mm-dd hh24:mi:ss') || q'^','yyyy-mm-dd hh24:mi:ss')^'); + ELSIF v_desc_tab(i).col_type = c_timestamp THEN + dbms_sql.column_value(v_cursor, i, v_buffer_timestamp); + util_clob_append(q'^to_timestamp('^' || to_char(v_buffer_timestamp, 'yyyy-mm-dd hh24:mi:ss.ff6') || q'^','yyyy-mm-dd hh24:mi:ss.ff6')^'); + ELSIF v_desc_tab(i).col_type = c_timestamp_tz THEN + dbms_sql.column_value(v_cursor, i, v_buffer_timestamp_tz); + util_clob_append(q'^to_timestamp_tz('^' || to_char(v_buffer_timestamp_tz, 'yyyy-mm-dd hh24:mi:ss.ff6 tzr') || q'^','yyyy-mm-dd hh24:mi:ss.ff6 tzr')^'); + ELSIF v_desc_tab(i).col_type = c_timestamp_ltz THEN + dbms_sql.column_value(v_cursor, i, v_buffer_timestamp_ltz); + util_clob_append(q'^to_timestamp('^' || to_char(v_buffer_timestamp_ltz, 'yyyy-mm-dd hh24:mi:ss.ff6') || q'^','yyyy-mm-dd hh24:mi:ss.ff6')^'); + ELSIF 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 - v_buffer_varchar2 := substr(v_buffer_clob, 1, c_vc2_max_size); - prepare_varchar2_buffer_for_scripting; + IF length(v_buffer_clob) <= c_vc2_max_size - 11 THEN + v_buffer_varchar2 := q'^to_clob('^' || substr(v_buffer_clob, 1, c_vc2_max_size-11) || q'^')^'; util_clob_append(v_buffer_varchar2); ELSE - v_buffer_varchar2 := 'CLOB value skipped - larger then ' || c_vc2_max_size || ' characters'; - prepare_varchar2_buffer_for_scripting; + v_buffer_varchar2 := 'NULL; -- 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(); - IF length(v_buffer_clob) <= c_vc2_max_size THEN - v_buffer_varchar2 := substr(v_buffer_clob, 1, c_vc2_max_size); - prepare_varchar2_buffer_for_scripting; + IF length(v_buffer_clob) <= c_vc2_max_size - 11 THEN + v_buffer_varchar2 := q'^xmltype('^' || substr(v_buffer_clob, 1, c_vc2_max_size - 11) || q'^')^'; util_clob_append(v_buffer_varchar2); ELSE - v_buffer_varchar2 := 'XML value skipped - larger then ' || c_vc2_max_size || ' characters'; - prepare_varchar2_buffer_for_scripting; + v_buffer_varchar2 := 'NULL; -- 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 @@ -1089,13 +1109,11 @@ BEGIN prepare_varchar2_buffer_for_scripting; util_clob_append(v_buffer_varchar2); ELSE - v_buffer_varchar2 := 'LONG value skipped - larger then ' || c_vc2_max_size || ' characters'; - prepare_varchar2_buffer_for_scripting; + v_buffer_varchar2 := 'NULL; -- LONG value skipped - larger then ' || c_vc2_max_size || ' characters'; util_clob_append(v_buffer_varchar2); END IF; ELSIF v_desc_tab(i).col_type IN (c_raw, c_long_raw, c_blob, c_bfile) THEN - v_buffer_varchar2 := 'Binary data type skipped - currently not supported'; - prepare_varchar2_buffer_for_scripting; + v_buffer_varchar2 := 'NULL; -- Binary data type skipped - currently not supported'; util_clob_append(v_buffer_varchar2); ELSE dbms_sql.column_value(v_cursor, i, v_buffer_varchar2); diff --git a/src/PLEX.pks b/src/PLEX.pks index 2ffaf85..86acfe8 100644 --- a/src/PLEX.pks +++ b/src/PLEX.pks @@ -1,6 +1,6 @@ CREATE OR REPLACE PACKAGE PLEX AUTHID current_user IS c_plex_name CONSTANT VARCHAR2(30 CHAR) := 'PLEX - PL/SQL Export Utilities'; -c_plex_version CONSTANT VARCHAR2(10 CHAR) := '2.2.0'; +c_plex_version CONSTANT VARCHAR2(10 CHAR) := '2.2.0.1'; c_plex_url CONSTANT VARCHAR2(40 CHAR) := 'https://github.com/ogobrecht/plex'; c_plex_license CONSTANT VARCHAR2(10 CHAR) := 'MIT'; c_plex_license_url CONSTANT VARCHAR2(60 CHAR) := 'https://github.com/ogobrecht/plex/blob/master/LICENSE.txt'; diff --git a/src/plex_test_types.sql b/src/plex_test_types.sql index f66b01a..9235d1a 100644 --- a/src/plex_test_types.sql +++ b/src/plex_test_types.sql @@ -1,5 +1,5 @@ timing start test_export -set verify off feedback off heading off timing on +set verify off feedback off heading off set trimout on trimspool on pagesize 0 linesize 5000 long 100000000 longchunksize 32767 whenever sqlerror exit sql.sqlcode rollback whenever oserror continue @@ -9,94 +9,98 @@ prompt prompt PLEX Test Export Format INSERT With Multiple Data Types prompt ======================================================= -prompt Drop existing test objects -begin - for i in ( - select object_type, object_name - from user_objects - where object_type = 'TABLE' and object_name = 'PLEX_TEST_MULTIPLE_DATATYPES' - or object_type = 'PACKAGE' and object_name = 'PLEX_TEST_MULTIPLE_DATATYPES_API') - loop - execute immediate 'drop ' || i.object_type || ' ' || i.object_name; - end loop; -end; -/ - -prompt Create table plex_test_multiple_datatypes -begin - for i in ( - select 'PLEX_TEST_MULTIPLE_DATATYPES' from dual - minus - select object_name from user_objects) - loop - execute immediate q'[ - create table plex_test_multiple_datatypes ( - ptmd_id integer generated always as identity, - ptmd_varchar varchar2(15 char) , - ptmd_char char(1 char) not null , - ptmd_integer integer , - ptmd_number number , - ptmd_number_x_5 number(*,5) , - ptmd_number_20_5 number(20,5) , - ptmd_float float , - ptmd_float_size_30 float(30) , - ptmd_xmltype xmltype , - ptmd_clob clob , - ptmd_blob blob , - ptmd_date date , - ptmd_timestamp timestamp , - ptmd_timestamp_tz timestamp with time zone , - ptmd_timestamp_ltz timestamp with local time zone , - -- - primary key (ptmd_id), - unique (ptmd_varchar) - ) - ]'; - end loop; -end; -/ - -prompt Create table API for plex_test_multiple_datatypes -begin - for i in ( - select 'PLEX_TEST_MULTIPLE_DATATYPES_API' from dual - minus - select object_name from user_objects) - loop - om_tapigen.compile_api( - p_table_name => 'PLEX_TEST_MULTIPLE_DATATYPES', - p_enable_custom_defaults => true); - end loop; -end; -/ - -prompt Insert 100 rows into plex_test_multiple_datatypes -declare - l_rows_tab plex_test_multiple_datatypes_api.t_rows_tab; - l_number_records pls_integer := 1; -begin - l_rows_tab := plex_test_multiple_datatypes_api.t_rows_tab(); - l_rows_tab.extend(l_number_records); - for i in 1 .. l_number_records loop - l_rows_tab(i) := plex_test_multiple_datatypes_api.get_a_row; - end loop; - plex_test_multiple_datatypes_api.create_rows(l_rows_tab); - commit; -end; -/ +--prompt Drop existing test objects +--begin +-- for i in ( +-- select object_type, object_name +-- from user_objects +-- where object_type = 'TABLE' and object_name = 'PLEX_TEST_MULTIPLE_DATATYPES' +-- or object_type = 'PACKAGE' and object_name = 'PLEX_TEST_MULTIPLE_DATATYPES_API') +-- loop +-- execute immediate 'drop ' || i.object_type || ' ' || i.object_name; +-- end loop; +--end; +--/ +-- +--prompt Create table plex_test_multiple_datatypes +--begin +-- for i in ( +-- select 'PLEX_TEST_MULTIPLE_DATATYPES' from dual +-- minus +-- select object_name from user_objects) +-- loop +-- execute immediate q'[ +-- create table plex_test_multiple_datatypes ( +-- ptmd_id integer generated always as identity, +-- ptmd_varchar varchar2(15 char) , +-- ptmd_char char(1 char) not null , +-- ptmd_integer integer , +-- ptmd_number number , +-- ptmd_number_x_5 number(*,5) , +-- ptmd_number_20_5 number(20,5) , +-- ptmd_float float , +-- ptmd_float_size_30 float(30) , +-- ptmd_xmltype xmltype , +-- ptmd_clob clob , +-- ptmd_blob blob , +-- ptmd_date date , +-- ptmd_timestamp timestamp , +-- ptmd_timestamp_tz timestamp with time zone , +-- ptmd_timestamp_ltz timestamp with local time zone , +-- -- +-- primary key (ptmd_id), +-- unique (ptmd_varchar) +-- ) +-- ]'; +-- end loop; +--end; +--/ +-- +--prompt Create table API for plex_test_multiple_datatypes +--begin +-- for i in ( +-- select 'PLEX_TEST_MULTIPLE_DATATYPES_API' from dual +-- minus +-- select object_name from user_objects) +-- loop +-- om_tapigen.compile_api( +-- p_table_name => 'PLEX_TEST_MULTIPLE_DATATYPES', +-- p_enable_custom_defaults => true); +-- end loop; +--end; +--/ +-- +--prompt Insert 100 rows into plex_test_multiple_datatypes +--declare +-- l_rows_tab plex_test_multiple_datatypes_api.t_rows_tab; +-- l_number_records pls_integer := 100; +--begin +-- l_rows_tab := plex_test_multiple_datatypes_api.t_rows_tab(); +-- l_rows_tab.extend(l_number_records); +-- for i in 1 .. l_number_records loop +-- l_rows_tab(i) := plex_test_multiple_datatypes_api.get_a_row; +-- end loop; +-- plex_test_multiple_datatypes_api.create_rows(l_rows_tab); +-- commit; +--end; +--/ prompt Run plex.backapp (this can take some time...) BEGIN :zip := plex.to_base64(plex.to_zip(plex.backapp( - p_app_id => 100, - p_include_object_ddl => true, - p_include_ords_modules => true, + p_app_id => null, --100, + p_include_object_ddl => false, + p_include_ords_modules => false, p_include_data => true, p_data_format => 'csv,insert', + p_data_table_name_like => 'PLEX_TEST_MULTIPLE_DATATYPES', p_include_templates => true))); END; / +prompt Delete old zip file from previous test: +host del app_100.zip + set termout off spool "app_100.zip.base64" print zip