File: lib-js/xbstable.js

Recommend this page to a friend!
  Classes of Alexey Znaev   XBSDB   lib-js/xbstable.js   Download  
File: lib-js/xbstable.js
Role: Class source
Content type: text/plain
Description: Table class
Class: XBSDB
Manipulate arrays with an SQL-like language
Author: By
Last change: changed Listing priority
Date: 14 years ago
Size: 27,549 bytes
 

Contents

Class file image Download
/////////////////////////////////////////////////////////////////////////// // // XBSDB - Cross-Browser JavaScript Database library // Copyright (C) 2010 Alexey A.Znayev // // This file is part of XBSDB. // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program 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 General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see <http://www.gnu.org/licenses/>. // // Alexey A.Znayev, znaeff@mail.ru // /////////////////////////////////////////////////////////////////////////// // This flie contains private class(es) and/or method(s) and may be changed any time /////////////////////////////////////////////////////////////////////////// // table (name, structure, number of records, hash of columns) // aStructure - array of arrays [ name, type ] function XBSTable(aStructure){ // public fields this.sResultCode = 'OK'; this._aStructure = aStructure; this._oCols = {}; // hash 'name' => 'column' this._aFieldNames = []; // solid array of names this._oFieldTypes = {}; // hash 'name' => 'type' for(var i = 0; i < this._aStructure.length; i++){ // solid if(typeof this._aStructure[i][1] != 'string'){ this.sResultCode = 'TABLE_STRUCTURE_BAD'; break; } switch(this._aStructure[i][1]){ case 'string' : case 'number' : this._oCols[this._aStructure[i][0]] = []; // this way to store records provides the minimum of dereferences (3) to access a row value, see sFieldBefore & sFieldAfter this._aFieldNames.push(this._aStructure[i][0]); this._oFieldTypes[this._aStructure[i][0]] = this._aStructure[i][1]; break; default : this.sResultCode = 'TABLE_FIELD_TYPE_UN'; }//switch if(this.sResultCode != 'OK'){ break; } }//for if(this.sResultCode == 'OK'){ this._nRecords = 0; this._oKeys = {}; // keys hash ['id'] => [XBSKey object] this._aDeleted = []; // not solid not packed array 'recodr number' => 'true' for deleted records } } //XBSTable.prototype.sFieldBefore = 'table._oCols.'; //XBSTable.prototype.sFieldBefore = 'table._aRecords[n][table._oCols["'; XBSTable.prototype.sFieldBefore = 'table._oCols.'; //XBSTable.prototype.sFieldAfter = '.GetValue(n)'; //XBSTable.prototype.sFieldAfter = '"]]'; XBSTable.prototype.sFieldAfter = '[n]'; XBSTable.prototype.oAllowedKeyOperations = { // 'a' : ['+'], // 'n' : ['+','-','*','/'], // 's' : ['+'] } XBSTable.prototype.Load = function(aRows){ this.sResultCode = 'OK'; var nFields = this._aFieldNames.length; this._aDeleted = []; this._nRecords = aRows.length; for(var nRec = 0; nRec < this._nRecords; nRec++){ for(var nField = 0; nField < nFields; nField++){ this._oCols[this._aFieldNames[nField]][nRec] = aRows[nRec][nField]; } } return true; } XBSTable.prototype.Dump = function(){ this.sResultCode = 'OK'; var oDump = {}, nFields = this._aStructure.length, aRecord; oDump['aStructure'] = []; for(var nField = 0; nField < nFields; nField++){ oDump['aStructure'][nField] = []; oDump['aStructure'][nField][0] = this._aStructure[nField][0]; oDump['aStructure'][nField][1] = this._aStructure[nField][1]; } oDump['aData'] = []; for(var nRec = 0; nRec < this._nRecords; nRec++){ if(!this._aDeleted[nRec]){ aRecord = []; for(var nField = 0; nField < nFields; nField++){ aRecord[nField] = this._oCols[this._aStructure[nField][0]][nRec]; } oDump['aData'].push(aRecord); } } return oDump; } XBSTable.prototype.InsertOneByFields = function(aFields,aValues){ this.sResultCode = 'OK'; var nRecNum, i; if(this._aDeleted.length > 0){ for(i = this._aDeleted.length - 1; i >= 0; i--){ // go back, seek true, delete elements from tail, when find true then store number and exit, not solid, with check if(this._aDeleted[i]){ nRecNum = i; this._aDeleted.pop(); break; }else{ this._aDeleted.pop(); } } for(i = this._aDeleted.length - 1; i >= 0; i--){ // go back, seek true, delete elements from tail, when find true then exit, not solid, with check if(this._aDeleted[i]){ break; }else{ this._aDeleted.pop(); } } }else{ nRecNum = this._nRecords; } if(nRecNum == this._nRecords){ this._nRecords++; } for(i = 0; i < aFields.length; i++){ // solid this._oCols[aFields[i]][nRecNum] = aValues[i]; } for(i in this._oKeys){ if(!this._oKeys[i].Rebuild()){ this.sResultCode = this._oKeys[i].sResultCode; return false; } } return true; } XBSTable.prototype.InsertOneByOrder = function(aValues){ this.sResultCode = 'OK'; var nRecNum, i; if(this._aDeleted.length > 0){ for(i = this._aDeleted.length - 1; i >= 0; i--){ // go back, seek true, delete elements from tail, when find true then store number and exit, not solid, with check if(this._aDeleted[i]){ nRecNum = i; this._aDeleted.pop(); break; }else{ this._aDeleted.pop(); } } for(i = this._aDeleted.length - 1; i >= 0; i--){ // go back, seek true, delete elements from tail, when find true then exit, not solid, with check if(this._aDeleted[i]){ break; }else{ this._aDeleted.pop(); } } }else{ nRecNum = this._nRecords; } if(nRecNum == this._nRecords){ this._nRecords++; } for(i = 0; (i < aValues.length) && (i < this._aFieldNames.length) ; i++){ // solid this._oCols[this._aFieldNames[i]][nRecNum] = aValues[i]; } for(i in this._oKeys){ if(!this._oKeys[i].Rebuild()){ this.sResultCode = this._oKeys[i].sResultCode; return false; } } return true; } XBSTable.prototype.InsertManyByFields = function(aFields,aRows){ this.sResultCode = 'OK'; var nRecNum, nInserted = 0, aNewRecord, j, i; if(aRows.length > 0){ for(j = 0; j < aRows.length; j++){ // solid if(this._aDeleted.length > 0){ for(i = this._aDeleted.length - 1; i >= 0; i--){ // go back, seek true, delete elements from tail, when find true then store number and exit, not solid, with check if(this._aDeleted[i]){ nRecNum = i; this._aDeleted.pop(); break; }else{ this._aDeleted.pop(); } } for(i = this._aDeleted.length - 1; i >= 0; i--){ // go back, seek true, delete elements from tail, when find true then exit, not solid, with check if(this._aDeleted[i]){ break; }else{ this._aDeleted.pop(); } } }else{ nRecNum = this._nRecords; } if(nRecNum == this._nRecords){ this._nRecords++; } for(i = 0; i < aFields.length; i++){ // solid this._oCols[aFields[i]][nRecNum] = aRows[j][i]; } nInserted++; } //for j for(i in this._oKeys){ if(!this._oKeys[i].Rebuild()){ this.sResultCode = this._oKeys[i].sResultCode; return false; } } } return nInserted; } XBSTable.prototype.InsertManyByOrder = function(aRows){ this.sResultCode = 'OK'; var nRecNum, nInserted = 0, aNewRecord, j, i; if(aRows.length > 0){ for(j = 0; j < aRows.length; j++){ // solid if(this._aDeleted.length > 0){ for(i = this._aDeleted.length - 1; i >= 0; i--){ // go back, seek true, delete elements from tail, when find true then store number and exit, not solid, with check if(this._aDeleted[i]){ nRecNum = i; this._aDeleted.pop(); break; }else{ this._aDeleted.pop(); } } for(i = this._aDeleted.length - 1; i >= 0; i--){ // go back, seek true, delete elements from tail, when find true then exit, not solid, with check if(this._aDeleted[i]){ break; }else{ this._aDeleted.pop(); } } }else{ nRecNum = this._nRecords; } if(nRecNum == this._nRecords){ this._nRecords++; } for(i = 0; (i < aRows[j].length) && (i < this._aFieldNames.length); i++){ // subarray solid this._oCols[this._aFieldNames[i]][nRecNum] = aRows[j][i]; } nInserted++; } for(i in this._oKeys){ if(!this._oKeys[i].Rebuild()){ this.sResultCode = this._oKeys[i].sResultCode; return false; } } } return nInserted; } XBSTable.prototype.UpdateByFields = function(aFields,aValues,aRecords){ this.sResultCode = 'OK'; if(aRecords.length <= 0){ return 0; } var nUpdated = 0, j, i; for(j = 0; j < aRecords.length; j++){ // solid if(this._IsRecordNumberOK(aRecords[j])){ for(i = 0; i < aFields.length; i++){ // solid this._oCols[aFields[i]][aRecords[j]] = aValues[i]; } nUpdated++; } } if(nUpdated>0){ for(i in this._oKeys){ // check names in indexes! for(j = 0; j < aFields.length; j++){// solid if(this._oKeys[i].oFields[aFields[j]]){ this._oKeys[i].Rebuild(); break; } } } } return nUpdated; } XBSTable.prototype.UpdateByOrder = function(aValues,aRecords){ this.sResultCode = 'OK'; if(aRecords.length <= 0){ return 0; } var nUpdated = 0, j, i; for(j = 0; j < aRecords.length; j++){ // solid if(this._IsRecordNumberOK(aRecords[j])){ for(i = 0; (i < aValues.length) && (i < this._aFieldNames.length); i++){ // solid this._oCols[this._aFieldNames[i]][aRecords[j]] = aValues[i]; } nUpdated++; } } if(nUpdated>0){ for(i in this._oKeys){ // check names in indexes! for(j = 0; (j < aValues.length) && (j < this._aFieldNames.length); j++){// solid if(this._oKeys[i].oFields[this._aFieldNames[j]]){ this._oKeys[i].Rebuild(); break; } } } } return nUpdated; } XBSTable.prototype.Delete = function(aRecords){ this.sResultCode = 'OK'; if(aRecords.length > 0){ var i, j; for(i = 0; i < aRecords.length; i++){ // solid for(j = 0; j < this._aFieldNames.length; j++){ // solid delete this._oCols[this._aFieldNames[j]][aRecords[i]]; } this._aDeleted[aRecords[i]] = true; if(aRecords[i] == this._nRecords - 1){ this._nRecords--; } } for(i in this._oKeys){ this._oKeys[i].Rebuild(); } } return aRecords.length; } XBSTable.prototype.AddKey = function(sExpression,aNumbersInit){ this.sResultCode = 'OK'; var oParser = new XBSEParser(); var vParserResult = oParser.Parse(sExpression,{'aFieldNames':this._aFieldNames, 'sFieldBefore':this.sFieldBefore, 'sFieldAfter':this.sFieldAfter, 'sExprType':'KEY'}); if(vParserResult && (vParserResult.sType == 'object_key_scalar')){ var oKey = new XBSKey(this,vParserResult.sExprFieldsX,vParserResult.oFields); if(aNumbersInit && Object.prototype.toString.call(aNumbersInit) === '[object Array]'){ oKey.Load(aNumbersInit); this._oKeys[vParserResult.sExprFields] = oKey; return vParserResult.sExprFields; }else{ if(oKey.Rebuild()){ this._oKeys[vParserResult.sExprFields] = oKey; return vParserResult.sExprFields; }else{ this.sResultCode = oKey.sResultCode; return false; } } }else{ this.sResultCode = oParser.sResultCode; return false; } } XBSTable.prototype.IsCol = function(sColName){ if(this._oCols[sColName]){ return true; }else{ return false; } } XBSTable.prototype.GetColTypeByName = function(sColName){ return this._oFieldTypes[sColName]; } XBSTable.prototype.GetColTypeByNumber = function(nColNumber){ return this._oFieldTypes[this._aFieldNames[nColNumber]]; } XBSTable.prototype.IsKey = function(sKeyID){ this.sResultCode = 'OK'; if(this._oKeys[sKeyID]){ return true; }else{ return false; } } XBSTable.prototype.GetKeyIDs = function(){ this.sResultCode = 'OK'; var aKeyIDs = []; for(var i in this._oKeys){ aKeyIDs.push(i); } return aKeyIDs; } XBSTable.prototype.DropKey = function(sKeyID){ this.sResultCode = 'OK'; if(this._oKeys[sKeyID]){ delete this._oKeys[sKeyID]; } return true; } XBSTable.prototype.GetKeyExpressionParsed = function(sExpr,aOpers){ this.sResultCode = 'OK'; if(!aOpers){ aOpers = ['+','-','*','/']} // think about possible using of this :-) var oParser = new XBSEParser(); var vParserResult = oParser.Parse(sExpr,{'aFieldNames':this._aFieldNames, 'sFieldBefore':this.sFieldBefore, 'sFieldAfter':this.sFieldAfter, 'sExprType':'KEY'}); if(vParserResult){ return vParserResult; }else{ this.sResultCode = oParser.sResultCode; return false; } } XBSTable.prototype.GetRecordsWhere = function(sWhere){ // base method, parse sWhere, process result and create record numbers array this.sResultCode = 'OK'; var oParser = new XBSEParser(); var vParserResult = oParser.Parse(sWhere,{'aFieldNames':this._aFieldNames, 'sFieldBefore':this.sFieldBefore, 'sFieldAfter':this.sFieldAfter, 'sExprType':'WHERE'}); if(!vParserResult){ this.sResultCode = oParser.sResultCode; return false; } var aFirstLevelRecords = this.GetRecordsAllUnPacked(); // temporary record numbers array, not packed var aResultRecords = this._GetRecordsByParsedArray(vParserResult,aFirstLevelRecords,1); if(aResultRecords){ return aResultRecords; }else{ return false; } } XBSTable.prototype.GetRows = function(aFields,aRecords,nOffset,nLimit){ this.sResultCode = 'OK'; var aRet = [], aRecord, nStart, nEnd, j, i; if(nOffset < 0){ nStart = 0; }else if(nOffset > aRecords.length - 1){ return aRet; }else{ nStart = nOffset; } if(nLimit <= 0){ return aRet; }else if(nLimit > aRecords.length - 1){ nEnd = aRecords.length; }else{ nEnd = nOffset + nLimit; if(nEnd > aRecords.length){ nEnd = aRecords.length; } } for(i = nStart; i < nEnd; i++){ // solid aRecord = []; for(j = 0; j < aFields.length; j++){ // solid aRecord.push(this._oCols[aFields[j]][aRecords[i]]); } aRet.push(aRecord); } return aRet; } XBSTable.prototype.GetRowsAll = function(aRecords,nOffset,nLimit){ this.sResultCode = 'OK'; var aRet = [], aRecord, nStart, nEnd, j, i; if(nOffset < 0){ nStart = 0; }else if(nOffset > aRecords.length - 1){ return aRet; }else{ nStart = nOffset; } if(nLimit <= 0){ return aRet; }else if(nLimit > aRecords.length - 1){ nEnd = aRecords.length; }else{ nEnd = nOffset + nLimit; if(nEnd > aRecords.length){ nEnd = aRecords.length; } } for(i = nStart; i < nEnd; i++){ // solid aRecord = []; for(j = 0; j < this._aFieldNames.length; j++){ // solid aRecord.push(this._oCols[this._aFieldNames[j]][aRecords[i]]); } aRet.push(aRecord); } return aRet; } XBSTable.prototype.GetRecordsAllPacked = function(){ var aRet = [], i; for(i = 0; i < this._nRecords; i++){ if(!this._aDeleted[i]){ aRet.push(i); } } return aRet; } XBSTable.prototype.GetRecordsAllUnPacked = function(){ return this._aRecordsUnPack(this.GetRecordsAllPacked()); } XBSTable.prototype.SortRecordsOrderBy = function(aRecords,sOrderBy,bReverse){ this.sResultCode = 'OK'; var oParser = new XBSEParser(); var vParserResult = oParser.Parse(sOrderBy,{'aFieldNames':this._aFieldNames, 'sFieldBefore':this.sFieldBefore, 'sFieldAfter':this.sFieldAfter, 'sExprType':'KEY'}); if(vParserResult && (vParserResult.sType == 'object_key_scalar')){ var oKey = new XBSKey(this,vParserResult.sExprFieldsX,vParserResult.oFields); if(oKey.Rebuild(aRecords)){ if(bReverse){ aRecords.reverse(); } return true; }else{ this.sResultCode = oKey.sResultCode; return false; } }else{ this.sResultCode = oParser.sResultCode; return false; } } XBSTable.prototype.GetRecordsGroupBy = function(aRecords,sGroupBy){ this.sResultCode = 'OK'; var oParser = new XBSEParser(); var vParserResult = oParser.Parse(sGroupBy,{'aFieldNames':this._aFieldNames, 'sFieldBefore':this.sFieldBefore, 'sFieldAfter':this.sFieldAfter, 'sExprType':'KEY'}); if(vParserResult && (vParserResult.sType == 'object_key_scalar')){ var vCurrValue, vPrevValue, aResultRecords = [], i, fFuncGroup = new Function('table', 'n', 'return(' + vParserResult.sExprFieldsX + ');'); for(i = 0; i < aRecords.length; i++){ // solid vCurrValue = fFuncGroup(this,aRecords[i]); // because packed if(vCurrValue != vPrevValue){ aResultRecords.push(aRecords[i]); vPrevValue = vCurrValue; } } return aResultRecords; }else{ this.sResultCode = oParser.sResultCode; return false; } } XBSTable.prototype.GetStructure = function(){ this.sResultCode = 'OK'; var aResult = []; for(var i=0; i<this._aStructure.length; i++){ aResult.push([this._aStructure[i][0],this._aStructure[i][1]]); } return aResult; } /////////////////////////////////////////////////////////////////////////////////////////////////////////// // private methods /////////////////////////////////////////////////////////////////////////////////////////////////////////// XBSTable.prototype._GetRecordsByParsedArray = function(oPA,aUpperRecords,nLevel){ //array_OR (OR array) //array_AND (AND array) //object_calc_scalar (scalar calculation object) //object_calc_logical (logical calculation object) - not done yet // aUpperRecords - not packed, for faster intersection of temporary results with it var aResultRecords = [], aResultRecordsU = [], i, j, vConstant; switch(oPA.sType){ case 'array_OR' : // (a)rray of (o)r elements // processing of OR-elements, result - union // aResultRecords - NOT PACKED here for faster unitization, will be packed after cycle var sExprOR = '', aBufRecords = []; for(i = 0; i < oPA.aOR.length; i++){ // solid switch(oPA.aOR[i].sType){ case 'object_calc_scalar' : try{ vConstant = eval(oPA.aOR[i].sConstant); }catch(e){ this.sResultCode = "TABLE_BAD_CONSTANT : " + oPA.aOR[i].sConstant; return false; } if(this.IsKey(oPA.aOR[i].sExprFields)){ // key exists if(nLevel>1){ // not first level, upper level records exist, intersect result with it aBufRecords = this._GetRecordsByKeyPacked(oPA.aOR[i].sExprFields,oPA.aOR[i].sOperation,vConstant,aUpperRecords); }else{ // first level, no upper level records exist aBufRecords = this._GetRecordsByKeyPacked(oPA.aOR[i].sExprFields,oPA.aOR[i].sOperation,vConstant); } if(!aBufRecords){ return false; } for(j = 0; j < aBufRecords.length; j++){ // solid aResultRecords[aBufRecords[j]] = true; } }else{ if(sExprOR.length > 0){ sExprOR += '||'; } sExprOR += '(' + '(' + oPA.aOR[i].sExprFieldsX + ') ' + oPA.aOR[i].sOperation + ' "' + vConstant.toString().replace('"','\"','g') + '"'+ ')'; } break; case 'object_calc_logical' : // (o)ject of (c)alculation of (l)ogical value if(sExprOR.length > 0){ sExprOR += '||'; } sExprOR += '(' + oPA.aOR[i].sExprFieldsX + ')'; break; case 'array_OR' : case 'array_AND' : aBufRecords = this._GetRecordsByParsedArray(oPA.aOR[i],aUpperRecords,nLevel+1); if(!aBufRecords){ return false; } for(j = 0; j < aBufRecords.length; j++){ // solid aResultRecords[aBufRecords[j]] = true; } break; }//switch }//for if(sExprOR.length > 0){ aBufRecords = this._GetRecordsByExpr(sExprOR,aUpperRecords); if(!aBufRecords){ return false; } for(j = 0; j < aBufRecords.length; j++){ // solid aResultRecords[aBufRecords[j]] = true; } } aResultRecords = this._aRecordsPack(aResultRecords); break; case 'array_AND' : // (a)rray of (a)nd elements // processing of AND-elements, result - intersection // aResultRecords - PACKED here for faster intersection, it will be used next seek on next condition of same key var sExprAND = '', aBufRecords = [], bFirstKeyCalc = true, bResultNotReady = true, sPrevKey = '', aBufRecords2; for(i = 0; i < oPA.aAND.length; i++){ // solid switch(oPA.aAND[i].sType){ case 'object_calc_scalar' : try{ vConstant = eval(oPA.aAND[i].sConstant); }catch(e){ this.sResultCode = "TABLE_BAD_CONSTANT : " + oPA.aAND[i].sConstant; return false; } if(this.IsKey(oPA.aAND[i].sExprFields)){ // key exists if(bFirstKeyCalc){ if(nLevel>1){ aResultRecords = this._GetRecordsByKeyPacked(oPA.aAND[i].sExprFields,oPA.aAND[i].sOperation,vConstant,aUpperRecords); }else{ aResultRecords = this._GetRecordsByKeyPacked(oPA.aAND[i].sExprFields,oPA.aAND[i].sOperation,vConstant); } if(!aResultRecords){ return false; } bFirstKeyCalc = false; }else{ if(sPrevKey==oPA.aAND[i].sExprFields){ aResultRecords = this._GetRecordsByKeyPacked(oPA.aAND[i].sExprFields,oPA.aAND[i].sOperation,vConstant,null,aResultRecords); }else{ aResultRecords = this._GetRecordsByKeyPacked(oPA.aAND[i].sExprFields,oPA.aAND[i].sOperation,vConstant,this._aRecordsUnPack(aResultRecords)); } } if(!aResultRecords){ return false; } bResultNotReady = false; sPrevKey = oPA.aAND[i].sExprFields; }else{ if(sExprAND.length > 0){ sExprAND += '&&'; } sExprAND += '(' + '(' + oPA.aAND[i].sExprFieldsX + ') ' + oPA.aAND[i].sOperation + ' "' + vConstant.toString().replace('"','\"') + '"'+ ')'; } break; case 'object_calc_logical' : // (o)ject of (c)alculation of (l)ogical value if(sExprAND.length > 0){ sExprAND += '&&'; } sExprAND += '(' + oPA.aAND[i].sExprFieldsX + ')'; break; case 'array_OR' : case 'array_AND' : if(bFirstKeyCalc){ aResultRecords = this._GetRecordsByParsedArray(oPA.aAND[i],aUpperRecords,nLevel+1); }else{ aResultRecords = this._GetRecordsByParsedArray(oPA.aAND[i],this._aRecordsUnPack(aResultRecords),nLevel+1); } if(!aResultRecords){ return false; } bResultNotReady = false; break; }//switch if(!bFirstKeyCalc && aResultRecords.length == 0){ break; } }//for if(sExprAND.length > 0){ if(bResultNotReady){ aResultRecords = this._GetRecordsByExpr(sExprAND,aUpperRecords); if(!aResultRecords){ return false; } }else{ if(aResultRecords.length > 0){ aResultRecords = this._GetRecordsByExpr(sExprAND,this._aRecordsUnPack(aResultRecords)); if(!aResultRecords){ return false; } } } } break; case 'object_calc_scalar' : // select records on object fields - expression with fields, comparsion, value try{ vConstant = eval(oPA.sConstant); }catch(e){ this.sResultCode = "TABLE_BAD_CONSTANT : " + oPA.sConstant; return false; } if(this.IsKey(oPA.sExprFields)){ // key exists if(nLevel>1){ aResultRecords = this._GetRecordsByKeyPacked(oPA.sExprFields,oPA.sOperation,vConstant,aUpperRecords); }else{ aResultRecords = this._GetRecordsByKeyPacked(oPA.sExprFields,oPA.sOperation,vConstant); } if(!aResultRecords){ return false; } }else{ var sExpr = '(' + oPA.sExprFieldsX + ') ' + oPA.sOperation + ' "' + vConstant.toString().replace('"','\"') + '"'; aResultRecords = this._GetRecordsByExpr(sExpr,aUpperRecords); if(!aResultRecords){ return false; } } break; case 'object_calc_logical' : // select records on object fields - expression with fields only var sExpr = '(' + oPA.sExprFieldsX + ')'; aResultRecords = this._GetRecordsByExpr(sExpr,aUpperRecords); if(!aResultRecords){ return false; } break; } if(this.sResultCode == 'OK'){ return aResultRecords; }else{ return false; } } XBSTable.prototype._aRecordsPack = function(aRecordsU){ var aRecordsP = [], i; for(i = 0; i < aRecordsU.length; i++){ // solid or not - no difference, pack true values only if(aRecordsU[i] == true){ aRecordsP.push(i); } } return aRecordsP; } XBSTable.prototype._aRecordsUnPack = function(aRecordsP){ var aRecordsU = [], i; for(i = 0; i < aRecordsP.length; i++){ // solid aRecordsU[aRecordsP[i]] = true; } return aRecordsU; } XBSTable.prototype._GetRecordsByKeyUnpacked = function(sKeyID,sKeyOper,vKeyValue,aUpperRecords,aExtRecords){ var aResultRecords; var oKey = this._oKeys[sKeyID]; switch(sKeyOper){ case '>=' : aResultRecords = oKey.GetRecordsUnpackedGREQ(vKeyValue,aUpperRecords,aExtRecords); break; //! index and value types match check case '<=' : aResultRecords = oKey.GetRecordsUnpackedLEEQ(vKeyValue,aUpperRecords,aExtRecords); break; case '!=' : aResultRecords = oKey.GetRecordsUnpackedNE(vKeyValue,aUpperRecords,aExtRecords); break; case '>' : aResultRecords = oKey.GetRecordsUnpackedGR(vKeyValue,aUpperRecords,aExtRecords); break; case '<' : aResultRecords = oKey.GetRecordsUnpackedLE(vKeyValue,aUpperRecords,aExtRecords); break; case '==' : aResultRecords = oKey.GetRecordsUnpackedEQ(vKeyValue,aUpperRecords,aExtRecords); break; } if(!aResultRecords){ this.sResultCode = oKey.sResultCode; return false; } return aResultRecords; } XBSTable.prototype._GetRecordsByKeyPacked = function(sKeyID,sKeyOper,vKeyValue,aUpperRecords,aExtRecords){ var aResultRecords; var oKey = this._oKeys[sKeyID]; switch(sKeyOper){ case '>=' : aResultRecords = oKey.GetRecordsPackedGREQ(vKeyValue,aUpperRecords,aExtRecords); break; //! index and value types match check case '<=' : aResultRecords = oKey.GetRecordsPackedLEEQ(vKeyValue,aUpperRecords,aExtRecords); break; case '!=' : aResultRecords = oKey.GetRecordsPackedNE(vKeyValue,aUpperRecords,aExtRecords); break; case '>' : aResultRecords = oKey.GetRecordsPackedGR(vKeyValue,aUpperRecords,aExtRecords); break; case '<' : aResultRecords = oKey.GetRecordsPackedLE(vKeyValue,aUpperRecords,aExtRecords); break; case '==' : aResultRecords = oKey.GetRecordsPackedEQ(vKeyValue,aUpperRecords,aExtRecords); break; } if(!aResultRecords){ this.sResultCode = oKey.sResultCode; return false; } return aResultRecords; } XBSTable.prototype._GetRecordsByExpr = function(sExpr,aUpperRecords){ var aResultRecords = [], i, fFunc = new Function('table', 'n', 'return(' + sExpr + ');'); try{ for(i = 0; i < aUpperRecords.length; i++){ // check solid or not if(aUpperRecords[i] && fFunc(this,i)){ // aUpperRecords[i] check true or not BEFORE function call aResultRecords.push(i); } } }catch(e){ this.sResultCode = 'TABLE_NOT_GET_RECORDS_BY_EXPR_UN'; return false; } return aResultRecords; } XBSTable.prototype._IsRecordNumberOK = function(nNumber){ if(nNumber < 0 || nNumber >= this._nRecords){ return false; } for(var i = 0; i < this._aDeleted.length; i++){ // not solid, not packed if(this._aDeleted[nNumber]){ return false; } } return true; }