mm_mysql 2.4.7 → 2.4.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +5 -5
- package/sql.js +6 -155
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mm_mysql",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.9",
|
|
4
4
|
"description": "这是超级美眉mysql帮助函数模块,用于便捷操作mysql,使用await方式,可以避免嵌套函数",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"dependencies": {
|
|
7
|
-
"mm_expand": "^2.4.
|
|
8
|
-
"mysql2": "^3.
|
|
7
|
+
"mm_expand": "^2.4.7",
|
|
8
|
+
"mysql2": "^3.23.2",
|
|
9
9
|
"sqlstring": "^2.3.3"
|
|
10
10
|
},
|
|
11
11
|
"scripts": {
|
|
@@ -36,8 +36,8 @@
|
|
|
36
36
|
"node": ">=12.0.0"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
|
-
"eslint": "^10.
|
|
40
|
-
"eslint-plugin-jsdoc": "^63.
|
|
39
|
+
"eslint": "^10.8.0",
|
|
40
|
+
"eslint-plugin-jsdoc": "^63.3.3",
|
|
41
41
|
"mm_eslint": "^1.7.5"
|
|
42
42
|
}
|
|
43
43
|
}
|
package/sql.js
CHANGED
|
@@ -1092,9 +1092,10 @@ Sql.prototype._tplQueryNoSep = function (param_dt, sql_dt) {
|
|
|
1092
1092
|
let conds = [];
|
|
1093
1093
|
for (let key in param_dt) {
|
|
1094
1094
|
value = escape(param_dt[key]);
|
|
1095
|
-
|
|
1095
|
+
let sql = sql_dt[key];
|
|
1096
|
+
if (sql) {
|
|
1096
1097
|
// 使用直接替换方式,避免模板替换错误
|
|
1097
|
-
conds.push(
|
|
1098
|
+
conds.push(sql.replaceAll('{0}', value.trim("'")));
|
|
1098
1099
|
} else {
|
|
1099
1100
|
conds.push(escapeId(key) + ' = ' + value);
|
|
1100
1101
|
}
|
|
@@ -1185,9 +1186,10 @@ Sql.prototype.tplBody = function (param_dt, sql_dt) {
|
|
|
1185
1186
|
} else {
|
|
1186
1187
|
for (let key in param_dt) {
|
|
1187
1188
|
let value = escape(param_dt[key]);
|
|
1188
|
-
|
|
1189
|
+
let sql = sql_dt[key];
|
|
1190
|
+
if (sql) {
|
|
1189
1191
|
// 使用直接替换方式,避免模板替换错误
|
|
1190
|
-
let replaced =
|
|
1192
|
+
let replaced = sql.replaceAll('{0}', value.trim("'"));
|
|
1191
1193
|
parts.push(replaced.replace(/\+ -/g, '- ').replace(/- -/g, '+ '));
|
|
1192
1194
|
} else {
|
|
1193
1195
|
parts.push(escapeId(key) + ' = ' + value);
|
|
@@ -1749,157 +1751,6 @@ Sql.prototype._parseSqlStatements = function (sql) {
|
|
|
1749
1751
|
return stmts;
|
|
1750
1752
|
};
|
|
1751
1753
|
|
|
1752
|
-
/**
|
|
1753
|
-
* @description 备份数据库到 SQL 文件
|
|
1754
|
-
* @param {string} file 备份文件路径
|
|
1755
|
-
* @param {boolean} create 是否导出创建表语句,默认为false
|
|
1756
|
-
* @returns {Promise<boolean>} 备份是否成功
|
|
1757
|
-
*/
|
|
1758
|
-
Sql.prototype.backup = async function (file, create = false) {
|
|
1759
|
-
if (!file || typeof file !== 'string') {
|
|
1760
|
-
throw new TypeError('文件路径必须为字符串');
|
|
1761
|
-
}
|
|
1762
|
-
|
|
1763
|
-
if (!this.table) {
|
|
1764
|
-
throw new TypeError('表名未设置');
|
|
1765
|
-
}
|
|
1766
|
-
|
|
1767
|
-
// 获取所有数据
|
|
1768
|
-
let data = await this.getSql('', '', '*');
|
|
1769
|
-
|
|
1770
|
-
if (!data || !Array.isArray(data)) {
|
|
1771
|
-
throw new Error('获取数据失败');
|
|
1772
|
-
}
|
|
1773
|
-
|
|
1774
|
-
// 构建 SQL 语句
|
|
1775
|
-
let sql_content = '';
|
|
1776
|
-
|
|
1777
|
-
// 添加表结构(简化版,实际应用中可能需要更复杂的表结构导出)
|
|
1778
|
-
sql_content += `-- 备份表: ${this.table}\n`;
|
|
1779
|
-
sql_content += `-- 备份时间: ${new Date().toISOString()}\n\n`;
|
|
1780
|
-
|
|
1781
|
-
// 如果create为true,添加创建表语句
|
|
1782
|
-
if (create) {
|
|
1783
|
-
let create_table_sql = await this._getCreateTableSql();
|
|
1784
|
-
if (create_table_sql) {
|
|
1785
|
-
sql_content += create_table_sql + '\n\n';
|
|
1786
|
-
}
|
|
1787
|
-
}
|
|
1788
|
-
|
|
1789
|
-
// 添加数据插入语句
|
|
1790
|
-
for (let row of data) {
|
|
1791
|
-
let keys = Object.keys(row).map(key => this.escapeId(key)).join(', ');
|
|
1792
|
-
let values = Object.values(row).map(value => this.escape(value)).join(', ');
|
|
1793
|
-
sql_content += `INSERT INTO \`${this.table}\` (${keys}) VALUES (${values});\n`;
|
|
1794
|
-
}
|
|
1795
|
-
|
|
1796
|
-
// 写入文件(这里需要文件系统模块,实际使用时需要引入 fs)
|
|
1797
|
-
let fs = require('fs');
|
|
1798
|
-
let path = require('path');
|
|
1799
|
-
|
|
1800
|
-
// 确保目录存在
|
|
1801
|
-
let dir = path.dirname(file);
|
|
1802
|
-
if (!fs.existsSync(dir)) {
|
|
1803
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
1804
|
-
}
|
|
1805
|
-
|
|
1806
|
-
fs.writeFileSync(file, sql_content, 'utf8');
|
|
1807
|
-
|
|
1808
|
-
return true;
|
|
1809
|
-
};
|
|
1810
|
-
|
|
1811
|
-
/**
|
|
1812
|
-
* @description 从 SQL 文件恢复数据库
|
|
1813
|
-
* @param {string} file 恢复文件路径
|
|
1814
|
-
* @returns {Promise<boolean>} 恢复是否成功
|
|
1815
|
-
*/
|
|
1816
|
-
Sql.prototype.restore = async function (file) {
|
|
1817
|
-
if (!file || typeof file !== 'string') {
|
|
1818
|
-
throw new TypeError('文件路径必须为字符串');
|
|
1819
|
-
}
|
|
1820
|
-
|
|
1821
|
-
if (!this.table) {
|
|
1822
|
-
throw new TypeError('表名未设置');
|
|
1823
|
-
}
|
|
1824
|
-
|
|
1825
|
-
let fs = require('fs');
|
|
1826
|
-
|
|
1827
|
-
// 检查文件是否存在
|
|
1828
|
-
if (!fs.existsSync(file)) {
|
|
1829
|
-
throw new Error('备份文件不存在');
|
|
1830
|
-
}
|
|
1831
|
-
|
|
1832
|
-
// 读取文件内容
|
|
1833
|
-
let sql_content = fs.readFileSync(file, 'utf8');
|
|
1834
|
-
|
|
1835
|
-
if (!sql_content) {
|
|
1836
|
-
throw new Error('备份文件为空');
|
|
1837
|
-
}
|
|
1838
|
-
|
|
1839
|
-
// 解析 SQL 语句
|
|
1840
|
-
let sql_stmts = this._parseSqlStatements(sql_content);
|
|
1841
|
-
|
|
1842
|
-
if (!sql_stmts || sql_stmts.length === 0) {
|
|
1843
|
-
throw new Error('未找到有效的 SQL 语句');
|
|
1844
|
-
}
|
|
1845
|
-
|
|
1846
|
-
// 开始事务
|
|
1847
|
-
await this.exec('START TRANSACTION');
|
|
1848
|
-
|
|
1849
|
-
try {
|
|
1850
|
-
// 逐个执行SQL语句
|
|
1851
|
-
for (let sql of sql_stmts) {
|
|
1852
|
-
let trim_sql = sql.trim();
|
|
1853
|
-
if (trim_sql) {
|
|
1854
|
-
await this.exec(trim_sql);
|
|
1855
|
-
}
|
|
1856
|
-
}
|
|
1857
|
-
|
|
1858
|
-
// 提交事务
|
|
1859
|
-
await this.exec('COMMIT');
|
|
1860
|
-
|
|
1861
|
-
if (this.config && this.config.debug) {
|
|
1862
|
-
this.log('info', '数据库恢复成功', {
|
|
1863
|
-
file: file,
|
|
1864
|
-
stmt_num: sql_stmts.length
|
|
1865
|
-
});
|
|
1866
|
-
}
|
|
1867
|
-
|
|
1868
|
-
return true;
|
|
1869
|
-
} catch (err) {
|
|
1870
|
-
// 回滚事务
|
|
1871
|
-
await this.exec('ROLLBACK').catch(rollback_err => {
|
|
1872
|
-
this.log('error', '事务回滚失败', rollback_err);
|
|
1873
|
-
});
|
|
1874
|
-
|
|
1875
|
-
// 记录错误日志
|
|
1876
|
-
this.log('error', 'SQL语句执行失败', err);
|
|
1877
|
-
throw err;
|
|
1878
|
-
}
|
|
1879
|
-
};
|
|
1880
|
-
|
|
1881
|
-
/**
|
|
1882
|
-
* @description 获取创建表的 SQL 语句
|
|
1883
|
-
* @returns {Promise<string>} 创建表的 SQL 语句
|
|
1884
|
-
* @private
|
|
1885
|
-
*/
|
|
1886
|
-
Sql.prototype._getCreateTableSql = async function () {
|
|
1887
|
-
// 查询表结构信息(MySQL 使用 SHOW CREATE TABLE)
|
|
1888
|
-
let sql = `SHOW CREATE TABLE \`${this.table}\``;
|
|
1889
|
-
let result = await this.run(sql);
|
|
1890
|
-
|
|
1891
|
-
if (result && result.length > 0 && result[0]['Create Table']) {
|
|
1892
|
-
// 在创建表语句中添加 IF NOT EXISTS 条件
|
|
1893
|
-
let create_sql = result[0]['Create Table'];
|
|
1894
|
-
if (create_sql.toUpperCase().startsWith('CREATE TABLE')) {
|
|
1895
|
-
create_sql = create_sql.replace('CREATE TABLE', 'CREATE TABLE IF NOT EXISTS');
|
|
1896
|
-
}
|
|
1897
|
-
return create_sql + ';';
|
|
1898
|
-
}
|
|
1899
|
-
|
|
1900
|
-
return '';
|
|
1901
|
-
};
|
|
1902
|
-
|
|
1903
1754
|
module.exports = {
|
|
1904
1755
|
Sql
|
|
1905
1756
|
};
|