JAVA Program for JDBC Driver Version and Database Information

I had seen people ask Questions about finding the edb-jdbc/postgresql driver version with Database Version. So, I thought to give one java script which can be use to find Database Details with edb-jdbc version.

Following is a JAVA Code which can be use to find the Database Version and EDB-JDBC/postgresql-jdbc Version:

File Name: DBinfo.java

import java.sql.*;

public class DBinfo
{
  public static void main(String[] args)
  {
    try
    {
	  Class.forName("com.edb.Driver");
	  Connection con = 
DriverManager.getConnection("jdbc:edb://localhost:5444/edb",
	  "enterprisedb","edb"); // Advanced Server Database Connection Information	
 DatabaseMetaData dbmd = con.getMetaData();  
    
     System.out.println("=====  Database info =====");  
     System.out.println("DatabaseProductName: " + dbmd.getDatabaseProductName() );  
     System.out.println("DatabaseProductVersion: " + dbmd.getDatabaseProductVersion() );  
     System.out.println("DatabaseMajorVersion: " + dbmd.getDatabaseMajorVersion() );  
     System.out.println("DatabaseMinorVersion: " + dbmd.getDatabaseMinorVersion() );  
     System.out.println("=====  Driver info =====");  
     System.out.println("DriverName: " + dbmd.getDriverName() );  
     System.out.println("DriverVersion: " + dbmd.getDriverVersion() );  
     System.out.println("DriverMajorVersion: " + dbmd.getDriverMajorVersion() );  
     System.out.println("DriverMinorVersion: " + dbmd.getDriverMinorVersion() );  
     System.out.println("=====  JDBC/DB attributes =====");  
     System.out.print("Supports getGeneratedKeys(): ");  
     if (dbmd.supportsGetGeneratedKeys() )  
       System.out.println("true");  
     else  
       System.out.println("false");  
	  con.close();
	  System.out.println("Command successfully executed");
     }

     catch(ClassNotFoundException e)
     {
	   System.out.println("Class Not Found : " + e.getMessage()); 
     }
	
     catch(SQLException exp) {
	System.out.println("SQL Exception: " + exp.getMessage());
	System.out.println("SQL State: " + exp.getSQLState());
	System.out.println("Vendor Error: " + exp.getErrorCode());    
     }	
  }
}

To compile this program, user has to copy edb-jdbc14.jar file in $JAVA_HOME/jre/lib/ext directory .
After copying the edb-jdbc driver use following command to compile the program:

javac DBinfo.java

Following is output of above java program:

vibhor@ubuntu:~$ java DBinfo 
=====  Database info =====
DatabaseProductName: EnterpriseDB
DatabaseProductVersion: 9.0.4.14
DatabaseMajorVersion: 9
DatabaseMinorVersion: 0
=====  Driver info =====
DriverName: Postgres Plus Advanced Server Native Driver
DriverVersion: Postgres Plus Advanced Server 9.0 (9.0.4.14)
DriverMajorVersion: 9
DriverMinorVersion: 0
=====  JDBC/DB attributes =====
Supports getGeneratedKeys(): true
Command successfully executed

Above java code can also be use for find postgreSQL jdbc driver version.
For using with postgresql-jdbc driver, User has to change following

  Connection con = 
Class.forName("com.edb.Driver");
DriverManager.getConnection("jdbc:edb://localhost:5444/edb",
	  "enterprisedb","edb"); // Advanced Server Database Connection Information	

with

Class.forName("org.postgresql.Driver");
Connection con = 
DriverManager.getConnection("jdbc:postgresql://localhost:5432/postgres",
	  "postgres","postgres"); // PostgreSQL Database Connection Information	

And has copy the postgresql-jdbc driver in $JAVA_HOME/jre/lib/ext

Then compile as mentioned above.
Following is output:

=====  Database info =====
DatabaseProductName: PostgreSQL
DatabaseProductVersion: 9.0.4.14
DatabaseMajorVersion: 9
DatabaseMinorVersion: 0
=====  Driver info =====
DriverName: PostgreSQL Native Driver
DriverVersion: PostgreSQL 8.4 JDBC4 (build 701)
DriverMajorVersion: 8
DriverMinorVersion: 4
=====  JDBC/DB attributes =====
Supports getGeneratedKeys(): true
Command successfully executed

Use Logrotator for managing slony files

Logrotator is a small C program which is well written and available on most of the UNIX based OS. It allows automatic rotation, compression of logfiles and removal of old logfiles. This small file can be use to manage applications logfiles. It can also use for managing slony logfiles.

For managing logfiles using logrotator user has to make a logrotator conf file, and can be scheduled in crontab for managing logile.

Let see how you can make a logrotator configuration file for slony.

I have slony master/slave daemon running on my slave maching has following location for slony logfiles:

/opt/PostgresPlus/9.0AS/slony_test/slony1/node1 -- For master
/opt/PostgresPlus/9.0AS/slony_test/slony1/node2 -- For slave.

For managing logfile, user can make logrotator configuration file similar to given below:

Configuration filename: /etc/logrotate.d/slonylogfiles

"/opt/PostgresPlus/9.0AS/slony_test/slony1/node[12]/*.log"  {
       rotate 5
       mail vibhor.aim@gmail.com
       size 1k
       copytruncate
       delaycompress
       compress
       notifempty
       missingok
       }

Above configuration file has been made to rotate the logfiles of slony as the size of logfile exceeds 1kilo bytes.

Following are the description of parameters used in configuration file:
rotate 5: this parameter directs logrotator to remove/mail to specified address/directory. If value is 0 then, logrotate will remove the old version of logfile at the place of rotate.

mail: this parameter tells logrotator about command which it can use to mail logfiles.

size: this parameter tells logrotator to rotate the logfile when logfile grow bigger than size mentioned with this parameter.

copytruncate: this parameter tells, logrotator to truncate the original logfile after creating a copy of the logfile.

delaycompress: This parameter is for postponing the compression of previous log file to the next rotation cycle.

compress: this tells logrotator to compress the old logfile using gzip.

notifempty: This parameter makes logrotator not to rotate the logfile if it is empty.

missingok: This parameter is for making logrotator to continue for the next logfile, if logfile is missing.

After making above logrotator configuration file, user can schedule logrotator in crontab as given below:

00 00 * * * logrotate -s /opt/PostgresPlus/9.0AS/slony.status //etc/logrotate.d/slonylogfiles 

Other form of configuration file is given below:
For daily Logrotator:

"/opt/PostgresPlus/9.0AS/slony_test/slony1/node[12]/*.log"  {
       daily
       rotate 5
       mail vibhor.aim@gmail.com
       size 1k
       copytruncate
       delaycompress
       compress
       notifempty
       missingok
       }

For monthly logrotator

"/opt/PostgresPlus/9.0AS/slony_test/slony1/node[12]/*.log"  {
       monthly
       rotate 5
       mail vibhor.aim@gmail.com
       size 1k
       copytruncate
       delaycompress
       compress
       notifempty
       missingok
       }

similarly user can make weekly slony configuration file.

Some Oracle Workarounds in Postgres Plus Advanced Server 9.0

Today, I though to mention some of Oracle workarounds which can be use for Migration of Oracle Database to PPAS 9.0(EnterpriseDB).

1. UTL_RAW.CAST_TO_RAW
This is a Oracle Packaged Function, which can be use to convert VARCHAR2 value into RAW Value. Lets see its example in Oracle:

SQL> select utl_raw.cast_to_raw('TESTING TESTING') from dual;

UTL_RAW.CAST_TO_RAW('TESTINGTESTING')
--------------------------------------------------------------------------------
54455354494E472054455354494E47

Since PPAS 9.0, doesn’t have this package in 9.0, therefore user can use postgresql function decode() for converting of varchar datatype to RAW/bytea data. Following is an example:

edb=# select decode('TESTING TESTING','escape') from dual;
              decode
----------------------------------
 \x54455354494e472054455354494e47
(1 row)

which is a same output.

2. UTL_RAW.CAST_TO_VARCHAR2

Using this packaged function user can convert raw value into a value of data type VARCHAR2 with the same number of data bytes. Following is an example:

SQL> select utl_raw.cast_to_varchar2(utl_raw.cast_to_raw('TESTING TESTING')) from dual;

UTL_RAW.CAST_TO_VARCHAR2(UTL_RAW.CAST_TO_RAW('TESTINGTESTING'))
--------------------------------------------------------------------------------
TESTING TESTING

For this function, PPAS 9.0 is having encode() function which can be use to convert raw/bytea value to VARCHAR/TEXT. Following is an example:

edb=# select encode(decode('TESTING TESTING','escape'),'escape') from dual;
     encode
-----------------
 TESTING TESTING
(1 row)

For more details of above two function, following link can be use:

http://www.enterprisedb.com/docs/en/9.0/pg/functions-binarystring.html

Using above basic function, user can immitate behavior of UTL_RAW Package in PPAS/PostgreSQL.

3. DBMS_OBFUSCATION.DESEncrypt & DBMS_OBFUSCATION.DESDecrypt Procedure
The DESEncrypt/DESDecrypt procedures generates the encrypted/decrypted form of the input data. It uses DES algorithm to encrypt data. Following is an Oracle Example:

DECLARE
   input_string        VARCHAR2(16) := 'tigertigertigert';
   raw_input           RAW(128) := UTL_RAW.CAST_TO_RAW(input_string);
   key_string          VARCHAR2(8)  := 'scottsco';
   raw_key             RAW(128) := UTL_RAW.CAST_TO_RAW(key_string);
   encrypted_raw               RAW(2048);
   encrypted_string            VARCHAR2(2048);
   decrypted_raw               RAW(2048);
   decrypted_string            VARCHAR2(2048);
   error_in_input_buffer_length EXCEPTION;
   PRAGMA EXCEPTION_INIT(error_in_input_buffer_length, -28232);
   INPUT_BUFFER_LENGTH_ERR_MSG VARCHAR2(100) :=
    '*** DES INPUT BUFFER NOT A MULTIPLE OF 8 BYTES - IGNORING
EXCEPTION ***';
   double_encrypt_not_permitted EXCEPTION;
   PRAGMA EXCEPTION_INIT(double_encrypt_not_permitted, -28233);
   DOUBLE_ENCRYPTION_ERR_MSG VARCHAR2(100) :=
    '*** CANNOT DOUBLE ENCRYPT DATA - IGNORING EXCEPTION ***';

-- 1. Begin testing raw data encryption and decryption
   BEGIN
   dbms_output.put_line('> ========= BEGIN TEST =========');
   dbms_output.put_line('> Raw input                        : ' ||
                 UTL_RAW.CAST_TO_VARCHAR2(raw_input));
   BEGIN
      dbms_obfuscation_toolkit.DESEncrypt(input => raw_input,
               key => raw_key, encrypted_data => encrypted_raw );
      dbms_output.put_line('> encrypted hex value              : ' ||
               rawtohex(encrypted_raw));
      dbms_obfuscation_toolkit.DESDecrypt(input => encrypted_raw,
               key => raw_key, decrypted_data => decrypted_raw);
      dbms_output.put_line('> Decrypted raw output             : ' ||
                    UTL_RAW.CAST_TO_VARCHAR2(decrypted_raw));
      dbms_output.put_line('>  ');
      if UTL_RAW.CAST_TO_VARCHAR2(raw_input) =
                    UTL_RAW.CAST_TO_VARCHAR2(decrypted_raw) THEN
         dbms_output.put_line('> Raw DES Encyption and Decryption successful');
      END if;
   EXCEPTION
      WHEN error_in_input_buffer_length THEN
             dbms_output.put_line('> ' || INPUT_BUFFER_LENGTH_ERR_MSG);
   END;
   dbms_output.put_line('>  ');
END;

Oracle Output:

========= BEGIN TEST =========
 Raw input      : tigertigertigert
 encrypted hex value     : 5AAB8C0D278AD75CA1968790D00FD75A
 Decrypted raw output     : tigertigertigert

 Raw DES Encyption and Decryption successful

PL/SQL procedure successfully completed.

In PPAS/PostgreSQL, user can use encrypt()/decrypt() function, which is a part of pgcrypto module supplied with PostgreSQL/PPAS. Following is an example in PPAS 9.0:

DECLARE
   input_string        VARCHAR2(16) := 'tigertigertigert';
   raw_input           RAW(128) := decode(input_string,'escape');
   key_string          VARCHAR2(8)  := 'scottsco';
   raw_key             RAW(128) := decode(key_string,'escape');
   encrypted_raw               RAW(2048);
   encrypted_string            VARCHAR2(2048);
   decrypted_raw               RAW(2048);
   decrypted_string            VARCHAR2(2048);
   error_in_input_buffer_length EXCEPTION;
   PRAGMA EXCEPTION_INIT(error_in_input_buffer_length, -20010);
   INPUT_BUFFER_LENGTH_ERR_MSG VARCHAR2(100) :=
    '*** DES INPUT BUFFER NOT A MULTIPLE OF 8 BYTES - IGNORING
EXCEPTION ***';
   double_encrypt_not_permitted EXCEPTION;
   PRAGMA EXCEPTION_INIT(double_encrypt_not_permitted, -20012);
   DOUBLE_ENCRYPTION_ERR_MSG VARCHAR2(100) :=
    '*** CANNOT DOUBLE ENCRYPT DATA - IGNORING EXCEPTION ***';

-- 1. Begin testing raw data encryption and decryption
   BEGIN
   dbms_output.put_line('> ========= BEGIN TEST RAW DATA =========');
   dbms_output.put_line('> Raw input                        : ' ||
                 encode(raw_input,'escape'));
   BEGIN
     select encrypt(raw_input,raw_key,'des') into encrypted_raw from dual;
      dbms_output.put_line('> encrypted hex value              : ' ||
               encode(encrypted_raw,'hex'));

     select decrypt(encrypted_raw,raw_key,'des') into decrypted_raw from dual;
      dbms_output.put_line('> Decrypted raw output             : ' ||
                    encode(decrypted_raw,'escape'));
      dbms_output.put_line('>  ');
      if encode(raw_input,'escape') =
                    encode(decrypted_raw,'escape') THEN
         dbms_output.put_line('> Raw DES Encyption and Decryption successful');
      END if;
   EXCEPTION
      WHEN error_in_input_buffer_length THEN
             dbms_output.put_line('> ' || INPUT_BUFFER_LENGTH_ERR_MSG);
   END;
   dbms_output.put_line('>  ');
END;

Output:

========= BEGIN TEST RAW DATA =========
 Raw input                        : tigertigertigert
 encrypted hex value              : 5aab8c0d278ad75ca1968790d00fd75a9931b6116d9d4346
 Decrypted raw output             : tigertigertigert

 Raw DES Encyption and Decryption successful

EDB-SPL Procedure successfully completed

4. UTL_HTTP.REQUEST Function.
Oracle provides UTL_HTTP.RQUEST function, which user can use to access data on the Internet. This function returns 2000 bytes of the data retrieved from the given URL.
Since PPAS/PostgreSQL doesn’t have direct support for this Function, so user can write plperlu function to get same features. Following is a small function/example:

CREATE OR REPLACE FUNCTION view_web_source(text) returns text
as
$$
use LWP::Simple;
my $ua = LWP::UserAgent->new;
$pageURL=$_[0];
$URLsource=get($pageURL);
my $req = HTTP::Request->new(GET => $pageURL);
my $res = $ua->request($req);
if ($res->status_line == "200 OK")
{ return $URLsource; }
 else
{
   return $res->status_line;
}
$$ language plperlu;

CREATE OR REPLACE FUNCTION url_request(url text) returns text
as
$$
select substring(view_web_source($1) from 1 for 2000);
$$ language sql;

Oracle Snapshot:

PPAS Snapshot