var DBPRV = WScript.Arguments(0);
var DBVER = WScript.Arguments(1);

var newdb = 'TEST_DB' + DBVER;
var olddb = 'TEST_DB' + DBPRV + 'toDB' + DBVER;

WScript.Echo("Comparing " + olddb + " to " + newdb)


var Oracle = new ActiveXObject("ADODB.Connection");
var strconn = "Provider=OraOLEDB.Oracle.1;"
            + "Data Source=Work;"
            + "User Id=system;"
            + "Password=XZSTXnHGjfNNODfQc";

Oracle.Open(strconn);
// De eerste paar onderkennen vooral als iets gedropt moet worden
checkora("all_tables", "TABLE_NAME")
checkora("all_views", "VIEW_NAME")
checkora("all_triggers", "TRIGGER_NAME, TABLE_NAME")
checkora("all_sequences", "SEQUENCE_NAME, MIN_VALUE, INCREMENT_BY", "SEQUENCE_OWNER")

// DATA_DEFAULT zou ik graag contoleren maar is WIDE-MEMO
checkora("all_tab_columns", "TABLE_NAME, COLUMN_NAME, DATA_TYPE, DATA_LENGTH, DATA_PRECISION, DATA_SCALE, NULLABLE")
// CONSTRAINT_NAME en R_CONSTRAINT_NAME, zou ik graag controleren maar is vaak systeem gegenereerd
checkora("all_constraints", "CONSTRAINT_TYPE, TABLE_NAME, DELETE_RULE")

// INDEX_NAME, zou ik graag controleren maar is vaak systeem gegenereerd
checkora("all_indexes", "TABLE_NAME, UNIQUENESS")


var sql = "SELECT *"
        + "  FROM all_tables"
        + " WHERE owner = UPPER('" + newdb + "')"
        + "   AND table_name <> 'ADM_TRACKING'"
        + "   AND table_name <> 'FAC_AUDIT'"
        + " ORDER BY table_name";
var oRs = Oracle.Execute(sql);
while (!oRs.Eof)
{
    checkauto(oRs("table_name").Value);
    oRs.MoveNext();
}

// Controleer default lcl's
var sql = "SELECT fac_srtnotificatie_oms"
        + "  FROM " + newdb + ".fac_srtnotificatie"
        + " WHERE NOT EXISTS"
        + "           (SELECT 1"
        + "              FROM " + newdb + ".fac_locale_xsl"
        + "             WHERE fac_locale_xsl_label = fac_srtnotificatie_oms)";
checkempty(sql, "ORA- fac_srtnotificatie_oms lcl's die in FAC_LCL.SRC missen");

var sql = "SELECT fac_menuitems_label"
        + "  FROM " + newdb + ".fac_menuitems"
        + " WHERE NOT EXISTS"
        + "           (SELECT 1"
        + "              FROM " + newdb + ".fac_locale_xsl"
        + "             WHERE fac_locale_xsl_label = fac_menuitems_label)";
checkempty(sql, "ORA- fac_menuitems_label lcl's die in FAC_LCL.SRC missen");

var sql = "SELECT fac_menu_altlabel"
        + "  FROM " + newdb + ".fac_menu"
        + " WHERE SUBSTR(fac_menu_altlabel, 1, 4) = 'lcl_'"
        + "   AND NOT EXISTS"
        + "           (SELECT 1"
        + "              FROM " + newdb + ".fac_locale_xsl"
        + "             WHERE fac_locale_xsl_label = fac_menu_altlabel)";
checkempty(sql, "ORA- fac_menu_altlabel lcl's die in FAC_LCL.SRC missen");

var sql = "SELECT fac_functie_omschrijving"
        + "  FROM " + newdb + ".fac_functie"
        + " WHERE NOT EXISTS"
        + "           (SELECT 1"
        + "              FROM " + newdb + ".fac_locale_xsl"
        + "             WHERE fac_locale_xsl_label = fac_functie_omschrijving)";
checkempty(sql, "ORA- fac_functie_omschrijving lcl's die in FAC_LCL.SRC missen");

var sql = "SELECT fac_functie_info"
        + "  FROM " + newdb + ".fac_functie"
        + " WHERE NOT EXISTS"
        + "           (SELECT 1"
        + "              FROM " + newdb + ".fac_locale_xsl"
        + "             WHERE fac_locale_xsl_label = fac_functie_info)";
checkempty(sql, "ORA- fac_functie_info lcl's die in FAC_LCL.SRC missen");

function checkora(sysview, cols, owner)
{
    owner = owner || 'OWNER';
    var sql = "SELECT " + cols
            + "  FROM " + sysview
            + " WHERE " + owner + " = UPPER('" + olddb + "')"
            + " MINUS "
            + "SELECT " + cols
            + "  FROM " + sysview
            + " WHERE " + owner + " = UPPER('" + newdb + "')";
    checkempty(sql, sysview + " in " + olddb + " maar niet in " + newdb);
    var sql = "SELECT " + cols
            + "  FROM " + sysview
            + " WHERE " + owner + " = UPPER('" + newdb + "')"
            + " MINUS "
            + "SELECT " + cols
            + "  FROM " + sysview
            + " WHERE " + owner + " = UPPER('" + olddb + "')";
    checkempty(sql, sysview + " in " + newdb + " maar niet in " +olddb);
}

function checkauto(tbl)
{
    var oldwhere = "";
    if (tbl == "FAC_LOCALE_XSL")
    {
        oldwhere = " WHERE FAC_LOCALE_XSL_LANG NOT IN ('DE', 'FR')";
    }
    WScript.Echo("Checking " + tbl);
    var cnt1 = Oracle.Execute("SELECT COUNT(*) FROM " + olddb + "." + tbl + oldwhere)(0).Value;
    var cnt2 = Oracle.Execute("SELECT COUNT(*) FROM " + newdb + "." + tbl)(0).Value;
    if (cnt1 != cnt2)
        WScript.Echo("Aantal records " + tbl + " verschilt: " + olddb + " " + cnt1 + ", " + newdb + " " + cnt2);

    var cols = [];
    var sql = "SELECT *"
            + "  FROM all_tab_columns"
            + " WHERE owner = UPPER('" + newdb + "')"
            + "   AND table_name = UPPER('" + tbl + "')"
            + "   AND data_type NOT IN ('DATE', 'LONG', 'MLD_T_UITVOERTIJD')";
    var oRs = Oracle.Execute(sql);
    while (!oRs.Eof)
    {
        var col = oRs("COLUMN_NAME").Value;
        if (!col.match(/(_KEY|_VOLGNR|_SALT|_HASH|_OTPSECRET|APIKEY|RES_RUIMTE_SYNCSTATE)$/))
            cols.push(col)
        oRs.MoveNext();
    }
    //WScript.Echo(cols);
    if (cols.length) // Niet alleen _KEY's
    {
        var where = "";
        if (tbl == 'FAC_SETTING')
            where = " WHERE fac_setting_name NOT IN ('fac_logfilename','fac_logfilename','puo_fclt_web_apikey')"
        check(tbl, cols, where);
    }
}

function checkempty(sql, txt)
{
    //WScript.Echo(sql);
    var oRs = Oracle.Execute(sql);
    if (!oRs.Eof)
    {
        WScript.Echo("==================== " + txt);
        //WScript.Echo(prettysql(sql));
        //WScript.Echo("\n");
        var n = 0;
        while (!oRs.Eof)
        {
            n++;
            var flds = [];
            for (var i = 0; i < oRs.Fields.Count; i++)
            {
                flds.push(oRs.Fields(i).Value);
            }
            WScript.Echo(flds.join(","));
            oRs.MoveNext();

        }
        //WScript.Echo("\nVreemd, " + n + " record(s));
        WScript.Echo("\n");
    }
    oRs.Close();
}

function check(tbl, cols, where)
{
    var oldwhere = "";
    if (tbl == "FAC_LOCALE_XSL")
    {
        oldwhere = " WHERE FAC_LOCALE_XSL_LANG NOT IN ('DE', 'FR')";
    }
    var sql = "SELECT " + cols
            + "  FROM " + olddb + "." + tbl
            + (where || "") + oldwhere
            + " MINUS "
            + "SELECT " + cols
            + "  FROM " + newdb + "." + tbl
            + (where || "");
    checkempty(sql, tbl + " in " + olddb + " maar niet in " + newdb);
    var sql = "SELECT " + cols
            + "  FROM " + newdb + "." + tbl
            + (where || "")
            + " MINUS "
            + "SELECT " + cols
            + "  FROM " + olddb + "." + tbl
            + (where || "") + oldwhere;
    checkempty(sql, tbl + " in " + newdb + " maar niet in " + olddb);
}

function createShiftArr(step) {

	var space = '    ';

	if ( isNaN(parseInt(step)) ) {  // argument is string
		space = step;
	} else { // argument is integer
		switch(step) {
			case 1: space = ' '; break;
			case 2: space = '  '; break;
			case 3: space = '   '; break;
			case 4: space = '    '; break;
			case 5: space = '     '; break;
			case 6: space = '      '; break;
			case 7: space = '       '; break;
			case 8: space = '        '; break;
			case 9: space = '         '; break;
			case 10: space = '          '; break;
			case 11: space = '           '; break;
			case 12: space = '            '; break;
		}
	}

	var shift = ['\n']; // array of shifts
	for(ix=0;ix<100;ix++){
		shift.push(shift[ix]+space);
	}
	return shift;
}


//----------------------------------------------------------------------------
// http://www.eslinstructor.net/vkbeautify/

function isSubquery(str, parenthesisLevel) {
	return  parenthesisLevel - (str.replace(/\(/g,'').length - str.replace(/\)/g,'').length )
}

function split_sql(str, tab) {

	return str.replace(/\s{1,}/g," ")

				.replace(/ AND /ig,"~::~"+tab+tab+"AND ")
				.replace(/ BETWEEN /ig,"~::~"+tab+"BETWEEN ")
				.replace(/ CASE /ig,"~::~"+tab+"CASE ")
				.replace(/ ELSE /ig,"~::~"+tab+"ELSE ")
				.replace(/ END /ig,"~::~"+tab+"END ")
				.replace(/ FROM /ig,"~::~FROM ")
				.replace(/ GROUP\s{1,}BY/ig,"~::~GROUP BY ")
				.replace(/ HAVING /ig,"~::~HAVING ")
				//.replace(/ SET /ig," SET~::~")
				.replace(/ IN /ig," IN ")

				.replace(/ JOIN /ig,"~::~JOIN ")
				.replace(/ CROSS~::~{1,}JOIN /ig,"~::~CROSS JOIN ")
				.replace(/ INNER~::~{1,}JOIN /ig,"~::~INNER JOIN ")
				.replace(/ LEFT~::~{1,}JOIN /ig,"~::~LEFT JOIN ")
				.replace(/ RIGHT~::~{1,}JOIN /ig,"~::~RIGHT JOIN ")

				.replace(/ ON /ig,"~::~"+tab+"ON ")
				.replace(/ OR /ig,"~::~"+tab+tab+"OR ")
				.replace(/ ORDER\s{1,}BY/ig,"~::~ORDER BY ")
				.replace(/ OVER /ig,"~::~"+tab+"OVER ")

				.replace(/\(\s{0,}SELECT /ig,"~::~(SELECT ")
				.replace(/\)\s{0,}SELECT /ig,")~::~SELECT ")

				.replace(/ THEN /ig," THEN~::~"+tab+"")
				.replace(/ MINUS /ig,"~::~MINUS~::~")
				.replace(/ UNION /ig,"~::~UNION~::~")
				.replace(/ USING /ig,"~::~USING ")
				.replace(/ WHEN /ig,"~::~"+tab+"WHEN ")
				.replace(/ WHERE /ig,"~::~WHERE ")
				.replace(/ WITH /ig,"~::~WITH ")

				//.replace(/\,\s{0,}\(/ig,",~::~( ")
				//.replace(/\,/ig,",~::~"+tab+tab+"")

				.replace(/ ALL /ig," ALL ")
				.replace(/ AS /ig," AS ")
				.replace(/ ASC /ig," ASC ")
				.replace(/ DESC /ig," DESC ")
				.replace(/ DISTINCT /ig," DISTINCT ")
				.replace(/ EXISTS /ig," EXISTS ")
				.replace(/ NOT /ig," NOT ")
				.replace(/ NULL /ig," NULL ")
				.replace(/ LIKE /ig," LIKE ")
				.replace(/\s{0,}SELECT /ig,"SELECT ")
				.replace(/\s{0,}UPDATE /ig,"UPDATE ")
				.replace(/ SET /ig," SET ")

				.replace(/~::~{1,}/g,"~::~")
				.split('~::~');
}

function prettysql(text,step)
{

	var ar_by_quote = text.replace(/\s{1,}/g," ")
							.replace(/\'/ig,"~::~\'")
							.split('~::~'),
		len = ar_by_quote.length,
		ar = [],
		deep = 0,
		tab = '    ',
		inComment = true,
		inQuote = false,
		parenthesisLevel = 0,
		str = '',
		ix = 0,
		shift = createShiftArr(4);

		for(ix=0;ix<len;ix++) {
			if(ix%2) {
				ar = ar.concat(ar_by_quote[ix]);
			} else {
				ar = ar.concat(split_sql(ar_by_quote[ix], tab) );
			}
		}

		len = ar.length;
		for(ix=0;ix<len;ix++)
		{
			parenthesisLevel = isSubquery(ar[ix], parenthesisLevel);

			if( /\s{0,}\s{0,}SELECT\s{0,}/.exec(ar[ix]))  {
				ar[ix] = ar[ix].replace(/\,/g,",\n"+tab+tab+"")
			}

			if( /\s{0,}\s{0,}SET\s{0,}/.exec(ar[ix]))  {
				ar[ix] = ar[ix].replace(/\,/g,",\n"+tab+tab+"")
			}

			if( /\s{0,}\(\s{0,}SELECT\s{0,}/.exec(ar[ix]))  {
				deep++;
				str += shift[deep]+ar[ix];
			} else
			if( /\'/.exec(ar[ix]) )  {
				if(parenthesisLevel<1 && deep) {
					deep--;
				}
				str += ar[ix];
			}
			else  {
				str += shift[deep]+ar[ix];
				if(parenthesisLevel<1 && deep) {
					deep--;
				}
			}
			var junk = 0;
		}

		str = str.replace(/^\n{1,}/,'').replace(/\n{1,}/g,"\n");
		return str;
}
