2015-01-23 13:09:30 +00:00
|
|
|
|
|
|
|
Db.Model = new Class ().extend
|
|
|
|
({
|
|
|
|
Status:
|
|
|
|
{
|
|
|
|
CLEAN : 1
|
|
|
|
,LOADING : 2
|
|
|
|
,READY : 3
|
|
|
|
,ERROR : 4
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
Db.Model.implement
|
|
|
|
({
|
|
|
|
Extends: Vn.Object
|
|
|
|
,Tag: 'db-model'
|
|
|
|
,Child: 'query'
|
|
|
|
,Properties:
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* The connection used to execute the statement.
|
|
|
|
**/
|
|
|
|
conn:
|
|
|
|
{
|
|
|
|
type: Db.Conn
|
|
|
|
,set: function (x)
|
|
|
|
{
|
|
|
|
this._conn = x;
|
|
|
|
this.refresh ();
|
|
|
|
}
|
|
|
|
,get: function ()
|
|
|
|
{
|
|
|
|
return this._conn;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
|
|
* The result index.
|
|
|
|
**/
|
|
|
|
resultIndex:
|
|
|
|
{
|
|
|
|
type: Number
|
|
|
|
,set: function (x)
|
|
|
|
{
|
|
|
|
this._resultIndex = x;
|
|
|
|
}
|
|
|
|
,get: function ()
|
|
|
|
{
|
|
|
|
return this._resultIndex;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
|
|
* The batch used to execute the statement.
|
|
|
|
**/
|
|
|
|
batch:
|
|
|
|
{
|
|
|
|
type: Sql.Batch
|
|
|
|
,set: function (x)
|
|
|
|
{
|
|
|
|
this.link ({_batch: x}, {'changed': this.refresh});
|
|
|
|
this.refresh ();
|
|
|
|
}
|
|
|
|
,get: function ()
|
|
|
|
{
|
|
|
|
return this._batch;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
|
|
* The model select statement.
|
|
|
|
**/
|
|
|
|
stmt:
|
|
|
|
{
|
|
|
|
type: Sql.Stmt
|
|
|
|
,set: function (x)
|
|
|
|
{
|
|
|
|
this._stmt = x;
|
|
|
|
this.refresh ();
|
|
|
|
}
|
|
|
|
,get: function ()
|
|
|
|
{
|
|
|
|
return this._stmt;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
|
|
* The model query.
|
|
|
|
**/
|
|
|
|
query:
|
|
|
|
{
|
|
|
|
type: String
|
|
|
|
,set: function (x)
|
|
|
|
{
|
|
|
|
this._stmt = new Sql.String ({query: x});
|
|
|
|
}
|
|
|
|
,get: function ()
|
|
|
|
{
|
|
|
|
return this._stmt.render (null);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
|
|
* The main table.
|
|
|
|
**/
|
|
|
|
mainTable:
|
|
|
|
{
|
|
|
|
type: String
|
|
|
|
,set: function (x)
|
|
|
|
{
|
|
|
|
this._mainTable = null;
|
|
|
|
this.requestedMainTable = x;
|
|
|
|
this.refreshMainTable ();
|
|
|
|
}
|
|
|
|
,get: function ()
|
|
|
|
{
|
|
|
|
return this._mainTable;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
|
|
* Determines if the model is updatable.
|
|
|
|
**/
|
|
|
|
updatable:
|
|
|
|
{
|
|
|
|
type: Boolean
|
|
|
|
,set: function (x)
|
|
|
|
{
|
|
|
|
this._updatable = false;
|
|
|
|
this.requestedUpdatable = x;
|
|
|
|
this.refreshUpdatable ();
|
|
|
|
}
|
|
|
|
,get: function ()
|
|
|
|
{
|
|
|
|
return this._updatable;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
|
|
* The number of rows in the model.
|
|
|
|
**/
|
|
|
|
numRows:
|
|
|
|
{
|
|
|
|
type: Number
|
|
|
|
,get: function ()
|
|
|
|
{
|
|
|
|
if (this.data)
|
|
|
|
return this.data.length;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
|
|
* The current status of the model.
|
|
|
|
**/
|
|
|
|
status:
|
|
|
|
{
|
|
|
|
type: Number
|
|
|
|
,get: function ()
|
|
|
|
{
|
|
|
|
return this._status;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
|
|
* Checks if the model data is ready.
|
|
|
|
**/
|
|
|
|
ready:
|
|
|
|
{
|
|
|
|
type: Boolean
|
|
|
|
,get: function ()
|
|
|
|
{
|
|
|
|
return this._status == Db.Model.Status.READY;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
,_resultIndex: 0
|
|
|
|
,_batch: null
|
|
|
|
,_stmt: null
|
|
|
|
,_status: Db.Model.Status.CLEAN
|
|
|
|
,requestedMainTable: null
|
|
|
|
,requestedUpdatable: true
|
|
|
|
,data: null
|
|
|
|
,columns: null
|
|
|
|
,columnMap: null
|
|
|
|
,insertedRow: -1
|
|
|
|
,defaults: []
|
|
|
|
,columnDefaults: []
|
|
|
|
,sortColumn: -1
|
2015-02-08 15:38:38 +00:00
|
|
|
,requestedIndexes: {}
|
|
|
|
,indexes: []
|
2015-01-23 13:09:30 +00:00
|
|
|
|
|
|
|
,initialize: function (props)
|
|
|
|
{
|
|
|
|
this.parent (props);
|
2015-02-08 15:38:38 +00:00
|
|
|
this.cleanData ();
|
|
|
|
this.setStatus (Db.Model.Status.CLEAN);
|
2015-01-23 13:09:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
,loadXml: function (builder, node)
|
|
|
|
{
|
|
|
|
this.parent (builder, node);
|
|
|
|
|
|
|
|
var query = node.firstChild.nodeValue;
|
|
|
|
|
|
|
|
if (query)
|
|
|
|
this.query = query;
|
|
|
|
}
|
|
|
|
|
|
|
|
,refresh: function ()
|
|
|
|
{
|
|
|
|
if (this._stmt && this._batch)
|
|
|
|
this._stmt.findHolders (this._batch);
|
|
|
|
|
|
|
|
if (this._conn && this._stmt
|
|
|
|
&& (!this._batch || this._batch.isReady ()))
|
|
|
|
{
|
|
|
|
this.setStatus (Db.Model.Status.LOADING);
|
|
|
|
this._conn.execStmt (this._stmt, this.selectDone.bind (this), this._batch);
|
|
|
|
}
|
|
|
|
else
|
2015-02-08 15:38:38 +00:00
|
|
|
{
|
|
|
|
this.cleanData ();
|
|
|
|
this.setStatus (Db.Model.Status.CLEAN);
|
|
|
|
}
|
2015-01-23 13:09:30 +00:00
|
|
|
}
|
|
|
|
|
2015-02-08 15:38:38 +00:00
|
|
|
|
2015-01-23 13:09:30 +00:00
|
|
|
,cleanData: function (error)
|
|
|
|
{
|
|
|
|
this.data = null;
|
|
|
|
this.columns = null;
|
|
|
|
this.columnMap = null;
|
2015-02-08 15:38:38 +00:00
|
|
|
this.indexes = [];
|
2015-01-23 13:09:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
,refreshUpdatable: function ()
|
|
|
|
{
|
|
|
|
var oldValue = this._updatable;
|
|
|
|
this._updatable = this._mainTable != null && this.requestedUpdatable;
|
|
|
|
|
|
|
|
if (oldValue != this._updatable)
|
|
|
|
this.signalEmit ('updatable-changed');
|
|
|
|
}
|
|
|
|
|
|
|
|
,refreshMainTable: function ()
|
|
|
|
{
|
|
|
|
var newMainTable = null;
|
|
|
|
var newMainSchema = null;
|
|
|
|
var x = this.columns;
|
|
|
|
|
|
|
|
if (x)
|
|
|
|
for (var i = 0; i < x.length; i++)
|
|
|
|
if (x[i].flags & Db.Conn.Flag.PRI_KEY)
|
|
|
|
if (!this.requestedMainTable
|
|
|
|
|| x[i].table === this.requestedMainTable)
|
|
|
|
{
|
|
|
|
newMainTable = x[i].table;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
this._mainTable = newMainTable;
|
|
|
|
this.refreshUpdatable ();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sets the default value for inserted fields.
|
|
|
|
*
|
|
|
|
* @param {String} field The destination field name
|
|
|
|
* @param {String} table The destination table name
|
|
|
|
* @param {Object} value The default value
|
|
|
|
**/
|
|
|
|
,setDefaultFromValue: function (field, table, value)
|
|
|
|
{
|
|
|
|
this.defaults.push
|
|
|
|
({
|
|
|
|
field: field
|
|
|
|
,table: table
|
|
|
|
,value: value
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Sets the default value for inserted fields from another column in the
|
|
|
|
* model.
|
|
|
|
*
|
|
|
|
* @param {String} field The destination field name
|
|
|
|
* @param {String} table The destination table name
|
|
|
|
* @param {String} srcColumn The source column
|
|
|
|
**/
|
|
|
|
,setDefaultFromColumn: function (field, table, srcColumn)
|
|
|
|
{
|
|
|
|
this.columnDefaults.push
|
|
|
|
({
|
|
|
|
field: field
|
|
|
|
,table: table
|
|
|
|
,srcColumn: srcColumn
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Checks if the column exists.
|
|
|
|
*
|
|
|
|
* @param {integer} column The column index
|
|
|
|
* @return {Boolean} %true if column exists, %false otherwise
|
|
|
|
**/
|
|
|
|
,checkColExists: function (column)
|
|
|
|
{
|
|
|
|
return this.columns && column >= 0 && column < this.columns.length;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Checks if the row exists.
|
|
|
|
*
|
|
|
|
* @param {integer} row The row index
|
|
|
|
* @return {Boolean} %true if row exists, %false otherwise
|
|
|
|
**/
|
|
|
|
,checkRowExists: function (row)
|
|
|
|
{
|
|
|
|
return this.data && row >= 0 && row < this.data.length;
|
|
|
|
}
|
|
|
|
|
|
|
|
,checkRowUpdatable: function (row)
|
|
|
|
{
|
|
|
|
return this.checkRowExists (row);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get the index of the column from its name.
|
|
|
|
*
|
|
|
|
* @param {string} columnName The column name
|
|
|
|
* @return {number} The column index or -1 if column not exists
|
|
|
|
**/
|
|
|
|
,getColumnIndex: function (columnName)
|
|
|
|
{
|
|
|
|
var index;
|
|
|
|
|
|
|
|
if (this.columnMap
|
|
|
|
&& (index = this.columnMap[columnName]) !== undefined)
|
|
|
|
return index;
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Gets a value from the model.
|
|
|
|
*
|
|
|
|
* @param {number} row The row index
|
|
|
|
* @param {string} columnName The column name
|
|
|
|
* @return {mixed} The value
|
|
|
|
**/
|
|
|
|
,get: function (row, columnName)
|
|
|
|
{
|
|
|
|
var index = this.getColumnIndex (columnName);
|
|
|
|
|
|
|
|
if (index != -1)
|
|
|
|
return this.getByIndex (row, index);
|
|
|
|
|
|
|
|
return undefined;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Updates a value on the model.
|
|
|
|
*
|
|
|
|
* @param {number} row The row index
|
|
|
|
* @param {string} columnName The column name
|
|
|
|
* @param {mixed} value The new value
|
|
|
|
**/
|
|
|
|
,set: function (row, columnName, value)
|
|
|
|
{
|
|
|
|
var index = this.getColumnIndex (columnName);
|
|
|
|
|
|
|
|
if (index != -1)
|
|
|
|
this.setByIndex (row, index, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Gets a value from the model using the column index.
|
|
|
|
*
|
|
|
|
* @param {number} row The row index
|
|
|
|
* @param {number} column The column index
|
|
|
|
* @return {mixed} The value
|
|
|
|
**/
|
|
|
|
,getByIndex: function (row, column)
|
|
|
|
{
|
|
|
|
if (this.checkRowExists (row) && this.checkColExists (column))
|
|
|
|
return this.data[row][column];
|
|
|
|
|
|
|
|
return undefined;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Updates a value on the model using the column index.
|
|
|
|
*
|
|
|
|
* @param {number} row The row index
|
|
|
|
* @param {number} col The column index
|
|
|
|
* @param {mixed} value The new value
|
|
|
|
**/
|
|
|
|
,setByIndex: function (row, col, value)
|
|
|
|
{
|
|
|
|
if (!(this.checkRowUpdatable (row) && this.checkColExists (col)))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (row == this.insertedRow)
|
|
|
|
{
|
|
|
|
this.performUpdate (row, [col], [value]);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
var column = this.columns[col];
|
|
|
|
var where = this.getWhere (column.table, row, false);
|
|
|
|
|
|
|
|
if (where)
|
|
|
|
{
|
|
|
|
var multiStmt = new Sql.MultiStmt ();
|
|
|
|
|
|
|
|
var table = new Sql.Table
|
|
|
|
({
|
|
|
|
name: column.orgtable
|
|
|
|
,schema: column.db
|
|
|
|
});
|
|
|
|
|
|
|
|
var update = new Sql.Update ({where: where});
|
|
|
|
update.addTarget (table);
|
|
|
|
update.addSet (column.orgname, value);
|
|
|
|
multiStmt.addStmt (update);
|
|
|
|
|
|
|
|
var select = new Sql.Select ({where: where});
|
|
|
|
select.addTarget (table);
|
|
|
|
select.addField (column.orgname);
|
|
|
|
multiStmt.addStmt (select);
|
|
|
|
|
|
|
|
var updateData = {
|
|
|
|
row: row
|
|
|
|
,columns: [col]
|
|
|
|
};
|
|
|
|
|
|
|
|
this._conn.execStmt (multiStmt,
|
|
|
|
this.updateDone.bind (this, updateData));
|
|
|
|
}
|
|
|
|
else
|
|
|
|
this.sendInsert (column.table, row, col, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Deletes a row from the model.
|
|
|
|
*
|
|
|
|
* @param {number} row The row index
|
|
|
|
**/
|
|
|
|
,deleteRow: function (row)
|
|
|
|
{
|
|
|
|
if (!this.checkRowUpdatable (row))
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (row != this.insertedRow)
|
|
|
|
{
|
|
|
|
var where = this.getWhere (this._mainTable, row, false);
|
|
|
|
|
|
|
|
if (where)
|
|
|
|
{
|
|
|
|
var deleteQuery = new Sql.Delete ({where: where});
|
|
|
|
|
|
|
|
var table = this.getTarget (this._mainTable);
|
|
|
|
deleteQuery.addTarget (table);
|
|
|
|
|
|
|
|
this._conn.execStmt (deleteQuery,
|
|
|
|
this.deleteDone.bind (this, row));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this.performDelete (row);
|
|
|
|
this.insertedRow = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Inserts a new row on the model.
|
|
|
|
*
|
|
|
|
* @return The index of the inserted row
|
|
|
|
**/
|
|
|
|
,insertRow: function ()
|
|
|
|
{
|
|
|
|
if (!this._updatable || this.insertedRow != -1)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
var x = this.columns;
|
|
|
|
var newRow = new Array (x.length);
|
|
|
|
|
|
|
|
for (var i = 0; i < x.length; i++)
|
|
|
|
if (x[i].table === this._mainTable)
|
|
|
|
newRow[i] = x[i].def;
|
|
|
|
else
|
|
|
|
newRow[i] = null;
|
|
|
|
|
|
|
|
this.insertedRow = this.data.push (newRow) - 1;
|
|
|
|
this.signalEmit ('row-inserted', this.insertedRow);
|
|
|
|
|
|
|
|
return this.insertedRow;
|
|
|
|
}
|
|
|
|
|
|
|
|
,performOperations: function ()
|
|
|
|
{
|
|
|
|
if (this.insertedRow == -1)
|
|
|
|
return;
|
|
|
|
|
|
|
|
this.sendInsert (this._mainTable, this.insertedRow, -1, null);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Function used to sort the model.
|
|
|
|
*/
|
|
|
|
,sortFunction: function (column, a, b)
|
|
|
|
{
|
|
|
|
if (a[column] < b[column])
|
|
|
|
return -1;
|
|
|
|
else if (a[column] > b[column])
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Orders the model by the specified column.
|
|
|
|
*
|
|
|
|
* @param {integer} column the column index
|
|
|
|
**/
|
|
|
|
,sort: function (column)
|
|
|
|
{
|
|
|
|
if (!this.checkColExists (column))
|
|
|
|
return;
|
|
|
|
|
|
|
|
this.setStatus (Db.Model.Status.LOADING);
|
|
|
|
|
|
|
|
if (column != this.sortColumn)
|
|
|
|
{
|
|
|
|
this.data.sort (this.sortFunction.bind (this, column));
|
|
|
|
this.sortColumn = column;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
this.data.reverse ();
|
|
|
|
|
|
|
|
this.setStatus (Db.Model.Status.READY);
|
|
|
|
}
|
|
|
|
|
2015-02-08 15:38:38 +00:00
|
|
|
/**
|
|
|
|
* Builds an internal hash index for the specified column, this speeds
|
|
|
|
* significantly searches on that column.
|
|
|
|
* Not implemented yet.
|
|
|
|
*
|
|
|
|
* @param {String} column The column name
|
|
|
|
**/
|
|
|
|
,indexColumn: function (column)
|
|
|
|
{
|
|
|
|
this.requestedIndexes[column] = true;
|
|
|
|
|
|
|
|
if (this._status == Db.Model.Status.READY)
|
|
|
|
this.buildIndex (column);
|
|
|
|
}
|
|
|
|
|
|
|
|
,buildIndex: function (column)
|
|
|
|
{
|
|
|
|
var columnIndex = this.getColumnIndex (column);
|
|
|
|
|
|
|
|
if (columnIndex != -1)
|
|
|
|
{
|
|
|
|
var index = {};
|
|
|
|
var data = this.data;
|
|
|
|
|
|
|
|
switch (this.columns[columnIndex].type)
|
|
|
|
{
|
|
|
|
case Db.Conn.Type.TIMESTAMP:
|
|
|
|
case Db.Conn.Type.DATE_TIME:
|
|
|
|
case Db.Conn.Type.DATE:
|
|
|
|
for (var i = 0; i < data.length; i++)
|
|
|
|
index[data[i][columnIndex].toString ()] = i;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
for (var i = 0; i < data.length; i++)
|
|
|
|
index[data[i][columnIndex]] = i;
|
|
|
|
}
|
|
|
|
|
|
|
|
this.indexes[columnIndex] = index;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-23 13:09:30 +00:00
|
|
|
/**
|
|
|
|
* Searchs a value on the model and returns the row index of the first
|
|
|
|
* ocurrence.
|
|
|
|
*
|
|
|
|
* @param {String} column The column name
|
|
|
|
* @param {Object} value The value to search
|
|
|
|
* @return {integer} The column index
|
|
|
|
**/
|
|
|
|
,search: function (column, value)
|
|
|
|
{
|
|
|
|
var index = this.getColumnIndex (column);
|
|
|
|
return this.searchByIndex (index, value);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Searchs a value on the model and returns the row index of the first
|
|
|
|
* ocurrence.
|
|
|
|
*
|
|
|
|
* @param {integer} col The column index
|
|
|
|
* @param {Object} value The value to search
|
|
|
|
* @return {integer} The column index
|
|
|
|
**/
|
|
|
|
,searchByIndex: function (col, value)
|
|
|
|
{
|
|
|
|
if (!this.checkColExists (col))
|
|
|
|
return -1;
|
2015-02-08 15:38:38 +00:00
|
|
|
|
|
|
|
if (value)
|
|
|
|
switch (this.columns[col].type)
|
|
|
|
{
|
|
|
|
case Db.Conn.Type.BOOLEAN:
|
|
|
|
value = !!value;
|
|
|
|
break;
|
|
|
|
case Db.Conn.Type.INTEGER:
|
|
|
|
value = parseInt (value);
|
|
|
|
break;
|
|
|
|
case Db.Conn.Type.DOUBLE:
|
|
|
|
value = parseFloat (value);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
value = value.toString ();
|
|
|
|
}
|
|
|
|
|
|
|
|
var index = this.indexes[col];
|
|
|
|
|
|
|
|
if (index)
|
|
|
|
{
|
|
|
|
if (index[value])
|
|
|
|
return index[value];
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
2015-01-23 13:09:30 +00:00
|
|
|
|
|
|
|
var data = this.data;
|
|
|
|
|
|
|
|
switch (this.columns[col].type)
|
|
|
|
{
|
|
|
|
case Db.Conn.Type.TIMESTAMP:
|
|
|
|
case Db.Conn.Type.DATE_TIME:
|
|
|
|
case Db.Conn.Type.DATE:
|
|
|
|
{
|
|
|
|
for (var i = 0; i < data.length; i++)
|
|
|
|
if (value === data[i][col].toString ());
|
|
|
|
return i;
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
for (var i = 0; i < data.length; i++)
|
|
|
|
if (value === data[i][col])
|
|
|
|
return i;
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// private:
|
|
|
|
|
|
|
|
,setStatus: function (status)
|
|
|
|
{
|
|
|
|
this._status = status;
|
|
|
|
this.signalEmit ('status-changed', status);
|
|
|
|
}
|
|
|
|
|
|
|
|
,getTarget: function (table)
|
|
|
|
{
|
|
|
|
var x = this.columns;
|
|
|
|
|
|
|
|
for (var i = 0; i < x.length; i++)
|
|
|
|
if (x[i].table == table)
|
|
|
|
return new Sql.Table
|
|
|
|
({
|
|
|
|
name: x[i].orgtable
|
|
|
|
,schema: x[i].db
|
|
|
|
});
|
|
|
|
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
|
|
|
,getWhere: function (table, rowIndex, forInsert)
|
|
|
|
{
|
|
|
|
var keyFound = false;
|
|
|
|
var row = this.data[rowIndex];
|
|
|
|
var andOp = new Sql.Operation ({type: Sql.Operation.Type.AND});
|
|
|
|
|
|
|
|
var x = this.columns;
|
|
|
|
|
|
|
|
for (var i = 0; i < x.length; i++)
|
|
|
|
if (x[i].flags & Db.Conn.Flag.PRI_KEY
|
|
|
|
&& x[i].table === table)
|
|
|
|
{
|
|
|
|
var equalOp = new Sql.Operation ({type: Sql.Operation.Type.EQUAL});
|
|
|
|
equalOp.exprs.add (new Sql.Field ({name: x[i].orgname}));
|
|
|
|
andOp.exprs.add (equalOp);
|
|
|
|
|
|
|
|
if (row[i])
|
|
|
|
equalOp.exprs.add (new Sql.Value ({value: row[i]}));
|
|
|
|
else if (x[i].flags & Db.Conn.Flag.AI && forInsert)
|
|
|
|
equalOp.exprs.add (new Sql.Func ({name: 'LAST_INSERT_ID'}));
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
|
|
|
|
keyFound = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (keyFound) ? andOp : null;
|
|
|
|
}
|
|
|
|
|
|
|
|
,sendInsert: function (table, rowIndex, singleColumn, newValue)
|
|
|
|
{
|
|
|
|
var where = this.getWhere (table, rowIndex, true);
|
|
|
|
|
|
|
|
if (!where)
|
|
|
|
return;
|
|
|
|
|
|
|
|
var multiStmt = new Sql.MultiStmt ();
|
|
|
|
var target = this.getTarget (table);
|
|
|
|
|
|
|
|
var insert = new Sql.Insert ();
|
|
|
|
insert.addTarget (target);
|
|
|
|
multiStmt.addStmt (insert);
|
|
|
|
|
|
|
|
var x = this.defaults;
|
|
|
|
|
|
|
|
for (var i = 0; i < x.length; i++)
|
|
|
|
if (x[i].table === table)
|
|
|
|
insert.addSet (x[i].field, x[i].value);
|
|
|
|
|
|
|
|
var x = this.columnDefaults;
|
|
|
|
|
|
|
|
for (var i = 0; i < x.length; i++)
|
|
|
|
if (x[i].table === table)
|
|
|
|
insert.addSet (x[i].field, this.get (rowIndex, x[i].srcColumn));
|
|
|
|
|
|
|
|
var select = new Sql.Select ({where: where});
|
|
|
|
select.addTarget (target);
|
|
|
|
multiStmt.addStmt (select);
|
|
|
|
|
|
|
|
var columns = [];
|
|
|
|
var row = this.data[rowIndex];
|
|
|
|
var x = this.columns;
|
|
|
|
|
|
|
|
for (var i = 0; i < x.length; i++)
|
|
|
|
if (x[i].table === table)
|
|
|
|
{
|
|
|
|
var setValue = singleColumn != i ? row[i] : newValue;
|
|
|
|
|
|
|
|
if (setValue)
|
|
|
|
insert.addSet (x[i].orgname, setValue);
|
|
|
|
|
|
|
|
select.addField (x[i].orgname);
|
|
|
|
columns.push (i);
|
|
|
|
}
|
|
|
|
|
|
|
|
var updateData = {
|
|
|
|
row: rowIndex
|
|
|
|
,columns: columns
|
|
|
|
};
|
|
|
|
|
|
|
|
this._conn.execStmt (multiStmt,
|
|
|
|
this.updateDone.bind (this, updateData));
|
|
|
|
}
|
|
|
|
|
|
|
|
,selectDone: function (resultSet)
|
|
|
|
{
|
|
|
|
var result;
|
|
|
|
var dataResult;
|
2015-02-08 15:38:38 +00:00
|
|
|
|
|
|
|
this.cleanData ();
|
2015-01-23 13:09:30 +00:00
|
|
|
|
|
|
|
for (var i = 0; result = resultSet.fetchResult (); i++)
|
|
|
|
if (i == this._resultIndex)
|
|
|
|
dataResult = result;
|
|
|
|
|
|
|
|
if (dataResult && typeof dataResult === 'object')
|
|
|
|
{
|
|
|
|
this.sortColumn = -1;
|
|
|
|
this.data = dataResult.data;
|
|
|
|
this.columns = dataResult.columns;
|
|
|
|
this.columnMap = dataResult.columnMap;
|
|
|
|
this.repairColumns (this.columns);
|
|
|
|
this.refreshMainTable ();
|
2015-02-08 15:38:38 +00:00
|
|
|
|
|
|
|
for (column in this.requestedIndexes)
|
|
|
|
this.buildIndex (column);
|
|
|
|
|
2015-01-23 13:09:30 +00:00
|
|
|
this.setStatus (Db.Model.Status.READY);
|
|
|
|
}
|
|
|
|
else
|
2015-02-08 15:38:38 +00:00
|
|
|
this.setStatus (Db.Model.Status.ERROR);
|
2015-01-23 13:09:30 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
,updateDone: function (updateData, resultSet)
|
|
|
|
{
|
|
|
|
var newValues;
|
|
|
|
|
|
|
|
if (resultSet.fetchResult () && (newValues = resultSet.fetchRow ()))
|
|
|
|
this.performUpdate (updateData.row, updateData.columns, newValues);
|
|
|
|
}
|
|
|
|
|
|
|
|
,performUpdate: function (rowIndex, columns, newValues)
|
|
|
|
{
|
|
|
|
this.signalEmit ('row-updated-before', rowIndex);
|
|
|
|
|
|
|
|
var row = this.data[rowIndex];
|
|
|
|
|
|
|
|
for (var i = 0; i < columns.length; i++)
|
|
|
|
row[columns[i]] = newValues[i];
|
|
|
|
|
|
|
|
this.signalEmit ('row-updated', rowIndex, columns);
|
|
|
|
}
|
|
|
|
|
|
|
|
,deleteDone: function (rowIndex, resultSet)
|
|
|
|
{
|
|
|
|
if (resultSet.fetchResult())
|
|
|
|
this.performDelete (rowIndex);
|
|
|
|
}
|
|
|
|
|
|
|
|
,performDelete: function (rowIndex)
|
|
|
|
{
|
|
|
|
var row = this.data[rowIndex];
|
|
|
|
|
|
|
|
if (!this.requestedMainTable)
|
|
|
|
{
|
|
|
|
this.signalEmit ('row-deleted-before', rowIndex);
|
|
|
|
this.data.splice (rowIndex, 1);
|
|
|
|
this.signalEmit ('row-deleted', rowIndex);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
this.signalEmit ('row-updated-before', rowIndex);
|
|
|
|
|
|
|
|
var columns = [];
|
|
|
|
|
|
|
|
for (var i = 0; i < this.columns.length; i++)
|
|
|
|
if (this.columns[i].table == this._mainTable)
|
|
|
|
{
|
|
|
|
row[i] = null;
|
|
|
|
columns.push (i);
|
|
|
|
}
|
|
|
|
|
|
|
|
this.signalEmit ('row-updated', rowIndex, columns);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Delete when MySQL FLAG and view orgname "bugs" are repaired:
|
|
|
|
|
|
|
|
,tableInfo: {}
|
|
|
|
,fieldFlags: {}
|
|
|
|
|
|
|
|
,setTableInfo: function (table, orgtable, db)
|
|
|
|
{
|
|
|
|
this.tableInfo[table] =
|
|
|
|
({
|
|
|
|
orgtable: orgtable
|
|
|
|
,db: db
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
,setFieldFlags: function (field, flags)
|
|
|
|
{
|
|
|
|
this.fieldFlags[field] = flags;
|
|
|
|
}
|
|
|
|
|
|
|
|
,repairColumns: function (columns)
|
|
|
|
{
|
|
|
|
for (var i = 0; i < columns.length; i++)
|
|
|
|
{
|
|
|
|
var newFlags = this.fieldFlags[columns[i].name];
|
|
|
|
|
|
|
|
if (newFlags)
|
|
|
|
columns[i].flags |= newFlags;
|
|
|
|
|
|
|
|
var tableInfo = this.tableInfo[columns[i].table];
|
|
|
|
|
|
|
|
if (tableInfo)
|
|
|
|
{
|
|
|
|
columns[i].orgtable = tableInfo.orgtable;
|
|
|
|
columns[i].db = tableInfo.db;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|