function toText(recordSet) {
  var result = '';
  for (var i=0; i<recordSet.length; i++) {
    result += (recordSet[i].length>1?recordSet[i].join():recordSet[i][0]) + '<br>';
  }
  return result;
}

function getIndex(recordSet, fieldName) {
  var result = -1;
  for (var i=0; i<recordSet[0].length; i++) {
    if (recordSet[0][i]==fieldName) {
      result = i;
      break;
    }
  }
  return result;
}

function makeRecordSet(sourceArray, separator) {
// converts an array of separator-separated value lists to a recordSet
  var result = new Array();
  for (var i=0; i<sourceArray.length; i++) {
    result.push(sourceArray[i].split(separator));
  }
  return result;
}

function makeArray(sourceRecordSet, columnIndex, startAt) {
// DWISOTT
  var startAt = startAt || 0;
  var columnIndex = columnIndex || 0;
  var result = new Array();
  for (var i=startAt; i<sourceRecordSet.length; i++) {
    result.push(sourceRecordSet[i][columnIndex]);
  }
  return result;
}

function applyFilter(recordSet, condition) {
  var resultRecordSet = new Array(recordSet[0]);
  for (var i=1; i<recordSet.length; i++) {
    var components = condition.split('==');
    if (components.length==2) {
      var fieldIndex = getIndex(recordSet, trimAll(components[0]))
      if (trimAll(components[1]) == recordSet[i][fieldIndex]) { resultRecordSet.push(recordSet[i]); }
    } else {
      components = condition.split('>');
      if (components.length==2) {
        var fieldIndex = getIndex(recordSet, trimAll(components[0]))
        if (trimAll(components[1]) > recordSet[i][fieldIndex]) { resultRecordSet.push(recordSet[i]); }
      } else {
        components = condition.split('<');
        if (components.length==2) {
          var fieldIndex = getIndex(recordSet, trimAll(components[0]))
          if (trimAll(components[1]) > recordSet[i][fieldIndex]) { resultRecordSet.push(recordSet[i]); }
        } else {
          components = condition.split('!=');
          if (components.length==2) {
            var fieldIndex = getIndex(recordSet, trimAll(components[0]))
            if (trimAll(components[1]) != recordSet[i][fieldIndex]) { resultRecordSet.push(recordSet[i]); }
          } else {
            components = condition.split('>=');
            if (components.length==2) {
              var fieldIndex = getIndex(recordSet, trimAll(components[0]))
              if (trimAll(components[1]) >= recordSet[i][fieldIndex]) { resultRecordSet.push(recordSet[i]); }
            } else {
              components = condition.split('<=');
              if (components.length==2) {
                var fieldIndex = getIndex(recordSet, trimAll(components[0]))
                if (trimAll(components[1]) <= recordSet[i][fieldIndex]) { resultRecordSet.push(recordSet[i]); }
              }
            }
          }
        }
      }
    }
  }
  return resultRecordSet;
}

function applyFieldList(recordSet, fieldList) {
// restricts recordSet to the named columns (acts like SQL SELECT)
  if (fieldList=='*') {
    return copyRecordSet(recordSet);
  } else {
    var resultRecordSet = new Array();
    fieldList += ',';
    for (var i=0; i<recordSet.length; i++) {
      var newRow = new Array();
      for (var j=0; j<recordSet[i].length; j++) {
        if (fieldList.indexOf(recordSet[0][j]+',')>=0) {
          newRow.push(recordSet[i][j]);
        }
      }
      resultRecordSet.push(newRow);
    }
    return resultRecordSet;
  }
}

function selectDistinct(recordSet, fieldList) {
// DWISOTT
  var accumulator = new Array();
  var constrainedRecordSet = applyFieldList(recordSet, fieldList);
  for (var i=0; i<constrainedRecordSet.length; i++) {
    var newCandidate = '';
    for (var j=0; j<constrainedRecordSet[i].length; j++) {
      newCandidate += (newCandidate.length>0?':':'') + constrainedRecordSet[i][j];
    }
    var exists = false;
    for (var k=0; k<accumulator.length; k++) {
      if (accumulator[k]==newCandidate) {
        exists = true;
        break;
      }
    }
    if (!exists) { accumulator.push(newCandidate); }
  }
  return makeRecordSet(accumulator, ':');
}

function tabulate(recordSet) {
// HTML-tabulates a recordSet
  var result = "<table border>";
  for (var i=0; i<recordSet.length; i++) {
    result +=  "<tr>";
    for (var j=0; j<recordSet[i].length; j++) {
      result += "<t" + (i==0?"h":"d") + " style='font-family:verdana;font-size:8pt'>" + recordSet[i][j];
    }
  }
  return result + "</table>";
}

function sortByFieldName(row1, row2, fieldName) {
  var fieldIndex = getIndex(db, fieldName);
  return (row1[fieldIndex]<row2[fieldIndex])?-1:((row1[fieldIndex]>row2[fieldIndex])?1:0);
}

function sortByColumn0(row1, row2) {
  return sortByFieldName(row1, row2, db[0][0]);
}

function sortByColumn1(row1, row2) {
  return sortByFieldName(row1, row2, db[0][1]);
}

function copyRecordSet(recordSet) {
  var resultRecordSet = new Array();
  for (var i=0; i<recordSet.length; i++) {
    var newRow = new Array();
    for (var j=0; j<recordSet[i].length; j++) {
      newRow.push(recordSet[i][j]);
    }
    resultRecordSet.push(newRow)
  }
  return resultRecordSet;
}

function copyRow(recordSet, index) {
  var resultRow = new Array();
  for (var i=0; i<recordSet[index].length; i++) {
    resultRow.push(recordSet[index][i]);
  }
  return resultRow;
}

function sortRecordSet(recordSet, functionName)  {
  var recordSetCopy = copyRecordSet(recordSet);
  var fieldNames = copyRow(recordSet, 0);
  recordSetCopy.splice(0, 1)
  recordSetCopy.sort(functionName);
  var resultRecordSet = new Array(fieldNames);
  for (var i=0; i<recordSetCopy.length; i++) {
    resultRecordSet.push(recordSetCopy[i]);
  }
  return resultRecordSet;
}

function trimAll(sString) {
  while (sString.substring(0,1) == ' ') {
    sString = sString.substring(1, sString.length);
  }
  while (sString.substring(sString.length-1, sString.length) == ' ') {
    sString = sString.substring(0,sString.length-1);
  }
  return sString;
}