UNPKG

tdataset

Version:

Delphi TDataset for node.js

441 lines (433 loc) 15 kB
/** * @overview TDataset server connection. * @author Serkan KOCAMAN * @version 0.0.1 */ var General = require('../lib/general.objects.js'); var Db = require('../lib/data.db.js'); var Fb = require('../lib/node.firebird.js'); var Dt = require('../lib/general.dateutils.js'); var SqlParser = require("sql-parser"); var TLtState = { "lsIgnore": 0, "lsFromSearch": 1, "lsTableSearch": 2, "lsNormal": 3, "lsAlias": 4, "lsField": 5, "lsTableAlias": 6 }; /** * TServerConnection class. Main DB Connection class. * @module TServerConnection */ var TServerConnection = function() { var FDB = null; /** * Database server address. Default localhost. * @member DBServer * @type {string} */ this.DBServer = "localhost"; /** * Database server port. Default 3305. * @member DBPort * @type {number} */ this.DBPort = 3305; /** * Database name. Default is "" * @member DBName * @type {string} */ this.DBName = ""; /** * Database user name. Default SYSDBA * @member DBUserName * @type {string} */ this.DBUserName = "SYSDBA"; /** * Database password. Default masterkey. * @member DBPassword * @type {string} */ this.DBPassword = "masterkey"; this.DBRole = ""; /** *@typedef connectionCallBack *@param {boolean} Result - This param return true connection established. *@param {object} dbConnection DB - This param return DB connection object. */ /** * Database connection method. * @method Connect * @param {callback} OnResult connectionCallBack */ this.Connect = function(OnResult) { Fb.ConnectDB(this.DBServer, this.DBPort, this.DBName, this.DBUserName, this.DBPassword, this.DBRole, function(DB) { FDB = DB; OnResult(true, DB); }, function(Err) { console.log("burdayım"); if(OnResult) OnResult(false, Err); }); }; var getFDB = function() { return FDB; }, setFDB = function(Value) { FDB = Value; }; Object.defineProperty(this, 'Connection', { get: getFDB, set: setFDB, configurable: true }); } /** * This class extend TDataset. This class binding DB. TDataset not binding. * @class TServerDataset * @author Serkan KOCAMAN */ var TServerDataSet = function() { TServerDataSet.prototype.constructor.call(this); var FSelectSQL = "", FLiteralCount = 0, FMasterTable = "", FMasterAlias = "", FDB = null, PlanList = new General.TList(), FKeyFieldSet = false, FRawFields = null; this.RawRows = null; this.InsertSQL = ""; this.UpdateSQL = ""; this.DeleteSQL = ""; this.CountSQL = ""; this.GeneratorName = ""; this.Session = null; this.Params = new Array();//!< Params property. This property include SQL params. SQL params character "?" /** * This method add a new record in dataset. * @method Append * @param {callBack} OnResult - nothing return any param. */ this.Append = function(OnResult) { this.AppendBase(); var Self = this; if(this.GeneratorName > '') { Fb.Execute(FDB, "Select Gen_Id("+this.GeneratorName+", 1) From RDB$DATABASE", null, function(Rows, Fields) { Self.Fields(Self.KeyFieldName).AsInteger = Rows[0][0]["low_"]; OnResult(); }); } else OnResult(); }; //OnSuccess(Success:Boolean;Err:Variant); /** * this method delete focused record in database. * @method Delete * @param {callback} OnSuccess - this callback return Result and Err params. Result params boolean, Err params string return value. */ this.Delete = function(OnSuccess) { //iyt 06.10.2012 09:44 this.DoBeforeDelete(); var Prm = new Array(1); Prm[0] = this.Fields[KeyFieldName].Value; this.prototype.Delete; Execute(FDB, this.DeleteSQL, Prm, function(Rows, Fields) { OnSuccess(true, null); this.DoAfterDelete; }); }; /** * this method save record to database. this method only calling dataset mode editing or inserting. * @method Post * @param {callback} OnSuccess - return Result boolean param and Err string param. */ this.Post = function(OnSuccess) { var Prm = null; var Self = this; function InsertRun() { Prm = new Array(this.FieldsCount); var J = 0; for(var i = 0; i <= Self.FieldsCount - 1; i++) { if(Self.Fields(i).Editable == true) { Prm[J]=Self.Fields(i).AsString; J = J + 1; } } this.DoBeforePost; console.log(Self.InsertSQL); console.log(Prm); Fb.Execute(FDB, Self.InsertSQL, Prm, function(Rows, Fields) { OnSuccess(true, null); this.DoAfterPost; }, function(Err) { OnSuccess(false, Err.message); }); } if(this.State == Db.TDataSetState.dsInsert) { this.PostBase(); if(this.GeneratorName == "" && this.Fields(this.KeyFieldName).Value == null) throw new Error('Dataset read only.'); InsertRun(); } if(this.State == Db.TDataSetState.dsEdit) { if(this.UpdateSQL == "") throw new Error('Dataset read only.'); if(this.Fields(this.KeyFieldName).Value == null) throw new Error('Dataset read only.'); this.PostBase(); Prm = []; var J = 0; for(var i = 0; i <= this.FieldsCount - 1; i++) if(this.Fields(i).KeyField == false && this.Fields(i).Editable == true) { Prm.push(this.Fields(i).Value); J = J + 1; } Prm.push(this.Fields(this.KeyFieldName).AsString); this.DoBeforePost; Fb.Execute(FDB, this.UpdateSQL, Prm, function(Rows, Fields) { OnSuccess(true, null); this.DoAfterPost; }, function(Err) { OnSuccess(false, Err.message); }); } }; this.GenerateRows = function() { var Count = Object.keys(FRawRows).length; for(var i = 0; i <= Count - 1; i++) { var R = new Db.TRow(); R.RecNo = i; for(var j = 0; j <= this.FieldsCount - 1; j++) { if(FRawRows[i][j] == null) R.Data.push(null); else if(this.Fields(j).FieldType == Db.TFieldType.ftTimeStamp) R.Data.push(Dt.FormatDateTime("L LT", FRawRows[i][j])); else if(this.Fields(j).FieldType == Db.TFieldType.ftDateTime) R.Data.push(Dt.FormatDateTime("L LT", FRawRows[i][j])); else if(this.Fields(j).FieldType == Db.TFieldType.ftDate) R.Data.push(Dt.FormatDateTime("L", FRawRows[i][j])); else if(this.Fields(j).FieldType == Db.TFieldType.ftTime) R.Data.push(Dt.FormatDateTime("LT", FRawRows[i][j])); else R.Data.push(FRawRows[i][j]); }; this.Rows.Add(R); } this.State = Db.TDataSetState.dsBrowse; this.First(); }; this.GenerateFields = function() { var Count = Object.keys(FRawFields).length; for(var i = 0; i <= Count - 1; i++) { var Fld = new Db.TField(); Fld.DataSet = this; Fld.FieldName = FRawFields[i]['alias']; Fld.FieldNo = i; switch(FRawFields[i]['type']) { case 452: Fld.FieldType = Db.TFieldType.ftString; break; case 448: Fld.FieldType = Db.TFieldType.ftString; break; case 500: Fld.FieldType = Db.TFieldType.ftShortint; break; case 496: Fld.FieldType = Db.TFieldType.ftInteger; break; case 482: Fld.FieldType = Db.TFieldType.ftFloat; break; case 480: Fld.FieldType = Db.TFieldType.ftFloat; break; case 530: Fld.FieldType = Db.TFieldType.ftFloat; break; case 510: Fld.FieldType = Db.TFieldType.ftTimeStamp; break; case 520: Fld.FieldType = Db.TFieldType.ftBlob; break; case 540: Fld.FieldType = Db.TFieldType.ftArray; break; case 550: Fld.FieldType = Db.TFieldType.ftLargeint; break; case 560: Fld.FieldType = Db.TFieldType.ftTime; break; case 570: Fld.FieldType = Db.TFieldType.ftDate; break; case 580: Fld.FieldType = Db.TFieldType.ftInteger; break; case 32764: Fld.FieldType = Db.TFieldType.ftBoolean; break; case 32766: Fld.FieldType = Db.TFieldType.ftVariant; break; } Fld.TableName = FRawFields[i]['relation']; if(Fld.TableName == FMasterTable && Fld.FieldName == this.KeyFieldName) { Fld.KeyField = true; FKeyFieldSet = true; } if (Fld.TableName == FMasterTable) Fld.Editable = true; if(FRawFields[i]['nullable'] == 'true') Fld.Nullable = true; else Fld.Nullable = false; this.AddField(Fld); } }; this.GenerateSQLs = function() { var Yed = "", Yed2 = ""; this.InsertSQL = "INSERT INTO " + FMasterTable + " ("; for(var i = 0; i <= this.FieldsCount - 1; i++) { if(this.Fields(i).TableName == FMasterTable) { Yed = Yed + this.Fields(i).FieldName + ", "; Yed2 = Yed2 + "?, "; } } this.InsertSQL = this.InsertSQL + Yed.substr(0, Yed.length - 2) + ") VALUES (" + Yed2.substr(0, Yed2.length - 2) + ")"; Yed = ""; Yed2 = ""; this.UpdateSQL = "UPDATE " + FMasterTable + " SET "; if(FKeyFieldSet) { for(var i = 0; i <= this.FieldsCount - 1; i++) { if(this.Fields(i).TableName == FMasterTable && !this.Fields(i).KeyField) Yed = Yed + this.Fields(i).FieldName + " = ? ,"; } this.UpdateSQL = this.UpdateSQL + Yed.substr(0, Yed.length - 2) + " WHERE " + this.KeyFieldName + " = ? "; this.DeleteSQL = "DELETE FROM " + FMasterTable + " WHERE " + this.KeyFieldName + " = ? "; } }; /** * this method onyl execute sql not return field or value. Example UPDATA T SET A = 1 * @method ExecQuery * @param {string} SQL * @param {callback} OnExecute */ this.ExecQuery = function(SQL, OnExecute) { var Self = this; Fb.Execute(FDB, SQL, Self.Params, function(Rows, Fields) { if(OnExecute) OnExecute(true, null); }); }; /** * This method open dataset and dataset mode setting browsing. * @method Open * @param {boolean} Fetch - this param using fetching limit (limit sql command) setting the true. * @param {integer} Skip - skip record size. * @param {integer} First - first record size. * @param {callback} OnConnect global return callback. */ this.Open = function(Fetch, Skip, First, OnConnect) { var Self = this; var SQL = ""; function SelfOpen() { SQL = FSelectSQL; Fb.Execute(FDB, SQL, Self.Params, function(Rows, Fields) { FRawRows = Rows; FRawFields = Fields; Self.GenerateFields(); Self.GenerateSQLs(); Self.GenerateRows(); if(OnConnect) OnConnect(true, null); Self.DoAfterOpen(); }, function(Err) { if (OnConnect) OnConnect(false, Err); }); } //iyt 30.09.2012 18:53 Self.DoBeforeOpen(); if(FMasterTable != "") { SQL = "SELECT RDB$INDEX_SEGMENTS.RDB$FIELD_NAME " + " FROM RDB$INDEX_SEGMENTS " + " LEFT JOIN RDB$INDICES ON RDB$INDICES.RDB$INDEX_NAME = " + " RDB$INDEX_SEGMENTS.RDB$INDEX_NAME " + " LEFT OUTER JOIN RDB$RELATION_CONSTRAINTS CO ON CO.RDB$CONSTRAINT_NAME = RDB$INDICES.RDB$INDEX_NAME " + " WHERE UPPER(RDB$INDICES.RDB$RELATION_NAME)= ? " + " AND RDB$INDICES.RDB$UNIQUE_FLAG IS NOT NULL " + " AND CO.RDB$CONSTRAINT_TYPE = 'PRIMARY KEY' "; Fb.Execute(FDB, SQL, [FMasterTable], function(Rows, Fields) { if(Object.keys(Rows).length > 0) Self.KeyFieldName = Rows[0].toString().trim().toUpperCase(); if(Fetch) { SQL = FSelectSQL.substr(1, 6) + ' first ' + First.toString() + ' skip ' + Skip.toString() + ' ' + FSelectSQL.substr(7, FSelectSQL.length - 6); Fb.Execute(FDB, CountSQL, Self.Params, function(Rows, Fields) { FetchedRecordCount = Rows[0][0]; Fb.Execute(DB, SQL, Self.Params, function(Rows, Fields) { FRawRows = Rows; FRawFields = Fields; this.GenerateFields(); this.GenerateSQLs(); this.GenerateRows(); if(OnConnect) OnConnect(true, null); Self.DoAfterOpen(); }, function(Err) { if (OnConnect) OnConnect(false, Err); }); }, function(Err) { if (OnConnect) OnConnect(false, Err); }); } else SelfOpen(); }); } //FMasterTable bos ise else SelfOpen(); }; this.GeneratePlan = function() { if(FSelectSQL != "") { var S = FSelectSQL; S = S.replace(/\?/g, "1"); Tokens = SqlParser.lexer.tokenize(S); FLiteralCount = Tokens.Count; PlanList = new General.TList(); LtState = TLtState.lsNormal; for(var i = 0; i < Object.keys(Tokens).length - 1; i++) { LtType = Tokens[i][0]; if(LtType == "SELECT" && LtState == TLtState.lsNormal) LtState = TLtState.lsFromSearch; else if(LtType == "LEFT_PAREN") LtState = TLtState.lsIgnore; else if(LtType == "RIGHT_PAREN") LtState = TLtState.lsFromSearch; else if(LtState == TLtState.lsFromSearch && LtType == "FROM") LtState = TLtState.lsTableSearch; else if(LtState == TLtState.lsTableSearch && LtType == "LITERAL") { FMasterTable = Tokens[i][1].toUpperCase(); LtState = TLtState.lsAlias; } else if(LtState == TLtState.lsAlias) { if(LtType == "LITERAL") FMasterAlias = Tokens[i][1].toUpperCase(); LtState = TLtState.lsNormal; } if(LtState == TLtState.lsTableSearch || LtState == TLtState.lsAlias || LtState == TLtState.lsNormal) if(Tokens[i][0] == "STRING") this.CountSQL = this.CountSQL + " '" + Tokens[i][1] + "'"; else this.CountSQL = this.CountSQL + " " + Tokens[i][1]; } this.CountSQL = "Select Count(*) " + this.CountSQL; } }; var SetSQL = function(Value) { //iyt 29.09.2012 23:26 FSelectSQL = Value; this.GeneratePlan(); }, GetSQL = function() { return this.FSelectSQL; }; Object.defineProperty(this, 'SelectSQL', { get: GetSQL, set: SetSQL, enumerable: true, configurable: true }); var getFDB = function() { return FDB; }, setFDB = function(Value) { FDB = Value; }; Object.defineProperty(this, 'Connection', { get: getFDB, set: setFDB, configurable: true }); }; TServerDataSet.prototype = Object.create(new Db.TDataSet()); exports.TServerDataSet = TServerDataSet; exports.TServerConnection = TServerConnection;