代码重构
parent
572f7580eb
commit
637f40a0e7
|
@ -1,3 +1,8 @@
|
||||||
|
2.1.0 / 2017-12-14
|
||||||
|
==================
|
||||||
|
* 大重构, 更加简练, 结构也更加合理
|
||||||
|
|
||||||
|
|
||||||
2.0.1 / 2017-05-22
|
2.0.1 / 2017-05-22
|
||||||
==================
|
==================
|
||||||
* 优化一处由于js对象引用类型引起的混乱
|
* 优化一处由于js对象引用类型引起的混乱
|
||||||
|
|
335
Readme.md
335
Readme.md
|
@ -1,255 +1,236 @@
|
||||||
![module info](https://nodei.co/npm/mysqli.png?downloads=true&downloadRank=true&stars=true)
|
![module info](https://nodei.co/npm/mysqli.png?downloads=true&downloadRank=true&stars=true)
|
||||||
|
|
||||||
# mysqli
|
# mysqli
|
||||||
> 本模块基于node-mysql模块二次封装,对基础的增删改查,主从库等按js的特点进行了简化,并对SQL注入进行安全过滤,让没有SQL基础的人,也能顺利使用;
|
|
||||||
> 当然,一些复杂的查询,以及事务等,这些不在我的服务之内,而且会用到这些功能的童鞋,本身也有一定的SQL基础了; 所以,这类童鞋,请自行使用各自习惯的SQL模块,或手写实现。
|
|
||||||
|
|
||||||
|
> 本模块基于 node-mysql 模块二次封装,对基础的增删改查,主从库等按 js 的特点进行
|
||||||
|
> 了简化,并对 SQL 注入进行安全过滤,让没有 SQL 基础的人,也能顺利使用 ; 当然,
|
||||||
|
> 一些复杂的查询,以及事务等,这些不在我的服务之内,而且会用到这些功能的童鞋,本
|
||||||
|
> 身也有一定的 SQL 基础了 ; 所以,这类童鞋,请自行使用各自习惯的 SQL 模块,或手
|
||||||
|
> 写实现。
|
||||||
|
|
||||||
|
## 使用 npm 安装
|
||||||
## 使用npm安装
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm install mysqli
|
npm install mysqli
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## 实例化
|
## 实例化
|
||||||
> 实例化可以传2种格式的配置,1是json对象,2是数组。
|
|
||||||
> 只有一个数据库时,默认是主库; 多于1个数据库服务时,自动以第1个为主库,其他的从库,故实例化时,`注意顺序`。
|
|
||||||
|
|
||||||
|
> 实例化可以传 2 种格式的配置,1 是 json 对象,2 是数组。只有一个数据库时,默认
|
||||||
|
> 是主库 ; 多于 1 个数据库服务时,自动以第 1 个为主库,其他的从库,故实例化时
|
||||||
|
> ,`注意顺序`。
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
|
|
||||||
let Mysqli = require('mysqli')
|
let Mysqli = require('mysqli')
|
||||||
|
|
||||||
//传入json
|
//传入json
|
||||||
let conn = new Mysqli({
|
let conn = new Mysqli({
|
||||||
host: '', // IP/域名
|
host: '', // IP/域名
|
||||||
post: 3306, //端口, 默认 3306
|
post: 3306, //端口, 默认 3306
|
||||||
user: '', //用户名
|
user: '', //用户名
|
||||||
passwd: '', //密码
|
passwd: '', //密码
|
||||||
charset: '', // 数据库编码,默认 utf8 【可选】
|
charset: '', // 数据库编码,默认 utf8 【可选】
|
||||||
db: '', // 可指定数据库,也可以不指定 【可选】
|
db: '' // 可指定数据库,也可以不指定 【可选】
|
||||||
})
|
})
|
||||||
|
|
||||||
// 传入数组
|
// 传入数组
|
||||||
let conn = new Mysqli([
|
let conn = new Mysqli([
|
||||||
{
|
{
|
||||||
host: 'host1', // IP/域名
|
host: 'host1', // IP/域名
|
||||||
post: 3306, //端口, 默认 3306
|
post: 3306, //端口, 默认 3306
|
||||||
user: '', //用户名
|
user: '', //用户名
|
||||||
passwd: '', //密码
|
passwd: '', //密码
|
||||||
charset: '', // 数据库编码,默认 utf8 【可选】
|
charset: '', // 数据库编码,默认 utf8 【可选】
|
||||||
db: '', // 可指定数据库,也可以不指定 【可选】
|
db: '' // 可指定数据库,也可以不指定 【可选】
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
host: 'host2', // IP/域名
|
host: 'host2', // IP/域名
|
||||||
post: 3306, //端口, 默认 3306
|
post: 3306, //端口, 默认 3306
|
||||||
user: '', //用户名
|
user: '', //用户名
|
||||||
passwd: '', //密码
|
passwd: '', //密码
|
||||||
charset: '', // 数据库编码,默认 utf8 【可选】
|
charset: '', // 数据库编码,默认 utf8 【可选】
|
||||||
db: '', // 可指定数据库,也可以不指定 【可选】
|
db: '' // 可指定数据库,也可以不指定 【可选】
|
||||||
},
|
}
|
||||||
])
|
])
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## API 方法
|
||||||
## API方法
|
|
||||||
|
|
||||||
|
|
||||||
### 1. escape(val)
|
### 1. escape(val)
|
||||||
> 这是`node-mysql`的内部方法,用于进行SQL安全过滤,这里只是做了搬运工,把它暴露出来给外部调用而已。
|
|
||||||
|
|
||||||
|
> 这是`node-mysql`的内部方法,用于进行 SQL 安全过滤,这里只是做了搬运工,把它暴
|
||||||
### 2. listDB()
|
> 露出来给外部调用而已。 **这个是静态方法**
|
||||||
> 顾名思义,该方法即用于列举当前账号权限范围内的所有的数据库名称,返回值是一个数组;
|
|
||||||
>
|
|
||||||
> **注:**`该方法配置await指令可得到纯粹的数据,否则返回的是一个Promise对象`
|
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
|
const Mysqli = require('mysqli')
|
||||||
|
|
||||||
async function(){
|
Mysqli.escape('这是文本')
|
||||||
let db = await conn.listDB()
|
```
|
||||||
console.log(db)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 不使用await指令时,返回的是Promise对象
|
### 2. emit(isSlave, dbName)
|
||||||
conn.listDB().then(db => {
|
|
||||||
console.log(db)
|
* isSlave `<Boolean>` 可选
|
||||||
|
* dbName `<String>` 可选。 如果在实例化连接时 , 已经传入 db, 则这里可不传值。
|
||||||
|
|
||||||
|
> 触发一个数据库实例 , 可接受 2 个参数 , 第 1 个为 " 是否从库 ", 第 2 个为 " 数
|
||||||
|
> 据库名称 "
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const Mysqli = require('mysqli')
|
||||||
|
let conn = new Mysqli({
|
||||||
|
/*...*/
|
||||||
})
|
})
|
||||||
|
let db = conn.emit(true, 'test')
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### 3. listDb()
|
||||||
|
|
||||||
### 3. useDB(db[, slave])
|
> 顾名思义,该方法即用于列举当前账号权限范围内的所有的数据库名称,返回值是一个数
|
||||||
- db `<String>`
|
> 组 ;
|
||||||
- slave `<Boolean>` 可选
|
>
|
||||||
|
> **注:**`方法返回的是一个 Promise 对象`
|
||||||
> 该方法用于切换数据库,仅限于同一台机器上的数据库; 在配置中没有指定数据库的情况下,必须先调用该方法才可以进行后续的增删改查等操作。
|
|
||||||
>
|
|
||||||
> `db`即为要切换的数据库名; `slave`为是否从库查询,默认主库。
|
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
|
db.listDb().then(list => {
|
||||||
|
console.log(list)
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
async function(){
|
### 4. listTable()
|
||||||
|
|
||||||
let docs = await conn.useDB('xx').query(`select * from users limit 10`);
|
> 该方法用于列举当前数据库数据表的集合
|
||||||
console.log(docs);
|
|
||||||
|
|
||||||
}
|
```javascript
|
||||||
|
db.listTable().then(list => {
|
||||||
|
console.log(list)
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. query(sql)
|
||||||
|
|
||||||
|
* sql `<String>`
|
||||||
|
|
||||||
|
> 该方法用于当内置的方法满足不了需求时,可以自行编写`sql 语句`执行 ; 但要注意防
|
||||||
|
> 止`sql 注入`,因为该方法是最基础的方法,模块不对传入的`sql 语句`进行任何的安全
|
||||||
|
> 过滤。
|
||||||
|
|
||||||
|
```javascript
|
||||||
// 不使用await指令时,返回的是Promise对象
|
// 不使用await指令时,返回的是Promise对象
|
||||||
conn.useDB('xx')
|
db.query(`select * from users limit 10`).then(row => {
|
||||||
.query(`select * from users limit 10`)
|
console.log(row)
|
||||||
.then(docs => {
|
})
|
||||||
console.log(docs)
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### 6. filter(condition, select)
|
||||||
|
|
||||||
|
* condition `<Object>`, 查询条件
|
||||||
|
* select `<Array>`, 要返回字段 , 默认全部返回
|
||||||
|
|
||||||
### 4. query(sql[, slave])
|
> 该方法用于查询多条数据。无论结果是多少条,返回的都是`数组格式`; 详细请看下面代
|
||||||
- sql `<String>`
|
> 码示例:
|
||||||
- slave `<Boolean>` 可选
|
|
||||||
|
|
||||||
> 该方法用于当内置的方法满足不了需求时,可以自行编写`sql语句`执行; 但要注意防止`sql注入`,因为该方法是最基础的方法,模块不对传入的`sql语句`进行任何的安全过滤。
|
|
||||||
>
|
|
||||||
> `sql`即为要执行的sql语句; `slave`为是否从库查询,默认主库。
|
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
|
db
|
||||||
async function(){
|
.filter(
|
||||||
|
{
|
||||||
let docs = await conn.query(`select * from users limit 10`);
|
table: '', // 要查询的表
|
||||||
console.log(docs);
|
where: [
|
||||||
|
{
|
||||||
}
|
//数组格式,可以组成多个条件,默认查询全表 【可选】
|
||||||
|
join: 'OR', //条件关系 AND, OR
|
||||||
// 不使用await指令时,返回的是Promise对象
|
op: '>', //关系符,如 =, >, <, <=, >=
|
||||||
conn.query(`select * from users limit 10`)
|
key: 'aa',
|
||||||
.then(docs => {
|
val: 23
|
||||||
console.log(docs)
|
}
|
||||||
})
|
],
|
||||||
|
sort: {
|
||||||
```
|
//排序, key是要排序的字段,value是排序方式, 1顺序,-1逆序 【可选】
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### 5. find(conf)
|
|
||||||
- conf `<Object>`
|
|
||||||
|
|
||||||
> 该方法用于查询多条数据。无论结果是多少条,返回的都是`数组格式`; 详细请看下面代码示例:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
|
|
||||||
conn.find({
|
|
||||||
table: '', // 要查询的表
|
|
||||||
select: ['a', 'b'], //要返回的字段,不传默认返回所有 【可选】
|
|
||||||
where: [{ //数组格式,可以组成多个条件,默认查询全表 【可选】
|
|
||||||
join: 'OR', //条件关系 AND, OR
|
|
||||||
op: '>', //关系符,如 =, >, <, <=, >=
|
|
||||||
key: 'aa',
|
|
||||||
val: 23
|
|
||||||
}],
|
|
||||||
sort: { //排序, key是要排序的字段,value是排序方式, 1顺序,-1逆序 【可选】
|
|
||||||
a: 1,
|
a: 1,
|
||||||
b: -1
|
b: -1
|
||||||
|
},
|
||||||
|
limit: [0, 1] // 查询范围,可用于分页 【可选】
|
||||||
},
|
},
|
||||||
limit: { // 查询范围,可用于分页 【可选】
|
['a', 'b']
|
||||||
start: 0,
|
)
|
||||||
size: 10
|
.then(row => {
|
||||||
},
|
console.log(row)
|
||||||
slave: false // 是否从库 【可选】
|
})
|
||||||
})
|
|
||||||
|
|
||||||
// 其中,table这一项,还可以联表,但是仅限于 'left join',要使用其他的方式联表,请自行编写sql语句
|
|
||||||
// where条件也可以直接使用sql语句,要注意防止注入。
|
|
||||||
|
|
||||||
conn.find({
|
|
||||||
table: {
|
|
||||||
master: 'xx',
|
|
||||||
unite: [
|
|
||||||
{
|
|
||||||
table: 'aa',
|
|
||||||
on: 'xx.id = aa.xid'
|
|
||||||
},
|
|
||||||
//... 可以联多个表, 但都是 left join
|
|
||||||
]
|
|
||||||
},
|
|
||||||
where: `xx.id = 123`
|
|
||||||
})
|
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### 7. filterOne(condition)
|
||||||
|
|
||||||
|
* condition `<Object>`
|
||||||
|
|
||||||
### 6. findOne(conf)
|
> 该方法与上面的`filter`方法的使用一致,区别只是该方法只返回一条数据,且为`json
|
||||||
- conf `<Object>`
|
> 格式`。
|
||||||
|
|
||||||
> 该方法与上面的`find`方法的使用一致,区别只是该方法只返回一条数据,且为`json格式`。
|
### 8. count(condition)
|
||||||
|
|
||||||
|
* condition `<Object>`
|
||||||
|
|
||||||
### 7. count(conf)
|
> 该方法与上面的`filter`方法的使用一致,不过返回的是条目总数 (`<Number>`)
|
||||||
- conf `<Object>`
|
|
||||||
|
|
||||||
> 该方法与上面的`find`方法的使用一致,不过返回的是条目总数(`<Number>`)
|
### 9. insert(condition, doc)
|
||||||
|
|
||||||
|
* condition `<Object>`, 插入的条件
|
||||||
|
* doc `<Object>`, 插入的数据
|
||||||
|
|
||||||
### 8. insert(conf)
|
> 该方法与上面的`filter`方法的使用类似,手于插入一条数据,具体请看下面代码 ;
|
||||||
- conf `<Object>`
|
>
|
||||||
|
|
||||||
> 该方法与上面的`find`方法的使用类似,手于插入一条数据,具体请看下面代码;
|
|
||||||
>
|
|
||||||
> **注:**`该方法一次只能插入一条数据`
|
> **注:**`该方法一次只能插入一条数据`
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
|
|
||||||
// 如果主键是自增ID,则结果返回的是 刚插入的数据的自增ID
|
// 如果主键是自增ID,则结果返回的是 刚插入的数据的自增ID
|
||||||
conn.insert({
|
db
|
||||||
table: 'xx',
|
.insert(
|
||||||
data: {}, //要插入的数据
|
{
|
||||||
})
|
table: 'xx'
|
||||||
|
},
|
||||||
|
{ xx: 1234 } //要插入的数据
|
||||||
|
)
|
||||||
|
.then(id => {
|
||||||
|
console.log(id)
|
||||||
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### 10. update(condition, doc)
|
||||||
|
|
||||||
### 9. update(conf)
|
* condition `<Object>`, 条件
|
||||||
- conf `<Object>`
|
* doc `<Object>`, 数据
|
||||||
|
|
||||||
> 该方法与上面的`find`方法的使用类似,用于更新数据,具体请看下面代码;
|
> 该方法与上面的`filter`方法的使用类似,用于更新数据,具体请看下面代码 ; `该方法返
|
||||||
> `该方法返回的是被修改的条目数量`
|
> 回的是被修改的条目数量`
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
|
|
||||||
// 如果修改成功,则返回被修改的数量
|
// 如果修改成功,则返回被修改的数量
|
||||||
conn.update({
|
db
|
||||||
table: 'xx',
|
.update(
|
||||||
data: {}, //要修改的数据
|
{
|
||||||
where: `id = 123`
|
table: 'xx'
|
||||||
})
|
},
|
||||||
|
{ xx: 1234 } //要插入的数据
|
||||||
|
)
|
||||||
|
.then(num => {
|
||||||
|
console.log(num)
|
||||||
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### 11. remove(condition)
|
||||||
|
|
||||||
### 10. remove(conf)
|
* condition `<Object>`
|
||||||
- conf `<Object>`
|
|
||||||
|
|
||||||
> 该方法与上面的`find`方法的使用类似,用于删除指定条件的数据; 具体请看下面代码;
|
> 该方法与上面的`update`方法的使用类似,用于删除指定条件的数据 ; 具体请看下面代码
|
||||||
> `该方法返回的是被删除的条目数量`
|
> ; `该方法返回的是被删除的条目数量`
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
|
|
||||||
// 如果修改成功,返回的是被删除的条目数量
|
// 如果修改成功,返回的是被删除的条目数量
|
||||||
conn.update({
|
db
|
||||||
table: 'xx',
|
.remove(
|
||||||
data: {}, //要修改的数据
|
{
|
||||||
where: `id = 123`
|
table: 'xx'
|
||||||
})
|
}
|
||||||
|
)
|
||||||
|
.then(num => {
|
||||||
|
console.log(num)
|
||||||
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
594
index.js
594
index.js
|
@ -4,531 +4,79 @@
|
||||||
* @date 2015-11-24 11:31:55
|
* @date 2015-11-24 11:31:55
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
"use strict";
|
'use strict'
|
||||||
require('es.shim')
|
require('es.shim')
|
||||||
let mysql = require('mysql')
|
const mysql = require('mysql')
|
||||||
/**
|
const Method = require('./lib/method')
|
||||||
* [parseWhere 格式化where条件]
|
|
||||||
* @param [array] arr [条件数组]
|
|
||||||
*/
|
|
||||||
|
|
||||||
function parseWhere(arr){
|
if (!Promise.defer) {
|
||||||
|
Promise.defer = function() {
|
||||||
if(typeof arr === 'string' && !!arr){
|
let obj = {}
|
||||||
return ' WHERE ' + arr
|
obj.promise = new this((yes, no) => {
|
||||||
}else if(Array.isArray(arr) && arr.length > 0){
|
obj.resolve = yes
|
||||||
|
obj.reject = no
|
||||||
let where = ''
|
})
|
||||||
for(let it of arr){
|
return obj
|
||||||
it.join = it.join || 'AND'
|
}
|
||||||
it.op = it.op || '='
|
}
|
||||||
|
class Mysqli {
|
||||||
let fixVal = it.val
|
/**
|
||||||
if(!/(^\(SELECT\s+.*\)$)|^`/.test(it.val) && !['IN', 'BETWEEN'].includes(it.op)){
|
* [constructor 构造数据库连接池]
|
||||||
|
*/
|
||||||
fixVal = mysql.escape(it.val)
|
constructor(config) {
|
||||||
}
|
if (!Array.isArray(config)) {
|
||||||
|
config = [config]
|
||||||
where += `${it.join.toUpperCase()} ${it.key} ${it.op} ${fixVal} `
|
|
||||||
}
|
|
||||||
|
|
||||||
where = ' WHERE ' + where.trim().replace(/^(AND|OR)/, ' ') + ' '
|
|
||||||
return where
|
|
||||||
|
|
||||||
}else{
|
|
||||||
return ' '
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//是否有从库
|
||||||
|
this.useSlaveDB = config.length > 1
|
||||||
|
this.pool = mysql.createPoolCluster()
|
||||||
|
|
||||||
|
config.forEach((item, i) => {
|
||||||
|
let { host, port, user, charset, passwd: password, db: database } = item
|
||||||
|
let name = i < 1 ? 'MASTER' : 'SLAVE' + i
|
||||||
|
|
||||||
|
charset = charset || 'utf8'
|
||||||
|
let collate =
|
||||||
|
charset + (charset === 'utf8mb4' ? '_unicode_ci' : '_general_ci')
|
||||||
|
|
||||||
|
this.pool.add(name, {
|
||||||
|
host,
|
||||||
|
port,
|
||||||
|
user,
|
||||||
|
charset,
|
||||||
|
collate,
|
||||||
|
password,
|
||||||
|
database
|
||||||
|
})
|
||||||
|
})
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
//对外的escape方法
|
||||||
|
static escape(val) {
|
||||||
|
return mysql.escape(val)
|
||||||
|
}
|
||||||
|
|
||||||
|
emit(fromSlave = false, db) {
|
||||||
|
const defer = Promise.defer()
|
||||||
|
const slave = fromSlave && this.useSlaveDB ? 'SLAVE*' : 'MASTER'
|
||||||
|
|
||||||
|
this.pool.getConnection(slave, (err, conn) => {
|
||||||
|
if (err) {
|
||||||
|
return defer.reject(`MySQL connect ${err}`)
|
||||||
|
}
|
||||||
|
if (db) {
|
||||||
|
conn.query('USE ' + db, err => {
|
||||||
|
if (err) {
|
||||||
|
return defer.reject('Select DB ' + err)
|
||||||
|
}
|
||||||
|
defer.resolve(conn)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return new Method(defer.promise)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Mysqli{
|
module.exports = Mysqli
|
||||||
|
|
||||||
/**
|
|
||||||
* [constructor 构造数据库连接]
|
|
||||||
*/
|
|
||||||
constructor(conf){
|
|
||||||
if(!Array.isArray(conf))
|
|
||||||
conf = [conf]
|
|
||||||
|
|
||||||
//是否有从库
|
|
||||||
this.slave = conf.length > 1
|
|
||||||
this.conn = null
|
|
||||||
|
|
||||||
this.pool = mysql.createPoolCluster()
|
|
||||||
let idx = 0
|
|
||||||
while(idx < conf.length){
|
|
||||||
let cf = conf[idx]
|
|
||||||
cf.charset = cf.charset || 'utf8'
|
|
||||||
let name = idx === 0 ? 'MASTER' : ('SLAVE' + idx)
|
|
||||||
|
|
||||||
idx++
|
|
||||||
this.pool.add(name, {
|
|
||||||
host: cf.host,
|
|
||||||
port: cf.port,
|
|
||||||
user: cf.user,
|
|
||||||
password: cf.passwd,
|
|
||||||
charset: cf.charset,
|
|
||||||
collate: cf.charset + ((cf.charset === 'utf8mb4') ? '_unicode_ci' : '_general_ci'),
|
|
||||||
database: cf.db
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//对外的escape方法
|
|
||||||
escape(val){
|
|
||||||
return mysql.escape(val)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//返回数据库列表
|
|
||||||
listDB(){
|
|
||||||
return new Promise((yes, no) => {
|
|
||||||
this.pool
|
|
||||||
.getConnection((err, conn) => {
|
|
||||||
if(err)
|
|
||||||
return no(`MySQL connect ${err}`)
|
|
||||||
|
|
||||||
conn.query('SHOW databases', (err, docs) => {
|
|
||||||
|
|
||||||
conn.release()
|
|
||||||
|
|
||||||
if(err)
|
|
||||||
return no('SHOW databases ' + err)
|
|
||||||
|
|
||||||
let res = []
|
|
||||||
for(let it of docs){
|
|
||||||
res.push(it.Database)
|
|
||||||
}
|
|
||||||
yes(res)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//选择database
|
|
||||||
useDB(db, slave){
|
|
||||||
slave = (slave && this.slave) ? 'SLAVE*' : 'MASTER'
|
|
||||||
|
|
||||||
this.conn = (async () => {
|
|
||||||
return await new Promise((yes, no) => {
|
|
||||||
|
|
||||||
this.pool
|
|
||||||
.getConnection(slave, (err, conn) => {
|
|
||||||
if(err)
|
|
||||||
return no(`MySQL connect ${err}`)
|
|
||||||
|
|
||||||
conn.query('USE ' + db, (err) => {
|
|
||||||
|
|
||||||
if(err)
|
|
||||||
return no('Select DB ' + err)
|
|
||||||
|
|
||||||
yes(conn)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
})
|
|
||||||
})()
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* [query sql语句执行]
|
|
||||||
* @param {[type]} sql [sql语句]
|
|
||||||
* @param {boolean} slave [是否从库]
|
|
||||||
*/
|
|
||||||
query(sql, slave){
|
|
||||||
slave = (slave && this.slave) ? 'SLAVE*' : 'MASTER'
|
|
||||||
|
|
||||||
if(typeof sql !== 'string')
|
|
||||||
return Promise.reject(`query error, argument sql must be string. ${typeof sql} given`)
|
|
||||||
|
|
||||||
return new Promise((yes, no) => {
|
|
||||||
|
|
||||||
if(this.conn){
|
|
||||||
this.conn.then(conn => {
|
|
||||||
|
|
||||||
conn.query(sql, (err, res) => {
|
|
||||||
conn.release()
|
|
||||||
this.conn = null
|
|
||||||
|
|
||||||
if(err)
|
|
||||||
return no(`Query ${err}; Last exec SQL: ${sql}`)
|
|
||||||
|
|
||||||
yes(res)
|
|
||||||
})
|
|
||||||
|
|
||||||
}).catch(no)
|
|
||||||
}else{
|
|
||||||
this.pool.getConnection(slave, (err, conn) => {
|
|
||||||
if(err)
|
|
||||||
return no(`MySQL connect ${err}`)
|
|
||||||
|
|
||||||
conn.query(sql, (err, res) => {
|
|
||||||
|
|
||||||
conn.release()
|
|
||||||
|
|
||||||
if(err)
|
|
||||||
return no(`Query ${err}; Last exec SQL: ${sql}`)
|
|
||||||
|
|
||||||
yes(res)
|
|
||||||
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* [find 基础的数据查询, 支持简单的联表查询]
|
|
||||||
* @param {[type]} conf [要查询的信息]
|
|
||||||
*
|
|
||||||
* e.g.
|
|
||||||
* .find({
|
|
||||||
* table: '',
|
|
||||||
* select: ['a', 'b'],
|
|
||||||
* where: [{ //数组格式,可以组成多个条件,默认查询全表 [可选]
|
|
||||||
* join: 'OR', //条件关系 AND, OR
|
|
||||||
* op: '>', //关系符,如 =, >, <, <=, >=
|
|
||||||
* key: 'aa',
|
|
||||||
* val: 23
|
|
||||||
* }],
|
|
||||||
* sort: { //排序, key是要排序的字段,value是排序方式, 1顺序,-1逆序 [可选]
|
|
||||||
* a: 1,
|
|
||||||
* b: -1
|
|
||||||
* },
|
|
||||||
* limit: { // 查询范围,可用于分页 [可选]
|
|
||||||
* start: 0,
|
|
||||||
* size: 10
|
|
||||||
* }
|
|
||||||
* })
|
|
||||||
*/
|
|
||||||
find(conf){
|
|
||||||
conf.slave = (conf.slave && this.slave) ? 'SLAVE*' : 'MASTER'
|
|
||||||
|
|
||||||
if(!conf.table)
|
|
||||||
return Promise.reject('Find Error: empty table')
|
|
||||||
|
|
||||||
let fields = '' //-------要返回的字段 ----------------
|
|
||||||
if(!conf.hasOwnProperty('select') || Object.empty(conf.select))
|
|
||||||
fields = '*'
|
|
||||||
else
|
|
||||||
fields = conf.select.join(',')
|
|
||||||
|
|
||||||
let sql = 'SELECT ' + fields
|
|
||||||
|
|
||||||
let table = '' //---------要查询的表 -----------------
|
|
||||||
if(typeof conf.table === 'string'){ //单表
|
|
||||||
table = ' FROM ' + conf.table
|
|
||||||
}else{ //联表
|
|
||||||
table = ' FROM ' + conf.table.master
|
|
||||||
for(let join of conf.table.unite){
|
|
||||||
table += ` LEFT JOIN ${join.table} ON ${join.on} `
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sql += table
|
|
||||||
|
|
||||||
//查询条件 ---------------------------------------
|
|
||||||
sql += parseWhere(conf.where)
|
|
||||||
|
|
||||||
let sort = '' //排序 ----------------------------------
|
|
||||||
if(conf.sort && typeof conf.sort === 'object'){
|
|
||||||
sort = ' ORDER BY '
|
|
||||||
for(let i in conf.sort){
|
|
||||||
let c = ''
|
|
||||||
if(conf.sort[i] === -1)
|
|
||||||
c = 'DESC'
|
|
||||||
|
|
||||||
sort += `${i} ${c},`
|
|
||||||
}
|
|
||||||
sort = sort.slice(0, -1)
|
|
||||||
}
|
|
||||||
sql += sort
|
|
||||||
|
|
||||||
let limit = '' //--------查询范围 ----------
|
|
||||||
if(conf.hasOwnProperty('limit')){
|
|
||||||
let start = conf.limit.start || 0
|
|
||||||
let size = (conf.limit.size && conf.limit.size > 0) ? conf.limit.size : 1
|
|
||||||
limit = ` LIMIT ${start},${size} `
|
|
||||||
}
|
|
||||||
sql += limit
|
|
||||||
|
|
||||||
return new Promise((yes, no) => {
|
|
||||||
|
|
||||||
if(this.conn){
|
|
||||||
this.conn.then(conn => {
|
|
||||||
|
|
||||||
conn.query(sql, (err, res) => {
|
|
||||||
conn.release()
|
|
||||||
this.conn = null
|
|
||||||
|
|
||||||
if(err)
|
|
||||||
return no(`Find ${err}; Last exec SQL: ${sql}`)
|
|
||||||
|
|
||||||
yes(res)
|
|
||||||
})
|
|
||||||
|
|
||||||
}).catch(no)
|
|
||||||
}else{
|
|
||||||
this.pool.getConnection(conf.slave, (err, conn) => {
|
|
||||||
if(err)
|
|
||||||
return no(`MySQL connect ${err}`)
|
|
||||||
|
|
||||||
conn.query(sql, (err, res) => {
|
|
||||||
|
|
||||||
conn.release()
|
|
||||||
|
|
||||||
if(err)
|
|
||||||
return no(`Find ${err}; Last exec SQL: ${sql}`)
|
|
||||||
|
|
||||||
yes(res)
|
|
||||||
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* [findOne 查找一条记录, 参数同 find]
|
|
||||||
*/
|
|
||||||
findOne(conf){
|
|
||||||
let res = (async () => this.find({
|
|
||||||
table: conf.table,
|
|
||||||
select: conf.select || [],
|
|
||||||
where: conf.where || '',
|
|
||||||
sort: conf.sort,
|
|
||||||
slave: conf.slave,
|
|
||||||
limit: {start: 0, size: 1}
|
|
||||||
}))()
|
|
||||||
return new Promise((yes, no) => {
|
|
||||||
res.then(list => {
|
|
||||||
yes(list[0] || null)
|
|
||||||
}, no)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* [count 计算结果总数, 参数同findOne]
|
|
||||||
*/
|
|
||||||
count(conf){
|
|
||||||
let res = (async () => this.find({
|
|
||||||
table: conf.table,
|
|
||||||
select: ['count(*) AS total'],
|
|
||||||
slave: conf.slave,
|
|
||||||
where: conf.where || ''
|
|
||||||
}))()
|
|
||||||
return new Promise((yes, no) => {
|
|
||||||
res.then(list => {
|
|
||||||
yes(list[0] && list[0].total || 0)
|
|
||||||
}, no)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* [insert 插入数据,单条]
|
|
||||||
* @param {[object]} conf [要插入的信息,{table: '', data: {}} ]
|
|
||||||
*
|
|
||||||
* eg.
|
|
||||||
* .insert({
|
|
||||||
* table: 'test',
|
|
||||||
* data: {aa: 123, bb: 456}
|
|
||||||
* }, function(id){...})
|
|
||||||
*/
|
|
||||||
insert(conf){
|
|
||||||
conf.slave = (conf.slave && this.slave) ? 'SLAVE*' : 'MASTER'
|
|
||||||
|
|
||||||
if(!conf.table)
|
|
||||||
return Promise.reject('Insert Error: empty table')
|
|
||||||
|
|
||||||
let sql = 'INSERT INTO ' + conf.table + ' ('
|
|
||||||
let keys = []
|
|
||||||
let vals = []
|
|
||||||
|
|
||||||
for(let i in conf.data){
|
|
||||||
keys.push(i)
|
|
||||||
vals.push(mysql.escape(conf.data[i]))
|
|
||||||
}
|
|
||||||
sql += `${keys.join(',')}) VALUES (${vals.join(',')})`
|
|
||||||
|
|
||||||
return new Promise((yes, no) => {
|
|
||||||
|
|
||||||
if(this.conn){
|
|
||||||
this.conn.then(conn => {
|
|
||||||
|
|
||||||
conn.query(sql, (err, res) => {
|
|
||||||
conn.release()
|
|
||||||
this.conn = null
|
|
||||||
|
|
||||||
if(err)
|
|
||||||
return no(`Insert ${err}; Last exec SQL: ${sql}`)
|
|
||||||
|
|
||||||
yes(res.insertId)
|
|
||||||
})
|
|
||||||
|
|
||||||
}).catch(no)
|
|
||||||
}else{
|
|
||||||
this.pool.getConnection(conf.slave, (err, conn) => {
|
|
||||||
if(err)
|
|
||||||
return no(`MySQL connect ${err}`)
|
|
||||||
|
|
||||||
conn.query(sql, (err, res) => {
|
|
||||||
|
|
||||||
conn.release()
|
|
||||||
|
|
||||||
if(err)
|
|
||||||
return no(`Insert ${err}; Last exec SQL: ${sql}`)
|
|
||||||
|
|
||||||
yes(res.insertId)
|
|
||||||
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* [insert 基础的数据修改]
|
|
||||||
* @param {[object]} conf [要修改的信息, {table: '', where: [], data: {}}]
|
|
||||||
*
|
|
||||||
* eg.
|
|
||||||
* .update({
|
|
||||||
* table: 'test',
|
|
||||||
* data: {aa: 123, bb: 456},
|
|
||||||
* where: [{ //数组格式,可以组成多个条件
|
|
||||||
* join: 'OR', //条件关系 AND, OR
|
|
||||||
* op: '>', //关系符,如 =, >, <, <=, >=
|
|
||||||
* key: 'aa',
|
|
||||||
* val: 23
|
|
||||||
* }]
|
|
||||||
* }, function(nums){...})
|
|
||||||
*/
|
|
||||||
update(conf){
|
|
||||||
conf.slave = (conf.slave && this.slave) ? 'SLAVE*' : 'MASTER'
|
|
||||||
|
|
||||||
if(!conf.table)
|
|
||||||
return Promise.reject('Update Error: empty table')
|
|
||||||
|
|
||||||
let sql = 'UPDATE ' + conf.table + ' SET '
|
|
||||||
|
|
||||||
let fields = [] //要更新的字段
|
|
||||||
for(let i in conf.data){
|
|
||||||
fields.push(i + ' = ' + mysql.escape(conf.data[i]))
|
|
||||||
}
|
|
||||||
sql += fields.join(',')
|
|
||||||
sql += parseWhere(conf.where)
|
|
||||||
|
|
||||||
return new Promise((yes, no) => {
|
|
||||||
|
|
||||||
if(this.conn){
|
|
||||||
this.conn.then(conn => {
|
|
||||||
|
|
||||||
conn.query(sql, (err, res) => {
|
|
||||||
conn.release()
|
|
||||||
this.conn = null
|
|
||||||
|
|
||||||
if(err)
|
|
||||||
return no(`Update ${err}; Last exec SQL: ${sql}`)
|
|
||||||
|
|
||||||
yes(res.affectedRows)
|
|
||||||
})
|
|
||||||
|
|
||||||
}).catch(no)
|
|
||||||
}else{
|
|
||||||
this.pool.getConnection(conf.slave, (err, conn) => {
|
|
||||||
if(err)
|
|
||||||
return no(`MySQL connect ${err}`)
|
|
||||||
|
|
||||||
conn.query(sql, (err, res) => {
|
|
||||||
|
|
||||||
conn.release()
|
|
||||||
|
|
||||||
if(err)
|
|
||||||
return no(`Update ${err}; Last exec SQL: ${sql}`)
|
|
||||||
|
|
||||||
yes(res.affectedRows)
|
|
||||||
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* [remove 基础的数据删除]
|
|
||||||
* @param {[type]} conf [要删除的信息, {table: '', where: []}]
|
|
||||||
*
|
|
||||||
* eg.
|
|
||||||
* .update({
|
|
||||||
* table: 'test',
|
|
||||||
* where: [{ //数组格式,可以组成多个条件
|
|
||||||
* join: 'OR', //条件关系 AND, OR
|
|
||||||
* op: '>', //关系符,如 =, >, <, <=, >=
|
|
||||||
* key: 'aa',
|
|
||||||
* val: 23
|
|
||||||
* }]
|
|
||||||
* }, function(nums){...})
|
|
||||||
*/
|
|
||||||
remove(conf){
|
|
||||||
conf.slave = (conf.slave && this.slave) ? 'SLAVE*' : 'MASTER'
|
|
||||||
|
|
||||||
if(!conf.table)
|
|
||||||
return Promise.reject('Remove Error: empty table')
|
|
||||||
|
|
||||||
let sql = 'DELETE FROM ' + conf.table
|
|
||||||
|
|
||||||
if(conf.where)
|
|
||||||
sql += parseWhere(conf.where)
|
|
||||||
|
|
||||||
return new Promise((yes, no) => {
|
|
||||||
|
|
||||||
if(this.conn){
|
|
||||||
this.conn.then(conn => {
|
|
||||||
|
|
||||||
conn.query(sql, (err, res) => {
|
|
||||||
conn.release()
|
|
||||||
this.conn = null
|
|
||||||
|
|
||||||
if(err)
|
|
||||||
return no(`Remove ${err}; Last exec SQL: ${sql}`)
|
|
||||||
|
|
||||||
yes(res.affectedRows)
|
|
||||||
})
|
|
||||||
|
|
||||||
}).catch(no)
|
|
||||||
}else{
|
|
||||||
this.pool.getConnection(conf.slave, (err, conn) => {
|
|
||||||
if(err)
|
|
||||||
return no(`MySQL connect ${err}`)
|
|
||||||
|
|
||||||
conn.query(sql, (err, res) => {
|
|
||||||
|
|
||||||
conn.release()
|
|
||||||
|
|
||||||
if(err)
|
|
||||||
return no(`Remove ${err}; Last exec SQL: ${sql}`)
|
|
||||||
|
|
||||||
yes(res.affectedRows)
|
|
||||||
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
module.exports = Mysqli
|
|
||||||
|
|
|
@ -0,0 +1,216 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @authors yutent (yutent@doui.cc)
|
||||||
|
* @date 2017-12-14 14:01:03
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
|
||||||
|
const { escape } = require('mysql')
|
||||||
|
const parser = require('./parser')
|
||||||
|
|
||||||
|
class Method {
|
||||||
|
constructor(defer) {
|
||||||
|
this.defer = defer
|
||||||
|
}
|
||||||
|
|
||||||
|
listDb() {
|
||||||
|
return this.defer.then(conn => {
|
||||||
|
const defer = Promise.defer()
|
||||||
|
|
||||||
|
conn.query('SHOW databases', (err, row) => {
|
||||||
|
if (err) {
|
||||||
|
return defer.reject('SHOW databases ' + err)
|
||||||
|
}
|
||||||
|
defer.resolve(row.map(it => it.Database))
|
||||||
|
// conn.release()
|
||||||
|
})
|
||||||
|
|
||||||
|
return defer.promise
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
//返回数据表
|
||||||
|
listTable() {
|
||||||
|
return this.defer.then(conn => {
|
||||||
|
const defer = Promise.defer()
|
||||||
|
|
||||||
|
conn.query('SHOW tables', (err, row) => {
|
||||||
|
if (err) {
|
||||||
|
return defer.reject('SHOW tables ' + err)
|
||||||
|
}
|
||||||
|
defer.resolve(row.map(it => Object.values(it)[0]))
|
||||||
|
// conn.release()
|
||||||
|
})
|
||||||
|
|
||||||
|
return defer.promise
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [query sql语句执行]
|
||||||
|
* @param {[type]} sql [sql语句]
|
||||||
|
*/
|
||||||
|
query(sql) {
|
||||||
|
if (typeof sql !== 'string')
|
||||||
|
return Promise.reject(
|
||||||
|
`Query error, argument sql must be string. ${typeof sql} given`
|
||||||
|
)
|
||||||
|
|
||||||
|
return this.defer.then(conn => {
|
||||||
|
const defer = Promise.defer()
|
||||||
|
|
||||||
|
conn.query(sql, (err, result) => {
|
||||||
|
if (err) {
|
||||||
|
return defer.reject(
|
||||||
|
`Query ${err}; \nLast exec SQL:「${this.lastSql}」`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
defer.resolve(result)
|
||||||
|
})
|
||||||
|
return defer.promise
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
filter(condition, select) {
|
||||||
|
const { table, leftJoin, rightJoin, join, where, sort, limit } = condition
|
||||||
|
|
||||||
|
if (!table) {
|
||||||
|
return Promise.reject('Filter Error: empty table')
|
||||||
|
}
|
||||||
|
|
||||||
|
let sql = parser.select(select)
|
||||||
|
sql += `FROM \`${table}\` `
|
||||||
|
if (leftJoin) {
|
||||||
|
sql += parser.leftJoin(leftJoin)
|
||||||
|
}
|
||||||
|
if (rightJoin) {
|
||||||
|
sql += parser.rightJoin(rightJoin)
|
||||||
|
}
|
||||||
|
if (join) {
|
||||||
|
sql += parser.join(join)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (where) {
|
||||||
|
sql += parser.where(where)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sort) {
|
||||||
|
sql += parser.sort(sort)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (limit) {
|
||||||
|
sql += parser.limit(limit)
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.defer.then(conn => {
|
||||||
|
const defer = Promise.defer()
|
||||||
|
|
||||||
|
conn.query(sql, (err, result) => {
|
||||||
|
if (err) {
|
||||||
|
return defer.reject(
|
||||||
|
`Filter ${err}; \nLast exec SQL:「${this.lastSql}」`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
defer.resolve(result)
|
||||||
|
})
|
||||||
|
return defer.promise
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
filterOne(condition, select) {
|
||||||
|
condition.limit = [1]
|
||||||
|
return this.filter(condition, select).then(row => {
|
||||||
|
return row[0] || null
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
count(condition) {
|
||||||
|
delete condition.limit
|
||||||
|
return this.filter(condition, ['count(*) AS total']).then(row => {
|
||||||
|
return (row[0] && row[0].total) || 0
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
insert({ table }, doc) {
|
||||||
|
if (!table) {
|
||||||
|
return Promise.reject('Insert Error: empty table')
|
||||||
|
}
|
||||||
|
|
||||||
|
let sql = `INSERT INTO \`${table}\` `
|
||||||
|
let keys = []
|
||||||
|
let vals = []
|
||||||
|
|
||||||
|
for (let i in doc) {
|
||||||
|
keys.push(i)
|
||||||
|
vals.push(escape(doc[i]))
|
||||||
|
}
|
||||||
|
sql += `(${keys.join(',')}) VALUES (${vals.join(',')})`
|
||||||
|
|
||||||
|
return this.defer.then(conn => {
|
||||||
|
const defer = Promise.defer()
|
||||||
|
|
||||||
|
conn.query(sql, (err, result) => {
|
||||||
|
if (err) {
|
||||||
|
return defer.reject(`Insert ${err}; Last exec SQL: ${sql}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer.resolve(result.insertId)
|
||||||
|
})
|
||||||
|
|
||||||
|
return defer.promise
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
update({ table, where }, doc) {
|
||||||
|
if (!table) {
|
||||||
|
return Promise.reject('Update Error: empty table')
|
||||||
|
}
|
||||||
|
|
||||||
|
let sql = `UPDATE \`${table}\` SET `
|
||||||
|
|
||||||
|
let fields = [] //要更新的字段
|
||||||
|
for (let i in doc) {
|
||||||
|
fields.push(i + ' = ' + escape(doc[i]))
|
||||||
|
}
|
||||||
|
sql += fields.join(',')
|
||||||
|
sql += parser.where(where)
|
||||||
|
|
||||||
|
return this.defer.then(conn => {
|
||||||
|
const defer = Promise.defer()
|
||||||
|
conn.query(sql, (err, res) => {
|
||||||
|
if (err) {
|
||||||
|
return defer.reject(`Update ${err}; Last exec SQL: ${sql}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer.resolve(res.affectedRows)
|
||||||
|
})
|
||||||
|
return defer.promise
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
remove({ table, where }) {
|
||||||
|
if (!table) {
|
||||||
|
return Promise.reject('Remove Error: empty table')
|
||||||
|
}
|
||||||
|
|
||||||
|
let sql = `DELETE FROM \`${table}\` `
|
||||||
|
|
||||||
|
if (where) {
|
||||||
|
sql += parser.where(where)
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.defer.then(conn => {
|
||||||
|
const defer = Promise.defer()
|
||||||
|
conn.query(sql, (err, res) => {
|
||||||
|
if (err) {
|
||||||
|
return defer.reject(`Remove ${err}; Last exec SQL: ${sql}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer.resolve(res.affectedRows)
|
||||||
|
})
|
||||||
|
return defer.promise
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Method
|
|
@ -0,0 +1,96 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @authors yutent (yutent@doui.cc)
|
||||||
|
* @date 2017-12-14 02:41:15
|
||||||
|
* @version $Id$
|
||||||
|
*/
|
||||||
|
const { escape } = require('mysql')
|
||||||
|
|
||||||
|
/**
|
||||||
|
* [parseWhere 格式化where条件]
|
||||||
|
* @param [array] arr [条件数组]
|
||||||
|
*/
|
||||||
|
|
||||||
|
function parseWhere(arr) {
|
||||||
|
if (typeof arr === 'string' && !!arr) {
|
||||||
|
return ' WHERE ' + arr
|
||||||
|
} else if (Array.isArray(arr) && arr.length > 0) {
|
||||||
|
let where = ''
|
||||||
|
for (let it of arr) {
|
||||||
|
it.join = it.join || 'AND'
|
||||||
|
it.op = it.op || '='
|
||||||
|
|
||||||
|
let fixVal = it.val
|
||||||
|
if (
|
||||||
|
!/(^\(SELECT\s+.*\)$)|^`/.test(it.val) &&
|
||||||
|
!['IN', 'BETWEEN'].includes(it.op)
|
||||||
|
) {
|
||||||
|
fixVal = escape(it.val)
|
||||||
|
}
|
||||||
|
|
||||||
|
where += `${it.join.toUpperCase()} ${it.key} ${it.op} ${fixVal} `
|
||||||
|
}
|
||||||
|
|
||||||
|
where = ' WHERE ' + where.trim().replace(/^(AND|OR)/, ' ') + ' '
|
||||||
|
return where
|
||||||
|
} else {
|
||||||
|
return ' '
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const Parser = {
|
||||||
|
leftJoin(tables) {
|
||||||
|
let sql = ''
|
||||||
|
for (let it of tables) {
|
||||||
|
sql += ` LEFT JOIN ${it[0]} ON ${it[1]} `
|
||||||
|
}
|
||||||
|
return sql
|
||||||
|
},
|
||||||
|
|
||||||
|
rightJoin(tables) {
|
||||||
|
let sql = ''
|
||||||
|
for (let it of tables) {
|
||||||
|
sql += ` RIGHT JOIN ${it[0]} ON ${it[1]} `
|
||||||
|
}
|
||||||
|
return sql
|
||||||
|
},
|
||||||
|
|
||||||
|
join(tables) {
|
||||||
|
let sql = ''
|
||||||
|
for (let it of tables) {
|
||||||
|
sql += ` JOIN ${it[0]} ON ${it[1]} `
|
||||||
|
}
|
||||||
|
return sql
|
||||||
|
},
|
||||||
|
|
||||||
|
where(where = '') {
|
||||||
|
return parseWhere(where)
|
||||||
|
},
|
||||||
|
|
||||||
|
select(arr = ['*']) {
|
||||||
|
return `SELECT ${arr.join(',')} `
|
||||||
|
},
|
||||||
|
|
||||||
|
// 排序 ----------------------------------
|
||||||
|
sort(obj = {}) {
|
||||||
|
let sort = ''
|
||||||
|
for (let i in obj) {
|
||||||
|
let c = ''
|
||||||
|
if (obj[i] === -1) {
|
||||||
|
c = 'DESC'
|
||||||
|
}
|
||||||
|
sort += `${i} ${c},`
|
||||||
|
}
|
||||||
|
if (sort) {
|
||||||
|
return ' ORDER BY ' + sort.slice(0, -1)
|
||||||
|
} else {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
limit(...args) {
|
||||||
|
return ` LIMIT ${args.join(',')} `
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Parser
|
Loading…
Reference in New Issue