<% /*
    $Revision$
    $Id$

    File:           model_generic.inc

    Description:    Generiek model voor willekeurige tabel
    Parameters:
    Context:

    Notes:
*/

function model_generic_template()
{
    this.table = "<unkown>";
    this.primary = "<unkown>";
    this.records_name = "<unkown>s";
    this.record_name = "<unkown>";
    this.fields = {};
    this.list = { columns: [] };
    this.search = { filters: [] };
    this.soft_delete = null;
    this.autfunction = "WEB_PRSSYS";
}

function _findseq(primary)
{
    var seq_name = primary.substr(0,3) + "_S_" + primary;
    var seq =  null;
    var sql = "SELECT sequence_name"
            + "  FROM user_sequences"
            + " WHERE sequence_name = " + safe.quoted_sql_upper(seq_name);
    var oRs = Oracle.Execute(sql);
    if (!oRs.Eof)
    {
        seq = oRs("sequence_name").Value.toLowerCase();
        __Log("Sequence {0} found".format(seq_name));
    }
    else
        __Log("Sequence {0} not found".format(seq_name));
    oRs.Close();
    return seq;
}

function model_generic(table, autfunction)
{
    var model = new model_generic_template();
    model.autfunction = autfunction;
    model.table = table.toLowerCase();
    model.record_name = table.substring(0,1).toUpperCase() + table.substring(1);
    model.records_name = model.record_name + "s";

    var sql = "SELECT LOWER(cols.column_name) column_name, cols.position, cons.status, cons.owner"
            + "  FROM user_constraints cons, user_cons_columns cols"
            + " WHERE cols.table_name = " + safe.quoted_sql_upper(table)
            + "   AND cons.constraint_type = 'P'"
            + "   AND cons.constraint_name = cols.constraint_name"
            + "   AND cons.owner = cols.owner"
            + " ORDER BY cols.table_name, cols.position";
    var oRs = Oracle.Execute(sql);
    if (oRs.Eof)
    {
        abort_with_warning("Unable to determine primary key for table {0}".format(table));
    }

    model.primary = oRs("column_name").Value;
    oRs.MoveNext();
    if (!oRs.Eof)
    {
        abort_with_warning("Composite primary key not supported for table {0}".format(table));
    }
    oRs.Close();


    var sql = "SELECT num_rows, last_analyzed"
            + "  FROM user_tables"
            + " WHERE table_name = " + safe.quoted_sql_upper(table);
    var oRs = Oracle.Execute(sql);
    model.estimated_rows = oRs("num_rows").Value;
    model.last_analyzed = oRs("last_analyzed").Value;
    oRs.Close;

    var sql = "SELECT LOWER(column_name) column_name"
        + "     , data_type"
        + "     , data_length"
        + "     , data_precision"
        + "     , data_scale"
        + "  FROM user_tab_columns utc"
        + " WHERE utc.table_name = UPPER(" + safe.quoted_sql_upper(table) + ")"
        + " ORDER BY column_id";
    var oRs = Oracle.Execute(sql);
    var hasName = false;
    model.nrfields = 0;
    var seq = _findseq(model.primary);
    while (!oRs.eof)
    {
        model.nrfields++;
        var field = { dbs: oRs.Fields("column_name").Value,
                      label: oRs.Fields("column_name").Value,
                      typ: "varchar"
                    };
        var ora_type = oRs("data_type").Value;
        var ora_length = oRs("data_length").Value;
        var ora_precision = oRs("data_precision").Value;
        var ora_scale = oRs("data_scale").Value;

        switch (ora_type)
        {
            case 'NUMBER':
                field.typ = 'number';
                if (ora_scale > 0)
                {
                    field.datatype = 'float';
                }
                if (field.dbs.match(/_key$/))
                {
                    field.typ = 'key';
                    if (field.dbs != model.primary)
                    {
                        var ftable = field.dbs.replace(/_key$/,"");// TODO ipv. de replace echt foreign-key constraint controleren

                        var sql = "SELECT table_name, num_rows"
                                + "  FROM user_tables"
                                + " WHERE table_name = " + safe.quoted_sql_upper(ftable)
                                + "    OR table_name = " + safe.quoted_sql_upper(ftable.substr(4)); // mld_alg_locatie_key bijv.
                        if (ftable.match(/ins_discipline$/))
                            sql += " OR table_name = 'INS_TAB_DISCIPLINE'";
                        var oRs2 = Oracle.Execute(sql);
                        if (!oRs2.Eof)
                        {
                            ftable = oRs2("table_name").Value.toLowerCase();
                            field.num_rows = oRs2("num_rows").Value; // voor scf auto-listboxen interessant
                            field.foreign = { tbl: ftable, key: field.dbs, desc: field.dbs };
                            // TODO: Kan dit niet (beter) terugvallen op foreignKeyTabel MLD_DISCIPLINE en zo?
                            if (ftable == "ins_tab_discipline")
                            {
                                field.foreign = { tbl: ftable, key: "ins_discipline_key", desc: "ins_discipline_omschrijving" };
                            }
                            field.infoPointer = { Url: "appl/mgt/mgt_generic.asp?mode=show&table=" + ftable + "&id=" };
                        }
                        oRs2.Close();

                        if (foreignKeyTable(ftable))
                        {
                            field.foreign = ftable;
                            field.label = field.label.replace(/_key$/, "(_key)"); // indicatie dat het foreign is
                            field.filter = "exact";
                        }
                    }
                }
                break;
            case "DATE":
                field.typ = 'datetime';
                if (field.dbs == model.table + "_datum" ||
                    field.dbs == model.table + "_van" ||
                    field.dbs == model.table + "_aanmaak")
                    field.filter = "range";
                break;
            case "VARCHAR2":
                field.typ = 'varchar';
                break;
            case "MLD_T_UITVOERTIJD":
                field.typ = 'varchar';
                field.readonly = true;
                // Het volgende werkt niet goed: er *moet* een table-alias voor die kan varieren?
                // field.sql = field.dbs + ".tijdsduur || " + field.dbs + ".eenheid";
                // field.sql = "'$mld_t_uitvoertijd not supported yet$'";
                field.sql = "mld.uitvoertijd_to_char({0})".format(field.dbs);
                break;
            default:
                abort_with_warning("Unknown Oracle type '{0}'".format(ora_type));
        }

        var fld = oRs.Fields("column_name").Value;

        if (fld == table.toLowerCase() + "_verwijder")
            model.soft_delete = fld;

        // Dan zien we hem ook nergens meer?
        if (fld == model.table + "_aanmaak")
            field.readonly = true;

        if (fld == model.primary)
        {
            field.filter = "exact";
            fld = "id";
            if (seq)
                field.seq = seq;
        }
        if (!hasName && fld.match(/_code$/))
        {
            field.filter = "like";
            fld = "name";
            hasName = true;
        }
        if (!hasName && fld.match(/(_omschrijving|_oms|_remark)$/))
        {
            field.filter = "like";
            fld = "name";
            hasName = true;
        }
        if (fld == model.table + "_module")
        {
            field.filter = "like";
        }
        if (field.filter)
            model.search.filters.push(fld);
        model.fields[fld] = field;

        if (fld == "id" || fld == "name" || fld == "description" || field.filter)
            model.list.columns.push(fld);

        oRs.MoveNext();
    }
    oRs.Close();

    api2.generic_REST(model);

    __Log(model);
    return model;
}

%>
