<% /*
     $Revision$
     $Id$
*/ %>
<%

var adExecuteNoRecords = 0x80;
var _LastFacError = {}; // Deze kun je direct na een error raadplegen voor een vriendelijkere tekst
// als catchErrors is gedefinieerd (overigens alleen ondersteund voor INSERT/UPDATE/DELETE en *niet* voor SELECT)
// dan worden alle Oracle errors afgevangen en wordt bij fouten _LastFacError opgeleverd
function SafeExec( sql, catchErrors ) {
  var result;
  var handle = __Log(sql, SafeExec.caller, true /* leave_open */);
  var startDate = new Date();
  var hasRecords = !sql.match(/^(DELETE|INSERT|UPDATE|BEGIN|DECLARE|ALTER)/ig); // Waarschijnlijk alleen SELECT en WITH over

  _LastFacError = { fullMsg: "", faccode : "", friendlyMsg : "" };
  try {
    if (hasRecords)
    {
        result = this.RealConnection.Execute( sql );
    }
    else
    {
        this.RealConnection.Execute( sql, null, adExecuteNoRecords); // Voorkomt out-of-cursors
        result = {}; // er moet later wel een err.friendlyMsg getest kunnen worden
    }
  } catch( e1 ) {
    __LogCloseLine(null, "FAIL", "#FF0000");
    var msg = e1.description;
    var knownError = false;
    _LastFacError = { fullMsg: msg,
                      faccode : "",
                      friendlyMsg : msg };
    if (msg.match(/^ORA-20000/i) || msg.match(/^ORA-20004/i) || msg.match(/^ORA-00001/i) || msg.match(/^ORA-02290/i))
    {
        RegCode = msg.match(/^ORA-20000: (\w*)(.*)\nORA-/i);     // Zoek: ORA-20000: res_m039 ORA-06512: at "UWVA_500.ALG_T_ALG_RUIMTE_B_IU", line 71 ORA-04088: error during execution of trigger 'UWVA_500.ALG_T_ALG_RUIMTE_B_IU'
        if (!RegCode || RegCode.length == 0)
            RegCode = msg.match(/^ORA-20004: (\w*)(.*)\nORA-/i); // Zoek: ORA-20004: ins_m145,Normverbruik,0, ORA-06512: at .......
        if (!RegCode || RegCode.length == 0)
            RegCode = msg.match(/^ORA-00001: .* \(.*\.(\w*)\)/i) // Zoek: ORA-00001: unique constraint (UWVA_500.ALG_U_ALG_RUIMTE_UPPER_NR) violated
        if (!RegCode || RegCode.length == 0)
            RegCode = msg.match(/^ORA-02290: .* \(.*\.(\w*)\)/i) // Zoek: ORA-02290: check constraint (UWVA_500.ALG_C_ALG_RUIMTE_UPPER_NR) violated

        if (RegCode && RegCode.length > 1)
        {
            _LastFacError.faccode = RegCode[1];
        }
        if (msg.match(/^ORA-20000/i) && RegCode && RegCode.length > 2)
        {
            _LastFacError.friendlyMsg = RegCode[2]; // een ORA-20000 met ingebouwde tekst zoals ORA-20000: alg_m999 Ruimte kan nog niet verwijderd worden. Er zijn nog lopende meldingen
            var knownError = true;
        }
        // We gaan proberen de tekst er bij te zoeken
        if (_LastFacError.faccode != "")
        {
            var sql2 = "select FAC_MESSAGE_TEXT from fac_message where fac_message_code = "+safe.quoted_sql_upper(_LastFacError.faccode);
            try {
                var oRs = this.RealConnection.Execute( sql2 );
            } catch (e2)
            {
                 // als dit mislukt weet ik het ook niet meer
            }
            if (!oRs.Eof)
            {
                var knownError = true;
                _LastFacError.friendlyMsg = oRs("FAC_MESSAGE_TEXT").Value + "\n(" + _LastFacError.faccode + ")";
            }
            oRs.Close();
        }
        var ignoreError = /res_m999|res_m960/; // Ruimte niet beschikbaar
        if (knownError && !_LastFacError.faccode.match(ignoreError))
        {
            if (!(Session("logging")&1))
                __DoLog(sql); // alsnog
            __SafeDoLog("<div style=\"border-top:1px solid red;\">Bovenstaande ging fout: <em>" + _LastFacError.faccode + "</em> betekent:<br/><strong>" + _LastFacError.friendlyMsg + "</strong></div>");
        }
        else
            __Log("Foutcode: " + _LastFacError.faccode + " niet gevonden in fac_message");
    }
    if (!knownError)
    {
        if (!(Session("logging")&1))
            __DoLog(sql); // alsnog
        __SafeDoLog("Database exception:<br>" + Server.HTMLEncode(e1.description).replace(/\n/g,"<br/>"), "#f00");
        try {
            if (Request.Form.Count>0) __DoLogForm("#FF0000");
        }
        catch(e)
        { /* er is al een Request.BinaryRead geweest */ }
    }

    if (!catchErrors)
    {
        Session("last_sql") = sql; // wordt door 500-error.asp opgepikt
        throw e1; // Throw again
    }
    else
        return _LastFacError;
  }

  // Geen errors blijkbaar.
  var eofText = ""
  try {
      if( hasRecords && result.State != 0 && result.Eof) // This Eof test may take some time!
        eofText = "<b>N/R</b>";
  } catch( e3 ) {
        __LogCloseLine(null, "<div style=\"background-color: #FF0000;\">Error while getting result.Eof: " + e3.description + "</div>");
        throw e3; // Throw again
  }

  var ms_taken = new Date() - startDate;

  // Indien ingesteld registreren we het aantal statements dat een bepaalde drempelwaarde
  // (in millisecondes) overschrijdt. Hoe, dat bepaalt een databaseprocedure.
  if (S("perfmon_threshold") > -1) {
    if (S("perfmon_threshold") < 500) S("perfmon_threshold") = 500; // daaronder wordt het riskanter en valsspelen.
    if (ms_taken > S("perfmon_threshold")) {
        var isql = "BEGIN fac.fac_perfmon_incr("+S("perfmon_threshold")+", "+ms_taken+"); END;"
        this.RealConnection.Execute( isql, null, adExecuteNoRecords);
        eofText = eofText+"<br><b>#P#</b>";
    }
  }

  __LogCloseLine(handle, eofText);

  return result;
}

function SafeOracle( ora ) {
  this.RealConnection = ora;
  this.Execute = SafeExec;
}

SafeOracle.prototype.rs2hash = function _rs2hash (oRs)
{
    var result = [];
    while(!oRs.Eof)
    {
        var datahash = {};
        for (var i = 0; i < oRs.Fields.Count; i++)
        {
            var v = oRs.Fields(i).Value;
            if (v != null && oRs.Fields(i).Type == 135) // adDBTimeStamp
                v = new Date(v);
            datahash[oRs.Fields(i).Name.toLowerCase()] = v;
        }
        result.push(datahash);
        oRs.MoveNext();
    }
    return result;
}
SafeOracle.prototype.Get = function _get (descfield, table, keyname, key)
{
    if (typeof key == "undefined")
    {
        key = keyname;
        keyname = table + "_KEY";
    }
    var sql = "SELECT {0} FROM {1} WHERE {2} = {3}".format(descfield, table, keyname, key);
    var oRs = this.Execute(sql);
    var res = oRs.Fields(0).Value;
    oRs.Close();
    return res;
}

// ===================================
// Initialize the global Oracle object
// ===================================
  if( ! this.Oracle )
  try {
        var str = Server.MapPath(custpath + "/Oracle.udl");
        var o = Server.CreateObject("ADODB.Connection");
        o.Open('File Name=' + str);
        Oracle = new SafeOracle(o);

  } catch( e1 ) {
        objFile = Server.CreateObject("Scripting.FileSystemObject");
        if (!objFile.FileExists(str))
        {
            Response.write("oracle.udl niet gevonden voor: " + customerId);
            Response.end;
        }
        __SafeDoLog(str + "<div style=\"background-color: #FF00FF;\">"+str+"<br>Cannot create database connection: " + e1.description + "</div>");
        throw e1; // Throw again, VERY fatal
  }

  // Merk op: iets als user_lang bepaling zou je eerder verwachten in common.inc
  // We zitten hier echter met een kip-ei probleem: we willen het *direct* gebruiken
  // voor fac.initsession maar kunnen het pas gebruiken als we database connectie
  // hebben. Daarom dus hier.
  var user_lang = Session("user_lang");
  var fac_lang = getQParamSafe("fac_lang", "").toUpperCase(); // overrule via param
  if (fac_lang)
  {
    if (typeof user_lang == "undefined")
        Session("user_lang") = fac_lang;
    user_lang = fac_lang; // In ieder geval voor *deze* pagina
  }

  if (!user_lang || typeof user_lang == "undefined")
  {
    var oRs = o.Execute("SELECT fac_version_lang FROM fac_version");
    user_lang = oRs("fac_version_lang").Value; // De database taal voorlopig.
    oRs.Close();
  }
  var oraprefix = "BEGIN fac.initsession("+safe.quoted_sql(user_lang)+"); END;";
  o.Execute( oraprefix );
%>
