mirror of
https://github.com/thinkjs/thinkjs.git
synced 2026-01-25 14:42:47 +00:00
880 lines
30 KiB
JavaScript
880 lines
30 KiB
JavaScript
var util = require('util');
|
||
var querystring = require('querystring');
|
||
/**
|
||
* Model类
|
||
* @type {[type]}
|
||
*/
|
||
var model = module.exports = Class(function(){
|
||
var _linkNum = [];
|
||
var _db = [];
|
||
return {
|
||
initAttr: function(){
|
||
// 当前使用的扩展模型
|
||
//this._extModel = null;
|
||
// 当前数据库操作对象
|
||
this.db = null;
|
||
// 主键名称
|
||
this.pk = "id";
|
||
// 数据表前缀
|
||
this.tablePrefix = "";
|
||
// 模型名称
|
||
this.name = "";
|
||
// 数据库名称
|
||
this.dbName = "";
|
||
// 数据库配置
|
||
this.connection = "";
|
||
// 数据表名(不包含表前缀)
|
||
this.tableName = "";
|
||
// 实际数据表名(包含表前缀)
|
||
this.trueTableName = "";
|
||
// 最近错误信息
|
||
this.error = "";
|
||
// 字段信息
|
||
this.fields = {};
|
||
// 数据信息
|
||
this._data = {};
|
||
// 查询表达式参数
|
||
this.options = {};
|
||
// 自动验证定义
|
||
//this._validate = [];
|
||
// 自动完成定义
|
||
//this._auto = [];
|
||
// 字段映射定义
|
||
//this._map = [];
|
||
// 命名范围定义
|
||
//this._scope = [];
|
||
// 是否自动检测数据表字段信息
|
||
this.autoCheckFields = true;
|
||
// 是否批处理验证
|
||
//this.patchValidate = false;
|
||
//初始化的promise
|
||
this.promise = null;
|
||
},
|
||
/**
|
||
* 架构函数
|
||
* 取得DB类的实例对象 字段检查
|
||
* @access public
|
||
* @param string $name 模型名称
|
||
* @param string $tablePrefix 表前缀
|
||
* @param mixed $connection 数据库连接信息
|
||
*/
|
||
init: function(name, tablePrefix, connection){
|
||
this.initAttr();
|
||
// 获取模型名称
|
||
if (name) {
|
||
if (name.indexOf(".") > -1) {
|
||
name = name.split(".");
|
||
this.dbName = name[0];
|
||
this.name = name[1];
|
||
}else{
|
||
this.name = name;
|
||
}
|
||
}else if(!this.name){
|
||
this.getModelName();
|
||
}
|
||
// 设置表前缀
|
||
this.tablePrefix = tablePrefix === undefined ? (this.tablePrefix || C("db_prefix")) : tablePrefix;
|
||
// 数据库初始化操作
|
||
// 获取数据库操作对象
|
||
// 当前模型有独立的数据库连接信息
|
||
this.promise = this.initDb(0, connection || this.connection);
|
||
this.initMethod && this.initMethod();
|
||
},
|
||
/**
|
||
* 初始化数据库连接
|
||
* @access public
|
||
* @param integer $linkNum 连接序号
|
||
* @param mixed $config 数据库连接信息
|
||
* @param array $params 模型参数
|
||
* @return Model
|
||
*/
|
||
initDb: function(linkNum, config, params){
|
||
linkNum = linkNum || 0;
|
||
if (!linkNum && this.db) {
|
||
return get_promise(this.db);
|
||
};
|
||
if (!_db[linkNum] || config && _linkNum[linkNum] != config) {
|
||
if (config && is_string(config) && config.indexOf("/") == -1) {
|
||
config = C(config);
|
||
};
|
||
_db[linkNum] = think_require("Db").getInstance(config);
|
||
}else if(config === null){
|
||
_db[linkNum].close();
|
||
delete _db[linkNum];
|
||
return get_promise(this);
|
||
}
|
||
if (params) {
|
||
extend(this, params);
|
||
};
|
||
// 记录连接信息
|
||
_linkNum[linkNum] = config;
|
||
this.db = _db[linkNum];
|
||
if (this.name && this.autoCheckFields) {
|
||
return this.checkTableInfo();
|
||
};
|
||
return get_promise(this);
|
||
},
|
||
/**
|
||
* 获取模型名
|
||
* @access public
|
||
* @return string
|
||
*/
|
||
getModelName: function(){
|
||
var filename = this.__filename || __filename;
|
||
if (!this.name) {
|
||
var name = filename.split("/").pop().replace(C('class_file_suffix'), "");
|
||
this.name = name.substr(0, name.length - 5);
|
||
};
|
||
return this.name;
|
||
},
|
||
/**
|
||
* 获取表名
|
||
* @return {[type]} [description]
|
||
*/
|
||
getTableName: function(){
|
||
if (!this.trueTableName) {
|
||
var tableName = this.tablePrefix || "";
|
||
tableName += this.tableName || parse_name(this.name);
|
||
this.trueTableName = tableName.toLowerCase();
|
||
};
|
||
var tableName = (this.dbName ? this.dbName + "." : "") + this.trueTableName;
|
||
return tableName;
|
||
},
|
||
/**
|
||
* 获取缓存数据表字段信息的缓存文件
|
||
* @return {[type]} [description]
|
||
*/
|
||
getFieldsCacheFile: function(){
|
||
var db = this.dbName || C('db_name');
|
||
return '_fields/' + db + "." + this.name.toLowerCase();
|
||
},
|
||
/**
|
||
* 自动检测数据表信息
|
||
* @access protected
|
||
* @return void
|
||
*/
|
||
checkTableInfo: function(){
|
||
// 如果不是Model类 自动记录数据表信息
|
||
// 只在第一次执行记录
|
||
if (is_empty(this.fields)) {
|
||
// 如果数据表字段没有定义则自动获取
|
||
if (C('db_fields_cache')) {
|
||
var fields = F(this.getFieldsCacheFile());
|
||
if (fields) {
|
||
this.fields = fields;
|
||
return get_promise(fields);
|
||
};
|
||
};
|
||
// 每次都会读取数据表信息
|
||
return this.flushFields();
|
||
};
|
||
return get_promise(this.fields);
|
||
},
|
||
/**
|
||
* 刷新数据表字段信息
|
||
* @return promise [description]
|
||
*/
|
||
flushFields: function(){
|
||
this.db.setModel(this.name);
|
||
var self = this;
|
||
return this.getTableFields(this.getTableName(), true).then(function(fields){
|
||
self.fields = fields;
|
||
if (C('db_fields_cache')) {
|
||
F(self.getFieldsCacheFile(), self.fields);
|
||
};
|
||
return self.fields;
|
||
})
|
||
},
|
||
/**
|
||
* 获取数据表的字段
|
||
* @param {[type]} table
|
||
* @param {[type]} all
|
||
* @return {[type]}
|
||
*/
|
||
getTableFields: function(table, all){
|
||
if (table === true) {
|
||
table = undefined;
|
||
all = true;
|
||
};
|
||
if (table) {
|
||
return this.db.getFields(table).then(function(data){
|
||
if (data === false) {
|
||
return [];
|
||
};
|
||
var fields = {
|
||
"_field": Object.keys(data || {}),
|
||
"_autoinc": false
|
||
};
|
||
var types = {};
|
||
for(var key in data){
|
||
var val = data[key];
|
||
types[key] = val.type;
|
||
if (val.primary) {
|
||
fields['_pk'] = key;
|
||
if (val.autoinc) {
|
||
fields['_autoinc'] = true;
|
||
};
|
||
};
|
||
}
|
||
fields['_type'] = types;
|
||
return all ? fields : fields["_field"];
|
||
})
|
||
};
|
||
if (!is_empty(this.fields)) {
|
||
return get_promise(all ? this.fields : this.fields["_field"]);
|
||
};
|
||
return this.getTableFields(this.getTableName(), all);
|
||
},
|
||
/**
|
||
* 获取上一次操作的sql
|
||
* @return {[type]} [description]
|
||
*/
|
||
getLastSql: function(){
|
||
return this.db.getLastSql();
|
||
},
|
||
/**
|
||
* 获取主键名称
|
||
* @access public
|
||
* @return string
|
||
*/
|
||
getPk: function(){
|
||
return this.fields['_pk'] || this.pk;
|
||
},
|
||
/**
|
||
* 缓存
|
||
* @param {[type]} key [description]
|
||
* @param {[type]} expire [description]
|
||
* @param {[type]} type [description]
|
||
* @return {[type]} [description]
|
||
*/
|
||
cache: function(key, expire, type){
|
||
//如果没有key,则根据sql语句自动生成
|
||
if (is_number(key)) {
|
||
type = expire;
|
||
expire = key;
|
||
key = "";
|
||
};
|
||
this.options.cache = {
|
||
key: key,
|
||
expire: expire,
|
||
type: type
|
||
};
|
||
return this;
|
||
},
|
||
/**
|
||
* 指定查询数量
|
||
* @param {[type]} offset [description]
|
||
* @param {[type]} length [description]
|
||
* @return {[type]} [description]
|
||
*/
|
||
limit: function(offset, length){
|
||
this.options.limit = length === undefined ? offset : offset + "," + length;
|
||
return this;
|
||
},
|
||
/**
|
||
* 指定分页
|
||
* @return {[type]} [description]
|
||
*/
|
||
page: function(page, listRows){
|
||
this.options.page = listRows === undefined ? page : page + "," + listRows;
|
||
return this;
|
||
},
|
||
/**
|
||
* where条件
|
||
* @return {[type]} [description]
|
||
*/
|
||
where: function(where){
|
||
if (is_string(where) && where) {
|
||
where = {
|
||
"_string": where
|
||
}
|
||
};
|
||
this.options.where = extend(this.options.where || {}, where);
|
||
return this;
|
||
},
|
||
/**
|
||
* 要查询的字段
|
||
* @return {[type]} [description]
|
||
*/
|
||
field: function(field){
|
||
if (!field) {
|
||
field = "*";
|
||
};
|
||
this.options.field = field;
|
||
return this;
|
||
},
|
||
/**
|
||
* 联合查询
|
||
* @return {[type]} [description]
|
||
*/
|
||
union: function(union){
|
||
if (!this.options.union) {
|
||
this.options.union = [];
|
||
};
|
||
this.options.union.push(union);
|
||
return this;
|
||
},
|
||
/**
|
||
* 联合查询
|
||
* @param {[type]} join [description]
|
||
* @return {[type]} [description]
|
||
*/
|
||
join: function(join){
|
||
if (is_array(join)) {
|
||
this.options.join = join;
|
||
}else{
|
||
if (!this.options.join) {
|
||
this.options.join = [];
|
||
};
|
||
this.options.join.push(join);
|
||
}
|
||
return this;
|
||
},
|
||
/**
|
||
* 获取错误信息
|
||
* @return {[type]} [description]
|
||
*/
|
||
getError: function(){
|
||
return this.error;
|
||
},
|
||
/**
|
||
* 获取数据库错误信息
|
||
* @return {[type]} [description]
|
||
*/
|
||
getDbError: function(){
|
||
return this.db.getError();
|
||
},
|
||
/**
|
||
* 生成查询SQL 可用于子查询
|
||
* @param {[type]} options [description]
|
||
* @return {[type]} [description]
|
||
*/
|
||
buildSql: function(options){
|
||
var self = this;
|
||
return this.parseOptions(options).then(function(options){
|
||
return "( " + self.db.buildSelectSql(options) + " )";
|
||
})
|
||
},
|
||
// rollback: function(){
|
||
// return this.db.rollback();
|
||
// },
|
||
// commit: function(){
|
||
// return this.db.commit();
|
||
// },
|
||
// startTrans: function(){
|
||
// this.commit();
|
||
// this.db.startTrans();
|
||
// return this;
|
||
// },
|
||
/**
|
||
* 解析参数,在this.promise后执行
|
||
* @param {[type]} options [description]
|
||
* @return promise [description]
|
||
*/
|
||
parseOptions: function(options, extraOptions){
|
||
var self = this;
|
||
options = this.parseWhereOptions(options);
|
||
options = extend(this.options, options);
|
||
options = extend(options, extraOptions);
|
||
// 查询过后清空sql表达式组装 避免影响下次查询
|
||
this.options = {};
|
||
var promise = null;
|
||
//获取数据表下的字段信息
|
||
if (options.table) {
|
||
promise = this.getTableFields(options.table);
|
||
}else{
|
||
options.table = this.getTableName();
|
||
if (is_empty(self.fields["_field"])) {
|
||
promise = this.promise.then(function(){
|
||
return self.fields["_field"];
|
||
});
|
||
}else{
|
||
promise = get_promise(self.fields["_field"]);
|
||
}
|
||
}
|
||
//数据表别名
|
||
if (options.alias) {
|
||
options.table += " " + options.alias;
|
||
};
|
||
options.modal = this.name;
|
||
return promise.then(function(fields){
|
||
// 字段类型验证
|
||
if (options.where && is_object(options.where) && !is_empty(fields)) {
|
||
// 对数组查询条件进行字段类型检查
|
||
for(var key in options.where){
|
||
var val = options.where[key];
|
||
key = key.trim();
|
||
if (fields.indexOf(key) > -1) {
|
||
if (is_scalar(val)) {
|
||
options.where = self.parseType(options.where, key);
|
||
};
|
||
}else if(key.substr(0, 1) !== "_" && !(/[\.\|\&]/.test(key))){
|
||
delete options.where[key];
|
||
}
|
||
}
|
||
};
|
||
options = self._optionsFilter(options);
|
||
return options;
|
||
});
|
||
},
|
||
/**
|
||
* 选项过滤器
|
||
* 具体的Model类里进行实现
|
||
* @param {[type]} options [description]
|
||
* @return {[type]} [description]
|
||
*/
|
||
_optionsFilter: function(options){
|
||
return options;
|
||
},
|
||
/**
|
||
* 数据类型检测
|
||
* @param {[type]} data [description]
|
||
* @param {[type]} key [description]
|
||
* @return {[type]} [description]
|
||
*/
|
||
parseType: function(data, key){
|
||
var fieldType = this.fields["_type"][key] || "";
|
||
if (fieldType.indexOf("bigint") === -1 && fieldType.indexOf("int") > -1) {
|
||
data[key] = parseInt(data[key], 10) || 0;
|
||
}else if(fieldType.indexOf("double") > -1 || fieldType.indexOf("float") > -1){
|
||
data[key] = parseFloat(data[key]) || 0.0;
|
||
}else if(fieldType.indexOf('bool') > -1){
|
||
data[key] = !! data[key];
|
||
}
|
||
return data;
|
||
},
|
||
/**
|
||
* 对插入到数据库中的数据进行处理,要在parseOptions后执行
|
||
* @param {[type]} data [description]
|
||
* @return {[type]} [description]
|
||
*/
|
||
parseData: function(data){
|
||
data = data || {};
|
||
if (!is_empty(this.fields)) {
|
||
for(var key in data){
|
||
var val = data[key];
|
||
if (this.fields["_field"].indexOf(key) === -1) {
|
||
delete data[key];
|
||
}else if(is_scalar(val)){
|
||
data = this.parseType(data, key);
|
||
}
|
||
}
|
||
};
|
||
//安全过滤
|
||
if (typeof this.options.filter == 'function') {
|
||
for(var key in data){
|
||
data[key] = this.options.filter.call(this, key, data[key]);
|
||
}
|
||
delete this.options.filter;
|
||
};
|
||
data = this._dataFilter(data);
|
||
return data;
|
||
},
|
||
/**
|
||
* 数据过滤器
|
||
* 具体的Model类里进行实现
|
||
* @param {[type]} data [description]
|
||
* @return {[type]} [description]
|
||
*/
|
||
_dataFilter: function(data){
|
||
return data;
|
||
},
|
||
/**
|
||
* 数据插入之前操作
|
||
* @param {[type]} data [description]
|
||
* @param {[type]} options [description]
|
||
* @return {[type]} [description]
|
||
*/
|
||
_beforeInsert: function(data, options){
|
||
return data;
|
||
},
|
||
/**
|
||
* 数据插入之后操作
|
||
* @param {[type]} data [description]
|
||
* @param {[type]} options [description]
|
||
* @return {[type]} [description]
|
||
*/
|
||
_afterInsert: function(data, options){
|
||
return data;
|
||
},
|
||
/**
|
||
* 添加一条或者多条数据
|
||
* @param {[type]} data [description]
|
||
* @param {[type]} options [description]
|
||
* @param {[type]} replace [description]
|
||
*/
|
||
add: function(data, options, replace){
|
||
//copy data
|
||
data = extend({}, data);
|
||
if (is_empty(data)) {
|
||
if (this._data) {
|
||
data = this._data;
|
||
this._data = {};
|
||
}else{
|
||
throw_error(L("_DATA_TYPE_INVALID_"));
|
||
return get_promise(false);
|
||
}
|
||
};
|
||
var self = this;
|
||
return this.parseOptions(options).then(function(options){
|
||
data = self.parseData(data);
|
||
data = self._beforeInsert(data, options);
|
||
//如果_beforeInsert返回false,则直接返回
|
||
if (data === false) {
|
||
return false;
|
||
};
|
||
return self.db.insert(data, options, replace).then(function(){
|
||
//获取插入的ID
|
||
var id = self.db.getLastInsertId();
|
||
if (id) {
|
||
data[self.getPk()] = id;
|
||
};
|
||
self._afterInsert(data, options);
|
||
return id;
|
||
});
|
||
});
|
||
},
|
||
/**
|
||
* 插入多条数据
|
||
* @param {[type]} data [description]
|
||
* @param {[type]} options [description]
|
||
* @param {[type]} replace [description]
|
||
*/
|
||
addAll: function(data, options, replace){
|
||
if (!is_array(data) || !is_object(data[0])) {
|
||
this.error = L("_DATA_TYPE_INVALID_");
|
||
return get_promise(false);
|
||
};
|
||
var self = this;
|
||
return this.parseOptions(options).then(function(options){
|
||
return self.db.insertAll(data, options, replace).then(function(){
|
||
return self.db.getLastInsertId();
|
||
})
|
||
})
|
||
},
|
||
/**
|
||
* 删除数据
|
||
* @return {[type]} [description]
|
||
*/
|
||
delete: function(options){
|
||
var self = this;
|
||
return this.parseOptions(options).then(function(options){
|
||
return self.db.delete(options);
|
||
})
|
||
},
|
||
_beforeUpdate: function(data, options){
|
||
return data;
|
||
},
|
||
_afterUpdate: function(data, options){
|
||
return data;
|
||
},
|
||
/**
|
||
* 更新数据
|
||
* @return {[type]} [description]
|
||
*/
|
||
update: function(data, options){
|
||
data = extend({}, data);
|
||
if (is_empty(data)) {
|
||
if (this._data) {
|
||
data = this._data;
|
||
this._data = {};
|
||
}else{
|
||
throw_error(L("_DATA_TYPE_INVALID_"));
|
||
return get_promise(false);
|
||
}
|
||
};
|
||
var self = this;
|
||
return this.parseOptions(options).then(function(options){
|
||
data = self.parseData(data);
|
||
if (self._beforeUpdate(data, options) === false) {
|
||
return false;
|
||
};
|
||
var pkValue = "";
|
||
var pk = self.getPk();
|
||
if (is_empty(self.options.where) && is_empty(options.where)) {
|
||
// 如果存在主键数据 则自动作为更新条件
|
||
if (!is_empty(data[pk])) {
|
||
var where = {};
|
||
where[pk] = data[pk];
|
||
options.where = where;
|
||
pkValue = data[pk];
|
||
delete data[pk];
|
||
}else{
|
||
self.error = L("_OPERATION_WRONG_");
|
||
return false;
|
||
}
|
||
};
|
||
return self.db.update(data, options).then(function(data){
|
||
if (data) {
|
||
if (pkValue) {
|
||
data[pk] = pkValue;
|
||
};
|
||
self._afterUpdate(data, options);
|
||
return data.affectedRows;
|
||
};
|
||
return false;
|
||
})
|
||
})
|
||
},
|
||
/**
|
||
* 更新某个字段的值
|
||
* @param {[type]} field [description]
|
||
* @param {[type]} value [description]
|
||
* @return {[type]} [description]
|
||
*/
|
||
updateField: function(field, value){
|
||
var data = {};
|
||
if (is_object(field)) {
|
||
data = field;
|
||
}else{
|
||
data[field] = value;
|
||
}
|
||
return this.update(data);
|
||
},
|
||
/**
|
||
* 字段值增长
|
||
* @return {[type]} [description]
|
||
*/
|
||
updateInc: function(field, step){
|
||
step = parseInt(step, 10) || 1;
|
||
return this.updateField(field, ["exp", field + "+" + step]);
|
||
},
|
||
/**
|
||
* 字段值减少
|
||
* @return {[type]} [description]
|
||
*/
|
||
updateDec: function(field, step){
|
||
step = parseInt(step, 10) || 1;
|
||
return this.updateField(field, ["exp", field + "-" + step]);
|
||
},
|
||
/**
|
||
* 解析options中简洁的where条件
|
||
* @return {[type]} [description]
|
||
*/
|
||
parseWhereOptions: function(options){
|
||
if (is_number(options) || is_string(options)) {
|
||
var pk = this.getPk();
|
||
options += "";
|
||
var where = {};
|
||
if (options.indexOf(",") > -1) {
|
||
where[pk] = ["IN", options];
|
||
}else{
|
||
where[pk] = options;
|
||
}
|
||
options = {
|
||
"where": where
|
||
};
|
||
}else if (!is_empty(options)) {
|
||
options = {
|
||
"where": options
|
||
};
|
||
};
|
||
return options || {};
|
||
},
|
||
/**
|
||
* 查询一条数据
|
||
* @return 返回一个promise
|
||
*/
|
||
find: function(options){
|
||
var self = this;
|
||
return this.parseOptions(options, {
|
||
limit: 1
|
||
}).then(function(options){
|
||
return self.db.select(options).then(function(data){
|
||
return data ? data[0] : [];
|
||
})
|
||
});
|
||
},
|
||
/**
|
||
* 查询数据
|
||
* @return 返回一个promise
|
||
*/
|
||
select: function(options){
|
||
var self = this;
|
||
return this.parseOptions(options).then(function(options){
|
||
return self.db.select(options);
|
||
});
|
||
},
|
||
selectAdd: function(fields, table, options){
|
||
var self = this;
|
||
return this.parseOptions(options).then(function(options){
|
||
fields = fields || options.field;
|
||
table = table || self.getTableName();
|
||
return self.db.selectInsert(fields, table, options);
|
||
});
|
||
},
|
||
/**
|
||
* 获取一条记录的某个字段值
|
||
* @return {[type]} [description]
|
||
*/
|
||
getField: function(field, sepa){
|
||
field = field.trim();
|
||
var self = this;
|
||
return this.parseOptions({
|
||
"field": field
|
||
}).then(function(options){
|
||
var multi = false;
|
||
if (field.indexOf(",") > -1) {
|
||
if (options.limit === undefined && is_number(sepa)) {
|
||
options.limit = sepa;
|
||
};
|
||
multi = true;
|
||
}else{
|
||
options.limit = is_number(sepa) ? sepa : 1;
|
||
}
|
||
return self.db.select(options).then(function(data){
|
||
if (data === false) {
|
||
return false;
|
||
};
|
||
if (multi) {
|
||
var length = field.split(",").length;
|
||
var field = Object.keys(data[0] || {});
|
||
var key = field.shift();
|
||
var key2 = field.shift();
|
||
var cols = {};
|
||
data.forEach(function(item){
|
||
var name = item[key];
|
||
if (length === 2) {
|
||
cols[name] = item[key2];
|
||
}else{
|
||
cols[name] = is_string(sepa) ? item.join(sepa) : item;
|
||
}
|
||
});
|
||
return cols;
|
||
}else{
|
||
if (sepa !== true && options.limit == 1) {
|
||
return data[0];
|
||
};
|
||
return Object.values(data[0] || {})[0];
|
||
}
|
||
});
|
||
})
|
||
},
|
||
/**
|
||
* SQL查询
|
||
* @return {[type]} [description]
|
||
*/
|
||
query: function(sql, parse){
|
||
if (parse !== undefined && !is_boolean(parse) && !is_array(parse)) {
|
||
parse = [].slice.call(arguments);
|
||
parse.shift();
|
||
};
|
||
var self = this;
|
||
return this.parseSql.then(function(sql){
|
||
return self.db.query(sql);
|
||
})
|
||
},
|
||
/**
|
||
* 执行SQL语法,非查询类的SQL语句,返回值为影响的行数
|
||
* @param {[type]} sql [description]
|
||
* @param {[type]} parse [description]
|
||
* @return {[type]} [description]
|
||
*/
|
||
execute: function(sql, parse){
|
||
if (parse !== undefined && !is_boolean(parse) && !is_array(parse)) {
|
||
parse = [].slice.call(arguments);
|
||
parse.shift();
|
||
};
|
||
var self = this;
|
||
return this.parseSql.then(function(sql){
|
||
return self.db.execute(sql);
|
||
})
|
||
},
|
||
/**
|
||
* 解析SQL语句
|
||
* @return {[type]} [description]
|
||
*/
|
||
parseSql: function(sql, parse){
|
||
var promise = null;
|
||
var self = this;
|
||
if (parse === true) {
|
||
promise = this.parseOptions().then(function(options){
|
||
return self.db.parseSql(options);
|
||
})
|
||
}else if (is_array(parse)) {
|
||
sql = util.format.apply(null, sql, parse);
|
||
promise = get_promise(sql);
|
||
}else{
|
||
var map = {
|
||
"__TABLE__": this.getTableName(),
|
||
"__PREFIX__": C('db_prefix')
|
||
};
|
||
sql = sql.replace(/__[A-Z]__/g, function(a){
|
||
return map[a] || a;
|
||
})
|
||
promise = get_promise(sql);
|
||
}
|
||
this.db.setModel(this.name);
|
||
return promise;
|
||
},
|
||
/**
|
||
* 设置数据对象值
|
||
* @return {[type]} [description]
|
||
*/
|
||
data: function(data){
|
||
if (data === true) {
|
||
return this._data;
|
||
};
|
||
if (is_string(data)) {
|
||
data = querystring.parse(data);
|
||
};
|
||
this._data = data;
|
||
return this;
|
||
}
|
||
}
|
||
}).extend(function(){
|
||
//追加的方法
|
||
var methods = {
|
||
initMethod: function(){
|
||
var self = this;
|
||
this.promise.then(function(){
|
||
var field = self.fields["_field"];
|
||
(field || []).forEach(function(item){
|
||
var name = "getBy" + parse_name(item, 1);
|
||
self[name] = function(arg){
|
||
var where = {}
|
||
where[item] = arg;
|
||
return this.where(where).find();
|
||
}
|
||
var fieldName = "getFieldBy" + parse_name(item, 1);
|
||
self[fieldName] = function(arg, arg1){
|
||
var where = {};
|
||
where[item] = arg;
|
||
return this.where(where).getField(arg1);
|
||
}
|
||
})
|
||
});
|
||
}
|
||
};
|
||
// 链操作方法列表
|
||
var methodNameList = [
|
||
'table','order','alias','having','group',
|
||
'lock','distinct','auto','filter','validate'
|
||
];
|
||
methodNameList.forEach(function(item){
|
||
methods[item] = function(data){
|
||
this.options[item] = data;
|
||
return this;
|
||
}
|
||
});
|
||
['count','sum','min','max','avg'].forEach(function(item){
|
||
methods[item] = function(data){
|
||
var field = data || "*";
|
||
return this.getField(item.toUpperCase() + "(" + field + ") AS thinkjs_" + item, true);
|
||
}
|
||
});
|
||
//方法别名
|
||
var aliasMethodMap = {
|
||
update: "save",
|
||
updateField: "setField",
|
||
updateInc: "setInc",
|
||
updateDec: "setDec"
|
||
};
|
||
Object.keys(aliasMethodMap).forEach(function(key){
|
||
var value = aliasMethodMap[key];
|
||
methods[value] = function(){
|
||
return this[key].apply(this, arguments);
|
||
}
|
||
})
|
||
return methods;
|
||
}) |