thinkjs/lib/Lib/Core/Db.class.js
2013-11-17 15:05:21 +08:00

382 lines
13 KiB
JavaScript

var url = require("url");
var querystring = require("querystring");
/**
* 数据库基类
* @return {[type]} [description]
*/
var db = module.exports = Class(function(){
return {
comparison: {
'eq': '=',
'neq': '<>',
'gt': '>',
'egt': '>=',
'lt': '<',
'elt': '<=',
'notlike': 'NOT LIKE',
'like': 'LIKE',
'in': 'IN',
'notin': 'NOT IN'
},
selectSql: 'SELECT%DISTINCT% %FIELD% FROM %TABLE%%JOIN%%WHERE%%GROUP%%HAVING%%ORDER%%LIMIT% %UNION%%COMMENT%',
initProp: function(){
// 数据库类型
this.dbType = null;
// 是否自动释放查询结果
this.autoFree = false;
// 当前操作所属的模型名
this.model = "_think_";
// 是否使用永久连接
this.pconnect = false;
// 当前SQL指令
this.queryStr = "";
this.modelSql = [];
// 最后插入ID
this.lastInsID = null;
// 返回或者影响记录数
this.numRows = 0;
// 返回字段数
this.numCols = 0;
// 事务指令数
this.transTimes = 0;
// 错误信息
this.error = "";
// 数据库连接ID 支持多个连接
this.linkID = [];
// 当前连接ID
this._linkID = null;
// 当前查询ID
this.queryId = null;
// 是否已经连接数据库
this.connected = false;
// 数据库连接参数配置
this.config = '';
// 数据库表达式
},
init: function(){
this.initProp();
},
parseSet: function(data){
data = data || {};
var set = [];
for(var key in data){
var value = this.parseValue(data[key]);
if (is_scalar(value)) {
set.push(this.parseKey(key) + "=" + value);
};
}
return "SET " + set.join(",");
},
parseKey: function(key){
return key;
},
/**
* value分析
* @param {[type]} value [description]
* @return {[type]} [description]
*/
parseValue: function(value){
if (is_string(value)) {
value = '\'' + this.escapeString(value) + '\'';
}else if(is_array(value)){
if ((value[0] + "").toLowerCase() == 'exp') {
value = this.escapeString(value[1]);
}else{
value = value.map(this.parseValue);
}
}else if(is_boolean(value)){
value = value ? "1" : "0";
}else if (value === null) {
value = 'null';
};
return value;
},
/**
* field分析
* @return {[type]} [description]
*/
parseField: function(fields){
if (is_string(fields) && fields.indexOf(',') > -1) {
fields = fields.split(",");
};
if (is_array(fields)) {
var self = this;
return fields.map(function(item){
return self.parseKey(item);
}).join(",");
}else if(is_object(fields)){
var data = [];
for(var key in fields){
data.push(this.parseKey(key) + " AS " + this.parseKey(fields[key]));
}
return data.join(",");
}else if(is_string(fields) && fields){
return this.parseKey(fields);
}
return "*";
},
/**
* table别名分析
* @param {[type]} tables [description]
* @return {[type]} [description]
*/
parseTable: function(tables){
if (is_string(tables)) {
tables = tables.split(",");
};
if (is_array(tables)) {
var self = this;
return tables.map(function(item){
return self.parseKey(item);
}).join(",");
}else if (is_object(tables)) {
var data = [];
for(var key in tables){
data.push(this.parseKey(key) + " AS " + this.parseKey(tables[key]));
}
return data.join(",");
}
},
/**
* where条件分析
* @param {[type]} where [description]
* @return {[type]} [description]
*/
parseWhere: function(where){
var whereStr = "";
var self = this;
if (is_string(where)) {
whereStr = where;
}else{
where = where || {};
var operate = (where["_logic"] + "").toUpperCase();
var oList = ["AND", "OR", "XOR"];
if (oList.indexOf(operate) > -1) {
// 定义逻辑运算规则 例如 OR XOR AND NOT
operate = " " + operate + " ";
delete where["_logic"];
}else{
operate = " AND ";
}
//key值的安全检测正则
var keySafeRegExp = /^[A-Z_\|\&\-.a-z0-9\(\)\,]+$/;
for(var key in where){
var val = where[key];
whereStr += "( ";
if (key.indexOf("_") === 0) {
// 解析特殊条件表达式
whereStr += this.parseThinkWhere(key, val);
}else{
if (!keySafeRegExp.test(key.trim())) {
throw_error(key + " is not safe");
};
var multi = where && where['_multi'];
key = key.trim();
// 支持 name|title|nickname 方式定义查询字段
if (key.indexOf('|') > -1) {
var arr = key.split("|");
whereStr += arr.map(function(item, i){
var v = multi ? val[i] : val;
return "(" + self.parseWhereItem(self.parseKey(item, v)) + ")";
}).join(" OR ");
}else if (key.indexOf("&") > -1) {
var arr = key.split("&");
whereStr += arr.map(function(item, i){
var v = multi ? val[i] : val;
return "(" + self.parseWhereItem(self.parseKey(item, v)) + ")";
}).join(" AND ");
}else{
whereStr += this.parseWhereItem(this.parseKey(key), val);
}
}
whereStr += ")" + operate;
}
whereStr = whereStr.substr(0, -operate.length);
}
return whereStr ? (" WHERE " + whereStr) : "";
},
parseWhereItem: function(key, val){
return "";
},
parseThinkWhere: function(key, val){
var whereStr = "";
switch(key){
// 字符串模式查询条件
case "_string":
return val;
// 复合查询条件
case "_complex":
return this.parseWhere(val).substr(6);
// 字符串模式查询条件
case "_query":
var where = querystring.parse(val);
var op = " AND ";
if ("_logic" in where) {
op = " " + where["_logic"].toLowerCase() + " ";
delete where["_logic"];
};
var arr = [];
for(var name in where){
var val = where[name];
val = this.parseKey(name) + " = " + this.parseValue(val);
arr.push(val);
}
whereStr = arr.join(op);
return whereStr;
default:
return "";
}
return "";
},
parseLimit: function(limit){
return limit ? (" LIMIT " + limit) : "";
},
parseJoin: function(join){
var joinStr = "";
if (join) {
if (is_object(join)) {
for(var key in join){
var val = join[key];
if (val.toLowerCase().indexOf("join") > -1) {
joinStr += val;
}else{
joinStr += " LEFT JOIN " + val;
}
}
}else{
joinStr += " LEFT JOIN " + join;
}
};
//将__TABLE_NAME__这样的字符串替换成正规的表名,并且带上前缀和后缀
joinStr = joinStr.replace(/__([A-Z_-]+)__/g, function(a, b){
return C('db_prefix') + b.toLowerCase();
});
return joinStr;
},
parseOrder: function(order){
var orderStr = "";
var self = this;
if (is_array(order)) {
orderStr = order.map(function(item){
return self.parseKey(item);
}).join(",");
}else if (is_object(order)) {
var arr = [];
for(var key in order){
var val = order[key];
val = this.parseKey(key) + " " + val;
arr.push(val);
}
orderStr = arr.join(",");
};
return order ? (" ORDER BY " + order) : "";
},
parseGroup: function(group){
return group ? (" GROUP BY " + group) : "";
},
parseHaving: function(having){
return having ? (" HAVING " + having) : "";
},
parseComment: function(comment){
return comment ? (" /* " + comment + "*/") : "";
},
parseDistinct: function(distinct){
return distinct ? (" Distinct " + distinct) : "";
},
parseUnion: function(union){
if (!union) {
return "";
};
var str = "";
if ("_all" in union) {
str = "UNION ALL ";
delete union["_all"];
}else{
str = "UNION ";
}
var sql = [];
for(var key in union){
var val = union[key];
val = str + (is_array(val) ? this.buildSelectSql(val) : val);
sql.push(sql);
}
return sql.join(" ");
}
}
});
/**
* 解析dsn
* 格式: mysql://username:passwd@localhost:3306/DbName
* @param string dsn [description]
* @return {[type]} [description]
*/
db.parseDSN = function(dsn){
if (!dsn) {
return false;
};
var info = url.parse(dsn);
var auth = (info.auth || "").split(":");
return {
"dbms": info.protocol,
"username": auth[0] || "",
"password": auth[1] || "",
"hostname": info.hostname || "",
"hostport": info.port || "",
"database": (info.pathname || "").substr(1),
"dsn": ""
}
}
/**
* 解析配置
* @param {[type]} config [description]
* @return {[type]} [description]
*/
db.parseConfig = function(config){
if (config && is_string(config)) {
return this.parseDSN(config);
}else if(is_object(config)){
return {
"dbms": config.db_type,
"username": config.db_user,
"password": config.db_pwd,
"hostname": config.db_host,
"hostport": config.db_port,
"database": config.db_name,
"dsn": config.db_dsn,
"params": config.db_params
}
}else if(!config){
if (C('db_dsn')) {
return this.parseDSN(C('db_dsn'));
};
return {
'dbms' : C('db_type'),
'username' : C('db_user'),
'password' : C('db_pwd'),
'hostname' : C('db_host'),
'hostport' : C('db_port'),
'database' : C('db_name'),
'dsn' : C('db_dsn'),
'params' : C('db_params'),
}
}
return config;
};
/**
* 根据配置获取对应的数据库实例
* @param {[type]} config [description]
* @return {[type]} [description]
*/
db.getInstance = function(config){
config = this.parseConfig(config);
if (!config.dbms) {
return throw_error("no dbms config");
};
//数据库类型
var dbType = config.dbms.toLowerCase();
dbType = dbType.substr(0, 1).toUpperCase() + dbType.substr(1);
var instance = think_require(dbType + "Db")(config);
instance.dbType = dbType.toUpperCase();
return instance;
}