/******************************************************************
* SimpleMySQLConnection JavaScript class for Mozilla
*
* by Moss Collum <moss@hamparts.com>
*
* Copyright (C) 2003 Doodlelab, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*
******************************************************************/

/*** Initialize RDF Components ***/

var RDFC = '@mozilla.org/rdf/container;1';
RDFC = Components.classes[RDFC].createInstance();
RDFC = RDFC.QueryInterface(Components.interfaces.nsIRDFContainer);

var RDFCUtils = '@mozilla.org/rdf/container-utils;1';
RDFCUtils = Components.classes[RDFCUtils].getService();
RDFCUtils = RDFCUtils.QueryInterface(Components.interfaces.nsIRDFContainerUtils);

var RDF = '@mozilla.org/rdf/rdf-service;1';
RDF = Components.classes[RDF].getService();
RDF = RDF.QueryInterface(Components.interfaces.nsIRDFService);

/*** SimpleMySQLConnection class ***/

function SimpleMySQLConnection(host, port, database, user, password, namespace) {
    debug("SimpleMySQLConnection");
    netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
    var mysql = Components.classes["@mozilla.org/mysql;1"].createInstance();
    mysql = mysql.QueryInterface(Components.interfaces.nsIMySQL);
    debug("  mysql: " + mysql);
    this.connection = new Object();
    this.connection = mysql.Connection(host, port, database, user, password);
    debug("  this.connection: " + this.connection);
    this.namespace = namespace;
}
SimpleMySQLConnection.prototype.getRDFResource = function(id) {
    return RDF.GetResource(this.namespace + '#' + id);
}
SimpleMySQLConnection.prototype.getDatasourceFromArray = function(arr) {
    var dsource = Components.classes['@mozilla.org/rdf/datasource;1?name=in-memory-datasource'].createInstance(Components.interfaces.nsIRDFDataSource);

    var rootSubject = RDF.GetResource('urn:root');

    var rowsPredicate = this.getRDFResource('rows');
    var rowsResource = RDF.GetAnonymousResource();
    var rowsList = RDFCUtils.MakeSeq(dsource, rowsResource);
    dsource.Assert(rootSubject, rowsPredicate, rowsResource, true);

    var columns = new Array();
    // get column names from first row and make RDF predicates for them
    for (columnName in arr[0]) {
        columns.push({name: columnName, predicate: this.getRDFResource(columnName)});
    }

    // for each row of the incoming data
    for (var i=0; i < arr.length; i++) {
        var row = RDF.GetAnonymousResource();

        // for each column of the incoming data
        for (var j=0; j < columns.length; j++) {
            var predicate = columns[j].predicate;
            var name = columns[j].name;
            var value = arr[i][name];
            dsource.Assert(row, predicate, RDF.GetLiteral(value), true);
        }

        rowsList.AppendElement(row);
    }

    return dsource;
}
SimpleMySQLConnection.prototype.executeQuery = function(query) {
    debug("SimpleMySQLConnection.executeQuery: " + query);
    debug("  this.connection: " + this.connection);
    try {
        this.connection.Execute(query, 1);
    } catch (e) {
        debug("  error in executeQuery: " + e);
    }

    var fieldNamesCnt = {value: 0};
    var fieldNames = {value: []};
    this.connection.FetchFieldNames(fieldNamesCnt, fieldNames);
    debug("  fieldNamesCnt: " + fieldNamesCnt + ", value: " + fieldNamesCnt.value);
    debug("  fieldNames: " + fieldNames + ", value: " + fieldNames.value);

    var rowCount = this.connection.NumRows();
    debug("  rowCount: " + rowCount);

    var resultSet = [];

    debug("  loading resultSet with data");
    for (var i=0; i<rowCount; i++) {
        debug("  Fetching row " + i);
        var rowDataCnt = {value: 0};
        var rowData = {value: []};
        this.connection.FetchRow(rowDataCnt, rowData);
        debug("  rowDataCnt: " + rowDataCnt + ", value: " + rowDataCnt.value);
        debug("  rowData: " + rowData + ", value: " + rowData.value);

        var row = {};
        for (var j=0; j<rowDataCnt.value; j++) {
            debug("  setting row[" + fieldNames.value[j] + "] = " + rowData.value[j]);
            row[fieldNames.value[j]] = rowData.value[j];
        }
        debug("  row: " + row);
        resultSet.push(row);
        debug("  finished resultSet.push(row)");
    }

    debug("  finished loading resultSet");

    // Store column names
    resultSet.columns = new Array();
    for (var i=0; i<fieldNamesCnt.value; i++) {
        resultSet.columns.push(fieldNames.value[i]);
    }

    return resultSet;
}
SimpleMySQLConnection.prototype.executeRDFQuery = function(query) {
    var rawData = this.executeQuery(query);
    return this.getDatasourceFromArray(rawData);
}
SimpleMySQLConnection.prototype.close = function() {
    this.connection.Finish();
}
