Thursday, December 15, 2011

PL/SQL to generate insert/update/delete stored procedures for Oracle tables

This pl/sql below creates function sp_generate_procs in the database. You can then call this function to generate insert/update/delete and select procedures. Example usage:
begin
:result := sp_generate_procs(p_table_name => 'candidate');
end;
Function definition:
create or replace function sp_generate_procs(p_table_name varchar2, p_owner varchar2 := null)
    return clob is
    result           clob;
    v_parameters     clob; -- column name parameters
    v_cols           clob; -- plain column names
    v_cols_variables clob; -- column name variables
    vComment         varchar2(1000);
    v_update         varchar2(1000) := 'UDPATE ';
    v_table_name     varchar2(40) := upper(p_table_name);
    v_curr_user      varchar2(100);
    v_colname        varchar2(100);
    v_pkname         varchar2(30);
    v_pktype         varchar2(30);
    v_wasPk          boolean := false;
begin
    /*open c for select *
    from   all_tab_columns
    where  table_name = p_table_name
    and    owner = v_curr_user;*/
    select c.column_name
      into v_pkname
      from user_constraints u, user_cons_columns c
     where u.constraint_type = 'P'
       and u.table_name = c.table_name
       and c.constraint_name = u.constraint_name
       and c.table_name = v_table_name;

    vComment := chr(13) || '--Procedure auto generated by sp_generate_procs on ' || sysdate ||
                chr(13);

    if p_owner is null then
        select SYS_CONTEXT('USERENV', 'CURRENT_USER') into v_curr_user from DUAL;
    else
        v_curr_user := p_owner;
    end if;

    v_update := chr(9) || 'UPDATE ' || v_table_name || ' SET ' || chr(13);

    for c in (select *
                from all_tab_columns
               where table_name = v_table_name
                 and owner = v_curr_user)
    loop
        if lower(v_pkname) = lower(c.column_name) then
            
            v_pktype  := c.data_type;
            v_colname := 'p_' || substr(c.column_name, 1, 28) || ' IN OUT ' || c.data_type;
        else
            v_colname := 'p_' || substr(c.column_name, 1, 28) || ' ' || c.data_type;
        end if;
        dbms_output.put_line(c.column_name);
        --v_colname := 'p_' || c.column_name || ' ' || c.data_type;
    
        if v_parameters is null then
            v_parameters     := chr(9) || chr(9) || v_colname;
            v_cols           := chr(9) || chr(9) || c.column_name;
            v_cols_variables := chr(9) || chr(9) || 'p_' || substr(c.column_name, 1, 28);
        else
            if (v_wasPk) then
                v_parameters := v_parameters || ', -- Primary key is IN/OUT';
                v_wasPk      := false;
            else
                v_parameters := v_parameters || ',';
            end if;
        
            v_parameters     := v_parameters || chr(13) || chr(9) || chr(9) || v_colname;
            v_cols           := v_cols || ',' || chr(13) || chr(9) || chr(9) || c.column_name;
            v_cols_variables := v_cols_variables || ',' || chr(13) || chr(9) || chr(9) || 'p_' ||
                                substr(c.column_name, 1, 28);
        end if;
    
        if lower(v_pkname) != lower(c.column_name) then
            v_update := v_update || chr(9) || chr(9) || c.column_name || '=' || 'p_' ||
                        substr(c.column_name, 1, 28) || ',' || chr(13);
        else
            v_wasPk   := true;
        end if;
    
    end loop;

    v_update := substr(v_update, 1, length(v_update) - 2);
    v_update := v_update || chr(13) || chr(9) || 'where ' || v_pkname || '= p_' || v_pkname || ';' ||
                chr(13);

    result := result || 'CREATE OR REPLACE PROCEDURE ' || v_table_name || '_SELECT (p_' || v_pkname || ' ' ||
              v_pktype || ',curs out sys_refcursor) AS ' || chr(13);
    result := result || vComment || 'begin' || chr(13);
    result := result || 'open curs for ' || chr(13);
    result := result || chr(9) || 'select ' || chr(13) || v_cols || chr(13) || chr(9) || ' from ' ||
              v_table_name || ' where ' || v_pkname || '= p_' || v_pkname || ';' || chr(13);
    result := result || chr(13);
    result := result || 'END;' || chr(13);
    result := result || '/' || chr(13);

    result := result || 'CREATE OR REPLACE PROCEDURE ' || v_table_name || '_INSERT (' || chr(13);
    result := result || v_parameters || ') AS ' || chr(13);
    result := result || vComment || 'begin' || chr(13);
    result := result || chr(9) || 'insert into ' || v_table_name || '(' || chr(13);
    result := result || v_cols || chr(13) || chr(9) || ') values (' || chr(13) || v_cols_variables || ');' ||
              chr(13);
    result := result || chr(13);
    result := result || 'END;' || chr(13);
    result := result || '/' || chr(13);

    result := result || 'CREATE OR REPLACE PROCEDURE ' || v_table_name || '_UPDATE (' || chr(13);
    result := result || v_parameters || ') AS ' || chr(13);
    result := result || 'begin' || chr(13) || vComment || chr(13);
    result := result || v_update;
    result := result || 'END;' || chr(13);
    result := result || '/' || chr(13);
    result := result || 'CREATE OR REPLACE PROCEDURE ' || v_table_name || '_DELETE(p_' || v_pkname || ' ' ||
              v_pktype || ') AS ' || chr(13);
    result := result || 'begin' || chr(13);
    result := result || chr(9) || 'delete from ' || v_table_name;
    result := result || chr(9) || ' where ' || v_pkname || '= p_' || v_pkname || ';' || chr(13);
    result := result || chr(13);
    result := result || 'END;' || chr(13);
    result := result || '/' || chr(13);
    return(result);

end sp_generate_procs;
/

Wednesday, December 7, 2011

Copying a Weblogic 10.3.5 domain to another server.

It seems that it is possible to file copy a weblogic domain to another server.
In fact we tried xopy on a windows server the whole weblogic server installation and it worked like a charm. See this post
It is a little more complicated than a plain copy if your server uses SSL (read below)

You can file copy a weblogic domain to another server provided that:

  1. The servers have identical directory structure for MIDDLEWARE_HOME.  In our case, it was /u01/app/oracle/product/middleware
  2. The linux username is the same.  In our case, it was oracle.
  3. The Fusion Middleware version is the same.  In our case it was 11.1.2.0
  4. There is no cluster configured in the domain.  

Steps Involved:
  1. Shutdown all weblogic servers and node manage in source server.
  2. Go to the 'AdminServer' root directory (should be under  $MIDDLEWARE_HOME/user_projects/domains/domain name/servers/AdminServer ) and delete all sub-directories except the "security" directory. This includes tmp, data, cache, etc .  Do the same for all managed servers in the domain
  3. Switch to domain root and execute command below to create a tar file with the domain contents.
    $ cd $MIDDLEWARE_HOME/user_projects/domains/
    $ tar -cvf mydomain.tar ./mydomain
  4. Ftp / copy tar file to target server 
  5. Login to target using weblogic server's user username and execute command below to extract tar file.
    $ cd $MIDDLEWARE_HOME/user_projects/domains
    $ tar -xvf domain.tar
    
  6. After extraction of domain files:
    1. Update the domain registry of weblogic installation to include the new domain.
    2. You will have to search and replace the source machine's hostname with the targets machine's hostname inside any non binary file in the MIDDLEWARE_HOME. For our web logic installation it was only in 1 file. For the Middleware home, it was multiple files.
    3. ONLY for servers that utilize SSL:Generate a new DemoIdentity.jks file for use with nodemanager (The one copied over was for source host).
    4. $ cd $MIDDLEWARE_HOME/wlserver_10.3/server/lib/
      $ . ../bin/setWLSEnv.sh
      $ java utils.CertGen -cn targethost.com -keyfilepass
      $ java utils.CertGen -cn targethost.com -keyfilepass DemoIdentityPassPhrase -certfile testcert -keyfile testkey
      $ java utils.ImportPrivateKey newkeystore.jks DemoIdentityKeyStorePassPhrase demoidentity DemoIdentityPassPhrase testcert.pem testkey.pem
      $ keytool -v -list -keystore newkeystore.jks -storepass DemoIdentityKeyStorePassPhrase
      $ cp newkeystore.jks DemoIdentity.jks
      
  7. Finally start the WebLogic nodemanager and servers on the target machine and verify that all is OK.

Tuesday, December 6, 2011

Yes, you can XCOPY a weblogic installation to another server

On Windows Servers (2003/2008), it is possible to xcopy the whole weblogic installation from one server to another, and it will actually work: All domains, servers and deployments work as expected. Even the Fusion Middleware worked as expected, with all the patches and megabytes of jars that Oracle shovels into the installation.

It goes without saying that: (1) the directory structure between the 2 servers should be identical, ie if on source Server weblogic was installed on c:\oracle\middleware, then on Server 2 it should be the same, (2) The Java jdk is installed at exactly the same path and (3) You will have to search and replace the hostnames inside configuration files in the installation.
While on destination server and assuming the source server is available over the network, the xcopy command is this:

xcopy \\server1\c$\oracle\middleware c:\oracle\middleware /E/ H
It is even a better approach to tar and compress the directory and then copy it. Just be sure to include any hidden files.

This is useful in cases where:

  • You need to transfer an installation to another server, for example a failover server
  • You need to transfer an installation from a staging virtual machine to production
  • You need to restore a corrupted weblogic domain from backup.