#!/usr/bin/perl

eval 'exec /usr/bin/perl  -S $0 ${1+"$@"}'
    if 0; # not running under some shell
#------------------------------------------------------------------------------
# Project  : Oracle to Postgresql converter
# Name     : ora2pg
# Author   : Gilles Darold, gilles _AT_ darold _DOT_ net
# Copyright: Copyright (c) 2000-2013 : Gilles Darold - All rights reserved -
# Function : Script used to convert Oracle Database to PostgreSQL
# Usage    : ora2pg configuration_file
#------------------------------------------------------------------------------
#
#        This program is free software: you can redistribute it and/or modify
#        it under the terms of the GNU General Public License as published by
#        the Free Software Foundation, either version 3 of the License, or
#        any later version.
# 
#        This program is distributed in the hope that it will be useful,
#        but WITHOUT ANY WARRANTY; without even the implied warranty of
#        MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#        GNU General Public License for more details.
# 
#        You should have received a copy of the GNU General Public License
#        along with this program. If not, see < http://www.gnu.org/licenses/ >.
# 
#------------------------------------------------------------------------------
use strict qw/vars/;

use Ora2Pg;
use Getopt::Long qw(:config no_ignore_case bundling);
use POSIX qw(locale_h sys_wait_h _exit);
setlocale(LC_NUMERIC, '');
setlocale(LC_ALL,     'C');

my $VERSION = '11.4';

my $CONFIG_FILE = '/etc/ora2pg/ora2pg.conf';
my $DEBUG = 0;
my $QUIET = 0;
my $HELP = 0;
my $LOGFILE = '';
my $EXPORT_TYPE = '';
my $OUTFILE = '';
my $OUTDIR = '';
my $SHOW_VER = 0;
my $PLSQL = 0;
my $DSN = '';
my $DBUSER = '';
my $DBPWD = '';
my $SCHEMA = '';
my $TABLEONLY = '';
my $FORCEOWNER = '';
my $ORA_ENCODING = '';
my $PG_ENCODING = '';
my $INPUT_FILE = '';
my $EXCLUDE = '';
my $ALLOW = '';
my $VIEW_AS_TABLE = '';
my $ESTIMATE_COST = 0;
my $COST_UNIT_VALUE = 0;
my $DUMP_AS_HTML = 0;
my $THREAD_COUNT = 0;
my $ORACLE_COPIES = 0;
my $DATA_LIMIT = 0;

my @CAPABILITIES = qw(
	TABLE PACKAGE INSERT COPY VIEW GRANT SEQUENCE TRIGGER QUERY KETTLE
	FUNCTION PROCEDURE TABLESPACE PARTITION TYPE MVIEW SHOW_VERSION
	SHOW_REPORT SHOW_SCHEMA SHOW_TABLE SHOW_COLUMN SHOW_ENCODING FDW
);

# Collect command line arguments
GetOptions (
	'a|allow=s' => \$ALLOW,
        'b|basedir=s' => \$OUTDIR,
        'c|conf=s' => \$CONFIG_FILE,
        'd|debug!' => \$DEBUG,
	'e|exclude=s' => \$EXCLUDE,
        'h|help!' => \$HELP,
	'i|input_file=s' => \$INPUT_FILE,
	'j|jobs=i' => \$THREAD_COUNT,
	'J|copies=i' => \$ORACLE_COPIES,
        'l|log=s' => \$LOGFILE,
	'L|limit=i' => \$DATA_LIMIT,
        'o|out=s' => \$OUTFILE,
	'p|plsql!' => \$PLSQL,
	'q|quiet!' => \$QUIET,
        't|type=s' => \$EXPORT_TYPE,
	'v|version!' => \$SHOW_VER,
	's|source=s' => \$DSN,
	'u|user=s' => \$DBUSER,
	'w|password=s' => \$DBPWD,
	'n|namespace=s' => \$SCHEMA,
	'x|xtable=s' => \$TABLEONLY, # Obsolete
	'forceowner=s' => \$FORCEOWNER,
	'nls_lang=s' => \$ORA_ENCODING,
	'client_encoding=s' => \$PG_ENCODING,
	'view_as_table=s' => \$VIEW_AS_TABLE,
	'estimate_cost!' =>\$ESTIMATE_COST,
	'cost_unit_value=i' =>\$COST_UNIT_VALUE,
	'dump_as_html!' =>\$DUMP_AS_HTML,
);

# Check command line parameters
if ($SHOW_VER) {
	print "Ora2Pg v$VERSION\n";
	exit 0;
}
if ($HELP) {
	&usage();
}
if (! -e $CONFIG_FILE) {
	print "FATAL: can't find configuration file $CONFIG_FILE\n";
	&usage();
}

# Validate export type
$EXPORT_TYPE = uc($EXPORT_TYPE);
$EXPORT_TYPE =~ s/DATA/INSERT/;
foreach my $t (split(/[,;\s\t]+/, $EXPORT_TYPE)) {
	if ($t && !grep(/^$t$/, @CAPABILITIES)) {
		print "FATAL: Unknow export type: $t. Type supported: ", join(',', @CAPABILITIES), "\n";
		&usage();
	}
}

# Preserve barckward compatibility
if ($TABLEONLY) {
	warn "-x | --xtable is deprecated, use -a | --allow option instead.\n";
	if (!$ALLOW) {
		$ALLOW = $TABLEONLY;
	}
}

sub getout
{
        my $sig = shift;
        print STDERR "Received terminating signal ($sig).\n";
        $SIG{INT} = \&getout;
        $SIG{TERM} = \&getout;
	exit 1;
}
$SIG{INT} = \&getout;
$SIG{TERM} = \&getout;

# Create an instance of the Ora2Pg perl module
my $schema = new Ora2Pg (
	config => $CONFIG_FILE,
	type   => $EXPORT_TYPE,
	debug  => $DEBUG,
	logfile=> $LOGFILE,
	output => $OUTFILE,
	output_dir => $OUTDIR,
	plsql_pgsql => $PLSQL,
	datasource => $DSN,
	user => $DBUSER,
	password => $DBPWD,
	schema => $SCHEMA,
	force_owner => $FORCEOWNER,
        nls_lang => $ORA_ENCODING,
        client_encoding => $PG_ENCODING,
        input_file => $INPUT_FILE,
	quiet => $QUIET,
	exclude => $EXCLUDE,
	allow => $ALLOW,
	view_as_table => $VIEW_AS_TABLE,
	estimate_cost => $ESTIMATE_COST,
	cost_unit_value => $COST_UNIT_VALUE,
	dump_as_html => $DUMP_AS_HTML,
	thread_count => $THREAD_COUNT,
	oracle_copies => $ORACLE_COPIES,
	data_limit => $DATA_LIMIT,
);


# Proceed to Oracle DB extraction following
# configuration file definitions.
if ( ($EXPORT_TYPE !~ /^SHOW_/i) && !$INPUT_FILE ) {
	$schema->export_schema();
}

exit(0);

sub usage
{
	print qq{
Usage: ora2pg [-dhpqv --estimate_cost --dump_as_html] [--option value]

    -a | --allow str  : coma separated list of objects to allow from export.
			Can be used with SHOW_COLUMN too.
    -b | --basedir dir: Used to set the default output directory, where files
			resulting from exports will be stored.
    -c | --conf file  : Used to set an alternate configuration file than the
			default /etc/ora2pg/ora2pg.conf.
    -d | --debug      : Enable verbose output.
    -e | --exclude str: coma separated list of objects to exclude from export.
			Can be used with SHOW_COLUMN too.
    -h | --help       : Print this short help.
    -i | --input file : File containing Oracle PL/SQL code to convert with
			no Oracle database connection initiated.
    -j | --jobs num   : number of parallel process to send data to PostgreSQL.
    -J | --copies num : number of parallel connection to extract data from Oracle.
    -l | --log file   : Used to set a log file. Default is stdout.
    -L | --limit num  : number of tuples extracted from Oracle and stored in
			memory before writing, default: 10000.
    -n | --namespace schema : Used to set the Oracle schema to extract from.
    -o | --out file   : Used to set the path to the output file where SQL will
			be written. Default: output.sql in running directory.
    -p | --plsql      : Enable PLSQL to PLPSQL code conversion.
    -q | --quiet      : disable progress bar.
    -s | --source DSN : Allow to set the Oracle DBI datasource.
    -t | --type export: Used to set the export type. It will override the one
			given in the configuration file (TYPE).
    -u | --user name  : Used to set the Oracle database connection user.
    -v | --version    : Show Ora2Pg Version and exit.
    -w | --password pwd : Used to set the password of the Oracle database user.
    --forceowner: if set to 1 force ora2pg to set tables and sequences owner
		  like in Oracle database. If the value is set to a username this
		  one will be used as the objects owner. By default it's the user
		  used to connect to the Pg database that will be the owner.
    --nls_lang code: use this to set the Oracle NLS_LANG client encoding.
    --client_encoding code: Use this to set the PostgreSQL client encoding.
    --view_as_table str: coma separated list of view to export as table.
    --estimate_cost   : activate the migration cost evalution with SHOW_REPORT
    --cost_unit_value minutes: number of minutes for a cost evalution unit.
		  default: 5 minutes, correspond to a migration conducted by a
		  PostgreSQL expert. Set it to 10 if this is your first migration.
   --dump_as_html     : force ora2pg to dump report in HTML, used only with
			SHOW_REPORT. Default is to dump report as simple text.

See full documentation at http://ora2pg.darold.net/ for more help or see
manpage with 'man ora2pg'.

};
	exit 0;

}

