Skip to content

Commit 9ea4f71

Browse files
committed
Init commit
1 parent 03eaf9e commit 9ea4f71

File tree

7 files changed

+567
-0
lines changed

7 files changed

+567
-0
lines changed

.eslintrc

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"extends": "think"
3+
}

index.js

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
const Abstract = require('think-model-abstract');
2+
const Query = require('./lib/query.js');
3+
const Schema = require('./lib/schema.js');
4+
5+
const QUERY = Symbol('think-model-query');
6+
const SCHEMA = Symbol('think-model-schema');
7+
8+
module.exports = class Mysql extends Abstract {
9+
/**
10+
* get query instance
11+
*/
12+
get query() {
13+
if (this[QUERY]) return this[QUERY];
14+
this[QUERY] = new Query(this.model.config);
15+
return this[QUERY];
16+
}
17+
/**
18+
* get schema instance
19+
*/
20+
get schema() {
21+
if (this[SCHEMA]) return this[SCHEMA];
22+
this[SCHEMA] = new Schema(this.model.config, this.model.schema, this.model.tableName);
23+
return this[SCHEMA];
24+
}
25+
};

lib/parser.js

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
const helper = require('think-helper');
2+
const {Parser} = require('think-model-abstract');
3+
4+
module.exports = class SQLiteParser extends Parser {
5+
/**
6+
* escape string
7+
* @param {String} str []
8+
* @return {String} []
9+
*/
10+
escapeString(str) {
11+
return str.replace(/'/g, '\'\'');
12+
}
13+
/**
14+
* parse limit
15+
* @param {Array} limit []
16+
* @return {String} []
17+
*/
18+
parseLimit(limit) {
19+
if (helper.isEmpty(limit)) return '';
20+
if (helper.isNumber(limit)) {
21+
return ` LIMIT ${limit}`;
22+
}
23+
if (helper.isString(limit)) {
24+
limit = limit.split(/\s*,\s*/);
25+
}
26+
if (limit[1]) {
27+
return ' LIMIT ' + (limit[1] | 0) + ' OFFSET ' + (limit[0] | 0);
28+
}
29+
return ' LIMIT ' + (limit[0] | 0);
30+
}
31+
};

lib/query.js

+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
const {Query} = require('think-model-abstract');
2+
const helper = require('think-helper');
3+
const Parser = require('./parser.js');
4+
const SQLiteSocket = require('./socket.js');
5+
6+
const PARSER = Symbol('think-model-sqlite-parser');
7+
const SOCKET = Symbol('think-model-sqlite-socket');
8+
9+
/**
10+
* mysql query
11+
*/
12+
module.exports = class SQLiteQuery extends Query {
13+
/**
14+
* get parser instance
15+
*/
16+
get parser() {
17+
if (this[PARSER]) return this[PARSER];
18+
this[PARSER] = new Parser(this.config);
19+
return this[PARSER];
20+
}
21+
/**
22+
* get socket
23+
* @param {String|Object} sql
24+
*/
25+
socket(sql) {
26+
if (sql && this.config.parser) {
27+
const config = Object.assign({}, this.config, this.config.parser(sql));
28+
return SQLiteSocket.getInstance(config);
29+
}
30+
if (this[SOCKET]) return this[SOCKET];
31+
this[SOCKET] = SQLiteSocket.getInstance(this.config);
32+
return this[SOCKET];
33+
}
34+
/**
35+
* query sql
36+
*/
37+
query(sqlOptions, connection) {
38+
const sql = helper.isString(sqlOptions) ? sqlOptions : sqlOptions.sql;
39+
this.lastSql = sql;
40+
return this.socket(sql).query(sqlOptions, connection);
41+
}
42+
/**
43+
* execute sql
44+
*/
45+
execute(sqlOptions, connection) {
46+
const sql = helper.isString(sqlOptions) ? sqlOptions : sqlOptions.sql;
47+
this.lastSql = sql;
48+
return this.socket(sql).execute(sqlOptions, connection).then(data => {
49+
if (data.insertId) {
50+
this.lastInsertId = data.insertId;
51+
}
52+
return data.affectedRows || 0;
53+
});
54+
}
55+
/**
56+
* add data list
57+
* @param {Array} data
58+
* @param {Object} options
59+
*/
60+
addMany(data, options) {
61+
return super.addMany(data, options).then(ret => {
62+
return ret;
63+
});
64+
}
65+
66+
startTrans(connection) {
67+
return this.socket().startTrans(connection).then(connection => {
68+
this.connection = connection;
69+
return connection;
70+
});
71+
}
72+
73+
commit(connection = this.connection) {
74+
return this.socket().commit();
75+
}
76+
77+
rollback(connection = this.connection) {
78+
return this.socket().rollback(connection);
79+
}
80+
81+
transaction(fn, connection) {
82+
return this.socket().transaction(fn, connection);
83+
}
84+
};

lib/schema.js

+128
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
const helper = require('think-helper');
2+
const {Schema} = require('think-model-abstract');
3+
const Debounce = require('think-debounce');
4+
const Query = require('./query.js');
5+
const Parser = require('./parser.js');
6+
7+
const QUERY = Symbol('think-model-sqlite-query');
8+
const PARSER = Symbol('think-model-sqlite-parser');
9+
const GET_SCHEMA = Symbol('think-model-sqlite-schema');
10+
const debounce = new Debounce();
11+
12+
/**
13+
* mysql Schema
14+
*/
15+
module.exports = class MysqlSchema extends Schema {
16+
/**
17+
* get query instance
18+
*/
19+
get query() {
20+
if (this[QUERY]) return this[QUERY];
21+
this[QUERY] = new Query(this.config);
22+
return this[QUERY];
23+
}
24+
/**
25+
* get parset instance
26+
*/
27+
get parser() {
28+
if (this[PARSER]) return this[PARSER];
29+
this[PARSER] = new Parser(this.config);
30+
return this[PARSER];
31+
}
32+
_getItemSchemaValidate(fieldData) {
33+
const validate = {};
34+
switch (fieldData.tinyType) {
35+
case 'tinyint':
36+
validate.int = {min: 0, max: 255};
37+
break;
38+
case 'smallint':
39+
validate.int = {min: fieldData.unsigned ? 0 : -32768, max: 32767};
40+
break;
41+
case 'int':
42+
validate.int = {min: fieldData.unsigned ? 0 : -2147483648, max: 2147483647};
43+
break;
44+
// case 'bigint':
45+
// validate.int = {min: fieldData.unique ? 0 : -9223372036854775808, max: 9223372036854775807};
46+
// break;
47+
case 'date':
48+
validate.date = true;
49+
break;
50+
};
51+
return validate;
52+
}
53+
_parseItemSchema(item) {
54+
const fieldData = {
55+
name: item.name,
56+
type: item.type,
57+
required: !!item.notnull,
58+
default: item.dflt_value || '',
59+
primary: !!item.pk,
60+
unique: item.unique,
61+
autoIncrement: false
62+
};
63+
const pos = item.Type.indexOf('(');
64+
fieldData.tinyType = (pos === -1 ? item.Type : item.Type.slice(0, pos)).toLowerCase();
65+
if (fieldData.default && fieldData.tinyType.indexOf('int') > -1) {
66+
fieldData.default = parseInt(fieldData.default);
67+
}
68+
if (item.Type.indexOf('unsigned') > -1) {
69+
fieldData.unsigned = true;
70+
}
71+
fieldData.validate = this._getItemSchemaValidate(fieldData);
72+
return fieldData;
73+
}
74+
/**
75+
* get table schema
76+
* @param {String} table
77+
*/
78+
getSchema(table = this.table) {
79+
const _getSchema = () => {
80+
return debounce.debounce(`getTable${table}Schema`, () => {
81+
table = this.parser.parseKey(table);
82+
const fieldsPromise = this.query.query(`PRAGMA table_info( ${table} )`);
83+
const indexesPromise = this.query.query(`PRAGMA INDEX_LIST( ${table} )`).then(list => {
84+
const indexes = {};
85+
const promises = list.map(item => {
86+
if (item.unique) return;
87+
return this.query.query(`PRAGMA index_info( ${item.name} )`).then(data => {
88+
data.forEach(item => {
89+
indexes[item.name] = {unique: true};
90+
});
91+
});
92+
});
93+
return Promise.all(promises).then(() => indexes);
94+
});
95+
return Promise.all([fieldsPromise, indexesPromise]).then(([fields, indexes]) => {
96+
const ret = {};
97+
fields.forEach(item => {
98+
item.unique = indexes[item.name].unique;
99+
ret[item.name] = this._parseItemSchema(item);
100+
});
101+
return helper.extend(ret, this.schema);
102+
});
103+
});
104+
};
105+
if (this[GET_SCHEMA] && this[GET_SCHEMA][table]) {
106+
return Promise.resolve(this[GET_SCHEMA][table]);
107+
}
108+
return _getSchema().then(data => {
109+
if (!this[GET_SCHEMA]) {
110+
this[GET_SCHEMA] = {};
111+
}
112+
this[GET_SCHEMA][table] = data;
113+
return data;
114+
});
115+
}
116+
/**
117+
* parse type
118+
* @param {String} tinyType
119+
* @param {Mixed} value
120+
*/
121+
parseType(tinyType, value) {
122+
if (tinyType === 'enum' || tinyType === 'set' || tinyType === 'bigint') return value;
123+
if (tinyType.indexOf('int') > -1) return parseInt(value, 10);
124+
if (['double', 'float', 'decimal'].indexOf(tinyType) > -1) return parseFloat(value, 10);
125+
if (tinyType === 'bool') return value ? 1 : 0;
126+
return value;
127+
}
128+
};

0 commit comments

Comments
 (0)