├── .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 | [![NPM version](https://img.shields.io/npm/v/onela.svg)](https://www.npmjs.com/package/onela) 9 | [![Downloads](https://img.shields.io/npm/dm/onela.svg)](https://www.npmjs.com/package/onela) 10 | 11 | [![NPM](https://nodei.co/npm/onela.png?downloads=true)](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 | --------------------------------------------------------------------------------