All Downloads are FREE. Search and download functionalities are using the official Maven repository.

plsql.NOORM_METADATA_body.sql Maven / Gradle / Ivy

CREATE OR REPLACE
PACKAGE BODY noorm_metadata AS

  PROCEDURE get_version(p_version OUT VARCHAR2) AS
  BEGIN
    p_version := '${pom.version}';
  END get_version;

  PROCEDURE find_table_metadata(p_table_metadata OUT table_metadata_refcur) AS
  BEGIN
	OPEN p_table_metadata FOR
    SELECT tc.table_name,
           tc.column_name,
           tc.data_type,
           tc.data_precision,
           tc.data_scale,
           tc.char_length,
           tc.nullable,
           tc.column_id,
           uc.updatable,
           uc.insertable
    FROM   user_tab_columns tc,
           user_updatable_columns uc
    WHERE  tc.table_name  = uc.table_name
    AND    tc.column_name = uc.column_name
    UNION
    SELECT us.synonym_name,
           tc.column_name,
           tc.data_type,
           tc.data_precision,
           tc.data_scale,
           tc.char_length,
           tc.nullable,
           tc.column_id,
           uc.updatable,
           uc.insertable
    FROM   all_tab_columns tc,
           all_updatable_columns uc,
           user_synonyms us
    WHERE  tc.table_name  = uc.table_name
    AND    tc.column_name = uc.column_name
    AND    tc.table_name  = us.table_name
    ORDER  BY table_name, column_id;
  END find_table_metadata;

  PROCEDURE find_package_names(p_search_regex IN VARCHAR2, p_package_names OUT name_refcur) AS
  BEGIN
    OPEN p_package_names FOR
    SELECT object_name name
    FROM   user_objects
    WHERE  object_type = 'PACKAGE'
    AND    REGEXP_LIKE(object_name, p_search_regex);
  END find_package_names;

  PROCEDURE find_procedure_names(p_package_name IN VARCHAR2, p_procedure_names OUT name_refcur) AS
  BEGIN
    OPEN p_procedure_names FOR
    SELECT procedure_name name
    FROM   user_procedures
    WHERE  object_name = p_package_name
    AND    procedure_name IS NOT NULL;
  END find_procedure_names;

  PROCEDURE find_sequence_names(p_sequence_names OUT name_refcur) AS
  BEGIN
    OPEN p_sequence_names FOR
    SELECT sequence_name name
    FROM   user_sequences;
  END find_sequence_names;

  PROCEDURE find_pk_columns(p_pk_columns OUT pk_refcur) AS
  BEGIN
    OPEN p_pk_columns FOR
    SELECT cc.table_name,
           cc.column_name,
           cc.position
    FROM   user_constraints uc,
           user_cons_columns cc
    WHERE  uc.table_name      = cc.table_name
    AND    uc.constraint_name = cc.constraint_name
    AND    uc.constraint_type = 'P';
  END find_pk_columns;

  /*
    Unfortunately, PL/SQL record definitions are only subject to the PL/SQL compiler interpretation
    and not available in the Oracle data dictionary. For reverse engineering PL/SQL procedure calls
    based on PL/SQL records (which include implicit record definitions using %ROWTYPE) the list of
    fields in the record can be retrieved using data dictionary view USER_ARGUMENTS, but without a
    reference to the declaring row-type, if any.
    For this reason, evaluating the referenced row-type is done by comparing the given list with all
    explicitly declared row-types, i.e. tables and views. Currently, this limits the supported record
    definitions to row-types declared by tables and views.
  */
  PROCEDURE find_procedure_parameters(p_package_name IN VARCHAR2,
                                      p_procedure_name IN VARCHAR2,
                                      p_parameters OUT parameter_refcur) AS
  BEGIN
    OPEN p_parameters FOR
    SELECT argument_name name,
           data_type,
           type_name,
           in_out direction
    FROM   user_arguments
    WHERE  object_name = p_procedure_name
    AND    package_name = p_package_name
    AND    data_level = 0
    AND    argument_name IS NOT NULL
    ORDER  BY sequence;
  END find_procedure_parameters;

  PROCEDURE get_package_hash_value(p_package_name IN VARCHAR2,
                                   p_code_hash_value OUT NUMBER) AS

    l_full_package_text VARCHAR2(32767);
    CURSOR c_package_source IS
      SELECT text
      FROM   user_source
      WHERE  type = 'PACKAGE'
      AND    name = UPPER(p_package_name)
      ORDER  BY line;
  BEGIN
    l_full_package_text := '';
    FOR source_line IN c_package_source LOOP
      l_full_package_text := concat(l_full_package_text, source_line.text);
    END LOOP;
    IF l_full_package_text IS NULL THEN
      p_code_hash_value := -1;
    ELSE
      l_full_package_text := regexp_replace(l_full_package_text, '\s*', '');
      p_code_hash_value := DBMS_UTILITY.GET_HASH_VALUE(l_full_package_text, 0, 2147483647);
    END IF;
  END get_package_hash_value;

  /*
    PL/SQL records declared on basis of a rowtype are hard to detect, since no data dictionary view provides
    the required information, thus the only way to get the required information is parsing the source code.
    For explicitly declared record types things are easier, since the internal name of the record type is
    available through data dictionary view USER_ARGUMENTS.
   */
  PROCEDURE get_parameter_rowtype(p_package_name IN VARCHAR2,
                                  p_procedure_name IN VARCHAR2,
                                  p_parameter_name IN VARCHAR2,
                                  p_rowtype_name OUT VARCHAR2) AS

    l_full_package_text VARCHAR2(32767);
    l_ref_cursor_search_regex VARCHAR2(512);
    l_rowtype_search_regex VARCHAR2(512);
    l_ref_cursor_name VARCHAR2(30);
    CURSOR c_package_source IS
      SELECT text
      FROM   user_source
      WHERE  type = 'PACKAGE'
      AND    name = UPPER(p_package_name)
      ORDER  BY line;
  BEGIN
    SELECT type_subname INTO p_rowtype_name
    FROM   user_arguments
    WHERE  package_name  = p_package_name
    AND    object_name   = p_procedure_name
    AND    data_type     = 'PL/SQL RECORD';
    IF (p_rowtype_name IS NULL OR p_rowtype_name = 'ID_RECORD') THEN
      l_full_package_text := '';
      FOR source_line IN c_package_source LOOP
        l_full_package_text := concat(l_full_package_text, source_line.text);
      END LOOP;
      -- The full package source is matched with a regular expression to extract the token
      -- we are interested in. The part preceding the token we are searching for is enclosed
      -- by brackets as well as the token itself.
      l_ref_cursor_search_regex := concat('(.*PROCEDURE *', p_procedure_name);
      l_ref_cursor_search_regex := concat(l_ref_cursor_search_regex, ' *\([[:alnum:][:space:]''_,]*');
      l_ref_cursor_search_regex := concat(l_ref_cursor_search_regex, p_parameter_name);
      l_ref_cursor_search_regex := concat(l_ref_cursor_search_regex, ' *OUT *)([[:alnum:]_\.]*)(.*)');
      l_ref_cursor_name := regexp_replace(l_full_package_text, l_ref_cursor_search_regex, '\2', 1, 1, 'in');
      -- The ref cursor name is the name of local ref cursor type definition and must be resolved to the ROWTYPE
      IF (l_ref_cursor_name = 'noorm_metadata.id_refcur') THEN
        p_rowtype_name := 'NOORM_METADATA_ID_RECORD';
      ELSE
        l_rowtype_search_regex := concat('(.*TYPE *', l_ref_cursor_name);
        l_rowtype_search_regex := concat(l_rowtype_search_regex, ' *IS *REF *CURSOR *RETURN *)([[:alnum:]_]*)(.*)');
        p_rowtype_name := regexp_replace(l_full_package_text, l_rowtype_search_regex, '\2', 1, 1, 'in');
      END IF;
    END IF;
  EXCEPTION
    WHEN OTHERS THEN
      raise_application_error(-20011, 'Error retrieving ref cursor usage in procedure parameters using source code.');
  END get_parameter_rowtype;

  /*
    Returned REF CURSOR type variables can either be mapped to a table or view (ROWTYPE) or to a PL/SQL
    record type as specified locally in a PL/SQL package. For the latter, the corresponding Java Bean must
    be assembled using the information available in data dictionary view USER_ARGUMENTS.
  */
  PROCEDURE find_record_metadata(p_record_metadata OUT table_metadata_refcur) AS
  BEGIN
    OPEN p_record_metadata FOR
    SELECT ref_cursor.type_subname table_name,
           record_elements.argument_name column_name,
           record_elements.data_type,
           record_elements.data_precision,
           record_elements.data_scale,
           record_elements.char_length,
           'Y' nullable,
           record_elements.position column_id,
           'NO' updatable,
           'NO' insertable
    FROM   user_arguments ref_cursor,
           user_arguments record_elements
    WHERE  ref_cursor.type_subname IS NOT NULL
    AND    ref_cursor.type_subname   != 'ID_RECORD'
    AND    ref_cursor.type_name      != 'NOORM_METADATA'
    AND    ref_cursor.data_type       = 'PL/SQL RECORD'
    AND    ref_cursor.object_name     = record_elements.object_name
    AND    ref_cursor.package_name    = record_elements.package_name
    AND    record_elements.data_level = 2
    AND    record_elements.data_type != 'PL/SQL RECORD'
    GROUP  BY ref_cursor.type_subname,
              record_elements.argument_name,
              record_elements.data_type,
              record_elements.data_length,
              record_elements.data_precision,
              record_elements.data_scale,
              record_elements.char_length,
              record_elements.position
    ORDER  BY ref_cursor.type_subname,
              record_elements.position;
  END find_record_metadata;

END noorm_metadata;
/




© 2015 - 2025 Weber Informatics LLC | Privacy Policy