├── .gitignore
├── LICENSE
├── README.md
├── doc
├── QQ-group-qr.png
└── SQLITE3-API-LIST.md
├── lib
├── BaseActionManager.js
├── OFInstance.js
├── OFramework.js
├── grammar
│ ├── mysql.js
│ ├── postgresql.js
│ ├── sqlite.js
│ └── sqlserver.js
├── instance
│ ├── MySQLActionManager.js
│ ├── PostgreSQLActionManager.js
│ ├── SQLServerActionManager.js
│ └── SQLiteSQLActionManager.js
├── oParameters.js
└── onela.js
├── package-lock.json
├── package.json
└── tests
├── sqlite_db.db
├── test.mysql.js
├── test.postgresql.js
├── test.sqlite.js
└── test.sqlserver.js
/.gitignore:
--------------------------------------------------------------------------------
1 | *.class
2 |
3 | # Mobile Tools for Java (J2ME)
4 | .mtj.tmp/
5 |
6 | # Package Files #
7 | *.jar
8 | *.war
9 | *.ear
10 |
11 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
12 | hs_err_pid*
13 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 2, June 1991
3 |
4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
6 | Everyone is permitted to copy and distribute verbatim copies
7 | of this license document, but changing it is not allowed.
8 |
9 | Preamble
10 |
11 | The licenses for most software are designed to take away your
12 | freedom to share and change it. By contrast, the GNU General Public
13 | License is intended to guarantee your freedom to share and change free
14 | software--to make sure the software is free for all its users. This
15 | General Public License applies to most of the Free Software
16 | Foundation's software and to any other program whose authors commit to
17 | using it. (Some other Free Software Foundation software is covered by
18 | the GNU Lesser General Public License instead.) You can apply it to
19 | your programs, too.
20 |
21 | When we speak of free software, we are referring to freedom, not
22 | price. Our General Public Licenses are designed to make sure that you
23 | have the freedom to distribute copies of free software (and charge for
24 | this service if you wish), that you receive source code or can get it
25 | if you want it, that you can change the software or use pieces of it
26 | in new free programs; and that you know you can do these things.
27 |
28 | To protect your rights, we need to make restrictions that forbid
29 | anyone to deny you these rights or to ask you to surrender the rights.
30 | These restrictions translate to certain responsibilities for you if you
31 | distribute copies of the software, or if you modify it.
32 |
33 | For example, if you distribute copies of such a program, whether
34 | gratis or for a fee, you must give the recipients all the rights that
35 | you have. You must make sure that they, too, receive or can get the
36 | source code. And you must show them these terms so they know their
37 | rights.
38 |
39 | We protect your rights with two steps: (1) copyright the software, and
40 | (2) offer you this license which gives you legal permission to copy,
41 | distribute and/or modify the software.
42 |
43 | Also, for each author's protection and ours, we want to make certain
44 | that everyone understands that there is no warranty for this free
45 | software. If the software is modified by someone else and passed on, we
46 | want its recipients to know that what they have is not the original, so
47 | that any problems introduced by others will not reflect on the original
48 | authors' reputations.
49 |
50 | Finally, any free program is threatened constantly by software
51 | patents. We wish to avoid the danger that redistributors of a free
52 | program will individually obtain patent licenses, in effect making the
53 | program proprietary. To prevent this, we have made it clear that any
54 | patent must be licensed for everyone's free use or not licensed at all.
55 |
56 | The precise terms and conditions for copying, distribution and
57 | modification follow.
58 |
59 | GNU GENERAL PUBLIC LICENSE
60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61 |
62 | 0. This License applies to any program or other work which contains
63 | a notice placed by the copyright holder saying it may be distributed
64 | under the terms of this General Public License. The "Program", below,
65 | refers to any such program or work, and a "work based on the Program"
66 | means either the Program or any derivative work under copyright law:
67 | that is to say, a work containing the Program or a portion of it,
68 | either verbatim or with modifications and/or translated into another
69 | language. (Hereinafter, translation is included without limitation in
70 | the term "modification".) Each licensee is addressed as "you".
71 |
72 | Activities other than copying, distribution and modification are not
73 | covered by this License; they are outside its scope. The act of
74 | running the Program is not restricted, and the output from the Program
75 | is covered only if its contents constitute a work based on the
76 | Program (independent of having been made by running the Program).
77 | Whether that is true depends on what the Program does.
78 |
79 | 1. You may copy and distribute verbatim copies of the Program's
80 | source code as you receive it, in any medium, provided that you
81 | conspicuously and appropriately publish on each copy an appropriate
82 | copyright notice and disclaimer of warranty; keep intact all the
83 | notices that refer to this License and to the absence of any warranty;
84 | and give any other recipients of the Program a copy of this License
85 | along with the Program.
86 |
87 | You may charge a fee for the physical act of transferring a copy, and
88 | you may at your option offer warranty protection in exchange for a fee.
89 |
90 | 2. You may modify your copy or copies of the Program or any portion
91 | of it, thus forming a work based on the Program, and copy and
92 | distribute such modifications or work under the terms of Section 1
93 | above, provided that you also meet all of these conditions:
94 |
95 | a) You must cause the modified files to carry prominent notices
96 | stating that you changed the files and the date of any change.
97 |
98 | b) You must cause any work that you distribute or publish, that in
99 | whole or in part contains or is derived from the Program or any
100 | part thereof, to be licensed as a whole at no charge to all third
101 | parties under the terms of this License.
102 |
103 | c) If the modified program normally reads commands interactively
104 | when run, you must cause it, when started running for such
105 | interactive use in the most ordinary way, to print or display an
106 | announcement including an appropriate copyright notice and a
107 | notice that there is no warranty (or else, saying that you provide
108 | a warranty) and that users may redistribute the program under
109 | these conditions, and telling the user how to view a copy of this
110 | License. (Exception: if the Program itself is interactive but
111 | does not normally print such an announcement, your work based on
112 | the Program is not required to print an announcement.)
113 |
114 | These requirements apply to the modified work as a whole. If
115 | identifiable sections of that work are not derived from the Program,
116 | and can be reasonably considered independent and separate works in
117 | themselves, then this License, and its terms, do not apply to those
118 | sections when you distribute them as separate works. But when you
119 | distribute the same sections as part of a whole which is a work based
120 | on the Program, the distribution of the whole must be on the terms of
121 | this License, whose permissions for other licensees extend to the
122 | entire whole, and thus to each and every part regardless of who wrote it.
123 |
124 | Thus, it is not the intent of this section to claim rights or contest
125 | your rights to work written entirely by you; rather, the intent is to
126 | exercise the right to control the distribution of derivative or
127 | collective works based on the Program.
128 |
129 | In addition, mere aggregation of another work not based on the Program
130 | with the Program (or with a work based on the Program) on a volume of
131 | a storage or distribution medium does not bring the other work under
132 | the scope of this License.
133 |
134 | 3. You may copy and distribute the Program (or a work based on it,
135 | under Section 2) in object code or executable form under the terms of
136 | Sections 1 and 2 above provided that you also do one of the following:
137 |
138 | a) Accompany it with the complete corresponding machine-readable
139 | source code, which must be distributed under the terms of Sections
140 | 1 and 2 above on a medium customarily used for software interchange; or,
141 |
142 | b) Accompany it with a written offer, valid for at least three
143 | years, to give any third party, for a charge no more than your
144 | cost of physically performing source distribution, a complete
145 | machine-readable copy of the corresponding source code, to be
146 | distributed under the terms of Sections 1 and 2 above on a medium
147 | customarily used for software interchange; or,
148 |
149 | c) Accompany it with the information you received as to the offer
150 | to distribute corresponding source code. (This alternative is
151 | allowed only for noncommercial distribution and only if you
152 | received the program in object code or executable form with such
153 | an offer, in accord with Subsection b above.)
154 |
155 | The source code for a work means the preferred form of the work for
156 | making modifications to it. For an executable work, complete source
157 | code means all the source code for all modules it contains, plus any
158 | associated interface definition files, plus the scripts used to
159 | control compilation and installation of the executable. However, as a
160 | special exception, the source code distributed need not include
161 | anything that is normally distributed (in either source or binary
162 | form) with the major components (compiler, kernel, and so on) of the
163 | operating system on which the executable runs, unless that component
164 | itself accompanies the executable.
165 |
166 | If distribution of executable or object code is made by offering
167 | access to copy from a designated place, then offering equivalent
168 | access to copy the source code from the same place counts as
169 | distribution of the source code, even though third parties are not
170 | compelled to copy the source along with the object code.
171 |
172 | 4. You may not copy, modify, sublicense, or distribute the Program
173 | except as expressly provided under this License. Any attempt
174 | otherwise to copy, modify, sublicense or distribute the Program is
175 | void, and will automatically terminate your rights under this License.
176 | However, parties who have received copies, or rights, from you under
177 | this License will not have their licenses terminated so long as such
178 | parties remain in full compliance.
179 |
180 | 5. You are not required to accept this License, since you have not
181 | signed it. However, nothing else grants you permission to modify or
182 | distribute the Program or its derivative works. These actions are
183 | prohibited by law if you do not accept this License. Therefore, by
184 | modifying or distributing the Program (or any work based on the
185 | Program), you indicate your acceptance of this License to do so, and
186 | all its terms and conditions for copying, distributing or modifying
187 | the Program or works based on it.
188 |
189 | 6. Each time you redistribute the Program (or any work based on the
190 | Program), the recipient automatically receives a license from the
191 | original licensor to copy, distribute or modify the Program subject to
192 | these terms and conditions. You may not impose any further
193 | restrictions on the recipients' exercise of the rights granted herein.
194 | You are not responsible for enforcing compliance by third parties to
195 | this License.
196 |
197 | 7. If, as a consequence of a court judgment or allegation of patent
198 | infringement or for any other reason (not limited to patent issues),
199 | conditions are imposed on you (whether by court order, agreement or
200 | otherwise) that contradict the conditions of this License, they do not
201 | excuse you from the conditions of this License. If you cannot
202 | distribute so as to satisfy simultaneously your obligations under this
203 | License and any other pertinent obligations, then as a consequence you
204 | may not distribute the Program at all. For example, if a patent
205 | license would not permit royalty-free redistribution of the Program by
206 | all those who receive copies directly or indirectly through you, then
207 | the only way you could satisfy both it and this License would be to
208 | refrain entirely from distribution of the Program.
209 |
210 | If any portion of this section is held invalid or unenforceable under
211 | any particular circumstance, the balance of the section is intended to
212 | apply and the section as a whole is intended to apply in other
213 | circumstances.
214 |
215 | It is not the purpose of this section to induce you to infringe any
216 | patents or other property right claims or to contest validity of any
217 | such claims; this section has the sole purpose of protecting the
218 | integrity of the free software distribution system, which is
219 | implemented by public license practices. Many people have made
220 | generous contributions to the wide range of software distributed
221 | through that system in reliance on consistent application of that
222 | system; it is up to the author/donor to decide if he or she is willing
223 | to distribute software through any other system and a licensee cannot
224 | impose that choice.
225 |
226 | This section is intended to make thoroughly clear what is believed to
227 | be a consequence of the rest of this License.
228 |
229 | 8. If the distribution and/or use of the Program is restricted in
230 | certain countries either by patents or by copyrighted interfaces, the
231 | original copyright holder who places the Program under this License
232 | may add an explicit geographical distribution limitation excluding
233 | those countries, so that distribution is permitted only in or among
234 | countries not thus excluded. In such case, this License incorporates
235 | the limitation as if written in the body of this License.
236 |
237 | 9. The Free Software Foundation may publish revised and/or new versions
238 | of the General Public License from time to time. Such new versions will
239 | be similar in spirit to the present version, but may differ in detail to
240 | address new problems or concerns.
241 |
242 | Each version is given a distinguishing version number. If the Program
243 | specifies a version number of this License which applies to it and "any
244 | later version", you have the option of following the terms and conditions
245 | either of that version or of any later version published by the Free
246 | Software Foundation. If the Program does not specify a version number of
247 | this License, you may choose any version ever published by the Free Software
248 | Foundation.
249 |
250 | 10. If you wish to incorporate parts of the Program into other free
251 | programs whose distribution conditions are different, write to the author
252 | to ask for permission. For software which is copyrighted by the Free
253 | Software Foundation, write to the Free Software Foundation; we sometimes
254 | make exceptions for this. Our decision will be guided by the two goals
255 | of preserving the free status of all derivatives of our free software and
256 | of promoting the sharing and reuse of software generally.
257 |
258 | NO WARRANTY
259 |
260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268 | REPAIR OR CORRECTION.
269 |
270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278 | POSSIBILITY OF SUCH DAMAGES.
279 |
280 | END OF TERMS AND CONDITIONS
281 |
282 | How to Apply These Terms to Your New Programs
283 |
284 | If you develop a new program, and you want it to be of the greatest
285 | possible use to the public, the best way to achieve this is to make it
286 | free software which everyone can redistribute and change under these terms.
287 |
288 | To do so, attach the following notices to the program. It is safest
289 | to attach them to the start of each source file to most effectively
290 | convey the exclusion of warranty; and each file should have at least
291 | the "copyright" line and a pointer to where the full notice is found.
292 |
293 | {description}
294 | Copyright (C) {year} {fullname}
295 |
296 | This program is free software; you can redistribute it and/or modify
297 | it under the terms of the GNU General Public License as published by
298 | the Free Software Foundation; either version 2 of the License, or
299 | (at your option) any later version.
300 |
301 | This program is distributed in the hope that it will be useful,
302 | but WITHOUT ANY WARRANTY; without even the implied warranty of
303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
304 | GNU General Public License for more details.
305 |
306 | You should have received a copy of the GNU General Public License along
307 | with this program; if not, write to the Free Software Foundation, Inc.,
308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
309 |
310 | Also add information on how to contact you by electronic and paper mail.
311 |
312 | If the program is interactive, make it output a short notice like this
313 | when it starts in an interactive mode:
314 |
315 | Gnomovision version 69, Copyright (C) year name of author
316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
317 | This is free software, and you are welcome to redistribute it
318 | under certain conditions; type `show c' for details.
319 |
320 | The hypothetical commands `show w' and `show c' should show the appropriate
321 | parts of the General Public License. Of course, the commands you use may
322 | be called something other than `show w' and `show c'; they could even be
323 | mouse-clicks or menu items--whatever suits your program.
324 |
325 | You should also get your employer (if you work as a programmer) or your
326 | school, if any, to sign a "copyright disclaimer" for the program, if
327 | necessary. Here is a sample; alter the names:
328 |
329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program
330 | `Gnomovision' (which makes passes at compilers) written by James Hacker.
331 |
332 | {signature of Ty Coon}, 1 April 1989
333 | Ty Coon, President of Vice
334 |
335 | This General Public License does not permit incorporating your program into
336 | proprietary programs. If your program is a subroutine library, you may
337 | consider it more useful to permit linking proprietary applications with the
338 | library. If this is what you want to do, use the GNU Lesser General
339 | Public License instead of this License.
340 |
341 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Onela一个Node.js开源的ORM对象关系映射框架
2 |
3 | > Onela是基于node.js开源的基于对象的映射框架,支持各种关系数据库数据基础设施。 同时支持各种数据库对象的读写分离,数据库实例垂直拆分。 在onela架构之上,您可以体验无SQL编程的乐趣,您只需要关注业务逻辑代码部分。 而且,我将在后面的版本的支持下加入分布式缓存来实现前端和后端的node.js程序来挑战大规模应用的情况。
4 | >
5 |
6 |
7 |
8 | [](https://www.npmjs.com/package/onela)
9 | [](https://www.npmjs.com/package/onela)
10 |
11 | [](https://nodei.co/npm/onela/)
12 |
13 |
14 |
15 | ### 重大更新:v2.0版本发布
16 |
17 | 此版本重大更新,原有如果使用了V2.0.0之前的版本请注意,升级到最新版,最原有代码也需要微调。
18 |
19 | 特别感谢Hugh-won在v2.0.0版本改进提供帮助~
20 |
21 | 目前(v2.3.0)已经支持 MySQL、PostgreSQL、SQL Server、SQLite数据库
22 |
23 | ### 步骤一:安装node模块(step 1 npm install node_modules)
24 |
25 | ~~~~~~
26 | npm install onela // 项目核心包
27 |
28 | 依赖包安装
29 | npm install mysql // MySQL数据库
30 | npm install pg // PostgreSQL数据库
31 | npm install sqlite3 // SQLite数据库
32 | npm install tedious // SQL Server数据库
33 | ~~~~~~
34 |
35 |
36 |
37 | ### 步骤二:配置数据源(step 2 Mapping data sources)
38 |
39 | 数据库的配置可以配置在config全局配置中,在初始化调用取出来就可以了了
40 |
41 | ```
42 | /**
43 | * 数据库配置,可以初始化多个数据库实例
44 | */
45 | let dbconfig = [{
46 | "engine": "default", // 数据库实例名称
47 | "type": "mysql", // 数据库类型:MYSQL(不区分大小写),支持类型:mysql、postgresql、sqlite、sqlserver
48 | "value": {
49 | "connectionLimit": 5,
50 | "host": "localhost",
51 | "user": "",
52 | "password": "",
53 | "database": "todo"
54 | }
55 | },
56 | {
57 | "engine": "default",
58 | "type": "PostgreSQL", // 数据库类型:PostgreSQL(不区分大小写)
59 | "value": {
60 | "port": 3432,
61 | "host": "127.0.0.1",
62 | "user": "manor",
63 | "password": "test",
64 | "database": "test_db"
65 | }
66 | }];
67 |
68 | ```
69 |
70 |
71 |
72 | ### 步骤三:Onela ORM对象初始化(step 3 Onela ORM object initialization)
73 |
74 | ~~~~~~
75 | const {Onela, OnelaBaseModel} = require("onela");
76 | // 初始化Onela模块(建议全局初始化)
77 | Onela.init(dbconfig);
78 | ~~~~~~
79 |
80 |
81 |
82 | ### 步骤四:单例(数据表)对象配置以及方法的扩展封装
83 |
84 | ~~~~~
85 | // 在OnelaBaseModel类中封装了常用的ORM方法
86 | class ToDoManager extends OnelaBaseModel {
87 | // 可以在此自定义扩展方法(默认封装没有的方法)
88 | }
89 |
90 | /**
91 | * 【重要】单例模式,数据表配置
92 | * tableName:数据表名
93 | * engine:数据库引擎名称,需要和dbconfig配置的名称对应起来
94 | * fields[n].name:数据表字段名
95 | * fields[n].type:数据表字段类型
96 | * fields[n].default:默认值
97 | * */
98 | ToDoManager.configs = {
99 | fields: [
100 | {name: "id", type: "int", default: null},
101 | {name: "content", type: "varchar"},
102 | {name: "is_done", type: "int", default: 0},
103 | {
104 | name: "create_time", type: "datetime", default: () => {
105 | return new Date()
106 | }
107 | },
108 | {name: "finish_time", type: "datetime", default: null}
109 | ],
110 | tableName: "todos",
111 | engine: "default"
112 | };
113 | ~~~~~
114 |
115 |
116 |
117 | ### 步骤五:常用CRUD操作代码示例(step 5 Examples of common CRUD operation code)
118 |
119 | 到这一步骤,可以直接使用ORM的方法了,增删改查,包含事务处理。
120 |
121 | ```
122 | // 【重要】单例模式,数据表配置
123 | ToDoManager.configs = {
124 | fields: [
125 | {name: "id", type: "int", default: null},
126 | {name: "content", type: "varchar"},
127 | {name: "is_done", type: "int", default: 0},
128 | {
129 | name: "create_time", type: "datetime", default: () => {
130 | return new Date()
131 | }
132 | },
133 | {name: "finish_time", type: "datetime", default: null}
134 | ],
135 | tableName: "todos",
136 | engine: "default"
137 | };
138 |
139 | /**
140 | * 事务
141 | */
142 | ToDoManager.transaction().then(t => {
143 | // 先新增一条记录
144 | ToDoManager.insertEntity({
145 | "content": "测试事务"
146 | }, {transaction: t})
147 | .then(data => {
148 | // 再对新增的记录执行修改
149 | return ToDoManager.updateEntity({
150 | "update": [
151 | {"key": "content", "value": "事务修改", "operator": "replace"} // 修改了content字段
152 | ],
153 | "where": [
154 | {"logic": "and", "key": "id", operator: "=", "value": 8}
155 | ]
156 | }, {transaction: t});
157 | })
158 | .then(data => {
159 | console.log('执行结果', data);
160 | t.commit().then(d=>{
161 | console.log(d);
162 | });
163 | })
164 | .catch(ex => {
165 | console.log('事务异常回滚', ex);
166 | t.rollback().then(d=>{
167 | console.log(d);
168 | });
169 | });
170 | });
171 |
172 |
173 | /**
174 | * 单例模式:数据查询
175 | */
176 | ToDoManager.getEntity({
177 | where: [
178 | //{"logic": "and", "key": "id", "operator": "=", "value": 1}
179 | ]
180 | }, null).then(data => {
181 | console.log('查询结果', data)
182 | }).then();
183 |
184 | /**
185 | * 单例模式:新增
186 | */
187 | ToDoManager.insertEntity({
188 | "content":"测试"
189 | }).then(data=>{console.log('查询结果',data)});
190 |
191 | /**
192 | * 单例模式:分页查询
193 | */
194 | ToDoManager.getEntityList({
195 | "where": [
196 | //{"logic": "and", "key": "id", "operator": "=", "value": 1}
197 | ]
198 | }).then(console.log);
199 |
200 | /**
201 | * 单例模式:新增
202 | */
203 | ToDoManager.insertEntity({
204 | content: "设计智能保险顾问的用户体系"
205 | }).then(console.log);
206 |
207 | /**
208 | * 单例模式:批量新增
209 | */
210 | ToDoManager.insertBatch([
211 | {content: "测试1"},
212 | {content: "测试2"},
213 | {content: "测试3"}
214 | ]).then(console.log);
215 |
216 | /**
217 | * 单例模式:删除(物理删除,不推荐使用)
218 | */
219 | ToDoManager.deleteEntity({
220 | "where": [
221 | {"key": "id", operator: "in", value: [12360,12361], logic: "and"},
222 | // {"key": "is_done", operator: "=", value: 1, logic: "and"}
223 | ]
224 | }).then(console.log);
225 |
226 | /**
227 | * 单例模式:更新(对于删除,建议使用逻辑删除)
228 | */
229 | ToDoManager.updateEntity({
230 | update: [
231 | {key: "is_done", value: 1, operator: "replace"}
232 | ],
233 | where: [
234 | {"key": "id", operator: "in", value: [12362], logic: "and"},
235 | ]
236 | }).then(console.log);
237 |
238 | /**
239 | * 单例模式:实时统计
240 | */
241 | ToDoManager.getEntityByAggregate({
242 | // where:
243 | "aggregate":[
244 | {"function": "count", "field": "is_done", "name": "undone_tasks"},
245 | ]
246 | }).then(console.log);
247 | ```
248 |
249 |
250 |
251 | Ok, you can now play happily~
252 |
253 | ### Use instance to show(方法使用示例)
254 |
255 | #### Query example(示例:查询)
256 |
257 | There are several ways to apply the query to different business scenarios. Paging query, waterfall flow inquiries, Standard query
258 |
259 | ~~~
260 | //parameter
261 | let p = {
262 | "select": ["t.id"], //Specify the output field, query all fields, use t. * Or select attributes by default
263 | "where": [
264 | {"logic": "and", "key": 'valid', "operator": "=", "value": 1},
265 | {"logic": "and", "key": 'id', "operator": "=", "value": id}
266 | ],
267 | "orderBy": {"created_time": "DESC"},
268 | "limit": [0, 1] //Take the first data of the query results
269 | }
270 | //execute select
271 | ToDoManager.getEntity(p)
272 | .then(function (data) {
273 | resolve(data);
274 | })
275 | .catch(function (err) {
276 | reject(err);
277 | });
278 | ~~~
279 |
280 |
281 |
282 | #### Insert example(示例:新增)
283 |
284 | There is also a new batch method db_instance.insertBatch(arr),The incoming value is an array of objects
285 |
286 | ~~~
287 | //parameter
288 | let p = {
289 | "name":"Sandy",
290 | "sex":"female",
291 | "email":"sandy@xxx.com"
292 | //……
293 | //Other fields are added in turn
294 | }
295 | //execute insert
296 | ToDoManager.insertEntity(p)
297 | .then((data)=> {
298 | resolve(data);
299 | })
300 | .catch(function (err) {
301 | reject(err);
302 | });
303 | ~~~
304 |
305 |
306 |
307 | #### Update example(示例:更新)
308 |
309 | There are two main ways to update the field,replace or plus
310 |
311 | ~~~
312 | //parameter
313 | var p = {
314 | "update": [
315 | //operator:replace update
316 | {"key": "name", "value": 'Sandy', "operator": "replace"},
317 | //operator:plus update,The field type needs to be a numeric type
318 | {"key": "money", "value": 2, "operator": "plus"},
319 | //operator:reduce update,The field type needs to be a numeric type
320 | {"key": "score", "value": 1, "operator": "reduce"}
321 |
322 | ],
323 | "where": [
324 | //where条件:一般以主键id作为更新条件,支持多条件组合语
325 | {"logic": "and","key": "id", "operator": "=", "value": 'abc'}
326 | ]
327 | }
328 | //execute update
329 | ToDoManager.updateEntity(p)
330 | .then((data)=> {
331 | resolve(data);
332 | })
333 | .catch(function (err) {
334 | reject(err);
335 | });
336 | ~~~
337 |
338 |
339 |
340 | #### Update example(示例:复杂SQL更新)
341 |
342 | case when then else end 用法举例
343 |
344 | ```
345 | SQL示例:update todos set is_done=1,content= (CASE id WHEN 12381 THEN '修改结果A' WHEN 12384 THEN '修改结果B' END) where 1=1 and id in (12381, 12384);
346 |
347 | //parameter
348 | var p = {
349 | update: [
350 | {key: "is_done", value: 1, operator: "replace"},
351 | {
352 | "key": "content", //update field
353 | "case_field": "id", //balance = CASE id
354 | "case_item": [
355 | {"case_value": 3, "value": "修改结果A", "operator": "replace"}, //WHEN '001' THEN 1
356 | {"case_value": 6, "value": "修改结果B", "operator": "replace"} //WHEN '001' THEN balance+2
357 | ]
358 | }
359 | ],
360 | where: [
361 | {"key": "id", operator: "in", value: [3,6], logic: "and"},
362 | ]
363 | }
364 | //execute update
365 | ToDoManager.updateEntity(p)
366 | .then((data)=> {
367 | resolve(data);
368 | })
369 | .catch(function (err) {
370 | reject(err);
371 | });
372 | ```
373 |
374 |
375 |
376 | #### Delete example(示例:删除)
377 |
378 | Physical deletion, generally do not recommend this operation, it is recommended to delete the logic
379 |
380 | ~~~
381 |
382 | //parameter
383 | let p = {
384 | "where": [
385 | //Allow multiple query conditions
386 | //{"key": "字段名1", "value": "值", "logic": "连接联符 (默认为and 非必须 )", operator: "关联符号 (默认为: =)"},
387 | {"key": "id", "value": "abc", "logic": "and", operator: "="}
388 | ]
389 | }
390 | //execute delete
391 | ToDoManager.deleteEntity(p)
392 | .then((data=>) {
393 | resolve(data);
394 | })
395 | .catch(function (err) {
396 | reject(err);
397 | });
398 | ~~~
399 |
400 |
401 |
402 | ### sql example(实例:直接执行SQL案例)
403 |
404 | Not recommended,Direct execution of sql can only be applied to specific types of databases
405 |
406 | ~~~
407 | var sql = "SELECT * FROM tableName Where ...";
408 |
409 | ToDoManager.streak(sql).then(result =>{
410 | // Get execution results
411 | });
412 | ~~~
413 |
414 |
415 |
416 | #### Transaction example(实例:事务)
417 |
418 | Can only achieve local Transaction
419 |
420 | ~~~
421 | // transaction
422 | ToDoManager.transaction().then(t => {
423 | // 先新增一条记录
424 | ToDoManager.insertEntity({
425 | "content": "测试"
426 | }, {transaction: t})
427 | .then(data => {
428 | // 再对新增的记录执行修改
429 | return ToDoManager.updateEntity({
430 | "update": [
431 | {"key": "content", "value": "执行修改测试", "operator": "replace"} // 修改了content字段
432 | ],
433 | "where": [
434 | {"logic": "and", "key": "id", operator: "=", "value": data.insertId}
435 | ]
436 | }, {transaction: t});
437 | })
438 | .then(data => {
439 | console.log('执行结果', data);
440 | // 事务提交
441 | t.commit();
442 | })
443 | .catch(ex => {
444 | console.log('事务异常回滚', ex.message);
445 | // 事务回滚
446 | t.rollback();
447 | });
448 | });
449 | ~~~
450 |
451 | *onela.js v1 版本已经下线*
452 |
453 | ~~~~~
454 | 在就版本中模块引用需要批量调整下(2.0.0之前的老版本兼容)
455 | const onela = require('onela');
456 | 更改为:
457 | const onela = require('onela').Old;
458 | ~~~~~
459 |
460 | 此版本文档已经更新为最新文档,v2.0.0之前的老版本文档请查看:[老版本文档](https://github.com/zouwei/onela/wiki/v1.*%E7%89%88%E6%9C%AC%E6%96%87%E6%A1%A3%EF%BC%88%E6%97%A7%E7%89%88%EF%BC%89)
461 |
462 |
--------------------------------------------------------------------------------
/doc/QQ-group-qr.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zouwei/onela/095335aadf9a33d34a2e12a0fb166402975bb19e/doc/QQ-group-qr.png
--------------------------------------------------------------------------------
/doc/SQLITE3-API-LIST.md:
--------------------------------------------------------------------------------
1 | ### SQLITE3-API-LIST
2 |
3 | API
4 | **1. new sqlite3.Database(filename,[mode],[callback])**
5 | 返回数据库对象并且自动打开和连接数据库
6 | 它没有独立打开数据库的方法
7 | **2. sqlite3.verbose()**
8 | 集成数据库的执行模式,以便于调试,它没有重置的方法。
9 | **3. Database#close([callback])**
10 | 关闭和释放数据库对象
11 | **4. Database#run(sql,param,...],[callback])**
12 | 运行指定参数的SQL语句,完成之后调用回调函数,它不返回任何数据,在回调函数里面有一个参数,SQL语句执行成功,则参数的值为null,反之为一个错误的对象,它返回的是数据库的操作对象。在这个回调函数里面当中的this,里面包含有lastId(插入的ID)和change(操作影响的行数,如果执行SQL语句失败,则change的值永远为0);
13 | **5. Database#get(sql,[param,...],[callback])**
14 | 运行指定参数的SQL语句,完成过后调用回调函数。如果执行成功,则回调函数中的第一个参数为null,第二个参数为结果集中的第一行数据,反之则回调函数中只有一个参数,只参数为一个错误的对象。
15 |
16 | **6. Database#all(sql,[param,...],[callback])**
17 | 运行指定参数的SQL语句,完成过后调用回调函数。如果执行成功,则回调函数中的第一个参数为null,第二个参数为查询的结果集,反之,则只有一个参数,且参数的值为一个错误的对象。
18 |
19 | **7. Database#prepare(sql,[param,...],[callback])**
20 |
21 | 预执行绑定指定参数的SQL语句,返回一个Statement对象,如果执行成功,则回调函数的第一个参数为null,反之为一个错误的对象。
--------------------------------------------------------------------------------
/lib/BaseActionManager.js:
--------------------------------------------------------------------------------
1 | /**
2 | * SQL实例基类
3 | */
4 | class BaseActionManager {
5 |
6 | static init(config) {
7 | throw new Error("not implemented");
8 | }
9 |
10 | }
11 |
12 | module.exports = {BaseActionManager};
--------------------------------------------------------------------------------
/lib/grammar/mysql.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 通用模块-命令行参数处理
3 | * author:joey
4 | * create time:2016-06-27
5 | */
6 |
7 | let m = {};
8 |
9 | /**
10 | * 获取分页参数,封装成执行SQL参数化的对象
11 | * @param paras 原始参数集合
12 | * {
13 | * "select":[], //需要查询的字段,可缺省,即表示“*”
14 | * "keyword":[]
15 | * "orderBy":{}
16 | * }
17 | * author:zack zou
18 | * create time:2016-06-27
19 | */
20 | m.getParameters = function (paras) {
21 | //返回的参数集合
22 | let _self = {'select': [], 'where': ' where 1=1 ', 'orderBy': '', 'parameters': [], "limit": ""};
23 |
24 | /**
25 | * 指定字段查询,可以包含聚合函数
26 | * paras.select是数组对象
27 | */
28 | if (paras.select && typeof paras.select === "object") {
29 | if (paras.select.length == 0)
30 | _self.select = 't.*';
31 | else if (paras.select.length == 1)
32 | _self.select = paras.select[0];
33 | else
34 | _self.select = paras.select.join(',');
35 | }
36 | else {
37 | //如果没有包含这个参数,默认查询全部数据
38 | _self.select = 't.*';
39 | }
40 |
41 | /**
42 | * 排序
43 | */
44 | if (paras.hasOwnProperty('orderBy') && paras.orderBy != null) {
45 | /**
46 | * 遍历排序数组
47 | * 支持多字段排序
48 | * @orderBy {"order":"ASC"}
49 | */
50 | for (let i in paras.orderBy) {
51 | if (_self.orderBy === '') {
52 | _self.orderBy += ' order by ' + i + ' ' + paras.orderBy[i] + ' ';
53 | }
54 | else {
55 | _self.orderBy += ',' + i + ' ' + paras.orderBy[i] + ' ';
56 | }
57 | }
58 | }
59 |
60 | /**
61 | * where条件以及参数处理
62 | * keyword:查询条件
63 | */
64 | paras.keyword = paras.keyword || paras.where;
65 | //遍历查询条件参数
66 | for (let i in paras.keyword) {
67 | /**
68 | * keyword里面是对象数组{"key":"","value":"","logic":"and","operator:"="}
69 | */
70 | if (paras.keyword[i] != '') {
71 | /**
72 | * 默认逻辑处理,允许部分参数不填写
73 | */
74 | if (!paras.keyword[i].hasOwnProperty('logic')) {
75 | paras.keyword[i].logic = "and";
76 | }
77 | _self.where += " " + paras.keyword[i].logic + " " + paras.keyword[i].key + " ";
78 |
79 | //逻辑运算
80 | if (paras.keyword[i].hasOwnProperty('operator')) {
81 | let oper = paras.keyword[i].operator;
82 | switch (oper) {
83 | case '=':
84 | case ">":
85 | case "<":
86 | case "<>":
87 | case ">=":
88 | case "<=":
89 | _self.where += (oper + "?");
90 | //参数化
91 | _self.parameters.push(paras.keyword[i].value);
92 | break;
93 | case "in":
94 | // //包含查询,利用数据遍历的方式实现
95 | // let p = [];
96 | // for (let c in paras.keyword[i].value) {
97 | // //参数化
98 | // _self.parameters.push(paras.keyword[i].value[c]);
99 | // p.push('?');
100 | // }
101 | // _self.where += "in (" + p.join(',') + ")";
102 | // break;
103 | case "not in":
104 | //包含查询,利用数据遍历的方式实现
105 | let p = [];
106 | for (let c in paras.keyword[i].value) {
107 | //参数化
108 | _self.parameters.push(paras.keyword[i].value[c]);
109 | p.push('?');
110 | }
111 | _self.where += " " + oper + " (" + p.join(',') + ")";
112 | break;
113 | case '%':
114 | //模糊查询,logic需要指定link逻辑运算
115 | //左侧模糊匹配查询
116 | _self.where += "like ?";
117 | //参数化
118 | _self.parameters.push('%' + paras.keyword[i].value);
119 | break;
120 | case 'x%':
121 | //模糊查询,logic需要指定link逻辑运算 where f like ?
122 | //右侧模糊匹配查询
123 | _self.where += "like ?";
124 | //参数化
125 | _self.parameters.push(paras.keyword[i].value + '%');
126 | break;
127 | case '%%':
128 | //模糊查询,logic需要指定link逻辑运算
129 | _self.where += "like ?";
130 | //参数化
131 | _self.parameters.push('%' + paras.keyword[i].value + '%');
132 | break;
133 | case 'is':
134 | _self.where += "is " + paras.keyword[i].value;
135 | break;
136 | default:
137 | _self.where += "";
138 | break;
139 | }
140 | }
141 | else {
142 | //运算符
143 | _self.where += "=?"
144 | //参数化
145 | _self.parameters.push(paras.keyword[i].value);
146 | }
147 |
148 |
149 | }
150 | }
151 | /**
152 | * 检测是否存在limit
153 | */
154 | if (paras.limit && paras.limit.length > 1) {
155 | _self.limit = " limit ?,?";
156 | _self.parameters.push(paras.limit[0]);
157 | _self.parameters.push(paras.limit[1]);
158 | }
159 | /**
160 | * 返回结果
161 | */
162 | return _self;
163 | };
164 |
165 |
166 | /**
167 | * 获取更新参数
168 | * @param paras 原始参数集合
169 | * author:zack zou
170 | * create time:2016-06-27
171 | */
172 | m.getUpdateParameters = function (paras) {
173 | //返回的参数集合
174 | let _self = {"set": [], "where": [], "parameters": []};
175 |
176 | /**
177 | * 更新字段
178 | * update:需要更新的字段
179 | */
180 | //遍历查询条件参数
181 | for (let i in paras.update) {
182 | /**
183 | * update里面是对象数组{"key":"","value":"","operator":"replace"}
184 | *
185 | {
186 | "key": "payment_no",
187 | "case_field": "id",
188 | "case_item": [{"case_value": "123", "value": "1", "operator": "replace"}]
189 | }
190 | */
191 |
192 |
193 | if (paras.update[i] == '') {
194 | continue;
195 | }
196 |
197 |
198 | //判断字段更新模式,常规更新还是case when then更新方式
199 | if (paras.update[i].hasOwnProperty('case_field')) {
200 | //遍历节点
201 | let item = paras.update[i];
202 | console.log('传入参数', item);
203 | // let kkk = {
204 | // "key": "payment_no",
205 | // "case_field": "id",
206 | // "case_item": [
207 | // {"case_value": "123", "value": "1", "operator": "replace"}
208 | // ]
209 | // }
210 |
211 | //条件判断
212 | if (!(item.case_item instanceof Array) || item.case_item.length == 0) {
213 | //条件不符合
214 | continue;
215 | }
216 |
217 | //开头
218 | let case_str = [];
219 | case_str.push(item.key + '= (CASE ' + item.case_field);
220 | //循环case_item分支
221 | for (let cw in item.case_item) {
222 | /**
223 | * 默认逻辑处理,默认替换更新
224 | */
225 | if (!item.case_item[cw].hasOwnProperty('operator')) {
226 | item.case_item[cw].operator = "replace";
227 | }
228 | //更新参数处理
229 | let oper = item.case_item[cw].operator;
230 | switch (oper) {
231 | case 'replace':
232 | /**
233 | * 值替换 // WHEN '1' THEN balance+2
234 | */
235 | case_str.push("WHEN ? THEN ?");
236 | _self.parameters.push(item.case_item[cw].case_value);
237 | _self.parameters.push(item.case_item[cw].value);
238 | break;
239 | case "plus":
240 | /**
241 | * 值累加
242 | */
243 | case_str.push("WHEN ? THEN " + item.key + " + ?");
244 | _self.parameters.push(item.case_item[cw].case_value);
245 | _self.parameters.push(item.case_item[cw].value);
246 | break;
247 | case "reduce":
248 | /**
249 | * 值累减
250 | */
251 | case_str.push("WHEN ? THEN " + item.key + " - ?");
252 | _self.parameters.push(item.case_item[cw].case_value);
253 | _self.parameters.push(item.case_item[cw].value);
254 | break;
255 | default:
256 | /**
257 | * 其他默认为值替换更新
258 | */
259 | case_str.push("WHEN ? THEN ? ");
260 | _self.parameters.push(item.case_item[cw].case_value);
261 | _self.parameters.push(item.case_item[cw].value);
262 | break;
263 | }
264 | }
265 | //结尾
266 | case_str.push("END) ");
267 | //追加到参数模型
268 | _self.set.push(case_str.join(' '));
269 |
270 | }
271 | else {
272 |
273 | /**
274 | * 默认逻辑处理,默认替换更新
275 | */
276 | if (!paras.update[i].hasOwnProperty('operator')) {
277 | paras.update[i].operator = "replace";
278 | }
279 | //更新参数处理
280 | let oper = paras.update[i].operator;
281 | switch (oper) {
282 | case 'replace':
283 | /**
284 | * 值替换
285 | */
286 | _self.set.push(paras.update[i].key + '=?');
287 | _self.parameters.push(paras.update[i].value);
288 | break;
289 | case "plus":
290 | /**
291 | * 值累加
292 | */
293 | _self.set.push(paras.update[i].key + '=' + paras.update[i].key + "+ ?");
294 | _self.parameters.push(paras.update[i].value);
295 | break;
296 | case "reduce":
297 | /**
298 | * 值累减
299 | */
300 | _self.set.push(paras.update[i].key + '=' + paras.update[i].key + "- ?");
301 | _self.parameters.push(paras.update[i].value);
302 | break;
303 | default:
304 | /**
305 | * 其他默认为值替换更新
306 | */
307 | _self.set.push(paras.update[i].key + '=?');
308 | _self.parameters.push(paras.update[i].value);
309 | break;
310 | }
311 | }
312 | }
313 |
314 | /**
315 | * where条件以及参数处理
316 | * keyword:查询条件
317 | */
318 | paras.keyword = paras.keyword || paras.where;
319 | //遍历查询条件参数
320 | for (let i in paras.keyword) {
321 | /**
322 | * keyword里面是对象数组{"key":"","value":"","logic":"and","operator:"="}
323 | */
324 | if (paras.keyword[i] != '') {
325 | /**
326 | * 默认逻辑处理,允许部分参数不填写
327 | */
328 | if (!paras.keyword[i].hasOwnProperty('logic')) {
329 | paras.keyword[i].logic = "and";
330 | }
331 |
332 | //逻辑运算
333 | if (paras.keyword[i].hasOwnProperty('operator')) {
334 | let oper = paras.keyword[i].operator;
335 | switch (oper) {
336 | case '=':
337 | case ">":
338 | case "<":
339 | case "<>":
340 | case ">=":
341 | case "<=":
342 | _self.where.push(' ' + paras.keyword[i].logic + ' ' + paras.keyword[i].key + oper + "?");
343 | //参数化
344 | _self.parameters.push(paras.keyword[i].value);
345 | break;
346 | case '%':
347 | //模糊查询,logic需要指定link逻辑运算
348 | //左侧模糊匹配查询
349 | _self.where.push(' ' + paras.keyword[i].logic + ' ' + paras.keyword[i].key + oper + "?");
350 | //参数化
351 | _self.parameters.push('%' + paras.keyword[i].value);
352 | break;
353 | case 'x%':
354 | //模糊查询,logic需要指定link逻辑运算
355 | //右侧模糊匹配查询
356 | _self.where.push(' ' + paras.keyword[i].logic + ' ' + paras.keyword[i].key + oper + "?");
357 | //参数化
358 | _self.parameters.push(paras.keyword[i].value + '%');
359 | break;
360 | case '%%':
361 | //模糊查询,logic需要指定link逻辑运算
362 | _self.where.push(' ' + paras.keyword[i].logic + ' ' + paras.keyword[i].key + oper + "?");
363 | //参数化
364 | _self.parameters.push('%' + paras.keyword[i].value + '%');
365 | break;
366 | case "in":
367 | case "not in":
368 | let _item = ' ' + paras.keyword[i].logic + ' ' + paras.keyword[i].key + " " + oper + " ("
369 | //包含查询,利用数据遍历的方式实现
370 | let p = [];
371 | for (let c in paras.keyword[i].value) {
372 | //参数化
373 | _self.parameters.push(paras.keyword[i].value[c]);
374 | p.push('?');
375 | }
376 | _item += p.join(',') + ")"; //sql语句
377 | _self.where.push(_item);
378 | break;
379 | }
380 | }
381 |
382 | }
383 | }
384 | /**
385 | * where条件字符串组装
386 | */
387 | _self.where = ' 1=1 ' + _self.where.join('');
388 | /**
389 | * 返回结果
390 | */
391 | return _self;
392 | }
393 |
394 | /**
395 | * 获取实例删除参数
396 | * 注意,一般情况下不推荐直接物理删除
397 | * @param paras 原始参数集合
398 | * {
399 | * "keyword":[]
400 | * }
401 | * author:zack zou
402 | * create time:2017-04-06
403 | */
404 | m.getDeleteParameters = function (paras) {
405 | //返回的参数集合
406 | let _self = {'where': [], 'parameters': []};
407 |
408 | /**
409 | * where条件以及参数处理
410 | * keyword:查询条件
411 | */
412 | paras.keyword = paras.keyword || paras.where;
413 | //遍历查询条件参数
414 | for (let i in paras.keyword) {
415 | /**
416 | * keyword里面是对象数组{"key":"","value":"","logic":"and","operator:"="}
417 | */
418 | if (paras.keyword[i] != '') {
419 | /**
420 | * 默认逻辑处理,允许部分参数不填写
421 | */
422 | if (!paras.keyword[i].hasOwnProperty('logic')) {
423 | paras.keyword[i].logic = "and";
424 | }
425 |
426 | //逻辑运算
427 | if (paras.keyword[i].hasOwnProperty('operator')) {
428 | let oper = paras.keyword[i].operator;
429 | switch (oper) {
430 | case '=':
431 | case ">":
432 | case "<":
433 | case "<>":
434 | case ">=":
435 | case "<=":
436 | _self.where.push(' ' + paras.keyword[i].logic + ' ' + paras.keyword[i].key + oper + "?");
437 | //参数化
438 | _self.parameters.push(paras.keyword[i].value);
439 | break;
440 | case '%':
441 | //模糊查询,logic需要指定link逻辑运算
442 | //左侧模糊匹配查询
443 | _self.where.push(' ' + paras.keyword[i].logic + ' ' + paras.keyword[i].key + oper + "?");
444 | //参数化
445 | _self.parameters.push('%' + paras.keyword[i].value);
446 | break;
447 | case 'x%':
448 | //模糊查询,logic需要指定link逻辑运算
449 | //右侧模糊匹配查询
450 | _self.where.push(' ' + paras.keyword[i].logic + ' ' + paras.keyword[i].key + oper + "?");
451 | //参数化
452 | _self.parameters.push(paras.keyword[i].value + '%');
453 | break;
454 | case '%%':
455 | //模糊查询,logic需要指定link逻辑运算
456 | _self.where.push(' ' + paras.keyword[i].logic + ' ' + paras.keyword[i].key + oper + "?");
457 | //参数化
458 | _self.parameters.push('%' + paras.keyword[i].value + '%');
459 | break;
460 | case "in":
461 | case "not in":
462 | let _item = ' ' + paras.keyword[i].logic + ' ' + paras.keyword[i].key + " " + oper + " ("
463 | //包含查询,利用数据遍历的方式实现
464 | let p = [];
465 | for (let c in paras.keyword[i].value) {
466 | //参数化
467 | _self.parameters.push(paras.keyword[i].value[c]);
468 | p.push('?');
469 | }
470 | _item += p.join(',') + ")"; //sql语句
471 | _self.where.push(_item);
472 | break;
473 | }
474 | }
475 |
476 | }
477 | }
478 | /**
479 | * where条件字符串组装
480 | */
481 | _self.where = ' 1=1 ' + _self.where.join('');
482 | /**
483 | * 返回结果
484 | */
485 | return _self;
486 | };
487 |
488 | module.exports = m;
--------------------------------------------------------------------------------
/lib/grammar/postgresql.js:
--------------------------------------------------------------------------------
1 | /**
2 | * PostgreSQL - 命令行参数处理
3 | * author:joey
4 | * create time:2018-04-25
5 | */
6 |
7 | let m = {};
8 |
9 | /**
10 | * 获取分页参数,封装成执行SQL参数化的对象
11 | * @param paras 原始参数集合
12 | * {
13 | * "select":[], //需要查询的字段,可缺省,即表示“*”
14 | * "keyword":[]
15 | * "orderBy":{}
16 | * }
17 | * author:zack zou
18 | * create time:2016-06-27
19 | */
20 | m.getParameters = function (paras) {
21 | // 索引
22 | let index = 0;
23 | //返回的参数集合
24 | let _self = {'select': [], 'where': ' where 1=1 ', 'orderBy': '', 'parameters': [], "limit": ""};
25 |
26 | /**
27 | * 指定字段查询,可以包含聚合函数
28 | * paras.select是数组对象
29 | */
30 | if (paras.select && typeof paras.select === "object") {
31 | if (paras.select.length == 0)
32 | _self.select = 't.*';
33 | else if (paras.select.length == 1)
34 | _self.select = paras.select[0];
35 | else
36 | _self.select = paras.select.join(',');
37 | }
38 | else {
39 | //如果没有包含这个参数,默认查询全部数据
40 | _self.select = 't.*';
41 | }
42 |
43 | /**
44 | * 排序
45 | */
46 | if (paras.hasOwnProperty('orderBy') && paras.orderBy != null) {
47 | /**
48 | * 遍历排序数组
49 | * 支持多字段排序
50 | * @orderBy {"order":"ASC"}
51 | */
52 | for (let i in paras.orderBy) {
53 | if (_self.orderBy === '') {
54 | _self.orderBy += ' order by ' + i + ' ' + paras.orderBy[i] + ' ';
55 | }
56 | else {
57 | _self.orderBy += ',' + i + ' ' + paras.orderBy[i] + ' ';
58 | }
59 | }
60 | }
61 |
62 | /**
63 | * GROUP BY 分组条件
64 | * */
65 | if (paras.hasOwnProperty('groupBy') && paras.groupBy.length > 0) {
66 | _self.groupBy = ` GROUP BY ${paras.groupBy.join(',')} `;
67 | } else {
68 | _self.groupBy = ``;
69 | }
70 |
71 | /**
72 | * where条件以及参数处理
73 | * keyword:查询条件
74 | */
75 | paras.keyword = paras.keyword || paras.where;
76 | //遍历查询条件参数
77 | for (let i in paras.keyword) {
78 | index++;
79 | /**
80 | * keyword里面是对象数组{"key":"","value":"","logic":"and","operator:"="}
81 | */
82 | if (paras.keyword[i] != '') {
83 | /**
84 | * 默认逻辑处理,允许部分参数不填写
85 | */
86 | if (!paras.keyword[i].hasOwnProperty('logic')) {
87 | paras.keyword[i].logic = "and";
88 | }
89 | _self.where += " " + paras.keyword[i].logic + " " + paras.keyword[i].key + " ";
90 |
91 | //逻辑运算
92 | if (paras.keyword[i].hasOwnProperty('operator')) {
93 | let oper = paras.keyword[i].operator;
94 | switch (oper) {
95 | case '=':
96 | case ">":
97 | case "<":
98 | case "<>":
99 | case ">=":
100 | case "<=":
101 | if(paras.keyword[i].format){
102 | index--;
103 | _self.where += `${oper} ${paras.keyword[i].value}`;
104 | } else {
105 | _self.where += (oper + "$" + index);
106 | //参数化
107 | _self.parameters.push(paras.keyword[i].value);
108 | }
109 |
110 | break;
111 | case "in":
112 | case "not in":
113 | //包含查询,利用数据遍历的方式实现
114 | let p = [];
115 | index--;
116 | for (let c in paras.keyword[i].value) {
117 | index++;
118 | //参数化
119 | _self.parameters.push(paras.keyword[i].value[c]);
120 | p.push('$' + index);
121 | }
122 | _self.where += " " + oper + " (" + p.join(',') + ")";
123 | break;
124 | case '%':
125 | //模糊查询,logic需要指定link逻辑运算
126 | //左侧模糊匹配查询
127 | _self.where += "like $" + index;
128 | //参数化
129 | _self.parameters.push('%' + paras.keyword[i].value);
130 | break;
131 | case 'x%':
132 | //模糊查询,logic需要指定link逻辑运算 where f like $
133 | //右侧模糊匹配查询
134 | _self.where += "like $" + index;
135 | //参数化
136 | _self.parameters.push(paras.keyword[i].value + '%');
137 | break;
138 | case '%%':
139 | //模糊查询,logic需要指定link逻辑运算
140 | _self.where += "like $" + index;
141 | //参数化
142 | _self.parameters.push('%' + paras.keyword[i].value + '%');
143 | break;
144 | case 'is':
145 | _self.where += "is " + paras.keyword[i].value;
146 | break;
147 | default:
148 | _self.where += "";
149 | break;
150 | }
151 | }
152 | else {
153 | //运算符
154 | _self.where += "=$" + index;
155 | //参数化
156 | _self.parameters.push(paras.keyword[i].value);
157 | }
158 |
159 |
160 | }
161 | }
162 | /**
163 | * 检测是否存在limit
164 | */
165 | if (paras.limit && paras.limit.length > 1) {
166 | index++;
167 | _self.limit = " limit $" + index + " offset $" + (index + 1);
168 | _self.parameters.push(paras.limit[1]);
169 | _self.parameters.push(paras.limit[0]);
170 | }
171 | /**
172 | * 返回结果
173 | */
174 | return _self;
175 | };
176 |
177 |
178 | /**
179 | * 获取更新参数
180 | * @param paras 原始参数集合
181 | * author:zack zou
182 | * create time:2016-06-27
183 | */
184 | m.getUpdateParameters = function (paras) {
185 | // 索引
186 | let index = 0;
187 | //返回的参数集合
188 | let _self = {"set": [], "where": [], "parameters": []};
189 |
190 | /**
191 | * 更新字段
192 | * update:需要更新的字段
193 | */
194 | //遍历查询条件参数
195 | for (let i in paras.update) {
196 | /**
197 | * update里面是对象数组{"key":"","value":"","operator":"replace"}
198 | *
199 | {
200 | "key": "payment_no",
201 | "case_field": "id",
202 | "case_item": [{"case_value": "123", "value": "1", "operator": "replace"}]
203 | }
204 | */
205 |
206 |
207 | if (paras.update[i] == '') {
208 | continue;
209 | }
210 |
211 | //判断字段更新模式,常规更新还是case when then更新方式
212 | if (paras.update[i].hasOwnProperty('case_field')) {
213 | //遍历节点
214 | let item = paras.update[i];
215 | console.log('传入参数', item);
216 | // let kkk = {
217 | // "key": "payment_no",
218 | // "case_field": "id",
219 | // "case_item": [
220 | // {"case_value": "123", "value": "1", "operator": "replace"}
221 | // ]
222 | // }
223 |
224 | //条件判断
225 | if (!(item.case_item instanceof Array) || item.case_item.length == 0) {
226 | //条件不符合
227 | continue;
228 | }
229 |
230 | //开头
231 | let case_str = [];
232 | case_str.push(item.key + '= (CASE ' + item.case_field);
233 | //循环case_item分支
234 | for (let cw in item.case_item) {
235 | index += 2;
236 | /**
237 | * 默认逻辑处理,默认替换更新
238 | */
239 | if (!item.case_item[cw].hasOwnProperty('operator')) {
240 | item.case_item[cw].operator = "replace";
241 | }
242 | //更新参数处理
243 | let oper = item.case_item[cw].operator;
244 | switch (oper) {
245 | case 'replace':
246 | /**
247 | * 值替换 // WHEN '1' THEN balance+2
248 | */
249 | case_str.push("WHEN $" + (index - 1) + " THEN $" + index);
250 | break;
251 | case "plus":
252 | /**
253 | * 值累加
254 | */
255 | case_str.push("WHEN $" + (index - 1) + " THEN " + item.key + " + $" + index + " ");
256 | break;
257 | case "reduce":
258 | /**
259 | * 值累减
260 | */
261 | case_str.push("WHEN $" + (index - 1) + " THEN " + item.key + " - $" + index + "");
262 | break;
263 | default:
264 | /**
265 | * 其他默认为值替换更新
266 | */
267 | case_str.push("WHEN $" + (index - 1) + " THEN $" + index + " ");
268 | break;
269 | }
270 |
271 | _self.parameters.push(item.case_item[cw].case_value);
272 | _self.parameters.push(item.case_item[cw].value);
273 | }
274 | //结尾
275 | case_str.push("END) ");
276 | //追加到参数模型
277 | _self.set.push(case_str.join(' '));
278 |
279 | }
280 | else {
281 | index++;
282 | /**
283 | * 默认逻辑处理,默认替换更新
284 | */
285 | if (!paras.update[i].hasOwnProperty('operator')) {
286 | paras.update[i].operator = "replace";
287 | }
288 | //更新参数处理
289 | let oper = paras.update[i].operator;
290 | switch (oper) {
291 | case 'replace':
292 | /**
293 | * 值替换
294 | */
295 | _self.set.push(paras.update[i].key + '=$' + index);
296 | _self.parameters.push(paras.update[i].value);
297 | break;
298 | case "plus":
299 | /**
300 | * 值累加
301 | */
302 | _self.set.push(paras.update[i].key + '=' + paras.update[i].key + "+ $" + index);
303 | _self.parameters.push(paras.update[i].value);
304 | break;
305 | case "reduce":
306 | /**
307 | * 值累减
308 | */
309 | _self.set.push(paras.update[i].key + '=' + paras.update[i].key + "- $" + index);
310 | _self.parameters.push(paras.update[i].value);
311 | break;
312 | default:
313 | /**
314 | * 其他默认为值替换更新
315 | */
316 | _self.set.push(paras.update[i].key + '=$' + index);
317 | _self.parameters.push(paras.update[i].value);
318 | break;
319 | }
320 | }
321 | }
322 |
323 | /**
324 | * where条件以及参数处理
325 | * keyword:查询条件
326 | */
327 | paras.keyword = paras.keyword || paras.where;
328 | //遍历查询条件参数
329 | for (let i in paras.keyword) {
330 | index++;
331 | /**
332 | * keyword里面是对象数组{"key":"","value":"","logic":"and","operator:"="}
333 | */
334 | if (paras.keyword[i] != '') {
335 | /**
336 | * 默认逻辑处理,允许部分参数不填写
337 | */
338 | if (!paras.keyword[i].hasOwnProperty('logic')) {
339 | paras.keyword[i].logic = "and";
340 | }
341 |
342 | //逻辑运算
343 | if (paras.keyword[i].hasOwnProperty('operator')) {
344 | let oper = paras.keyword[i].operator;
345 | switch (oper) {
346 | case '=':
347 | case ">":
348 | case "<":
349 | case "<>":
350 | case ">=":
351 | case "<=":
352 | _self.where.push(' ' + paras.keyword[i].logic + ' ' + paras.keyword[i].key + oper + "$" + index);
353 | //参数化
354 | _self.parameters.push(paras.keyword[i].value);
355 | break;
356 | case '%':
357 | //模糊查询,logic需要指定link逻辑运算
358 | //左侧模糊匹配查询
359 | _self.where.push(' ' + paras.keyword[i].logic + ' ' + paras.keyword[i].key + oper + "$" + index);
360 | //参数化
361 | _self.parameters.push('%' + paras.keyword[i].value);
362 | break;
363 | case 'x%':
364 | //模糊查询,logic需要指定link逻辑运算
365 | //右侧模糊匹配查询
366 | _self.where.push(' ' + paras.keyword[i].logic + ' ' + paras.keyword[i].key + oper + "$" + index);
367 | //参数化
368 | _self.parameters.push(paras.keyword[i].value + '%');
369 | break;
370 | case '%%':
371 | //模糊查询,logic需要指定link逻辑运算
372 | _self.where.push(' ' + paras.keyword[i].logic + ' ' + paras.keyword[i].key + oper + "$" + index);
373 | //参数化
374 | _self.parameters.push('%' + paras.keyword[i].value + '%');
375 | break;
376 | case "in":
377 | case "not in":
378 | let _item = ' ' + paras.keyword[i].logic + ' ' + paras.keyword[i].key + " " + oper + " ("
379 | //包含查询,利用数据遍历的方式实现
380 | let p = [];
381 | index--;
382 | for (let c in paras.keyword[i].value) {
383 | index++;
384 | //参数化
385 | _self.parameters.push(paras.keyword[i].value[c]);
386 | p.push('$' + index);
387 | }
388 | _item += p.join(',') + ")"; //sql语句
389 | _self.where.push(_item);
390 | break;
391 | }
392 | }
393 |
394 | }
395 | }
396 | /**
397 | * where条件字符串组装
398 | */
399 | _self.where = ' 1=1 ' + _self.where.join('');
400 | /**
401 | * 返回结果
402 | */
403 | return _self;
404 | };
405 |
406 | /**
407 | * 获取实例删除参数
408 | * 注意,一般情况下不推荐直接物理删除
409 | * @param paras 原始参数集合
410 | * {
411 | * "keyword":[]
412 | * }
413 | * author:zack zou
414 | * create time:2017-04-06
415 | */
416 | m.getDeleteParameters = function (paras) {
417 | // 索引
418 | let index = 0;
419 | //返回的参数集合
420 | let _self = {'where': [], 'parameters': []};
421 |
422 | /**
423 | * where条件以及参数处理
424 | * keyword:查询条件
425 | */
426 | paras.keyword = paras.keyword || paras.where;
427 | //遍历查询条件参数
428 | for (let i in paras.keyword) {
429 | index++;
430 | /**
431 | * keyword里面是对象数组{"key":"","value":"","logic":"and","operator:"="}
432 | */
433 | if (paras.keyword[i] != '') {
434 | /**
435 | * 默认逻辑处理,允许部分参数不填写
436 | */
437 | if (!paras.keyword[i].hasOwnProperty('logic')) {
438 | paras.keyword[i].logic = "and";
439 | }
440 |
441 | //逻辑运算
442 | if (paras.keyword[i].hasOwnProperty('operator')) {
443 | let oper = paras.keyword[i].operator;
444 | switch (oper) {
445 | case '=':
446 | case ">":
447 | case "<":
448 | case "<>":
449 | case ">=":
450 | case "<=":
451 | _self.where.push(' ' + paras.keyword[i].logic + ' ' + paras.keyword[i].key + oper + "$" + index);
452 | //参数化
453 | _self.parameters.push(paras.keyword[i].value);
454 | break;
455 | case '%':
456 | //模糊查询,logic需要指定link逻辑运算
457 | //左侧模糊匹配查询
458 | _self.where.push(' ' + paras.keyword[i].logic + ' ' + paras.keyword[i].key + oper + "$" + index);
459 | //参数化
460 | _self.parameters.push('%' + paras.keyword[i].value);
461 | break;
462 | case 'x%':
463 | //模糊查询,logic需要指定link逻辑运算
464 | //右侧模糊匹配查询
465 | _self.where.push(' ' + paras.keyword[i].logic + ' ' + paras.keyword[i].key + oper + "$" + index);
466 | //参数化
467 | _self.parameters.push(paras.keyword[i].value + '%');
468 | break;
469 | case '%%':
470 | //模糊查询,logic需要指定link逻辑运算
471 | _self.where.push(' ' + paras.keyword[i].logic + ' ' + paras.keyword[i].key + oper + "$" + index);
472 | //参数化
473 | _self.parameters.push('%' + paras.keyword[i].value + '%');
474 | break;
475 | case "in":
476 | case "not in":
477 | let _item = ' ' + paras.keyword[i].logic + ' ' + paras.keyword[i].key + " " + oper + " (";
478 | //包含查询,利用数据遍历的方式实现
479 | let p = [];
480 | index--;
481 | for (let c in paras.keyword[i].value) {
482 | index++;
483 | //参数化
484 | _self.parameters.push(paras.keyword[i].value[c]);
485 | p.push('$' + index);
486 | }
487 | _item += p.join(',') + ")"; //sql语句
488 | _self.where.push(_item);
489 | break;
490 | }
491 | }
492 |
493 | }
494 | }
495 | /**
496 | * where条件字符串组装
497 | */
498 | _self.where = ' 1=1 ' + _self.where.join('');
499 | /**
500 | * 返回结果
501 | */
502 | return _self;
503 | };
504 |
505 | module.exports = m;
--------------------------------------------------------------------------------
/lib/grammar/sqlite.js:
--------------------------------------------------------------------------------
1 | /**
2 | * SQLite - 命令行参数处理
3 | * author:joey
4 | * create time:2018-04-26
5 | */
6 |
7 | let m = {};
8 |
9 | /**
10 | * 获取分页参数,封装成执行SQL参数化的对象
11 | * @param paras 原始参数集合
12 | * {
13 | * "select":[], //需要查询的字段,可缺省,即表示“*”
14 | * "where":[]
15 | * "orderBy":{}
16 | * }
17 | * author:joey
18 | * create time:2018-04-26
19 | */
20 | m.getParameters = function (paras) {
21 | console.log('参数合集',JSON.stringify(paras));
22 | //返回的参数集合
23 | let _self = {'select': [], 'where': ' where 1=1 ', 'orderBy': '', 'parameters': [], "limit": ""};
24 |
25 | /**
26 | * 指定字段查询,可以包含聚合函数
27 | * paras.select是数组对象
28 | */
29 | if (paras.select && typeof paras.select === "object") {
30 | if (paras.select.length == 0)
31 | _self.select = 't.*';
32 | else if (paras.select.length == 1)
33 | _self.select = paras.select[0];
34 | else
35 | _self.select = paras.select.join(',');
36 | }
37 | else {
38 | //如果没有包含这个参数,默认查询全部数据
39 | _self.select = 't.*';
40 | }
41 |
42 | /**
43 | * 排序
44 | */
45 | if (paras.hasOwnProperty('orderBy') && paras.orderBy != null) {
46 | /**
47 | * 遍历排序数组
48 | * 支持多字段排序
49 | * @orderBy {"order":"ASC"}
50 | */
51 | for (let i in paras.orderBy) {
52 | if (_self.orderBy === '') {
53 | _self.orderBy += ' order by ' + i + ' ' + paras.orderBy[i] + ' ';
54 | }
55 | else {
56 | _self.orderBy += ',' + i + ' ' + paras.orderBy[i] + ' ';
57 | }
58 | }
59 | }
60 |
61 | /**
62 | * where条件以及参数处理
63 | * keyword:查询条件
64 | */
65 | paras.keyword = paras.keyword || paras.where;
66 | //遍历查询条件参数
67 | for (let i in paras.keyword) {
68 | /**
69 | * keyword里面是对象数组{"key":"","value":"","logic":"and","operator:"="}
70 | */
71 | if (paras.keyword[i] != '') {
72 | /**
73 | * 默认逻辑处理,允许部分参数不填写
74 | */
75 | if (!paras.keyword[i].hasOwnProperty('logic')) {
76 | paras.keyword[i].logic = "and";
77 | }
78 | _self.where += " " + paras.keyword[i].logic + " " + paras.keyword[i].key + " ";
79 |
80 | //逻辑运算
81 | if (paras.keyword[i].hasOwnProperty('operator')) {
82 | let oper = paras.keyword[i].operator;
83 | switch (oper) {
84 | case '=':
85 | case ">":
86 | case "<":
87 | case "<>":
88 | case ">=":
89 | case "<=":
90 | _self.where += (oper + "?");
91 | //参数化
92 | _self.parameters.push(paras.keyword[i].value);
93 | break;
94 | case "in":
95 | // //包含查询,利用数据遍历的方式实现
96 | // let p = [];
97 | // for (let c in paras.keyword[i].value) {
98 | // //参数化
99 | // _self.parameters.push(paras.keyword[i].value[c]);
100 | // p.push('?');
101 | // }
102 | // _self.where += "in (" + p.join(',') + ")";
103 | // break;
104 | case "not in":
105 | //包含查询,利用数据遍历的方式实现
106 | let p = [];
107 | for (let c in paras.keyword[i].value) {
108 | //参数化
109 | _self.parameters.push(paras.keyword[i].value[c]);
110 | p.push('?');
111 | }
112 | _self.where += " " + oper + " (" + p.join(',') + ")";
113 | break;
114 | case '%':
115 | //模糊查询,logic需要指定link逻辑运算
116 | //左侧模糊匹配查询
117 | _self.where += "like ?";
118 | //参数化
119 | _self.parameters.push('%' + paras.keyword[i].value);
120 | break;
121 | case 'x%':
122 | //模糊查询,logic需要指定link逻辑运算 where f like ?
123 | //右侧模糊匹配查询
124 | _self.where += "like ?";
125 | //参数化
126 | _self.parameters.push(paras.keyword[i].value + '%');
127 | break;
128 | case '%%':
129 | //模糊查询,logic需要指定link逻辑运算
130 | _self.where += "like ?";
131 | //参数化
132 | _self.parameters.push('%' + paras.keyword[i].value + '%');
133 | break;
134 | case 'is':
135 | _self.where += "is " + paras.keyword[i].value;
136 | break;
137 | default:
138 | _self.where += "";
139 | break;
140 | }
141 | }
142 | else {
143 | //运算符
144 | _self.where += "=?"
145 | //参数化
146 | _self.parameters.push(paras.keyword[i].value);
147 | }
148 |
149 |
150 | }
151 | }
152 | /**
153 | * 检测是否存在limit
154 | */
155 | if (paras.limit && paras.limit.length > 1) {
156 | _self.limit = " limit ?,?";
157 | _self.parameters.push(paras.limit[0]);
158 | _self.parameters.push(paras.limit[1]);
159 | }
160 | /**
161 | * 返回结果
162 | */
163 | return _self;
164 | };
165 |
166 |
167 | /**
168 | * 获取更新参数
169 | * @param paras 原始参数集合
170 | * author:zack zou
171 | * create time:2016-06-27
172 | */
173 | m.getUpdateParameters = function (paras) {
174 | //返回的参数集合
175 | let _self = {"set": [], "where": [], "parameters": []};
176 |
177 | /**
178 | * 更新字段
179 | * update:需要更新的字段
180 | */
181 | //遍历查询条件参数
182 | for (let i in paras.update) {
183 | /**
184 | * update里面是对象数组{"key":"","value":"","operator":"replace"}
185 | *
186 | {
187 | "key": "payment_no",
188 | "case_field": "id",
189 | "case_item": [{"case_value": "123", "value": "1", "operator": "replace"}]
190 | }
191 | */
192 |
193 |
194 | if (paras.update[i] == '') {
195 | continue;
196 | }
197 |
198 |
199 | //判断字段更新模式,常规更新还是case when then更新方式
200 | if (paras.update[i].hasOwnProperty('case_field')) {
201 | //遍历节点
202 | let item = paras.update[i];
203 | console.log('传入参数', item);
204 | // let kkk = {
205 | // "key": "payment_no",
206 | // "case_field": "id",
207 | // "case_item": [
208 | // {"case_value": "123", "value": "1", "operator": "replace"}
209 | // ]
210 | // }
211 |
212 | //条件判断
213 | if (!(item.case_item instanceof Array) || item.case_item.length == 0) {
214 | //条件不符合
215 | continue;
216 | }
217 |
218 | //开头
219 | let case_str = [];
220 | case_str.push(item.key + '= (CASE ' + item.case_field);
221 | //循环case_item分支
222 | for (let cw in item.case_item) {
223 | /**
224 | * 默认逻辑处理,默认替换更新
225 | */
226 | if (!item.case_item[cw].hasOwnProperty('operator')) {
227 | item.case_item[cw].operator = "replace";
228 | }
229 | //更新参数处理
230 | let oper = item.case_item[cw].operator;
231 | switch (oper) {
232 | case 'replace':
233 | /**
234 | * 值替换 // WHEN '1' THEN balance+2
235 | */
236 | case_str.push("WHEN ? THEN ?");
237 | _self.parameters.push(item.case_item[cw].case_value);
238 | _self.parameters.push(item.case_item[cw].value);
239 | break;
240 | case "plus":
241 | /**
242 | * 值累加
243 | */
244 | case_str.push("WHEN ? THEN " + item.key + " + ?");
245 | _self.parameters.push(item.case_item[cw].case_value);
246 | _self.parameters.push(item.case_item[cw].value);
247 | break;
248 | case "reduce":
249 | /**
250 | * 值累减
251 | */
252 | case_str.push("WHEN ? THEN " + item.key + " - ?");
253 | _self.parameters.push(item.case_item[cw].case_value);
254 | _self.parameters.push(item.case_item[cw].value);
255 | break;
256 | default:
257 | /**
258 | * 其他默认为值替换更新
259 | */
260 | case_str.push("WHEN ? THEN ? ");
261 | _self.parameters.push(item.case_item[cw].case_value);
262 | _self.parameters.push(item.case_item[cw].value);
263 | break;
264 | }
265 | }
266 | //结尾
267 | case_str.push("END) ");
268 | //追加到参数模型
269 | _self.set.push(case_str.join(' '));
270 |
271 | }
272 | else {
273 |
274 | /**
275 | * 默认逻辑处理,默认替换更新
276 | */
277 | if (!paras.update[i].hasOwnProperty('operator')) {
278 | paras.update[i].operator = "replace";
279 | }
280 | //更新参数处理
281 | let oper = paras.update[i].operator;
282 | switch (oper) {
283 | case 'replace':
284 | /**
285 | * 值替换
286 | */
287 | _self.set.push(paras.update[i].key + '=?');
288 | _self.parameters.push(paras.update[i].value);
289 | break;
290 | case "plus":
291 | /**
292 | * 值累加
293 | */
294 | _self.set.push(paras.update[i].key + '=' + paras.update[i].key + "+ ?");
295 | _self.parameters.push(paras.update[i].value);
296 | break;
297 | case "reduce":
298 | /**
299 | * 值累减
300 | */
301 | _self.set.push(paras.update[i].key + '=' + paras.update[i].key + "- ?");
302 | _self.parameters.push(paras.update[i].value);
303 | break;
304 | default:
305 | /**
306 | * 其他默认为值替换更新
307 | */
308 | _self.set.push(paras.update[i].key + '=?');
309 | _self.parameters.push(paras.update[i].value);
310 | break;
311 | }
312 | }
313 | }
314 |
315 | /**
316 | * where条件以及参数处理
317 | * keyword:查询条件
318 | */
319 | paras.keyword = paras.keyword || paras.where;
320 | //遍历查询条件参数
321 | for (let i in paras.keyword) {
322 | /**
323 | * keyword里面是对象数组{"key":"","value":"","logic":"and","operator:"="}
324 | */
325 | if (paras.keyword[i] != '') {
326 | /**
327 | * 默认逻辑处理,允许部分参数不填写
328 | */
329 | if (!paras.keyword[i].hasOwnProperty('logic')) {
330 | paras.keyword[i].logic = "and";
331 | }
332 |
333 | //逻辑运算
334 | if (paras.keyword[i].hasOwnProperty('operator')) {
335 | let oper = paras.keyword[i].operator;
336 | switch (oper) {
337 | case '=':
338 | case ">":
339 | case "<":
340 | case "<>":
341 | case ">=":
342 | case "<=":
343 | _self.where.push(' ' + paras.keyword[i].logic + ' ' + paras.keyword[i].key + oper + "?");
344 | //参数化
345 | _self.parameters.push(paras.keyword[i].value);
346 | break;
347 | case '%':
348 | //模糊查询,logic需要指定link逻辑运算
349 | //左侧模糊匹配查询
350 | _self.where.push(' ' + paras.keyword[i].logic + ' ' + paras.keyword[i].key + oper + "?");
351 | //参数化
352 | _self.parameters.push('%' + paras.keyword[i].value);
353 | break;
354 | case 'x%':
355 | //模糊查询,logic需要指定link逻辑运算
356 | //右侧模糊匹配查询
357 | _self.where.push(' ' + paras.keyword[i].logic + ' ' + paras.keyword[i].key + oper + "?");
358 | //参数化
359 | _self.parameters.push(paras.keyword[i].value + '%');
360 | break;
361 | case '%%':
362 | //模糊查询,logic需要指定link逻辑运算
363 | _self.where.push(' ' + paras.keyword[i].logic + ' ' + paras.keyword[i].key + oper + "?");
364 | //参数化
365 | _self.parameters.push('%' + paras.keyword[i].value + '%');
366 | break;
367 | case "in":
368 | case "not in":
369 | let _item = ' ' + paras.keyword[i].logic + ' ' + paras.keyword[i].key + " " + oper + " ("
370 | //包含查询,利用数据遍历的方式实现
371 | let p = [];
372 | for (let c in paras.keyword[i].value) {
373 | //参数化
374 | _self.parameters.push(paras.keyword[i].value[c]);
375 | p.push('?');
376 | }
377 | _item += p.join(',') + ")"; //sql语句
378 | _self.where.push(_item);
379 | break;
380 | }
381 | }
382 |
383 | }
384 | }
385 | /**
386 | * where条件字符串组装
387 | */
388 | _self.where = ' 1=1 ' + _self.where.join('');
389 | /**
390 | * 返回结果
391 | */
392 | return _self;
393 | }
394 |
395 | /**
396 | * 获取实例删除参数
397 | * 注意,一般情况下不推荐直接物理删除
398 | * @param paras 原始参数集合
399 | * {
400 | * "where":[]
401 | * }
402 | * author:joey
403 | * create time:2018-04-26
404 | */
405 | m.getDeleteParameters = function (paras) {
406 | //返回的参数集合
407 | let _self = {'where': [], 'parameters': []};
408 |
409 | /**
410 | * where条件以及参数处理
411 | * keyword:查询条件
412 | */
413 | paras.keyword = paras.keyword || paras.where;
414 | //遍历查询条件参数
415 | for (let i in paras.keyword) {
416 | /**
417 | * keyword里面是对象数组{"key":"","value":"","logic":"and","operator:"="}
418 | */
419 | if (paras.keyword[i] != '') {
420 | /**
421 | * 默认逻辑处理,允许部分参数不填写
422 | */
423 | if (!paras.keyword[i].hasOwnProperty('logic')) {
424 | paras.keyword[i].logic = "and";
425 | }
426 |
427 | //逻辑运算
428 | if (paras.keyword[i].hasOwnProperty('operator')) {
429 | let oper = paras.keyword[i].operator;
430 | switch (oper) {
431 | case '=':
432 | case ">":
433 | case "<":
434 | case "<>":
435 | case ">=":
436 | case "<=":
437 | _self.where.push(' ' + paras.keyword[i].logic + ' ' + paras.keyword[i].key + oper + "?");
438 | //参数化
439 | _self.parameters.push(paras.keyword[i].value);
440 | break;
441 | case '%':
442 | //模糊查询,logic需要指定link逻辑运算
443 | //左侧模糊匹配查询
444 | _self.where.push(' ' + paras.keyword[i].logic + ' ' + paras.keyword[i].key + oper + "?");
445 | //参数化
446 | _self.parameters.push('%' + paras.keyword[i].value);
447 | break;
448 | case 'x%':
449 | //模糊查询,logic需要指定link逻辑运算
450 | //右侧模糊匹配查询
451 | _self.where.push(' ' + paras.keyword[i].logic + ' ' + paras.keyword[i].key + oper + "?");
452 | //参数化
453 | _self.parameters.push(paras.keyword[i].value + '%');
454 | break;
455 | case '%%':
456 | //模糊查询,logic需要指定link逻辑运算
457 | _self.where.push(' ' + paras.keyword[i].logic + ' ' + paras.keyword[i].key + oper + "?");
458 | //参数化
459 | _self.parameters.push('%' + paras.keyword[i].value + '%');
460 | break;
461 | case "in":
462 | case "not in":
463 | let _item = ' ' + paras.keyword[i].logic + ' ' + paras.keyword[i].key + " " + oper + " ("
464 | //包含查询,利用数据遍历的方式实现
465 | let p = [];
466 | for (let c in paras.keyword[i].value) {
467 | //参数化
468 | _self.parameters.push(paras.keyword[i].value[c]);
469 | p.push('?');
470 | }
471 | _item += p.join(',') + ")"; //sql语句
472 | _self.where.push(_item);
473 | break;
474 | }
475 | }
476 |
477 | }
478 | }
479 | /**
480 | * where条件字符串组装
481 | */
482 | _self.where = ' 1=1 ' + _self.where.join('');
483 | /**
484 | * 返回结果
485 | */
486 | return _self;
487 | };
488 |
489 | module.exports = m;
--------------------------------------------------------------------------------
/lib/instance/MySQLActionManager.js:
--------------------------------------------------------------------------------
1 | /**
2 | * MySql对象关系实例
3 | */
4 | const {BaseActionManager} = require('../BaseActionManager');
5 | // 语法处理
6 | const GrammarMysql = require("../grammar/mysql.js");
7 | /**
8 | * MYSQL
9 | * 单例的数据库操作管理者,负责这个数据库的基本crud,负责全局的一个连接;
10 | */
11 | class MySQLActionManager extends BaseActionManager {
12 |
13 | /**
14 | * 数据库初始化
15 | * @param config
16 | */
17 | static init(config) {
18 | const mysql = require("mysql");
19 | let connPool = mysql.createPool(config);
20 | this.conn = connPool;
21 | }
22 |
23 | // 创建事务连接
24 | static createTransaction() {
25 | let self = this;
26 | // 事务开始
27 | let begin = () => {
28 | return new Promise(function (resolve, reject) {
29 | // 直接开始事务
30 | begin.transaction.client.beginTransaction(function (err) {
31 | if (err) {
32 | throw err;
33 | }
34 | // 直接返回已经开始事务的连接池
35 | resolve(begin.transaction);
36 | });
37 | });
38 | };
39 | // 提交事务
40 | let commit = () => {
41 | return new Promise(function (resolve, reject) {
42 | commit.transaction.client.commit(() => {
43 | resolve("Transaction submitted successfully"); // 事务提交成功
44 | commit.transaction.client.release(() => {
45 |
46 | });
47 | });
48 | })
49 | };
50 | // 回滚事务
51 | let rollback = () => {
52 | return new Promise(function (resolve, reject) {
53 | rollback.transaction.client.rollback(() => {
54 | resolve("Transaction rolled back"); // 事务已回滚
55 | rollback.transaction.client.release(() => {
56 |
57 | });
58 | });
59 | });
60 | };
61 |
62 |
63 | return new Promise(function (resolve, reject) {
64 | self.conn.getConnection(function (err, connection) {
65 | if (err) {
66 | console.log('An exception occurred when creating a transaction connection', err); // 创建事务连接出现异常
67 | reject(new Error('An exception occurred when creating a transaction connection')); // 创建事务连接出现异常
68 | } else {
69 | // 事务对象
70 | let _transaction = {
71 | "client": connection
72 | // "done": done
73 | };
74 | begin.transaction = commit.transaction = rollback.transaction = _transaction;
75 | // 事件绑定
76 | _transaction.begin = begin;
77 | _transaction.commit = commit;
78 | _transaction.rollback = rollback;
79 | resolve(_transaction);
80 |
81 | // // resolve(connection);
82 | // let transaction = {
83 | // "client": connection,
84 | // // "done": done,
85 | // "begin": begin, // 开始事务
86 | // "commit": commit, // 提交事务
87 | // "rollback": rollback // 事务回滚
88 | // };
89 | // resolve(transaction);
90 | }
91 | });
92 | });
93 | }
94 |
95 | // 执行SQL
96 | static execute(sql, parameters) {
97 | let self = this;
98 | return new Promise(function (resolve, reject) {
99 | if (self.conn) {
100 | //console.time("【onela】执行SQL时间");
101 |
102 | self.conn.query(sql, parameters, function (err, doc) {
103 | //console.timeEnd("【onela】执行SQL时间");
104 | if (err) {
105 | reject(err);
106 | }
107 | else {
108 | resolve(doc);
109 | }
110 | });
111 | }
112 | else {
113 | // 数据库实例engine实例未正确指向,请检查单例configs配置是否跟dbconfig配置的engine一致
114 | reject(new Error("The database instance engine instance is not pointed correctly. Please check whether the singleton configs configuration is consistent with the engine configured in dbconfig."));
115 | }
116 | });
117 | }
118 |
119 | // 执行带事务的实例对象
120 | static executeTransaction(sql, parameters, transaction) {
121 |
122 | return new Promise((resolve, reject) => {
123 | // console.log(sql);
124 | //console.log('事务对象', transaction.client.query)
125 | if (transaction && transaction.client) {
126 | //console.time("【onela】执行SQL时间");
127 | // 事务连接池
128 | transaction.client.query(sql, parameters, function (err, doc) {
129 | //console.timeEnd("【onela】执行SQL时间");
130 | if (err) {
131 | reject(err);
132 | }
133 | else {
134 | resolve(doc);
135 | }
136 | });
137 | }
138 | else {
139 | // 数据库实例engine实例未正确指向,请检查单例configs配置是否跟dbconfig配置的engine一致
140 | reject(new Error("The database instance engine instance is not pointed correctly. Please check whether the singleton configs configuration is consistent with the engine configured in dbconfig."));
141 | }
142 | });
143 | }
144 |
145 | /**
146 | * 数据实例查询
147 | * @param params 查询模型参数
148 | * @param option 其他参数
149 | * @returns {Promise.}
150 | */
151 | static queryEntity(params, option = {"transaction": null}) {
152 | let self = this;
153 | let p = GrammarMysql.getParameters(params);
154 |
155 | let sql = "select " + p["select"] + " from " + params.configs.tableName + " as t " + p.where + p.orderBy + p.limit + ";";
156 | // 执行SQL
157 | if (option && option.transaction) {
158 | // 事务连接池
159 | return self.executeTransaction(sql, p.parameters, option.transaction)
160 | .catch(err => {
161 | console.log('Error when executing execute query data list', err); // 执行execute查询数据列表出错
162 | return Promise.reject(err);
163 | });
164 | }
165 | else {
166 | return self.execute(sql, p.parameters)
167 | .catch(err => {
168 | console.error('Error when executing execute query data list', err); // 执行execute查询数据列表出错
169 | return Promise.reject(err);
170 | });
171 | }
172 | }
173 |
174 | /**
175 | * 分页查询数据列表
176 | * @param params 查询参数
177 | * @param option 其他参数
178 | * @returns {Promise.}
179 | */
180 | static queryEntityList(params, option = {"transaction": null}) {
181 | let self = this;
182 | let p = GrammarMysql.getParameters(params);
183 | /**
184 | * 分页数据查询
185 | */
186 | let sql = "select " + p["select"] + " from " + params.configs.tableName + " t " + p.where + " " + p.orderBy + p.limit + ";";
187 | let count_sql = "select count(0) total from " + params.configs.tableName + " t " + p.where;
188 |
189 | //执行SQL
190 | if (option && option.transaction) {
191 | return Promise.all([
192 | self.executeTransaction(sql, p.parameters, option.transaction),
193 | self.executeTransaction(count_sql, p.parameters, option.transaction)
194 | ]).then(result => {
195 | return Promise.resolve({data: result[0], recordsTotal: result[1]});
196 | }).catch(ex => {
197 | console.error('Error when executing execute query data list', ex); // 执行execute查询数据列表出错
198 | return Promise.reject(ex);
199 | });
200 |
201 | }
202 | else {
203 | return Promise.all([
204 | self.execute(sql, p.parameters),
205 | self.execute(count_sql, p.parameters)
206 | ]).then(result => {
207 | return Promise.resolve({data: result[0], recordsTotal: result[1]});
208 | }).catch(ex => {
209 | console.error('Error when executing execute query data list', ex); // 执行execute查询数据列表出错
210 | return Promise.reject(ex);
211 | });
212 | }
213 | }
214 |
215 | /**
216 | * 获取数据瀑布
217 | * @param params 查询参数
218 | * @param option 其他参数
219 | * @returns {Promise.}
220 | */
221 | static getEntityWaterfall(params, option = {"transaction": null}) {
222 | let self = this;
223 | // 参数预处理
224 | if (params.hasOwnProperty("limit")) {
225 | //如果limit里面参数个数不符合
226 | if (params.limit.length == 1) {
227 | params.limit = [0, params.limit[0]]; //默认10个
228 | }
229 | //这里处理
230 | params.limit[0] = parseInt(params.limit[0]);
231 | //长度+1
232 | params.limit[1] = parseInt(params.limit[1]) + 1;
233 | }
234 | // 参数结构化
235 | let p = GrammarMysql.getParameters(params);
236 | // 拼装SQL
237 | let sql = ["select ", p["select"], " from ", params.configs.tableName, " as t ", p.where, p.orderBy, p.limit + ";"];
238 | // 执行SQL
239 | if (option && option.transaction) {
240 | // 事务连接池
241 | return self.executeTransaction(sql.join(""), p.parameters, option.transaction).then(data => {
242 | // 定义返回结果
243 | let result = {"data": data, "isLastPage": false};
244 | if (result.data.length == 0) {
245 | result.isLastPage = true; // 未查询到数据,显示最后一页
246 | }
247 | else if (result.data.length < (params.limit[1] - 1)) {
248 | //最后一页数据
249 | result.isLastPage = true; // 最后一页
250 | }
251 | else {
252 | //记录数等于length+1,删除最后一条数据
253 | if (result.data.length > (params.limit[1] - 1))
254 | result.data.pop();
255 | }
256 | return Promise.resolve(result);
257 | }).catch(err => {
258 | console.error('Error when executing execute query data list', err); // 执行execute查询数据列表出错
259 | return Promise.reject(err);
260 | });
261 | }
262 | else {
263 | return self.execute(sql.join(""), p.parameters).then(data => {
264 | // 定义返回结果
265 | let result = {"data": data, "isLastPage": false};
266 | if (result.data.length == 0) {
267 | result.isLastPage = true; // 未查询到数据,显示最后一页
268 | }
269 | else if (result.data.length < (params.limit[1] - 1)) {
270 | //最后一页数据
271 | result.isLastPage = true; // 最后一页
272 | }
273 | else {
274 | //记录数等于length+1,删除最后一条数据
275 | if (result.data.length > (params.limit[1] - 1))
276 | result.data.pop();
277 | }
278 | return Promise.resolve(result);
279 | }).catch(err => {
280 | console.error('Error when executing execute query data list', err); // 执行execute查询数据列表出错
281 | return Promise.reject(err);
282 | });
283 | }
284 | }
285 |
286 | /**
287 | * 新增
288 | * @param entity 新增实体对象
289 | * @param option 其他参数
290 | * @returns {Promise.}
291 | */
292 | static insert(params, option = {"transaction": null}) {
293 | let p = [], f = [], s = [];
294 | for (let i in params.insertion) {
295 | //参数值
296 | p.push(params.insertion[i]);
297 | //字段名称集合
298 | f.push(i);
299 | //sql参数化处理符合
300 | s.push('?');
301 | }
302 | let sql = "insert into " + params.configs.tableName + "(" + f.join(',') + ") values(" + s.join(',') + ");";
303 |
304 | // 执行SQL
305 | if (option && option.transaction) {
306 | return this.executeTransaction(sql, p, option.transaction).then((data) => {
307 | // 返回浅拷贝
308 | let insertion = Object.assign(params.insertion, {"_returns": data});
309 | return Promise.resolve(insertion);
310 | }).catch(ex => {
311 | throw ex;
312 | });
313 | }
314 | else {
315 | return this.execute(sql, p).then((data) => {
316 | // 返回浅拷贝
317 | let insertion = Object.assign(params.insertion, {"_returns": data});
318 | return Promise.resolve(insertion);
319 | }).catch(ex => {
320 | throw ex;
321 | });
322 | }
323 | }
324 |
325 | /**
326 | * 批量新增
327 | * @param entity_list 新增实体对象列表
328 | * @param option 其他参数
329 | * @returns {Promise.}
330 | */
331 | static insertBatch(params, option = {"transaction": null}) {
332 | let p = [], f = [], s = [];
333 | for (let i in params.insertion) {
334 | let s2 = [];
335 | for (let j in params.insertion[i]) {
336 | if (i == 0) {
337 | //字段名称集合,大于0就不需要继续了
338 | f.push("`" + j + "`");
339 | }
340 | //参数值
341 | p.push(params.insertion[i][j]);
342 | //sql参数化处理符合
343 | s2.push('?');
344 | }
345 | //置入
346 | s.push('(' + s2.join(',') + ')');
347 | }
348 | //SQL执行
349 | let sql = "insert into " + params.configs.tableName + "(" + f.join(',') + ") values" + s.join(',') + ";";
350 | // 执行SQL
351 | if (option && option.transaction) {
352 | return this.executeTransaction(sql, p, option.transaction);
353 | }
354 | else {
355 | return this.execute(sql, p);
356 | }
357 | }
358 |
359 | /**
360 | * 物理删除
361 | * @param params 删除条件参数
362 | * @param option 其他参数
363 | * @returns {Promise.}
364 | */
365 | static deleteEntity(params, option = {"transaction": null}) {
366 | if ((!params.hasOwnProperty('keyword') || params.keyword.length == 0) && (!params.hasOwnProperty('where') || params.where.length == 0)) {
367 | return Promise.reject('Deletion conditions need to be specified to prevent the entire table data from being accidentally deleted.'); // 需要指定删除条件,防止整表数据误删除
368 | }
369 | let p = GrammarMysql.getDeleteParameters(params);
370 | let sql = "delete from " + params.configs.tableName + " where " + p.where + ";";
371 |
372 | // 执行SQL
373 | if (option && option.transaction) {
374 | return this.executeTransaction(sql, p.parameters, option.transaction);
375 | }
376 | else {
377 | return this.execute(sql, p.parameters);
378 | }
379 | }
380 |
381 | /**
382 | * 实体对象更新
383 | * @param params 更新模型参数
384 | * @param option 其他参数
385 | * @returns {*}
386 | */
387 | static updateEntity(params, option = {"transaction": null}) {
388 | let p = GrammarMysql.getUpdateParameters(params);
389 | let _limit = "";
390 | if (params.limit && params.hasOwnProperty('limit')) {
391 | _limit = " limit ?";
392 | p.parameters.push(params.limit);
393 | }
394 | let sql = "update " + params.configs.tableName + " set " + p.set.join(',') + " where " + p.where + _limit + ";";
395 | // 执行SQL
396 | if (option && option.transaction) {
397 | return this.executeTransaction(sql, p.parameters, option.transaction);
398 | }
399 | else {
400 | return this.execute(sql, p.parameters);
401 | }
402 | }
403 |
404 | /**
405 | * 统计查询
406 | * @param params 查询参数
407 | * @param option 其他参数
408 | * @returns {Promise.}
409 | */
410 | static statsByAggregate(params, option = {"transaction": null}) {
411 | let p = GrammarMysql.getParameters(params);
412 | let check = {
413 | "count": "COUNT",
414 | "sum": "SUM",
415 | "max": "MAX",
416 | "min": "MIN",
417 | "abs": "ABS",
418 | "avg": "AVG"
419 | };
420 | let show = [];
421 | for (let i in params.aggregate) {
422 | let c = params.aggregate[i];
423 | let item = check[c.function.toLowerCase()];
424 | if (item) {
425 | show.push(item + "(" + c.field + ") as " + c.name);
426 | }
427 | }
428 | //sql
429 | let sql = "select " + show.join(',') + " from " + params.configs.tableName + " " + p.where + p.limit + ";";
430 | // 执行SQL
431 | if (option && option.transaction) {
432 | return this.executeTransaction(sql, p.parameters, option.transaction);
433 | }
434 | else {
435 | return this.execute(sql, p.parameters);
436 | }
437 | }
438 |
439 | /**
440 | * 自定义SQL执行(裸奔,一般不建议用)
441 | * @param sql SQL语句
442 | * @param parameters 参数
443 | * @param option 其他参数
444 | * @returns {Promise.}
445 | */
446 | static streak(sql, parameters, option = {"transaction": null}) {
447 | let self = this;
448 |
449 | // 执行SQL
450 | if (option && option.transaction) {
451 | // 事务连接池
452 | return self.executeTransaction(sql, parameters, option.transaction,"all")
453 | .catch(err => {
454 | console.error('Exception when executing execute query data list', err); // 执行execute查询数据列表异常
455 | return Promise.reject(err);
456 | });
457 | }
458 | else {
459 | return self.execute(sql, parameters,"all")
460 | .catch(err => {
461 | console.error('Exception when executing execute query data list', err); // 执行execute查询数据列表异常
462 | return Promise.reject(err);
463 | });
464 | }
465 | }
466 | }
467 |
468 | module.exports = {MySQLActionManager};
--------------------------------------------------------------------------------
/lib/instance/PostgreSQLActionManager.js:
--------------------------------------------------------------------------------
1 | /**
2 | * MySql对象关系实例
3 | */
4 | const {BaseActionManager} = require('../BaseActionManager');
5 | // 语法处理
6 | const GrammarMysql = require("../grammar/postgresql.js");
7 | /**
8 | * PostgreSQL
9 | * 单例的数据库操作管理者,负责这个数据库的基本crud,负责全局的一个连接;
10 | */
11 | class PostgreSQLActionManager extends BaseActionManager {
12 |
13 | /**
14 | * 数据库初始化
15 | * @param config
16 | */
17 | static init(config) {
18 | const {Pool, Client} = require('pg');
19 | // const pool = new Pool({
20 | // user: 'dbuser',
21 | // host: 'database.server.com',
22 | // database: 'mydb',
23 | // password: 'secretpassword',
24 | // port: 3211,
25 | // })
26 | const connPool = new Pool(config);
27 | this.conn = connPool;
28 | }
29 |
30 | // 创建事务连接
31 | static createTransaction() {
32 | let self = this;
33 |
34 | // 事务开始
35 | let begin = () => {
36 | return new Promise(function (resolve, reject) {
37 | // 直接开始事务
38 |
39 | begin.transaction.client.query('BEGIN', (ex) => {
40 | if (ex) {
41 | begin.transaction.client.query('ROLLBACK', (err) => {
42 | console.error('Transaction exception!', err); // 事务异常
43 | reject("Transaction exception!")
44 | });
45 | }
46 | else {
47 | // 开始提交事务
48 | resolve(null);
49 | }
50 | });
51 | });
52 | };
53 | // 提交事务
54 | let commit = () => {
55 | return new Promise(function (resolve, reject) {
56 |
57 | commit.transaction.client.query('COMMIT', (err) => {
58 | if (err) {
59 | console.error('Error committing transaction', err.stack)
60 | }
61 | commit.transaction.done();
62 | resolve("Transaction submitted successfully!"); // 事务提交成功
63 | });
64 | })
65 | };
66 | // 回滚事务
67 | let rollback = () => {
68 | return new Promise(function (resolve, reject) {
69 | // 事务回滚
70 | rollback.transaction.client.query('ROLLBACK', (err) => {
71 | if (err) {
72 | console.error('Error rolling back client', err.stack)
73 | reject(Error('Error rolling back client ' + err.stack));
74 | }
75 | // release the client back to the pool
76 | rollback.transaction.done();
77 | resolve("Transaction rolled back!"); // 事务已回滚
78 | });
79 | });
80 | };
81 |
82 | return new Promise(function (resolve, reject) {
83 | // 创建事务连接
84 | self.conn.connect((err, client, done) => {
85 | if (err) {
86 | console.error('An exception occurred when creating a transaction connection', err); // 创建事务连接出现异常
87 | reject(new Error('An exception occurred when creating a transaction connection')); // An exception occurred when creating a transaction connection
88 | } else {
89 | // 事务对象
90 | let _transaction = {
91 | "client": client,
92 | "done": done
93 | };
94 | begin.transaction = commit.transaction = rollback.transaction = _transaction
95 | // 事件绑定
96 | _transaction.begin = begin;
97 | _transaction.commit = commit;
98 | _transaction.rollback = rollback;
99 |
100 | // let transaction = {
101 | // // "client": client,
102 | // // "done": done,
103 | // "begin": begin, // 事务开始
104 | // "commit": commit, // 事务提交
105 | // "rollback": rollback // 事务回滚
106 | // };
107 |
108 |
109 | resolve(_transaction);
110 | }
111 | });
112 | });
113 | }
114 |
115 | // 执行SQL
116 | static execute(sql, parameters) {
117 | let self = this;
118 | return new Promise(function (resolve, reject) {
119 | if (self.conn) {
120 | //console.time("【onela】执行SQL时间");
121 |
122 | const query = {
123 | text: sql, //'INSERT INTO users(name, email) VALUES($1, $2)',
124 | values: parameters, //['brianc', 'brian.m.carlson@gmail.com'],
125 | };
126 | // console.log("query", query)
127 | self.conn.query(query, function (err, doc) {
128 | //console.timeEnd("【onela】执行SQL时间");
129 | if (err) {
130 | reject(err);
131 | }
132 | else {
133 | resolve(doc);
134 | }
135 | });
136 | }
137 | else {
138 | // 数据库实例engine实例未正确指向,请检查单例configs配置是否跟dbconfig配置的engine一致
139 | reject(new Error("The database instance engine instance is not pointed correctly. Please check whether the singleton configs configuration is consistent with the engine configured in dbconfig."));
140 | }
141 | });
142 | }
143 |
144 | // 执行带事务的实例对象
145 | static executeTransaction(sql, parameters, transaction) {
146 |
147 | return new Promise((resolve, reject) => {
148 | console.log('Execute transaction', sql); // 执行事务
149 | if (transaction && transaction.client) {
150 | //console.time("【onela】执行SQL时间");
151 | // 事务连接池
152 | const query = {
153 | text: sql, //'INSERT INTO users(name, email) VALUES($1, $2)',
154 | values: parameters, //['brianc', 'brian.m.carlson@gmail.com'],
155 | };
156 | //console.log('事务对象', transaction.client)
157 | transaction.client.query(query, function (err, doc) {
158 | //console.timeEnd("【onela】执行SQL时间");
159 | if (err) {
160 | console.error('Execution transaction exception!', err)
161 | reject(err);
162 | }
163 | else {
164 | resolve(doc);
165 | }
166 | });
167 | }
168 | else {
169 | // 数据库实例engine实例未正确指向,请检查单例configs配置是否跟dbconfig配置的engine一致
170 | reject(new Error("The database instance engine instance is not pointed correctly. Please check whether the singleton configs configuration is consistent with the engine configured in dbconfig."));
171 | }
172 | });
173 | }
174 |
175 | /**
176 | * 数据实例查询
177 | * @param params 查询模型参数
178 | * @param option 其他参数
179 | * @returns {Promise.}
180 | */
181 | static queryEntity(params, option = {"transaction": null}) {
182 | let self = this;
183 | let p = GrammarMysql.getParameters(params);let sql = `SELECT ${p["select"]} FROM ${params.configs.tableName} as t ${p.where} ${p.groupBy} ${p.orderBy} ${p.limit};`;
184 | //console.log('sql>>>', sql);
185 | // 执行SQL
186 | if (option && option.transaction) {
187 | // 事务连接池
188 | return self.executeTransaction(sql, p.parameters, option.transaction)
189 | .then(data => {
190 | return Promise.resolve(data.rows);
191 | })
192 | .catch(err => {
193 | console.error('Error when executing execute query data list', err); // 执行execute查询数据列表出错
194 | return Promise.reject(err);
195 | });
196 | }
197 | else {
198 | return self.execute(sql, p.parameters)
199 | .then(data => {
200 | return Promise.resolve(data.rows);
201 | })
202 | .catch(err => {
203 | console.error('Error when executing execute query data list', err); // 执行execute查询数据列表出错
204 | return Promise.reject(err);
205 | });
206 | }
207 | }
208 |
209 | /**
210 | * 分页查询数据列表
211 | * @param params 查询参数
212 | * @param option 其他参数
213 | * @returns {Promise.}
214 | */
215 | static queryEntityList(params, option = {"transaction": null}) {
216 | let self = this;
217 | let p = GrammarMysql.getParameters(params);
218 |
219 | //变量定义
220 | let result = {
221 | "data": [], //数据列表
222 | "recordsTotal": 0 //查询记录总数
223 | };
224 | /**
225 | * 分页数据查询
226 | */
227 | let sql = `select ${p["select"]} from ${params.configs.tableName} t ${p.where} ${p.orderBy} ${p.limit};`;
228 | let count_sql = `select count(0) total from ${params.configs.tableName} t ${p.where}`;
229 | // count 参数
230 | var countP = [...p.parameters];
231 | if (params.limit && params.limit.length>0) {
232 | countP = countP.splice(0,countP.length -params.limit.length);
233 | }
234 |
235 | //执行SQL
236 | if (option && option.transaction) {
237 | return Promise.all([
238 | self.executeTransaction(sql, p.parameters, option.transaction).then(data => {
239 | return Promise.resolve(data.rows)
240 | }),
241 | self.executeTransaction(count_sql, countP, option.transaction).then(data => {
242 | return Promise.resolve(data.rows)
243 | })
244 | ]).then(result => {
245 | return Promise.resolve({data: result[0], recordsTotal: result[1]});
246 | }).catch(ex => {
247 | console.error('Error when executing execute query data list', ex); // 执行execute查询数据列表出错
248 | return Promise.reject(ex);
249 | });
250 | }
251 | else {
252 | return Promise.all([
253 | self.execute(sql, p.parameters).then(data => {
254 | return Promise.resolve(data.rows)
255 | }),
256 | self.execute(count_sql, countP).then(data => {
257 | return Promise.resolve(data.rows)
258 | })
259 | ]).then(result => {
260 | return Promise.resolve({data: result[0], recordsTotal: result[1]});
261 | }).catch(ex => {
262 | console.error('Error when executing execute query data list', ex); // 执行execute查询数据列表出错
263 | return Promise.reject(ex);
264 | });
265 | }
266 |
267 | }
268 |
269 | /**
270 | * 获取数据瀑布
271 | * @param params 查询参数
272 | * @param option 其他参数
273 | * @returns {Promise.}
274 | */
275 | static getEntityWaterfall(params, option = {"transaction": null}) {
276 | let self = this;
277 | // 参数预处理
278 | if (params.hasOwnProperty("limit")) {
279 | //如果limit里面参数个数不符合
280 | if (params.limit.length == 1) {
281 | params.limit = [0, params.limit[0]]; //默认10个
282 | }
283 | //这里处理
284 | params.limit[0] = parseInt(params.limit[0]);
285 | //长度+1
286 | params.limit[1] = parseInt(params.limit[1]) + 1;
287 | }
288 | // 参数结构化
289 | let p = GrammarMysql.getParameters(params);
290 | // 拼装SQL
291 | let sql = ["select ", p["select"], " from ", params.configs.tableName, " as t ", p.where, p.orderBy, p.limit + ";"];
292 | // 执行SQL
293 | if (option && option.transaction) {
294 | // 事务连接池
295 | return self.executeTransaction(sql.join(""), p.parameters, option.transaction).then(data => {
296 | // 定义返回结果
297 | let result = {"data": data.rows, "isLastPage": false};
298 | if (result.data.length == 0) {
299 | result.isLastPage = true; // 未查询到数据,显示最后一页
300 | }
301 | else if (result.data.length < (params.limit[1] - 1)) {
302 | //最后一页数据
303 | result.isLastPage = true; // 最后一页
304 | }
305 | else {
306 | //记录数等于length+1,删除最后一条数据
307 | if (result.data.length > (params.limit[1] - 1))
308 | result.data.pop();
309 | }
310 | return Promise.resolve(result);
311 | }).catch(err => {
312 | console.error('Error when executing execute query data list', err); // 执行execute查询数据列表出错
313 | return Promise.reject(err);
314 | });
315 | }
316 | else {
317 | return self.execute(sql.join(""), p.parameters).then(data => {
318 | // 定义返回结果
319 | let result = {"data": data.rows, "isLastPage": false};
320 | if (result.data.length == 0) {
321 | result.isLastPage = true; // 未查询到数据,显示最后一页
322 | }
323 | else if (result.data.length < (params.limit[1] - 1)) {
324 | //最后一页数据
325 | result.isLastPage = true; // 最后一页
326 | }
327 | else {
328 | //记录数等于length+1,删除最后一条数据
329 | if (result.data.length > (params.limit[1] - 1))
330 | result.data.pop();
331 | }
332 | return Promise.resolve(result);
333 | }).catch(err => {
334 | console.error('Error when executing execute query data list', err); // 执行execute查询数据列表出错
335 | return Promise.reject(err);
336 | });
337 | }
338 | }
339 |
340 | /**
341 | * 新增
342 | * @param entity 新增实体对象
343 | * @param option 其他参数
344 | * @returns {Promise.}
345 | */
346 | static insert(params, option = {"transaction": null}) {
347 | let p = [], f = [], s = [], index = 0;
348 | for (let i in params.insertion) {
349 | //参数值
350 | p.push(params.insertion[i]);
351 | //字段名称集合
352 | f.push(i);
353 | //sql参数化处理符合
354 | index++;
355 | s.push('$' + index);
356 | }
357 | let sql = "insert into " + params.configs.tableName + "(" + f.join(',') + ") values(" + s.join(',') + ");";
358 |
359 |
360 |
361 | // 执行SQL
362 | if (option && option.transaction) {
363 | return this.executeTransaction(sql, p, option.transaction).then((data) => {
364 | // 返回浅拷贝
365 | let insertion = Object.assign(params.insertion, {"_returns": data});
366 | return Promise.resolve(insertion);
367 | }).catch(ex => {
368 | throw ex;
369 | });
370 | }
371 | else {
372 | return this.execute(sql, p).then((data) => {
373 | // 返回浅拷贝
374 | let insertion = Object.assign(params.insertion, {"_returns": data});
375 | return Promise.resolve(insertion);
376 | }).catch(ex => {
377 | throw ex;
378 | });
379 | }
380 | }
381 |
382 | /**
383 | * 批量新增
384 | * @param entity_list 新增实体对象列表
385 | * @param option 其他参数
386 | * @returns {Promise.}
387 | */
388 | static insertBatch(params, option = {"transaction": null}) {
389 | let p = [], f = [], s = [], index = 0;
390 | for (let i in params.insertion) {
391 | let s2 = [];
392 | for (let j in params.insertion[i]) {
393 | if (i == 0) {
394 | //字段名称集合,大于0就不需要继续了
395 | f.push(j);
396 | }
397 | //参数值
398 | p.push(params.insertion[i][j]);
399 | //sql参数化处理符合
400 | index++;
401 | s2.push('$' + index);
402 | }
403 | //置入
404 | s.push('(' + s2.join(',') + ')');
405 | }
406 | //SQL执行
407 | let sql = "insert into " + params.configs.tableName + "(" + f.join(',') + ") values" + s.join(',') + ";";
408 | // 执行SQL
409 | if (option && option.transaction) {
410 | return this.executeTransaction(sql, p, option.transaction);
411 | }
412 | else {
413 | return this.execute(sql, p);
414 | }
415 | }
416 |
417 | /**
418 | * 物理删除
419 | * @param params 删除条件参数
420 | * @param option 其他参数
421 | * @returns {Promise.}
422 | */
423 | static deleteEntity(params, option = {"transaction": null}) {
424 | if ((!params.hasOwnProperty('keyword') || params.keyword.length == 0) && (!params.hasOwnProperty('where') || params.where.length == 0)) {
425 | return Promise.reject('Deletion conditions need to be specified to prevent the entire table data from being accidentally deleted.'); // 需要指定删除条件,防止整表数据误删除
426 | }
427 | let p = GrammarMysql.getDeleteParameters(params);
428 | let sql = "delete from " + params.configs.tableName + " where " + p.where + ";";
429 |
430 | // 执行SQL
431 | if (option && option.transaction) {
432 | return this.executeTransaction(sql, p.parameters, option.transaction);
433 | }
434 | else {
435 | return this.execute(sql, p.parameters);
436 | }
437 | }
438 |
439 | /**
440 | * 实体对象更新
441 | * @param params 更新模型参数
442 | * @param option 其他参数
443 | * @returns {*}
444 | */
445 | static updateEntity(params, option = {"transaction": null}) {
446 | let p = GrammarMysql.getUpdateParameters(params);
447 | let _limit = "";
448 | if (params.limit && params.hasOwnProperty('limit')) {
449 | _limit = " limit ?";
450 | p.parameters.push(params.limit);
451 | }
452 | let sql = "update " + params.configs.tableName + " set " + p.set.join(',') + " where " + p.where + _limit + ";";
453 | // 执行SQL
454 | if (option && option.transaction) {
455 | return this.executeTransaction(sql, p.parameters, option.transaction);
456 | }
457 | else {
458 | return this.execute(sql, p.parameters);
459 | }
460 | }
461 |
462 | /**
463 | * 统计查询
464 | * @param params 查询参数
465 | * @param option 其他参数
466 | * @returns {Promise.}
467 | */
468 | static statsByAggregate(params, option = {"transaction": null}) {
469 | let p = GrammarMysql.getParameters(params);
470 | let check = {
471 | "count": "COUNT",
472 | "sum": "SUM",
473 | "max": "MAX",
474 | "min": "MIN",
475 | "abs": "ABS",
476 | "avg": "AVG"
477 | };
478 | let show = [];
479 | for (let i in params.aggregate) {
480 | let c = params.aggregate[i];
481 | let item = check[c.function.toLowerCase()];
482 | if (item) {
483 | show.push(item + "(" + c.field + ") as " + c.name);
484 | }
485 | }
486 | //sql
487 | let sql = "select " + show.join(',') + " from " + params.configs.tableName + " " + p.where + p.limit + ";";
488 | // 执行SQL
489 | if (option && option.transaction) {
490 | return this.executeTransaction(sql, p.parameters, option.transaction)
491 | .then(data => {
492 | return Promise.resolve(data.rows);
493 | });
494 | }
495 | else {
496 | return this.execute(sql, p.parameters).then(data => {
497 | return Promise.resolve(data.rows);
498 | });
499 | }
500 | }
501 |
502 | /**
503 | * 自定义SQL执行(裸奔,一般不建议用)
504 | * @param sql SQL语句
505 | * @param parameters 参数
506 | * @param option 其他参数
507 | * @returns {Promise.}
508 | */
509 | static streak(sql, parameters, option = {"transaction": null}) {
510 | let self = this;
511 |
512 | // 执行SQL
513 | if (option && option.transaction) {
514 | // 事务连接池
515 | return self.executeTransaction(sql, parameters, option.transaction,"all")
516 | .catch(err => {
517 | console.error('Exception when executing execute query data list', err); // 执行execute查询数据列表异常
518 | return Promise.reject(err);
519 | });
520 | }
521 | else {
522 | return self.execute(sql, parameters,"all")
523 | .catch(err => {
524 | console.error('Exception when executing execute query data list', err); // 执行execute查询数据列表异常
525 | return Promise.reject(err);
526 | });
527 | }
528 | }
529 | }
530 |
531 | module.exports = {PostgreSQLActionManager};
--------------------------------------------------------------------------------
/lib/instance/SQLiteSQLActionManager.js:
--------------------------------------------------------------------------------
1 | /**
2 | * MySql对象关系实例
3 | */
4 | const {BaseActionManager} = require('../BaseActionManager');
5 | // 语法处理
6 | const GrammarSqlite = require("../grammar/sqlite.js");
7 | /**
8 | * MYSQL
9 | * 单例的数据库操作管理者,负责这个数据库的基本crud,负责全局的一个连接;
10 | */
11 | class SQLiteActionManager extends BaseActionManager {
12 |
13 | /**
14 | * 数据库初始化
15 | * @param config
16 | */
17 | static init(config) {
18 | // console.log('配置信息', config);
19 |
20 | const SQLite3 = require('sqlite3').verbose();
21 |
22 | // 链接数据库对象
23 | this.host = config.host; // 数据库文件(文件路径+文件名)
24 |
25 | // 打开的数据库对象(不存在则创建)
26 | this.conn = new SQLite3.Database(config.host, function (err) {
27 | if (err) console.log("SQLite database connection exception", err); // SQLite数据库连接异常
28 | else console.log("SQLite database connection successful"); // SQLite数据库连接成功
29 | });
30 | }
31 |
32 | // 数据库连接
33 | static connectDataBase() {
34 | let self = this;
35 | return new Promise((resolve, reject) => {
36 | if (!self.conn) {
37 | self.conn = new SQLite3.Database(self.host, function (err) {
38 | if (err) reject(new Error(err));
39 | resolve(self.conn);
40 | });
41 | }
42 | else {
43 | resolve(self.conn);
44 | }
45 | });
46 | }
47 |
48 | // 创建事务连接
49 | static createTransaction() {
50 | let self = this;
51 | // 事务开始
52 | let begin = () => {
53 | return new Promise(function (resolve, reject) {
54 | // 直接开始事务
55 | begin.transaction.client.run("BEGIN");
56 | // 直接返回已经开始事务的连接池
57 | resolve(null);
58 |
59 | //function (err) {
60 | // if (err) {
61 | // throw err;
62 | // }
63 | // // 直接返回已经开始事务的连接池
64 | // resolve(t);
65 | // });
66 | });
67 | };
68 | // 提交事务
69 | let commit = () => {
70 | return new Promise(function (resolve, reject) {
71 | commit.transaction.client.run("COMMIT");
72 | resolve("Transaction submitted successfully"); // 事务提交成功
73 |
74 | // () => {
75 | // t.client.release(() => {
76 | // resolve("事务提交成功");
77 | // });
78 | // });
79 | })
80 | };
81 | // 回滚事务
82 | let rollback = () => {
83 | return new Promise(function (resolve, reject) {
84 | rollback.transaction.client.run("ROLLBACK");
85 | resolve("Transaction rolled back"); // 事务已回滚
86 |
87 | // t.client.rollback(() => {
88 | // t.client.release(() => {
89 | // resolve("事务已回滚");
90 | // });
91 | // });
92 | });
93 | };
94 |
95 | return new Promise(function (resolve, reject) {
96 | // 事务对象
97 | let _transaction = {
98 | "client": self.conn
99 | };
100 | begin.transaction = commit.transaction = rollback.transaction = _transaction;
101 | // 事件绑定
102 | _transaction.begin = begin;
103 | _transaction.commit = commit;
104 | _transaction.rollback = rollback;
105 |
106 | resolve(_transaction);
107 |
108 | //
109 | // self.conn.getConnection(function (err, connection) {
110 | // if (err) {
111 | // console.log('创建事务连接出现异常', err);
112 | // reject(new Error('创建事务连接出现异常'));
113 | // } else {
114 | // // resolve(connection);
115 | // let transaction = {
116 | // "client": connection,
117 | // // "done": done,
118 | // "begin": begin, // 开始事务
119 | // "commit": commit, // 提交事务
120 | // "rollback": rollback // 事务回滚
121 | // };
122 | // resolve(transaction);
123 | // }
124 | // });
125 | });
126 | }
127 |
128 | // 执行SQL
129 | static execute(sql, parameters, mode) {
130 | let self = this;
131 | // console.log('sql打印', sql, parameters)
132 | return new Promise(function (resolve, reject) {
133 |
134 | if (self.conn) {
135 | console.time("【onela】SQL execution time"); //【onela】执行SQL时间
136 | mode = mode == 'all' ? 'all' : (mode == 'get' ? 'get' : 'run');
137 | self.conn[mode](sql, parameters, function (err, data) {
138 | //console.timeEnd("【onela】执行SQL时间");
139 | if (err) {
140 | reject(err);
141 | }
142 | else {
143 | if (data) {
144 | resolve(data); // 返回数据查询成功的结果
145 | } else {
146 | resolve("success"); // 提示 增 删 改 操作成功
147 | }
148 | }
149 | });
150 | }
151 | else {
152 | // 数据库实例engine实例未正确指向,请检查单例configs配置是否跟dbconfig配置的engine一致
153 | reject(new Error("The database instance engine instance is not pointed correctly. Please check whether the singleton configs configuration is consistent with the engine configured in dbconfig."));
154 | }
155 | });
156 | }
157 |
158 | // 执行带事务的实例对象
159 | static executeTransaction(sql, parameters, transaction, mode) {
160 |
161 | return new Promise((resolve, reject) => {
162 | if (transaction && transaction.client) {
163 | //console.time("【onela】执行SQL时间");
164 | mode = mode == 'all' ? 'all' : (mode == 'get' ? 'get' : 'run');
165 | // 事务连接池
166 | transaction.client[mode](sql, parameters, function (err, data) {
167 | //console.timeEnd("【onela】执行SQL时间");
168 | if (err) {
169 | reject(err);
170 | }
171 | else {
172 | if (data) {
173 | resolve(data); // 返回数据查询成功的结果
174 | } else {
175 | resolve("success"); // 提示 增 删 改 操作成功
176 | }
177 | }
178 | });
179 | }
180 | else {
181 | // 数据库实例engine实例未正确指向,请检查单例configs配置是否跟dbconfig配置的engine一致
182 | reject(new Error("The database instance engine instance is not pointed correctly. Please check whether the singleton configs configuration is consistent with the engine configured in dbconfig."));
183 | }
184 | });
185 | }
186 |
187 |
188 | /**
189 | * 自定义SQL执行(裸奔,一般不建议用)
190 | * @param sql SQL语句
191 | * @param parameters 参数
192 | * @param option 其他参数
193 | * @returns {Promise.}
194 | */
195 | static streak(sql, parameters, option = {"transaction": null}) {
196 | let self = this;
197 |
198 | // 执行SQL
199 | if (option && option.transaction) {
200 | // 事务连接池
201 | return self.executeTransaction(sql, parameters, option.transaction,"all")
202 | .catch(err => {
203 | console.error('Exception when executing execute query data list', err); // 执行execute查询数据列表异常
204 | return Promise.reject(err);
205 | });
206 | }
207 | else {
208 | return self.execute(sql, parameters,"all")
209 | .catch(err => {
210 | console.error('Exception when executing execute query data list', err); // 执行execute查询数据列表异常
211 | return Promise.reject(err);
212 | });
213 | }
214 | }
215 |
216 |
217 | /**
218 | * 数据实例查询
219 | * @param params 查询模型参数
220 | * @param option 其他参数
221 | * @returns {Promise.}
222 | */
223 | static queryEntity(params, option = {"transaction": null}) {
224 | let self = this;
225 | let p = GrammarSqlite.getParameters(params);
226 | // 拼装SQL
227 | // let sql = "select " + p["select"] + " from " + params.configs.tableName + " as t " + p.where + p.orderBy + p.limit + ";";
228 | let sql = `SELECT ${p["select"]} FROM ${params.configs.tableName} ${p.where} ${p.orderBy} ${p.limit};`;
229 | // 执行SQL
230 | if (option && option.transaction) {
231 | // 事务连接池
232 | return self.executeTransaction(sql, p.parameters, option.transaction, "all")
233 | .catch(err => {
234 | console.error('Exception when executing execute query data list', err); // 执行execute查询数据列表异常
235 | return Promise.reject(err);
236 | });
237 | }
238 | else {
239 | return self.execute(sql, p.parameters, "all")
240 | .catch(err => {
241 | console.error('Exception when executing execute query data list', err); // 执行execute查询数据列表异常
242 | return Promise.reject(err);
243 | });
244 | }
245 | }
246 |
247 | /**
248 | * 分页查询数据列表
249 | * @param params 查询参数
250 | * @param option 其他参数
251 | * @returns {Promise.}
252 | */
253 | static queryEntityList(params, option = {"transaction": null}) {
254 | let self = this;
255 | let p = GrammarSqlite.getParameters(params);
256 | /**
257 | * 分页数据查询
258 | */
259 | let sql = "select " + p["select"] + " from " + params.configs.tableName + " t " + p.where + " " + p.orderBy + p.limit + ";";
260 | let count_sql = "select count(0) total from " + params.configs.tableName + " t " + p.where + ";";
261 |
262 | //执行SQL
263 | if (option && option.transaction) {
264 | return Promise.all([
265 | self.executeTransaction(sql, p.parameters, option.transaction, "all"),
266 | self.execute(count_sql, p.parameters.slice(0, p.parameters.length - p.limit.length || 0), "all")
267 | ]).then(result => {
268 | return Promise.resolve({data: result[0], recordsTotal: result[1][0].total || 0});
269 | }).catch(ex => {
270 | console.error('Exception when executing execute query data list', ex); // 执行execute查询数据列表异常
271 | return Promise.reject(ex);
272 | });
273 |
274 | }
275 | else {
276 | return Promise.all([
277 | self.execute(sql, p.parameters, "all"),
278 | self.execute(count_sql, p.parameters.slice(0, p.parameters.length - p.limit.length || 0), "all")
279 | ]).then(result => {
280 |
281 | return Promise.resolve({data: result[0], recordsTotal: result[1][0].total || 0});
282 | }).catch(ex => {
283 | console.error('Exception when executing execute query data list', ex); // 执行execute查询数据列表异常
284 | return Promise.reject(ex);
285 | });
286 | }
287 |
288 | }
289 |
290 | /**
291 | * 获取数据瀑布
292 | * @param params 查询参数
293 | * @param option 其他参数
294 | * @returns {Promise.}
295 | */
296 | static getEntityWaterfall(params, option = {"transaction": null}) {
297 | let self = this;
298 | // 参数预处理
299 | if (params.hasOwnProperty("limit")) {
300 | //如果limit里面参数个数不符合
301 | if (params.limit.length == 1) {
302 | params.limit = [0, params.limit[0]]; //默认10个
303 | }
304 | //这里处理
305 | params.limit[0] = parseInt(params.limit[0]);
306 | //长度+1
307 | params.limit[1] = parseInt(params.limit[1]) + 1;
308 | }
309 | // 参数结构化
310 | let p = GrammarSqlite.getParameters(params);
311 | // 拼装SQL
312 | let sql = ["select ", p["select"], " from ", params.configs.tableName, " as t ", p.where, p.orderBy, p.limit + ";"];
313 | // 执行SQL
314 | if (option && option.transaction) {
315 | // 事务连接池
316 | return self.executeTransaction(sql.join(""), p.parameters, option.transaction, "all").then(data => {
317 | // 定义返回结果
318 | let result = {"data": data, "isLastPage": false};
319 | if (result.data.length == 0) {
320 | result.isLastPage = true; // 未查询到数据,显示最后一页
321 | }
322 | else if (result.data.length < (params.limit[1] - 1)) {
323 | //最后一页数据
324 | result.isLastPage = true; // 最后一页
325 | }
326 | else {
327 | //记录数等于length+1,删除最后一条数据
328 | if (result.data.length > (params.limit[1] - 1))
329 | result.data.pop();
330 | }
331 | return Promise.resolve(result);
332 | }).catch(err => {
333 | console.error('Exception when executing execute query data list', err); // 执行execute查询数据列表异常
334 | return Promise.reject(err);
335 | });
336 | }
337 | else {
338 | return self.execute(sql.join(""), p.parameters, "all").then(data => {
339 | // 定义返回结果
340 | let result = {"data": data, "isLastPage": false};
341 | if (result.data.length == 0) {
342 | result.isLastPage = true; // 未查询到数据,显示最后一页
343 | }
344 | else if (result.data.length < (params.limit[1] - 1)) {
345 | //最后一页数据
346 | result.isLastPage = true; // 最后一页
347 | }
348 | else {
349 | //记录数等于length+1,删除最后一条数据
350 | if (result.data.length > (params.limit[1] - 1))
351 | result.data.pop();
352 | }
353 | return Promise.resolve(result);
354 | }).catch(err => {
355 | console.error('Exception when executing execute query data list', err); // 执行execute查询数据列表异常
356 | return Promise.reject(err);
357 | });
358 | }
359 | }
360 |
361 | /**
362 | * 新增
363 | * @param entity 新增实体对象
364 | * @param option 其他参数
365 | * @returns {Promise.}
366 | */
367 | static insert(params, option = {"transaction": null}) {
368 | let p = [], f = [], s = [];
369 | for (let i in params.insertion) {
370 | //参数值
371 | p.push(params.insertion[i]);
372 | //字段名称集合
373 | f.push(i);
374 | //sql参数化处理符合
375 | s.push('?');
376 | }
377 | let sql = "insert into " + params.configs.tableName + " (" + f.join(',') + ") values(" + s.join(',') + ");";
378 |
379 | // 执行SQL
380 | if (option && option.transaction) {
381 | return this.executeTransaction(sql, p, option.transaction, "run").then((data) => {
382 | // 返回浅拷贝
383 | let insertion = Object.assign(params.insertion, {"_returns": data});
384 | return Promise.resolve(insertion);
385 | }).catch(ex => {
386 | throw ex;
387 | });
388 | }
389 | else {
390 | return this.execute(sql, p, "run").then((data) => {
391 | // 返回浅拷贝
392 | let insertion = Object.assign(params.insertion, {"_returns": data});
393 | return Promise.resolve(insertion);
394 | }).catch(ex => {
395 | throw ex;
396 | });
397 | }
398 | }
399 |
400 | /**
401 | * 批量新增
402 | * @param entity_list 新增实体对象列表
403 | * @param option 其他参数
404 | * @returns {Promise.}
405 | */
406 | static insertBatch(params, option = {"transaction": null}) {
407 | let p = [], f = [], s = [];
408 | for (let i in params.insertion) {
409 | let s2 = [];
410 | for (let j in params.insertion[i]) {
411 | if (i == 0) {
412 | //字段名称集合,大于0就不需要继续了
413 | f.push("`" + j + "`");
414 | }
415 | //参数值
416 | p.push(params.insertion[i][j]);
417 | //sql参数化处理符合
418 | s2.push('?');
419 | }
420 | //置入
421 | s.push('(' + s2.join(',') + ')');
422 | }
423 | //SQL执行
424 | let sql = "insert into " + params.configs.tableName + "(" + f.join(',') + ") values" + s.join(',') + ";";
425 | // 执行SQL
426 | if (option && option.transaction) {
427 | return this.executeTransaction(sql, p, option.transaction, "run");
428 | }
429 | else {
430 | return this.execute(sql, p, "run");
431 | }
432 | }
433 |
434 | /**
435 | * 物理删除
436 | * @param params 删除条件参数
437 | * @param option 其他参数
438 | * @returns {Promise.}
439 | */
440 | static deleteEntity(params, option = {"transaction": null}) {
441 | if ((!params.hasOwnProperty('keyword') || params.keyword.length == 0) && (!params.hasOwnProperty('where') || params.where.length == 0)) {
442 | return Promise.reject('Deletion conditions need to be specified to prevent the entire table data from being accidentally deleted.'); // 需要指定删除条件,防止整表数据误删除
443 | }
444 | let p = GrammarSqlite.getDeleteParameters(params);
445 | let sql = "delete from " + params.configs.tableName + " where " + p.where + ";";
446 |
447 | // 执行SQL
448 | if (option && option.transaction) {
449 | return this.executeTransaction(sql, p.parameters, option.transaction, "run");
450 | }
451 | else {
452 | return this.execute(sql, p.parameters, "run");
453 | }
454 | }
455 |
456 | /**
457 | * 实体对象更新
458 | * @param params 更新模型参数
459 | * @param option 其他参数
460 | * @returns {*}
461 | */
462 | static updateEntity(params, option = {"transaction": null}) {
463 | let p = GrammarSqlite.getUpdateParameters(params);
464 | let _limit = "";
465 | if (params.limit && params.hasOwnProperty('limit')) {
466 | _limit = " limit ?";
467 | p.parameters.push(params.limit);
468 | }
469 | let sql = "update " + params.configs.tableName + " set " + p.set.join(',') + " where " + p.where + _limit + ";";
470 | // 执行SQL
471 | if (option && option.transaction) {
472 | return this.executeTransaction(sql, p.parameters, option.transaction, "run");
473 | }
474 | else {
475 | return this.execute(sql, p.parameters, "run");
476 | }
477 | }
478 |
479 | /**
480 | * 统计查询
481 | * @param params 查询参数
482 | * @param option 其他参数
483 | * @returns {Promise.}
484 | */
485 | static statsByAggregate(params, option = {"transaction": null}) {
486 | let p = GrammarSqlite.getParameters(params);
487 | let check = {
488 | "count": "COUNT",
489 | "sum": "SUM",
490 | "max": "MAX",
491 | "min": "MIN",
492 | "abs": "ABS",
493 | "avg": "AVG"
494 | };
495 | let show = [];
496 | for (let i in params.aggregate) {
497 | let c = params.aggregate[i];
498 | let item = check[c.function.toLowerCase()];
499 | if (item) {
500 | show.push(item + "(" + c.field + ") as " + c.name);
501 | }
502 | }
503 | //sql
504 | let sql = "select " + show.join(',') + " from " + params.configs.tableName + " " + p.where + p.limit + ";";
505 | // 执行SQL
506 | if (option && option.transaction) {
507 | return this.executeTransaction(sql, p.parameters, option.transaction, "all");
508 | }
509 | else {
510 | return this.execute(sql, p.parameters, "all");
511 | }
512 | }
513 | }
514 |
515 | module.exports = {SQLiteActionManager};
--------------------------------------------------------------------------------
/lib/oParameters.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 通用模块-命令行参数处理
3 | * author:zack zou
4 | * create time:2016-06-27
5 | */
6 |
7 | var m = {}
8 |
9 | /**
10 | * 获取分页参数,封装成执行SQL参数化的对象
11 | * @param paras 原始参数集合
12 | * {
13 | * "select":[], //需要查询的字段,可缺省,即表示“*”
14 | * "keyword":[]
15 | * "orderBy":{}
16 | * }
17 | * author:zack zou
18 | * create time:2016-06-27
19 | */
20 | m.getParameters = function (paras) {
21 | //返回的参数集合
22 | var _self = {'select': [], 'where': ' where 1=1 ', 'orderBy': '', 'parameters': [], "limit": ""};
23 |
24 | /**
25 | * 指定字段查询,可以包含聚合函数
26 | * paras.select是数组对象
27 | */
28 | if (paras.select && typeof paras.select === "object") {
29 | if (paras.select.length == 0)
30 | _self.select = 't.*';
31 | else if (paras.select.length == 1)
32 | _self.select = paras.select[0];
33 | else
34 | _self.select = paras.select.join(',');
35 | }
36 | else {
37 | //如果没有包含这个参数,默认查询全部数据
38 | _self.select = 't.*';
39 | }
40 |
41 | /**
42 | * 排序
43 | */
44 | if (paras.hasOwnProperty('orderBy') && paras.orderBy != null) {
45 | /**
46 | * 遍历排序数组
47 | * 支持多字段排序
48 | * @orderBy {"order":"ASC"}
49 | */
50 | for (var i in paras.orderBy) {
51 | if (_self.orderBy === '') {
52 | _self.orderBy += ' order by ' + i + ' ' + paras.orderBy[i] + ' ';
53 | }
54 | else {
55 | _self.orderBy += ',' + i + ' ' + paras.orderBy[i] + ' ';
56 | }
57 | }
58 | }
59 |
60 | /**
61 | * where条件以及参数处理
62 | * keyword:查询条件
63 | */
64 | //遍历查询条件参数
65 | for (var i in paras.keyword) {
66 | /**
67 | * keyword里面是对象数组{"key":"","value":"","logic":"and","operator:"="}
68 | */
69 | if (paras.keyword[i] != '') {
70 | /**
71 | * 默认逻辑处理,允许部分参数不填写
72 | */
73 | if (!paras.keyword[i].hasOwnProperty('logic')) {
74 | paras.keyword[i].logic = "and";
75 | }
76 | _self.where += " " + paras.keyword[i].logic + " " + paras.keyword[i].key + " ";
77 |
78 | //逻辑运算
79 | if (paras.keyword[i].hasOwnProperty('operator')) {
80 | var oper = paras.keyword[i].operator;
81 | switch (oper) {
82 | case '=':
83 | case ">":
84 | case "<":
85 | case "<>":
86 | case ">=":
87 | case "<=":
88 | _self.where += (oper + "?");
89 | //参数化
90 | _self.parameters.push(paras.keyword[i].value);
91 | break;
92 | case "in":
93 | // //包含查询,利用数据遍历的方式实现
94 | // var p = [];
95 | // for (var c in paras.keyword[i].value) {
96 | // //参数化
97 | // _self.parameters.push(paras.keyword[i].value[c]);
98 | // p.push('?');
99 | // }
100 | // _self.where += "in (" + p.join(',') + ")";
101 | // break;
102 | case "not in":
103 | //包含查询,利用数据遍历的方式实现
104 | var p = [];
105 | for (var c in paras.keyword[i].value) {
106 | //参数化
107 | _self.parameters.push(paras.keyword[i].value[c]);
108 | p.push('?');
109 | }
110 | _self.where += " " + oper + " (" + p.join(',') + ")";
111 | break;
112 | case '%':
113 | //模糊查询,logic需要指定link逻辑运算
114 | //左侧模糊匹配查询
115 | _self.where += "like ?";
116 | //参数化
117 | _self.parameters.push('%' + paras.keyword[i].value);
118 | break;
119 | case 'x%':
120 | //模糊查询,logic需要指定link逻辑运算 where f like ?
121 | //右侧模糊匹配查询
122 | _self.where += "like ?";
123 | //参数化
124 | _self.parameters.push(paras.keyword[i].value + '%');
125 | break;
126 | case '%%':
127 | //模糊查询,logic需要指定link逻辑运算
128 | _self.where += "like ?";
129 | //参数化
130 | _self.parameters.push('%' + paras.keyword[i].value + '%');
131 | break;
132 | case 'is':
133 | _self.where += "is " + paras.keyword[i].value;
134 | break;
135 | default:
136 | _self.where += "";
137 | break;
138 | }
139 | }
140 | else {
141 | //运算符
142 | _self.where += "=?"
143 | //参数化
144 | _self.parameters.push(paras.keyword[i].value);
145 | }
146 |
147 |
148 | }
149 | }
150 | /**
151 | * 检测是否存在limit
152 | */
153 | if (paras.limit && paras.limit.length > 1) {
154 | _self.limit = " limit ?,?";
155 | _self.parameters.push(paras.limit[0]);
156 | _self.parameters.push(paras.limit[1]);
157 | }
158 | /**
159 | * 返回结果
160 | */
161 | return _self;
162 | }
163 |
164 |
165 | /**
166 | * 获取更新参数
167 | * @param paras 原始参数集合
168 | * author:zack zou
169 | * create time:2016-06-27
170 | */
171 | m.getUpdateParameters = function (paras) {
172 | //返回的参数集合
173 | var _self = {"set": [], "where": [], "parameters": []};
174 |
175 | /**
176 | * 更新字段
177 | * update:需要更新的字段
178 | */
179 | //遍历查询条件参数
180 | for (var i in paras.update) {
181 | /**
182 | * update里面是对象数组{"key":"","value":"","operator":"replace"}
183 | *
184 | {
185 | "key": "payment_no",
186 | "case_field": "id",
187 | "case_item": [{"case_value": "123", "value": "1", "operator": "replace"}]
188 | }
189 | */
190 |
191 | if (paras.update[i] == '') {
192 | continue;
193 | }
194 |
195 | //判断字段更新模式,常规更新还是case when then更新方式
196 | if (paras.update[i].hasOwnProperty('case_field')) {
197 | //遍历节点
198 | var item = paras.update[i];
199 | console.log('Pass in parameters', item);
200 | // var kkk = {
201 | // "key": "payment_no",
202 | // "case_field": "id",
203 | // "case_item": [
204 | // {"case_value": "123", "value": "1", "operator": "replace"}
205 | // ]
206 | // }
207 |
208 | //条件判断
209 | if (!(item.case_item instanceof Array) || item.case_item.length == 0) {
210 | //条件不符合
211 | continue;
212 | }
213 |
214 | // console.log('开始执行111');
215 | // balance = CASE id
216 | // WHEN '1' THEN balance+2
217 | // WHEN '2' THEN balance+20
218 | // END
219 |
220 | //开头
221 | var case_str = [];
222 | case_str.push(item.key + '= (CASE ' + item.case_field);
223 | //循环case_item分支
224 | for (var cw in item.case_item) {
225 | /**
226 | * 默认逻辑处理,默认替换更新
227 | */
228 | if (!item.case_item[cw].hasOwnProperty('operator')) {
229 | item.case_item[cw].operator = "replace";
230 | }
231 | //更新参数处理
232 | var oper = item.case_item[cw].operator;
233 | switch (oper) {
234 | case 'replace':
235 | /**
236 | * 值替换 // WHEN '1' THEN balance+2
237 | */
238 | case_str.push("WHEN ? THEN ?");
239 | _self.parameters.push(item.case_item[cw].case_value);
240 | _self.parameters.push(item.case_item[cw].value);
241 | break;
242 | case "plus":
243 | /**
244 | * 值累加
245 | */
246 | case_str.push("WHEN ? THEN " + item.key + " + ?");
247 | _self.parameters.push(item.case_item[cw].case_value);
248 | _self.parameters.push(item.case_item[cw].value);
249 | break;
250 | case "reduce":
251 | /**
252 | * 值累减
253 | */
254 | case_str.push("WHEN ? THEN " + item.key + " - ?");
255 | _self.parameters.push(item.case_item[cw].case_value);
256 | _self.parameters.push(item.case_item[cw].value);
257 | break;
258 | default:
259 | /**
260 | * 其他默认为值替换更新
261 | */
262 | case_str.push("WHEN ? THEN ? ");
263 | _self.parameters.push(item.case_item[cw].case_value);
264 | _self.parameters.push(item.case_item[cw].value);
265 | break;
266 | }
267 | }
268 | //结尾
269 | case_str.push("END) ");
270 | //追加到参数模型
271 | _self.set.push(case_str.join(' '));
272 |
273 | }
274 | else {
275 |
276 | /**
277 | * 默认逻辑处理,默认替换更新
278 | */
279 | if (!paras.update[i].hasOwnProperty('operator')) {
280 | paras.update[i].operator = "replace";
281 | }
282 | //更新参数处理
283 | var oper = paras.update[i].operator;
284 | switch (oper) {
285 | case 'replace':
286 | /**
287 | * 值替换
288 | */
289 | _self.set.push(paras.update[i].key + '=?');
290 | _self.parameters.push(paras.update[i].value);
291 | break;
292 | case "plus":
293 | /**
294 | * 值累加
295 | */
296 | _self.set.push(paras.update[i].key + '=' + paras.update[i].key + "+ ?");
297 | _self.parameters.push(paras.update[i].value);
298 | break;
299 | case "reduce":
300 | /**
301 | * 值累减
302 | */
303 | _self.set.push(paras.update[i].key + '=' + paras.update[i].key + "- ?");
304 | _self.parameters.push(paras.update[i].value);
305 | break;
306 | default:
307 | /**
308 | * 其他默认为值替换更新
309 | */
310 | _self.set.push(paras.update[i].key + '=?');
311 | _self.parameters.push(paras.update[i].value);
312 | break;
313 | }
314 | }
315 | }
316 |
317 | /**
318 | * where条件以及参数处理
319 | * keyword:查询条件
320 | */
321 | //遍历查询条件参数
322 | for (var i in paras.keyword) {
323 | /**
324 | * keyword里面是对象数组{"key":"","value":"","logic":"and","operator:"="}
325 | */
326 | if (paras.keyword[i] != '') {
327 | /**
328 | * 默认逻辑处理,允许部分参数不填写
329 | */
330 | if (!paras.keyword[i].hasOwnProperty('logic')) {
331 | paras.keyword[i].logic = "and";
332 | }
333 |
334 | //逻辑运算
335 | if (paras.keyword[i].hasOwnProperty('operator')) {
336 | var oper = paras.keyword[i].operator;
337 | switch (oper) {
338 | case '=':
339 | case ">":
340 | case "<":
341 | case "<>":
342 | case ">=":
343 | case "<=":
344 | _self.where.push(' ' + paras.keyword[i].logic + ' ' + paras.keyword[i].key + oper + "?");
345 | //参数化
346 | _self.parameters.push(paras.keyword[i].value);
347 | break;
348 | case '%':
349 | //模糊查询,logic需要指定link逻辑运算
350 | //左侧模糊匹配查询
351 | _self.where.push(' ' + paras.keyword[i].logic + ' ' + paras.keyword[i].key + oper + "?");
352 | //参数化
353 | _self.parameters.push('%' + paras.keyword[i].value);
354 | break;
355 | case 'x%':
356 | //模糊查询,logic需要指定link逻辑运算
357 | //右侧模糊匹配查询
358 | _self.where.push(' ' + paras.keyword[i].logic + ' ' + paras.keyword[i].key + oper + "?");
359 | //参数化
360 | _self.parameters.push(paras.keyword[i].value + '%');
361 | break;
362 | case '%%':
363 | //模糊查询,logic需要指定link逻辑运算
364 | _self.where.push(' ' + paras.keyword[i].logic + ' ' + paras.keyword[i].key + oper + "?");
365 | //参数化
366 | _self.parameters.push('%' + paras.keyword[i].value + '%');
367 | break;
368 | case "in":
369 | case "not in":
370 | var _item = ' ' + paras.keyword[i].logic + ' ' + paras.keyword[i].key + " " + oper + " ("
371 | //包含查询,利用数据遍历的方式实现
372 | var p = [];
373 | for (var c in paras.keyword[i].value) {
374 | //参数化
375 | _self.parameters.push(paras.keyword[i].value[c]);
376 | p.push('?');
377 | }
378 | _item += p.join(',') + ")"; //sql语句
379 | _self.where.push(_item);
380 | break;
381 | }
382 | }
383 |
384 | }
385 | }
386 | /**
387 | * where条件字符串组装
388 | */
389 | _self.where = ' 1=1 ' + _self.where.join('');
390 | /**
391 | * 返回结果
392 | */
393 | return _self;
394 | }
395 |
396 | /**
397 | * 获取实例删除参数
398 | * 注意,一般情况下不推荐直接物理删除
399 | * @param paras 原始参数集合
400 | * {
401 | * "keyword":[]
402 | * }
403 | * author:zack zou
404 | * create time:2017-04-06
405 | */
406 | m.getDeleteParameters = function (paras) {
407 | //返回的参数集合
408 | var _self = {'where': [], 'parameters': []};
409 |
410 | /**
411 | * where条件以及参数处理
412 | * keyword:查询条件
413 | */
414 | //遍历查询条件参数
415 | for (var i in paras.keyword) {
416 | /**
417 | * keyword里面是对象数组{"key":"","value":"","logic":"and","operator:"="}
418 | */
419 | if (paras.keyword[i] != '') {
420 | /**
421 | * 默认逻辑处理,允许部分参数不填写
422 | */
423 | if (!paras.keyword[i].hasOwnProperty('logic')) {
424 | paras.keyword[i].logic = "and";
425 | }
426 |
427 | //逻辑运算
428 | if (paras.keyword[i].hasOwnProperty('operator')) {
429 | var oper = paras.keyword[i].operator;
430 | switch (oper) {
431 | case '=':
432 | case ">":
433 | case "<":
434 | case "<>":
435 | case ">=":
436 | case "<=":
437 | _self.where.push(' ' + paras.keyword[i].logic + ' ' + paras.keyword[i].key + oper + "?");
438 | //参数化
439 | _self.parameters.push(paras.keyword[i].value);
440 | break;
441 | case '%':
442 | //模糊查询,logic需要指定link逻辑运算
443 | //左侧模糊匹配查询
444 | _self.where.push(' ' + paras.keyword[i].logic + ' ' + paras.keyword[i].key + oper + "?");
445 | //参数化
446 | _self.parameters.push('%' + paras.keyword[i].value);
447 | break;
448 | case 'x%':
449 | //模糊查询,logic需要指定link逻辑运算
450 | //右侧模糊匹配查询
451 | _self.where.push(' ' + paras.keyword[i].logic + ' ' + paras.keyword[i].key + oper + "?");
452 | //参数化
453 | _self.parameters.push(paras.keyword[i].value + '%');
454 | break;
455 | case '%%':
456 | //模糊查询,logic需要指定link逻辑运算
457 | _self.where.push(' ' + paras.keyword[i].logic + ' ' + paras.keyword[i].key + oper + "?");
458 | //参数化
459 | _self.parameters.push('%' + paras.keyword[i].value + '%');
460 | break;
461 | case "in":
462 | case "not in":
463 | var _item = ' ' + paras.keyword[i].logic + ' ' + paras.keyword[i].key + " " + oper + " ("
464 | //包含查询,利用数据遍历的方式实现
465 | var p = [];
466 | for (var c in paras.keyword[i].value) {
467 | //参数化
468 | _self.parameters.push(paras.keyword[i].value[c]);
469 | p.push('?');
470 | }
471 | _item += p.join(',') + ")"; //sql语句
472 | _self.where.push(_item);
473 | break;
474 | }
475 | }
476 |
477 | }
478 | }
479 | /**
480 | * where条件字符串组装
481 | */
482 | _self.where = ' 1=1 ' + _self.where.join('');
483 | /**
484 | * 返回结果
485 | */
486 | return _self;
487 | }
488 |
489 | module.exports = m;
--------------------------------------------------------------------------------
/lib/onela.js:
--------------------------------------------------------------------------------
1 | const { MySQLActionManager } = require("./instance/MySQLActionManager");
2 | const { PostgreSQLActionManager } = require("./instance/PostgreSQLActionManager");
3 | const { SQLiteActionManager } = require("./instance/SQLiteSQLActionManager");
4 | const { SQLServerActionManager } = require("./instance/SQLServerActionManager");
5 | // 老版本兼容
6 | const Old = require("./OFramework");
7 |
8 | /**
9 | * 负责多个database的管理,能够初始化数据库连接
10 | */
11 | class Onela {
12 |
13 | /**
14 | * 数据库实例对象识别
15 | * @param db_type 数据类型
16 | * @returns {MySQLActionManager}
17 | */
18 | static getActionManagerClass(db_type) {
19 | switch (db_type.toLowerCase()) {
20 | case "mysql":
21 | return MySQLActionManager;
22 | case "postgresql":
23 | return PostgreSQLActionManager;
24 | case "sqlite":
25 | return SQLiteActionManager;
26 | case "sqlserver":
27 | return SQLServerActionManager;
28 | default:
29 | return null;
30 | }
31 | }
32 |
33 | /**
34 | * 数据库实例初始化(多类型多实例)
35 | * @param config_list
36 | */
37 | static init(config_list) {
38 | let self = this;
39 | for (let tempConfig of config_list) {
40 | let temp_am = self.getActionManagerClass(tempConfig.type);
41 | // 检测实例对象是否存在
42 | if (temp_am) {
43 | temp_am.init(tempConfig.value);
44 | self._connections[tempConfig.engine] = temp_am;
45 | }
46 | else {
47 | // 数据库实例类型{0}不存在
48 | console.error("Database instance type ", tempConfig.type, " does not exist");
49 | }
50 | }
51 | }
52 |
53 | static getActionManager(engine) {
54 | let self = this;
55 | if (!(engine in this._connections)) {
56 | throw new Error(`invalid engine: ${engine}`);
57 | }
58 | return Promise.resolve(self._connections[engine]);
59 | }
60 |
61 | /**
62 | * 获取事务实例对象
63 | * @param name
64 | */
65 | static getActionTransaction(engine) {
66 | // 连接对象
67 | let self = this;
68 | // 检测链接池是否存在
69 | if (!(engine in this._connections)) {
70 | throw new Error(`invalid engine: ${engine}`);
71 | }
72 |
73 | // 获取事务对象
74 | return self._connections[engine].createTransaction()
75 | .then(connection => {
76 | return Promise.resolve(connection);
77 | })
78 | .catch(ex => {
79 | return Promise.reject(ex);
80 | });
81 |
82 | }
83 | }
84 |
85 | /**
86 | * 连接对象
87 | * 一般情况下需要一个数据库连接对象即可,onela在框架设计上直接支持多个不同类型的数据库同时创建连接
88 | * 事务只能在同一个connection对象里面才回生效
89 | */
90 | Onela._connections = {};
91 |
92 | /**
93 | * 模型的基类,负责该模型的crud基本操作
94 | */
95 | class OnelaBaseModel {
96 |
97 | static getActionManager() {
98 | if (!(this.action_manager)) {
99 | this.action_manager = Onela.getActionManager(this.configs.engine);
100 | }
101 |
102 | return this.action_manager;
103 | }
104 |
105 | /**
106 | * 获取事务连接对象
107 | * @returns {*}
108 | */
109 | static transaction() {
110 |
111 | return new Promise((resolve, reject) => {
112 | Onela.getActionTransaction(this.configs.engine).then(connection => {
113 | // 默认自动开始事务执行
114 | // console.log('事务对象',connection.client)
115 | connection.begin(connection).then((connection2) => {
116 | // 直接返回已经开始事务的连接池
117 | resolve(connection2 || connection);
118 | });
119 | });
120 | });
121 |
122 | }
123 |
124 | /**
125 | * 查询实体对象
126 | * @param args 查询参数
127 | * {
128 | * "select":["*"], // select,默认查询*,可以指定输出特定的字段
129 | * "where":[ // where,是查询条件模型数组,对应SQL语句where条件
130 | * { // 例句:select * from tableName where 1=1 and valid = 1
131 | * "logic": "and", // logic,逻辑运算符,对应SQL语句运算符,可选值:and、or等
132 | * "key": "valid", // key,字段关键字,对应数据表表字段名称
133 | * "operator":"=", // operator,运算符,对应字段对比关系,可选值:=、>、>=、<、<=、<>、%、x%、%%、in、not in等
134 | * "value": 1 // value,查询条件值
135 | * }
136 | * ],
137 | * "orderBy":
138 | * {
139 | * "id":"DESC", // 根据id排序,DESC降序排列,可选值:DESC、ASC;排序字段对照数据库表字段
140 | * "valid":"ASC" // 可组合排序
141 | * },
142 | * "limit":[0,10] // limit,查询输出限制,0表示从条件模型中查询数据索引从0的位置开始查询,10表示一次性查询10条数据记录
143 | * }
144 | * @param option 其他参数
145 | * @returns {Promise.} 出参
146 | * [ // 查询结果数据列表
147 | * {"id":"1","valid":1},
148 | * {"id":"2","valid":1}
149 | * ]
150 | */
151 | static getEntity(args, option) {
152 | let params = Object.assign({}, args);
153 | params.configs = this.configs;
154 | // 返回执行结果
155 | return this.getActionManager().then(_connection => {
156 | return _connection.queryEntity(params, option)
157 | });
158 | }
159 |
160 | /**
161 | * 获取实体对象列表
162 | * @param args 查询参数
163 | * {
164 | * "select":["*"], // select,默认查询*,可以指定输出特定的字段
165 | * "where":[ // where是查询条件模型数组,对应SQL语句where条件
166 | * { // 例句:select * from tableName where 1=1 and valid = 1
167 | * "logic": "and", // logic,逻辑运算符,对应SQL语句运算符,可选值:and、or等
168 | * "key": "valid", // key,字段关键字,对应数据表表字段名称
169 | * "operator":"=", // operator,运算符,对应字段对比关系,可选值:=、>、>=、<、<=、<>、%、x%、%%、in、not in等
170 | * "value": 1 // value,查询条件值
171 | * }
172 | * ],
173 | * "orderBy":
174 | * {
175 | * "id":"DESC", // 根据id排序,DESC降序排列,可选值:DESC、ASC;排序字段对照数据库表字段
176 | * "valid":"ASC" // 可组合排序
177 | * },
178 | * "limit":[0,10] // limit,查询输出限制,0表示从条件模型中查询数据索引从0的位置开始查询,10表示一次性查询10条数据记录
179 | * }
180 | * @param option 其他参数
181 | * @returns {Promise.} 出参
182 | * {
183 | * "data":[ // 查询结果数据列表
184 | * {"id":"1","valid":1},
185 | * {"id":"2","valid":1}
186 | * ],
187 | * "recordsTotal":4 // recordsTotal,查询结果记录总数
188 | * }
189 | */
190 | static getEntityList(args, option) {
191 | let params = Object.assign({}, args);
192 | params.configs = this.configs;
193 | // 返回执行结果
194 | return this.getActionManager()
195 | .then(_connection => {
196 | return _connection.queryEntityList(params, option)
197 | }).catch(ex => {
198 | throw ex;
199 | });
200 | }
201 |
202 | /**
203 | * 获取数据瀑布
204 | * @param params 查询参数
205 | * {
206 | * "select":["*"], // select,默认查询*,可以指定输出特定的字段
207 | * "where":[ // where是查询条件模型数组,对应SQL语句where条件
208 | * { // 例句:select * from tableName where 1=1 and valid = 1
209 | * "logic": "and", // logic,逻辑运算符,对应SQL语句运算符,可选值:and、or等
210 | * "key": "valid", // key,字段关键字,对应数据表表字段名称
211 | * "operator":"=", // operator,运算符,对应字段对比关系,可选值:=、>、>=、<、<=、<>、%、x%、%%、in、not in等
212 | * "value": 1 // value,查询条件值
213 | * }
214 | * ],
215 | * "orderBy":
216 | * {
217 | * "id":"DESC", // 根据id排序,DESC降序排列,可选值:DESC、ASC;排序字段对照数据库表字段
218 | * "valid":"ASC" // 可组合排序
219 | * },
220 | * "limit":[0,10] // limit,查询输出限制,0表示从条件模型中查询数据索引从0的位置开始查询,10表示一次性查询10条数据记录
221 | * }
222 | * @param args 其他参数
223 | * @returns {Promise.} 出参
224 | * {
225 | * "data":[ // 查询结果数据列表
226 | * {"id":"1"},
227 | * {"id":"2"}
228 | * ],
229 | * "isLastPage":false // 当前数据库是否为查询条件结果的最后一页,false表示不是,true表示是
230 | * }
231 | */
232 | static getEntityWaterfall(args, option) {
233 | let params = Object.assign({}, args);
234 | params.configs = this.configs;
235 | // 返回执行结果
236 | return this.getActionManager()
237 | .then(_connection => {
238 | return _connection.getEntityWaterfall(params, option)
239 | }).catch(ex => {
240 | throw ex;
241 | });
242 | }
243 |
244 | /**
245 | * 新增实体对象
246 | * @param args ,新增实体对象
247 | * {
248 | * "id":"3", // 字段1,
249 | * "valid":1, // 字段2,
250 | * }
251 | * @param option 其他参数
252 | * @returns {Promise.} 出参,返回新增实体对象
253 | * {
254 | * "id":"3",
255 | * "valid":1,
256 | * "_returns":{} // _returns 节点返回底层执行的结果,不同的数据库返回的数据不同,有些每个这个节点,使用的时候需要注意
257 | * }
258 | */
259 | static insertEntity(args, option) {
260 | let p = {};
261 | let entity = Object.assign({}, args);
262 | entity.configs = this.configs;
263 | for (let field of this.configs.fields) {
264 | if (field.name in entity) {
265 | p[field.name] = entity[field.name];
266 | } else {
267 | let default_value = null;
268 | if (field.default === undefined) {
269 | throw new Error(`field:${field.name} required`);
270 | }
271 | if (field.default instanceof Function) {
272 | default_value = field.default();
273 | } else {
274 | default_value = field.default;
275 | }
276 | // 如果是主键自增,则跳出
277 | if (field.increment)
278 | continue;
279 | p[field.name] = default_value;
280 | }
281 | }
282 | // 返回执行结果
283 | return this.getActionManager()
284 | .then(_connection => {
285 | return _connection.insert({ insertion: p, configs: this.configs }, option)
286 | }).catch(ex => {
287 | throw ex;
288 | });
289 | }
290 |
291 | /**
292 | * 批量新增
293 | * @param entity_list 新增实体对象列表
294 | * [
295 | * {
296 | * "id":"10", // 批量新增对象1
297 | * "valid":1
298 | * },
299 | * {
300 | * "id":"10", // 批量新增对象2
301 | * "valid":1
302 | * }
303 | * ]
304 | * @param option 其他参数
305 | * @returns {Promise.}
306 | */
307 | static insertBatch(entity_list, option) {
308 | let insert_list = [];
309 | for (let entity of entity_list) {
310 | let insert_obj = {};
311 | for (let field of this.configs.fields) {
312 | if (field.name in entity) {
313 | insert_obj[field.name] = entity[field.name];
314 | } else {
315 | let default_value = null;
316 | if (field.default === undefined) {
317 | throw new Error(`field:${field.name} required`);
318 | }
319 | if (field.default instanceof Function) {
320 | default_value = field.default();
321 | } else {
322 | default_value = field.default;
323 | }
324 | // 如果是主键自增,则跳出
325 | if (field.increment)
326 | continue;
327 | insert_obj[field.name] = default_value;
328 | }
329 | }
330 | insert_list.push(insert_obj);
331 | }
332 | // 返回执行结果
333 | return this.getActionManager()
334 | .then(_connection => {
335 | return _connection.insertBatch({ insertion: insert_list, configs: this.configs }, option)
336 | }).catch(ex => {
337 | throw ex;
338 | });
339 | }
340 |
341 | /**
342 | * 物理删除
343 | * @param args 查询参数
344 | * {
345 | * "where":[ // where是查询条件模型数组,对应SQL语句where条件
346 | * { // 例句:select * from tableName where 1=1 and valid = 1
347 | * "logic": "and", // logic,逻辑运算符,对应SQL语句运算符,可选值:and、or等
348 | * "key": "id", // key,字段关键字,对应数据表表字段名称
349 | * "operator":"=", // operator,运算符,对应字段对比关系,可选值:=、>、>=、<、<=、<>、%、x%、%%、in、not in等
350 | * "value": 1 // value,查询条件值
351 | * }
352 | * ]
353 | * }
354 | * @param option 其他参数
355 | * @returns {Promise.} 出参
356 | * }
357 | */
358 | static deleteEntity(args, option) {
359 |
360 | let params = Object.assign({}, args);
361 | params.configs = this.configs;
362 | // 返回执行结果
363 | return this.getActionManager()
364 | .then(_connection => {
365 | return _connection.deleteEntity(params, option)
366 | }).catch(ex => {
367 | throw ex;
368 | });
369 | }
370 |
371 | /**
372 | * 实体对象更新
373 | * @param args 更新对象模型
374 | * {
375 | * "where":[ // where,是查询条件模型数组,对应SQL语句where条件
376 | * { // 例句:select * from tableName where 1=1 and valid = 1
377 | * "logic": "and", // logic,逻辑运算符,对应SQL语句运算符,可选值:and、or等
378 | * "key": "valid", // key,字段关键字,对应数据表表字段名称
379 | * "operator":"=", // operator,运算符,对应字段对比关系,可选值:=、>、>=、<、<=、<>、%、x%、%%、in、not in等
380 | * "value": 1 // value,查询条件值
381 | * }
382 | * ],
383 | * "update":[ // where,是更新对象,对应SQL语句中的set更新
384 | * {
385 | * "key": "name", // 更新字段
386 | * "value": "更改名字", // 更新之后的值
387 | * "operator": "replace" // 更新方式:replace(替换更新)、plus(+=更新,例如金额更新)、reduce(-=更新,例如金额更新)
388 | * },
389 | * { // WHEN THEN CASE 更新
390 | * "key": "money", // 更新字段
391 | * "case_field": "id", // CASE 条件字段
392 | * "case_item": [
393 | * {
394 | * "case_value": "22", // 把id值为22的这条记录
395 | * "value": 12, // 例句:WHEN '22' THEN money += 12
396 | * "operator": "plus" //
397 | * },
398 | * {"case_value": 23, "value": "B", "operator": "replace"} //WHEN '001' THEN balance+2
399 | * ]
400 | * }
401 | * ]
402 | * }
403 | * @param option 其他参数
404 | * @returns {Promise.} 出参
405 | */
406 | static updateEntity(args, option) {
407 | let params = Object.assign({}, args);
408 |
409 | if ((!params.hasOwnProperty('keyword') || params.keyword.length == 0) && (!params.hasOwnProperty('where') || params.where.length == 0)) {
410 | return Promise.reject(new Error('paras.where update condition (array) must exist condition')); // paras.where更新条件(数组)必须存在条件
411 | }
412 | params.configs = this.configs;
413 | // 返回执行结果
414 | return this.getActionManager()
415 | .then(_connection => {
416 | return _connection.updateEntity(params, option)
417 | }).catch(ex => {
418 | throw ex;
419 | });
420 | }
421 |
422 | /**
423 | * 批量更新(未实现)
424 | * @param update_list 批量更新
425 | * @param option 其他参数
426 | */
427 | static updateBatch(update_list, option) {
428 | var self = this;
429 | let p = Promise.resolve();
430 | for (let update_info of update_list) {
431 | p.then(self.updateEntity(update_info, option));
432 | }
433 | }
434 |
435 | /**
436 | * 统计查询(聚合函数的使用)
437 | * @param args 统计查询参数
438 | * {
439 | * "where":[ // where,是查询条件模型数组,对应SQL语句where条件
440 | * { // 例句:select * from tableName where 1=1 and valid = 1
441 | * "logic": "and", // logic,逻辑运算符,对应SQL语句运算符,可选值:and、or等
442 | * "key": "valid", // key,字段关键字,对应数据表表字段名称
443 | * "operator":"=", // operator,运算符,对应字段对比关系,可选值:=、>、>=、<、<=、<>、%、x%、%%、in、not in等
444 | * "value": 1 // value,查询条件值
445 | * }
446 | * ],
447 | * "aggregate":[
448 | * {
449 | * "function": "count", // function,聚合函数:COUNT、SUM、MAX、MIN、ABS、AVG
450 | * "field": "id", // 字段
451 | * "name": "total" // 输出字段重命名
452 | * },
453 | * ]
454 | * }
455 | * @param option 其他参数
456 | * @returns {Promise.} 出参
457 | */
458 | static getEntityByAggregate(args, option) {
459 | let params = Object.assign({}, args);
460 | params.configs = this.configs;
461 | // 返回执行结果
462 | return this.getActionManager()
463 | .then(_connection => {
464 | return _connection.statsByAggregate(params, option)
465 | }).catch(ex => {
466 | throw ex;
467 | });
468 | }
469 |
470 | /**
471 | * 自定义SQL执行(裸奔,一般不建议用)
472 | * @param sql SQL语句
473 | * @param parameters 参数
474 | * @param option 其他参数
475 | * @returns {Promise.}
476 | */
477 | static streak(sql, option) {
478 | return this.getActionManager().then(_connection => {
479 | if (_connection.streak)
480 | //支持此方法
481 | return _connection.streak(sql, option);
482 | else
483 | return Promise.reject(new Error("This type of database does not support the stream method")); // 该类型数据库不支持streak方法
484 |
485 | }).catch(ex => {
486 | throw ex;
487 | });
488 | }
489 | }
490 |
491 | OnelaBaseModel.action_manager = null; // 连接初始化后绑定到这里来
492 | OnelaBaseModel.configs = {
493 | fields: [],
494 | tableName: '',
495 | engine: "default"
496 | };
497 |
498 | // module.exports = BaseModelManager;
499 |
500 | module.exports = { Old, Onela, OnelaBaseModel };
--------------------------------------------------------------------------------
/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "onela",
3 | "version": "2.2.0",
4 | "lockfileVersion": 1
5 | }
6 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "onela",
3 | "version": "2.4.15",
4 | "description": "Onela is an object-based mapping framework based on node.js open source, supporting a variety of relational database data infrastructure. At the same time support a variety of database object read and write separation, the database instance vertical split. On top of the onela architecture you can experience the fun of programming without SQL, and you only need to focus on the business logic code section. And, I will be in the later version of the support to join the distributed cache to achieve the front and back end with node.js program to challenge the case of large-scale applications.",
5 | "main": "lib/onela.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "repository": {
10 | "type": "git",
11 | "url": "https://github.com/zouwei/onela/"
12 | },
13 | "keywords": [
14 | "onela",
15 | "orm",
16 | "orm framework",
17 | "Mysql",
18 | "PostgreSQL",
19 | "Postgre",
20 | "SQLite",
21 | "SQL Server",
22 | "object relational mapper"
23 | ],
24 | "author": "SHIYE",
25 | "license": "SHIYE",
26 | "maintainers": [
27 | {
28 | "name": "SHIYE",
29 | "email": "huzougege@qq.com"
30 | }
31 | ],
32 | "dependencies": {}
33 | }
34 |
--------------------------------------------------------------------------------
/tests/sqlite_db.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/zouwei/onela/095335aadf9a33d34a2e12a0fb166402975bb19e/tests/sqlite_db.db
--------------------------------------------------------------------------------
/tests/test.mysql.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 数据库配置,可以初始化多个数据库实例
3 | */
4 | let dbconfig = [{
5 | "engine": "default", // 数据库实例名称
6 | "type": "mysql", // 数据库类型
7 | "value": {
8 | "connectionLimit": 5,
9 | "host": "127.0.0.1",
10 | "user": "test",
11 | "password": "7t1tusx+pvluIj",
12 | "database": "test_db"
13 | }
14 | }];
15 |
16 | const {Onela, OnelaBaseModel} = require("../lib/onela");
17 | // 初始化Onela模块
18 | Onela.init(dbconfig);
19 | // 已经在OnelaBaseModel封装的常用方法,可以在此基础自行扩展
20 |
21 | class tableInstance extends OnelaBaseModel {
22 | // 可以在此自定义扩展方法(默认封装没有的方法)
23 | }
24 |
25 | // 【重要】单例模式,数据表配置
26 | tableInstance.configs = {
27 | fields: [
28 | {name: "id", type: "int", default: null},
29 | {name: "content", type: "varchar"},
30 | {name: "is_done", type: "int", default: 0},
31 | {
32 | name: "create_time", type: "datetime", default: () => {
33 | return new Date()
34 | }
35 | },
36 | {
37 | name: "finish_time", type: "datetime", default: () => {
38 | return new Date()
39 | }
40 | }
41 | ],
42 | tableName: "core_offline_order",
43 | engine: "default"
44 | };
45 |
46 | /**
47 | * 事务
48 | */
49 | tableInstance.transaction().then(t => {
50 | // 先新增一条记录
51 | ToDoManager.insertEntity({
52 | "content": "测试"
53 | }, {transaction: t})
54 | .then(data => {
55 | // 再对新增的记录执行修改
56 | return ToDoManager.updateEntity({
57 | "update": [
58 | {"key": "content", "value": "执行修改测试", "operator": "replace"} // 修改了content字段
59 | ],
60 | "where": [
61 | {"logic": "and", "key": "id", operator: "=", "value": data.insertId}
62 | ]
63 | }, {transaction: t});
64 | })
65 | .then(data => {
66 | console.log('执行结果', data);
67 | t.commit().then(d => {
68 | console.log(d);
69 | });
70 | })
71 | .catch(ex => {
72 | console.log('事务异常回滚', ex);
73 | t.rollback().then(d => {
74 | console.log(d);
75 | });
76 | });
77 | });
78 |
79 |
80 | /**
81 | * 单例模式:数据查询
82 | */
83 | tableInstance.getEntity({
84 | where: [
85 | //{"logic": "and", "key": "id", "operator": "=", "value": 1}
86 | ]
87 | }, null).then(data => {
88 | console.log('查询结果', data)
89 | }).then();
90 |
91 | /**
92 | * 单例模式:新增
93 | */
94 | tableInstance.insertEntity({
95 | "content": "测试"
96 | }).then(data => {
97 | console.log('查询结果', data)
98 | });
99 |
100 | /**
101 | * 单例模式:分页查询
102 | */
103 | tableInstance.getEntityList({
104 | "where": [
105 | //{"logic": "and", "key": "id", "operator": "=", "value": 1}
106 | ]
107 | }).then(console.log);
108 |
109 | /**
110 | * 获取数据瀑布
111 | * @param 入参
112 | * {
113 | * "where":[ // where是查询条件模型数组,对应SQL语句where条件
114 | * { // 例句:select * from tableName where 1=1 and valid = 1
115 | * "logic": "and", // logic,逻辑运算符,对应SQL语句运算符,可选值:and、or等
116 | * "key": "valid", // key,字段关键字,对应数据表表字段名称
117 | * "operator":"=", // operator,运算符,对应字段对比关系,可选值:=、>、>=、<、<=、<>、%、x%、%%、in、not in等
118 | * "value": 1 // value,查询条件值
119 | * }
120 | * ],
121 | * "orderBy":
122 | * {
123 | * "id":"DESC", // 根据id排序,DESC降序排列,可选值:DESC、ASC;排序字段对照数据库表字段
124 | * "valid":"ASC" // 可组合排序
125 | * },
126 | * "limit":[0,2] // limit,查询输出限制,0表示从条件模型中查询数据索引从0的位置开始查询,10表示一次性查询10条数据记录
127 | * }
128 | * @return 出参
129 | * {
130 | * "data":[ // 查询结果数据列表
131 | * {"id":"1"},
132 | * {"id":"2"}
133 | * ],
134 | * "isLastPage":false // 当前数据库是否为查询条件结果的最后一页,false表示不是,true表示是
135 | * }
136 | */
137 | tableInstance.getEntityWaterfall({
138 | "where": [
139 | {"logic": "and", "key": "valid", "operator": "=", "value": 1}
140 | ],
141 | "limit": [230, 10]
142 | }).then(console.log);
143 |
144 |
145 | /**
146 | * 单例模式:批量新增
147 | */
148 | tableInstance.insertBatch([
149 | {content: "测试1"},
150 | {content: "测试2"},
151 | {content: "测试3"}
152 | ]).then(console.log);
153 |
154 | /**
155 | * 单例模式:删除(物理删除,不推荐使用)
156 | */
157 | tableInstance.deleteEntity({
158 | "where": [
159 | {"key": "id", operator: "in", value: [12360, 12361], logic: "and"},
160 | // {"key": "is_done", operator: "=", value: 1, logic: "and"}
161 | ]
162 | }).then(console.log);
163 |
164 | /**
165 | * 单例模式:更新(对于删除,建议使用逻辑删除)
166 | */
167 | tableInstance.updateEntity({
168 | update: [
169 | {key: "is_done", value: 1, operator: "replace"},
170 | {
171 | "key": "content", //update field
172 | "case_field": "id", //balance = CASE id
173 | "case_item": [
174 | {"case_value": 12381, "value": "修改结果A", "operator": "replace"}, //WHEN '001' THEN 1
175 | {"case_value": 12384, "value": "修改结果B", "operator": "replace"} //WHEN '001' THEN balance+2
176 | ]
177 | }
178 | ],
179 | where: [
180 | {"key": "id", operator: "in", value: [12381, 12384], logic: "and"},
181 | ]
182 | }).then(console.log);
183 |
184 |
185 | /**
186 | * 单例模式:实时统计
187 | */
188 | tableInstance.getEntityByAggregate({
189 | // where:
190 | "aggregate": [
191 | {"function": "count", "field": "is_done", "name": "undone_tasks"},
192 | ]
193 | }).then(console.log);
194 |
195 |
--------------------------------------------------------------------------------
/tests/test.postgresql.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 数据库配置,可以初始化多个数据库实例
3 | */
4 | let dbconfig = [{
5 | "engine": "default",
6 | "type": "PostgreSQL", // 不区分大小写
7 | "value": {
8 | "port": 3432,
9 | "host": "127.0.0.1",
10 | "user": "test",
11 | "password": "test&kjkdj9034",
12 | "database": "test_db"
13 | }
14 | }];
15 |
16 | const {Old, Onela, OnelaBaseModel} = require("../lib/onela");
17 |
18 | // 初始化Onela模块
19 | Onela.init(dbconfig);
20 | // 已经在OnelaBaseModel封装的常用方法,可以在此基础自行扩展
21 |
22 | class ToDoManager extends OnelaBaseModel {
23 | // 可以在此自定义扩展方法(默认封装没有的方法)
24 | }
25 |
26 | // 【重要】单例模式,数据表配置
27 | ToDoManager.configs = {
28 | fields: [
29 | {name: "id", type: "int", default: null, increment: true},
30 | {name: "content", type: "varchar"},
31 | {name: "is_done", type: "int", default: 0},
32 | {
33 | name: "create_time", type: "datetime", default: () => {
34 | return new Date()
35 | }
36 | },
37 | {
38 | name: "finish_time", type: "datetime", default: null, default: () => {
39 | return new Date()
40 | }
41 | }
42 | ],
43 | tableName: "todos",
44 | engine: "default"
45 | };
46 |
47 | /**
48 | * 事务
49 | */
50 | ToDoManager.transaction().then(t => {
51 | // 先新增一条记录
52 | ToDoManager.insertEntity({
53 | "content": "测试事务"
54 | }, {transaction: t})
55 | .then(data => {
56 | // 再对新增的记录执行修改
57 | return ToDoManager.updateEntity({
58 | "update": [
59 | {"key": "content", "value": "事务修改", "operator": "replace"} // 修改了content字段
60 | ],
61 | "where": [
62 | {"logic": "and", "key": "id", operator: "=", "value": 8}
63 | ]
64 | }, {transaction: t});
65 | })
66 | .then(data => {
67 | console.log('执行结果', data);
68 | t.commit().then(d => {
69 | console.log(d);
70 | });
71 | })
72 | .catch(ex => {
73 | console.log('事务异常回滚', ex);
74 | t.rollback().then(d => {
75 | console.log(d);
76 | });
77 | });
78 | });
79 |
80 |
81 | /**
82 | * 单例模式:新增
83 | */
84 | ToDoManager.insertEntity({
85 | "content": "测试"
86 | }).then(data => {
87 | console.log('查询结果', data)
88 | });
89 |
90 |
91 | /**
92 | * 单例模式:数据查询
93 | */
94 | ToDoManager.getEntity({
95 | where: [
96 | {"logic": "and", "key": "id", "operator": "=", "value": 6},
97 | {"logic": "and", "key": "id", "operator": "=", "value": 6},
98 | {"logic": "and", "key": "id", "operator": "in", "value": [4, 6]}
99 | ]
100 | }, null).then(data => {
101 | console.log('查询结果', data)
102 | }).then();
103 |
104 |
105 | /**
106 | * 单例模式:分页查询
107 | */
108 | ToDoManager.getEntityList({
109 | "where": [
110 | {"logic": "and", "key": "id", "operator": "=", "value": 2}
111 | ]
112 | }).then(console.log);
113 |
114 | /**
115 | * 获取数据瀑布
116 | */
117 | ToDoManager.getEntityWaterfall({
118 | "where": [
119 | // {"logic": "and", "key": "valid", "operator": "=", "value": 1}
120 | ],
121 | "limit":[0,6]
122 | }).then(console.log);
123 |
124 | /**
125 | * 单例模式:批量新增
126 | */
127 | ToDoManager.insertBatch([
128 | {content: "测试1"},
129 | {content: "测试2"},
130 | {content: "测试3"}
131 | ]).then(console.log);
132 |
133 | /**
134 | * 单例模式:删除(物理删除,不推荐使用)
135 | */
136 | ToDoManager.deleteEntity({
137 | "where": [
138 | {"key": "id", operator: "in", value: [9, 10], logic: "and"},
139 | // {"key": "is_done", operator: "=", value: 1, logic: "and"}
140 | ]
141 | }).then(console.log);
142 |
143 | /**
144 | * 单例模式:更新(对于删除,建议使用逻辑删除)
145 | */
146 | ToDoManager.updateEntity({
147 | update: [
148 | {key: "is_done", value: 1, operator: "replace"},
149 | {
150 | "key": "content", //update field
151 | "case_field": "id", //balance = CASE id
152 | "case_item": [
153 | {"case_value": 3, "value": "修改结果A", "operator": "replace"}, //WHEN '001' THEN 1
154 | {"case_value": 6, "value": "修改结果B", "operator": "replace"} //WHEN '001' THEN balance+2
155 | ]
156 | }
157 | ],
158 | where: [
159 | {"key": "id", operator: "in", value: [3, 6], logic: "and"},
160 | ]
161 | }).then(console.log);
162 |
163 | /**
164 | * 单例模式:实时统计
165 | */
166 | ToDoManager.getEntityByAggregate({
167 | // where:
168 | "aggregate": [
169 | {"function": "count", "field": "is_done", "name": "undone_tasks"},
170 | ]
171 | }).then(console.log);
172 |
173 |
--------------------------------------------------------------------------------
/tests/test.sqlite.js:
--------------------------------------------------------------------------------
1 | /**
2 | * SQLite数据库实例
3 | * 数据库配置,可以初始化多个数据库实例
4 | */
5 | let dbconfig = [{
6 | "engine": "default", // 数据库实例名称
7 | "type": "sqlite", // 数据库类型
8 | "value": {
9 | "host": "./sqlite_db.db"
10 |
11 | }
12 | }];
13 |
14 | const {Onela, OnelaBaseModel} = require("../lib/onela");
15 | // 初始化Onela模块
16 | Onela.init(dbconfig);
17 | // 已经在OnelaBaseModel封装的常用方法,可以在此基础自行扩展
18 |
19 | class tableInstance extends OnelaBaseModel {
20 | // 可以在此自定义扩展方法(默认封装没有的方法)
21 | }
22 |
23 | // 【重要】单例模式,数据表配置
24 | tableInstance.configs = {
25 | fields: [
26 | {name: "id", type: "int", default: null, increment: true},
27 | {name: "content", type: "varchar"},
28 | {name: "is_done", type: "int", default: 0},
29 | {
30 | name: "create_time", type: "datetime", default: () => {
31 | return new Date()
32 | }
33 | },
34 | {
35 | name: "finish_time", type: "datetime", default: null, default: () => {
36 | return new Date()
37 | }
38 | }
39 | ],
40 | tableName: "todos",
41 | engine: "default"
42 | };
43 |
44 | /**
45 | * 事务(仅支持本地事务)
46 | */
47 | tableInstance.transaction().then(t => {
48 | // 先新增一条记录
49 | tableInstance.insertEntity({
50 | "content": "执行事务新增测试A"
51 | }, {transaction: t})
52 | .then(data => {
53 | // 再对新增的记录执行修改
54 | return tableInstance.updateEntity({
55 | "update": [
56 | {"key": "content", "value": "执行事务修改测试A", "operator": "replace"} // 修改了content字段
57 | ],
58 | "where": [
59 | {"logic": "and", "key": "id", operator: "=", "value": 9}
60 | ]
61 | }, {transaction: t});
62 | })
63 | .then(data => {
64 | console.log('执行结果', data);
65 | t.commit();
66 | })
67 | .catch(ex => {
68 | console.log('事务异常回滚', ex);
69 | t.rollback();
70 | });
71 | });
72 |
73 | // /**
74 | // * 获取数据瀑布
75 | // */
76 | // tableInstance.getEntityWaterfall({
77 | // "where": [
78 | // // {"logic": "and", "key": "valid", "operator": "=", "value": 1}
79 | // ],
80 | // "limit":[0,2]
81 | // }).then(console.log);
82 |
83 |
84 | /**
85 | * 新增实体对象
86 | * @param params ,新增实体对象
87 | * {
88 | * "id":"3", // 字段1,
89 | * "valid":1, // 字段2,
90 | * }
91 | * @returns {Promise.} 出参,返回新增实体对象
92 | * {
93 | * "id":"3",
94 | * "valid":1
95 | * }
96 | */
97 | // tableInstance.insertEntity({
98 | // "content": "测试00"
99 | // }).then(data => {
100 | // console.log('查询结果', data)
101 | // });
102 |
103 | //
104 | //
105 | // /**
106 | // * 单例模式:数据查询
107 | // */
108 | // tableInstance.getEntity({
109 | // select:["id","content"],
110 | // where: [
111 | // //{"logic": "and", "key": "id", "operator": "in", "value": [9,10]}
112 | // ],
113 | // orderBy:{"id":"desc"},
114 | // limit:[0,10]
115 | // }, null).then(data => {
116 | // console.log('查询结果', data)
117 | // }).then();
118 |
119 | //
120 | // /**
121 | // * 单例模式:分页查询
122 | // */
123 | // tableInstance.getEntityList({
124 | // "where": [
125 | // //{"logic": "and", "key": "id", "operator": "=", "value": 1}
126 | // ],
127 | // "limit":[0,2]
128 | // }).then(console.log);
129 |
130 | // /**
131 | // * 批量新增
132 | // * @param entity_list 新增实体对象列表
133 | // * [
134 | // * {
135 | // * "id":"10", // 批量新增对象1
136 | // * "valid":1
137 | // * },
138 | // * {
139 | // * "id":"10", // 批量新增对象2
140 | // * "valid":1
141 | // * }
142 | // * ]
143 | // * @returns {Promise.}
144 | // */
145 | // tableInstance.insertBatch([
146 | // {content: "测试A"},
147 | // {content: "测试B"},
148 | // {content: "测试C"}
149 | // ]).then(console.log);
150 | //
151 |
152 | // /**
153 | // * 物理删除(数据不可恢复,慎用)
154 | // * @param params 查询参数
155 | // * {
156 | // * "where":[ // where是查询条件模型数组,对应SQL语句where条件
157 | // * { // 例句:select * from tableName where 1=1 and valid = 1
158 | // * "logic": "and", // logic,逻辑运算符,对应SQL语句运算符,可选值:and、or等
159 | // * "key": "id", // key,字段关键字,对应数据表表字段名称
160 | // * "operator":"=", // operator,运算符,对应字段对比关系,可选值:=、>、>=、<、<=、<>、%、x%、%%、in、not in等
161 | // * "value": 1 // value,查询条件值
162 | // * }
163 | // * ]
164 | // * }
165 | // * @param option 其他参数
166 | // * @returns {Promise.} 出参
167 | // * }
168 | // */
169 | // tableInstance.deleteEntity({
170 | // "where": [
171 | // {"key": "id", operator: ">=", value:10, logic: "and"}
172 | // ]
173 | // }).then(console.log);
174 |
175 | // /**
176 | // * 实例更新(支持WHEN THEN CASE 更新)
177 | // * @param params 更新对象模型
178 | // * {
179 | // * "where":[ // where,是查询条件模型数组,对应SQL语句where条件
180 | // * { // 例句:select * from tableName where 1=1 and valid = 1
181 | // * "logic": "and", // logic,逻辑运算符,对应SQL语句运算符,可选值:and、or等
182 | // * "key": "valid", // key,字段关键字,对应数据表表字段名称
183 | // * "operator":"=", // operator,运算符,对应字段对比关系,可选值:=、>、>=、<、<=、<>、%、x%、%%、in、not in等
184 | // * "value": 1 // value,查询条件值
185 | // * }
186 | // * ],
187 | // * "update":[ // where,是更新对象,对应SQL语句中的set更新
188 | // * {
189 | // * "key": "name", // 更新字段
190 | // * "value": "更改名字", // 更新之后的值
191 | // * "operator": "replace" // 更新方式:replace(替换更新)、plus(+=更新,例如金额更新)、reduce(-=更新,例如金额更新)
192 | // * },
193 | // * { // WHEN THEN CASE 更新
194 | // * "key": "money", // 更新字段
195 | // * "case_field": "id", // CASE 条件字段
196 | // * "case_item": [
197 | // * {
198 | // * "case_value": "22", // 把id值为22的这条记录
199 | // * "value": 12, // 例句:WHEN '22' THEN money += 12
200 | // * "operator": "plus" //
201 | // * },
202 | // * {"case_value": 23, "value": "B", "operator": "replace"} //WHEN '001' THEN balance+2
203 | // * ]
204 | // * }
205 | // * ]
206 | // * }
207 | // * @returns {Promise.} 出参
208 | // */
209 | // tableInstance.updateEntity({
210 | // update: [
211 | // {key: "is_done", value: 1, operator: "replace"},
212 | // {
213 | // "key": "content", //update field
214 | // "case_field": "id", //balance = CASE id
215 | // "case_item": [
216 | // {"case_value": 22, "value": "A", "operator": "replace"}, //WHEN '001' THEN 1
217 | // {"case_value": 23, "value": "B", "operator": "replace"} //WHEN '001' THEN balance+2
218 | // ]
219 | // }
220 | // ],
221 | // where: [
222 | // {"key": "id", operator: "in", value: [22, 23], logic: "and"},
223 | // ]
224 | // }).then(console.log);
225 |
226 | // /**
227 | // * 统计查询(聚合函数的使用)
228 | // * @param params 统计查询参数
229 | // * {
230 | // * "where":[ // where,是查询条件模型数组,对应SQL语句where条件
231 | // * { // 例句:select * from tableName where 1=1 and valid = 1
232 | // * "logic": "and", // logic,逻辑运算符,对应SQL语句运算符,可选值:and、or等
233 | // * "key": "valid", // key,字段关键字,对应数据表表字段名称
234 | // * "operator":"=", // operator,运算符,对应字段对比关系,可选值:=、>、>=、<、<=、<>、%、x%、%%、in、not in等
235 | // * "value": 1 // value,查询条件值
236 | // * }
237 | // * ],
238 | // * "aggregate":[
239 | // * {
240 | // * "function": "count", // function,聚合函数:COUNT、SUM、MAX、MIN、ABS、AVG
241 | // * "field": "id", // 字段
242 | // * "name": "total" // 输出字段重命名
243 | // * },
244 | // * ]
245 | // * }
246 | // * @returns {Promise.} 出参
247 | // * [
248 | // * { total: 0 }
249 | // * ]
250 | // */
251 | // tableInstance.getEntityByAggregate({
252 | // // where:
253 | // "aggregate":[
254 | // {"function": "count", "field": "id", "name": "total"},
255 | // ]
256 | // }).then(console.log);
257 |
258 |
--------------------------------------------------------------------------------
/tests/test.sqlserver.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 数据库配置,可以初始化多个数据库实例
3 | */
4 | let dbconfig = [{
5 | "engine": "default", // 数据库实例名称
6 | "type": "sqlserver", // 数据库类型
7 | "value": {
8 | // "connectionLimit": 5,
9 | "host": "127.0.0.1",
10 | "port": 3433,
11 | "user": "onela",
12 | "password": "onela@123",
13 | "database": "test_db"
14 | }
15 | }];
16 |
17 | const {Onela, OnelaBaseModel} = require("../lib/onela");
18 | // 初始化Onela模块
19 | Onela.init(dbconfig);
20 | // 已经在OnelaBaseModel封装的常用方法,可以在此基础自行扩展
21 |
22 | class ToDoManager extends OnelaBaseModel {
23 | // 可以在此自定义扩展方法(默认封装没有的方法)
24 | }
25 |
26 | // 【重要】单例模式,数据表配置
27 | ToDoManager.configs = {
28 | fields: [
29 | {name: "id", type: "Int", default: null, increment: true},
30 | {name: "content", type: "nvarchar"},
31 | {name: "is_done", type: "int", default: 0},
32 | {
33 | name: "create_time", type: "datetime", default: () => {
34 | return new Date()
35 | }
36 | },
37 | {
38 | name: "finish_time", type: "datetime", default: () => {
39 | return new Date()
40 | }
41 | }
42 | ],
43 | tableName: "todos",
44 | engine: "default"
45 | };
46 |
47 |
48 | /**
49 | * 单例模式:新增
50 | */
51 | ToDoManager.insertEntity({
52 | "content": "中文2",
53 | "is_done": 100
54 | }).then(data => {
55 | console.log('查询结果', data);
56 | }).catch(ex => {
57 | console.log(ex);
58 | });
59 |
60 | /**
61 | * 单例模式:批量新增
62 | */
63 | ToDoManager.insertBatch([
64 | {content: "批量01", "is_done": 100},
65 | {content: "批量02", "is_done": 100}
66 | ]).then(data => {
67 | console.log(data);
68 | }).catch(ex => {
69 | console.log(ex);
70 | });
71 |
72 | /**
73 | * 单例模式:数据查询
74 | */
75 | ToDoManager.getEntity({
76 | where: [
77 | {"logic": "and", "key": "id", "operator": ">=", "value": 12},
78 | {"logic": "and", "key": "id", "operator": "=", "value": 13}
79 | ]
80 | }, null).then(data => {
81 | console.log(data);
82 | }).catch(ex => {
83 | console.log(ex);
84 | });
85 |
86 | /**
87 | * 单例模式:分页查询
88 | */
89 | ToDoManager.getEntityList({
90 | "where": [
91 | {"logic": "and", "key": "id", "operator": ">", "value": 12}
92 | ]
93 | }).then(data => {
94 | console.log(data);
95 | }).catch(ex => {
96 | console.log(ex);
97 | });
98 |
99 | /**
100 | * 获取数据瀑布
101 | */
102 | ToDoManager.getEntityWaterfall({
103 | "where": [
104 | // {"logic": "and", "key": "valid", "operator": "=", "value": 1}
105 | ],
106 | "limit":[0,6]
107 | }).then(console.log);
108 |
109 | /**
110 | * 单例模式:删除(物理删除,不推荐使用)
111 | */
112 | ToDoManager.deleteEntity({
113 | "where": [
114 | {"key": "id", operator: "in", value: [16], logic: "and"}
115 | ]
116 | }).then(data => {
117 | console.log(data);
118 | }).catch(ex => {
119 | console.log(ex);
120 | });
121 |
122 |
123 | /**
124 | * 单例模式:更新(对于删除,建议使用逻辑删除)
125 | */
126 | ToDoManager.updateEntity({
127 | update: [
128 | {key: "is_done", value: 99, operator: "replace"},
129 | {
130 | "key": "content", //update field
131 | "case_field": "id", //balance = CASE id
132 | "case_item": [
133 | {"case_value": 14, "value": "修改结果A", "operator": "replace"}, //WHEN '001' THEN 1
134 | {"case_value": 15, "value": "修改结果B", "operator": "replace"} //WHEN '001' THEN balance+2
135 | ]
136 | }
137 | ],
138 | where: [
139 | {"key": "id", operator: "in", value: [14, 15], logic: "and"}
140 | ]
141 | }).then(data => {
142 | console.log(data);
143 | }).catch(ex => {
144 | console.log(ex);
145 | });
146 |
147 |
148 | /**
149 | * 单例模式:实时统计
150 | */
151 | ToDoManager.getEntityByAggregate({
152 | // where:
153 | "aggregate": [
154 | {"function": "count", "field": "is_done", "name": "undone_tasks"},
155 | ]
156 | }).then(data => {
157 | console.log(data);
158 | }).catch(ex => {
159 | console.log(ex);
160 | });
161 |
162 |
163 | /**
164 | * 事务
165 | */
166 | ToDoManager.transaction().then(t => {
167 | // 先新增一条记录
168 | ToDoManager.insertEntity({
169 | "content": "测试事务新增"
170 | }, {transaction: t})
171 | .then(data => {
172 | // 再对新增的记录执行修改
173 | return ToDoManager.updateEntity({
174 | "update": [
175 | {"key": "content", "value": "执行事务修改测试", "operator": "replace"} // 修改了content字段
176 | ],
177 | "where": [
178 | {"logic": "and", "key": "id", operator: "=", "value": 20}
179 | ]
180 | }, {transaction: t});
181 | })
182 | .then(data => {
183 | console.log('执行结果', data);
184 | t.commit().then(d => {
185 | console.log(d);
186 | });
187 | })
188 | .catch(ex => {
189 | console.log('事务异常回滚', ex);
190 | t.rollback().then(d => {
191 | console.log(d);
192 | });
193 | });
194 | });
195 |
--------------------------------------------------------------------------------