w-orm-postgresql 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.editorconfig +9 -0
- package/.eslintignore +3 -0
- package/.eslintrc.js +55 -0
- package/.jsdoc +25 -0
- package/LICENSE +21 -0
- package/README.md +324 -0
- package/SECURITY.md +5 -0
- package/babel.config.js +15 -0
- package/dist/w-orm-postgresql.umd.js +7 -0
- package/dist/w-orm-postgresql.umd.js.map +1 -0
- package/docs/WOrmPostgresql.html +1655 -0
- package/docs/WOrmPostgresql.mjs.html +952 -0
- package/docs/fonts/Montserrat/Montserrat-Bold.eot +0 -0
- package/docs/fonts/Montserrat/Montserrat-Bold.ttf +0 -0
- package/docs/fonts/Montserrat/Montserrat-Bold.woff +0 -0
- package/docs/fonts/Montserrat/Montserrat-Bold.woff2 +0 -0
- package/docs/fonts/Montserrat/Montserrat-Regular.eot +0 -0
- package/docs/fonts/Montserrat/Montserrat-Regular.ttf +0 -0
- package/docs/fonts/Montserrat/Montserrat-Regular.woff +0 -0
- package/docs/fonts/Montserrat/Montserrat-Regular.woff2 +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.eot +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.svg +978 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.ttf +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-light-webfont.woff2 +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.eot +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.svg +1049 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.ttf +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff +0 -0
- package/docs/fonts/Source-Sans-Pro/sourcesanspro-regular-webfont.woff2 +0 -0
- package/docs/index.html +84 -0
- package/docs/scripts/collapse.js +39 -0
- package/docs/scripts/commonNav.js +28 -0
- package/docs/scripts/linenumber.js +25 -0
- package/docs/scripts/nav.js +12 -0
- package/docs/scripts/polyfill.js +4 -0
- package/docs/scripts/prettify/Apache-License-2.0.txt +202 -0
- package/docs/scripts/prettify/lang-css.js +2 -0
- package/docs/scripts/prettify/prettify.js +28 -0
- package/docs/scripts/search.js +99 -0
- package/docs/styles/jsdoc.css +776 -0
- package/docs/styles/prettify.css +80 -0
- package/g-basic.mjs +306 -0
- package/package.json +32 -0
- package/script.txt +18 -0
- package/src/WOrmPostgresql.mjs +880 -0
- package/test/basic.test.mjs +429 -0
- package/toolg/addVersion.mjs +4 -0
- package/toolg/cleanFolder.mjs +4 -0
- package/toolg/gDistRollup.mjs +25 -0
- package/toolg/modifyReadme.mjs +4 -0
|
@@ -0,0 +1,952 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
|
|
5
|
+
<meta charset="utf-8">
|
|
6
|
+
<title>WOrmPostgresql.mjs - Documentation</title>
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
<script src="scripts/prettify/prettify.js"></script>
|
|
10
|
+
<script src="scripts/prettify/lang-css.js"></script>
|
|
11
|
+
<!--[if lt IE 9]>
|
|
12
|
+
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
|
13
|
+
<![endif]-->
|
|
14
|
+
<link type="text/css" rel="stylesheet" href="styles/prettify.css">
|
|
15
|
+
<link type="text/css" rel="stylesheet" href="styles/jsdoc.css">
|
|
16
|
+
<script src="scripts/nav.js" defer></script>
|
|
17
|
+
|
|
18
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
19
|
+
</head>
|
|
20
|
+
<body>
|
|
21
|
+
|
|
22
|
+
<input type="checkbox" id="nav-trigger" class="nav-trigger" />
|
|
23
|
+
<label for="nav-trigger" class="navicon-button x">
|
|
24
|
+
<div class="navicon"></div>
|
|
25
|
+
</label>
|
|
26
|
+
|
|
27
|
+
<label for="nav-trigger" class="overlay"></label>
|
|
28
|
+
|
|
29
|
+
<nav >
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
<h2><a href="index.html">Home</a></h2><h3>Classes</h3><ul><li><a href="WOrmPostgresql.html">WOrmPostgresql</a><ul class='methods'><li data-type='method'><a href="WOrmPostgresql.html#.createTable">createTable</a></li><li data-type='method'><a href="WOrmPostgresql.html#.del">del</a></li><li data-type='method'><a href="WOrmPostgresql.html#.delAll">delAll</a></li><li data-type='method'><a href="WOrmPostgresql.html#.insert">insert</a></li><li data-type='method'><a href="WOrmPostgresql.html#.save">save</a></li><li data-type='method'><a href="WOrmPostgresql.html#.select">select</a></li></ul></li></ul>
|
|
33
|
+
|
|
34
|
+
</nav>
|
|
35
|
+
|
|
36
|
+
<div id="main">
|
|
37
|
+
|
|
38
|
+
<h1 class="page-title">WOrmPostgresql.mjs</h1>
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
<section>
|
|
47
|
+
<article>
|
|
48
|
+
<pre class="prettyprint source linenums"><code>import events from 'events'
|
|
49
|
+
import pg from 'pg'
|
|
50
|
+
import mongoSql from 'mongo-sql'
|
|
51
|
+
import size from 'lodash-es/size.js'
|
|
52
|
+
import get from 'lodash-es/get.js'
|
|
53
|
+
import map from 'lodash-es/map.js'
|
|
54
|
+
import keys from 'lodash-es/keys.js'
|
|
55
|
+
import filter from 'lodash-es/filter.js'
|
|
56
|
+
import omit from 'lodash-es/omit.js'
|
|
57
|
+
import trim from 'lodash-es/trim.js'
|
|
58
|
+
import isEqual from 'lodash-es/isEqual.js'
|
|
59
|
+
import cloneDeep from 'lodash-es/cloneDeep.js'
|
|
60
|
+
import isstr from 'wsemi/src/isstr.mjs'
|
|
61
|
+
import isestr from 'wsemi/src/isestr.mjs'
|
|
62
|
+
import isarr from 'wsemi/src/isarr.mjs'
|
|
63
|
+
import isearr from 'wsemi/src/isearr.mjs'
|
|
64
|
+
import iseobj from 'wsemi/src/iseobj.mjs'
|
|
65
|
+
import isnum from 'wsemi/src/isnum.mjs'
|
|
66
|
+
import isint from 'wsemi/src/isint.mjs'
|
|
67
|
+
import isbol from 'wsemi/src/isbol.mjs'
|
|
68
|
+
import isDate from 'wsemi/src/isDate.mjs'
|
|
69
|
+
import pmSeries from 'wsemi/src/pmSeries.mjs'
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* 操作資料庫(PostgreSQL)
|
|
74
|
+
*
|
|
75
|
+
* @class
|
|
76
|
+
* @param {Object} [opt={}] 輸入設定物件,預設{}
|
|
77
|
+
* @param {String} [opt.url='postgresql://127.0.0.1:5432'] 輸入連接資料庫字串,預設'postgresql://127.0.0.1:5432'
|
|
78
|
+
* @param {String} [opt.db='worm'] 輸入使用資料庫名稱字串,預設'worm'
|
|
79
|
+
* @param {String} [opt.cl='test'] 輸入使用資料表名稱字串,預設'test'
|
|
80
|
+
* @returns {Object} 回傳操作資料庫物件,各事件功能詳見說明
|
|
81
|
+
*/
|
|
82
|
+
function WOrmPostgresql(opt = {}) {
|
|
83
|
+
|
|
84
|
+
//url
|
|
85
|
+
let url = get(opt, 'url')
|
|
86
|
+
if (!isestr(url)) {
|
|
87
|
+
// url = `postgresql://${user}:${password}@${ip}:${port}`
|
|
88
|
+
url = 'postgresql://user:password@127.0.0.1:5432'
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
//db
|
|
92
|
+
let db = get(opt, 'db')
|
|
93
|
+
if (!isestr(db)) {
|
|
94
|
+
db = 'worm'
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
//cl
|
|
98
|
+
let cl = get(opt, 'cl')
|
|
99
|
+
if (!isestr(cl)) {
|
|
100
|
+
cl = 'test'
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
//getValueType
|
|
104
|
+
function getValueType(value) {
|
|
105
|
+
if (isstr(value)) {
|
|
106
|
+
let isoTimeRegex = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z)?$/
|
|
107
|
+
return isoTimeRegex.test(value) ? 'TIMESTAMPTZ' : 'TEXT'
|
|
108
|
+
}
|
|
109
|
+
else if (isnum(value)) {
|
|
110
|
+
return isint(value) ? 'INTEGER' : 'DOUBLE PRECISION'
|
|
111
|
+
}
|
|
112
|
+
else if (isbol(value)) {
|
|
113
|
+
return 'BOOLEAN'
|
|
114
|
+
}
|
|
115
|
+
else if (value === null) {
|
|
116
|
+
return 'TEXT'
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
return 'JSONB'
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
//genSqlForCreateTable
|
|
124
|
+
function genSqlForCreateTable(tableName, pk, obj) {
|
|
125
|
+
|
|
126
|
+
//check
|
|
127
|
+
if (!iseobj(obj)) {
|
|
128
|
+
throw new Error(`obj[${obj}] is not an effective object`)
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
//columns
|
|
132
|
+
let columns = Object.entries(obj).map(([key, value]) => {
|
|
133
|
+
let type = getValueType(value)
|
|
134
|
+
let c = ` ${key} ${type}`
|
|
135
|
+
if (key === pk) {
|
|
136
|
+
c = `${c} PRIMARY KEY`
|
|
137
|
+
}
|
|
138
|
+
return c
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
//c
|
|
142
|
+
let c = `CREATE TABLE ${tableName} (\n${columns.join(',\n')}\n);`
|
|
143
|
+
// console.log('c', c)
|
|
144
|
+
|
|
145
|
+
return c
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
//genConflictSQL
|
|
149
|
+
function genConflictSQL(obj) {
|
|
150
|
+
|
|
151
|
+
//allKeys
|
|
152
|
+
let allKeys = keys(obj)
|
|
153
|
+
|
|
154
|
+
//conflictKeys
|
|
155
|
+
let conflictKeys = ['time']
|
|
156
|
+
|
|
157
|
+
//updateKeys
|
|
158
|
+
let updateKeys = filter(allKeys, (k) => {
|
|
159
|
+
return !conflictKeys.includes(k)
|
|
160
|
+
})
|
|
161
|
+
|
|
162
|
+
//check
|
|
163
|
+
if (size(updateKeys) === 0) {
|
|
164
|
+
return ''
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
//updateClause
|
|
168
|
+
let updateClause = updateKeys
|
|
169
|
+
.map(key => `${key} = EXCLUDED.${key}`)
|
|
170
|
+
.join(',\n ')
|
|
171
|
+
|
|
172
|
+
//c
|
|
173
|
+
let c = `
|
|
174
|
+
ON CONFLICT (${conflictKeys.join(', ')}) DO UPDATE SET
|
|
175
|
+
${updateClause}
|
|
176
|
+
`
|
|
177
|
+
|
|
178
|
+
//trim
|
|
179
|
+
c = trim(c)
|
|
180
|
+
|
|
181
|
+
return c
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
//connectionString
|
|
185
|
+
let connectionString = `${url}/${db}`
|
|
186
|
+
// console.log('connectionString', connectionString)
|
|
187
|
+
|
|
188
|
+
//ee
|
|
189
|
+
let ee = new events.EventEmitter()
|
|
190
|
+
|
|
191
|
+
//PgClient
|
|
192
|
+
let PgClient = pg.Client
|
|
193
|
+
// console.log('PgClient', PgClient)
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* 創建資料表
|
|
197
|
+
*
|
|
198
|
+
* @memberOf WOrmPostgresql
|
|
199
|
+
* @param {String} cl 輸入資料表名字串
|
|
200
|
+
* @param {String} pk 輸入主鍵字串
|
|
201
|
+
* @param {Array|Object} arr 輸入數據物件陣列或數據物件
|
|
202
|
+
* @returns {Promise} 回傳Promise,resolve回傳成功訊息,reject回傳錯誤訊息
|
|
203
|
+
*/
|
|
204
|
+
async function createTable(cl, pk, arr) {
|
|
205
|
+
let isErr = false
|
|
206
|
+
let res = null
|
|
207
|
+
|
|
208
|
+
//client
|
|
209
|
+
let client = new PgClient({ connectionString })
|
|
210
|
+
|
|
211
|
+
//connect
|
|
212
|
+
try {
|
|
213
|
+
|
|
214
|
+
//connect
|
|
215
|
+
await client.connect()
|
|
216
|
+
|
|
217
|
+
}
|
|
218
|
+
catch (err) {
|
|
219
|
+
isErr = true
|
|
220
|
+
res = err
|
|
221
|
+
client = null
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
//check
|
|
225
|
+
if (isErr) {
|
|
226
|
+
return Promise.reject(res)
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
try {
|
|
230
|
+
|
|
231
|
+
//obj
|
|
232
|
+
let obj = arr
|
|
233
|
+
if (isearr(obj)) {
|
|
234
|
+
obj = obj[0]
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
//check
|
|
238
|
+
if (!iseobj(obj)) {
|
|
239
|
+
throw new Error(`obj[${obj}] is not an effective object`)
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
//sql
|
|
243
|
+
let sql = genSqlForCreateTable(cl, pk, obj)
|
|
244
|
+
// console.log('sql', sql)
|
|
245
|
+
|
|
246
|
+
//select
|
|
247
|
+
await client.query(sql)
|
|
248
|
+
.then(() => {
|
|
249
|
+
res = {
|
|
250
|
+
ok: 1,
|
|
251
|
+
}
|
|
252
|
+
})
|
|
253
|
+
.catch((err) => {
|
|
254
|
+
isErr = true
|
|
255
|
+
res = err.message
|
|
256
|
+
})
|
|
257
|
+
|
|
258
|
+
}
|
|
259
|
+
catch (err) {
|
|
260
|
+
isErr = true
|
|
261
|
+
res = err
|
|
262
|
+
}
|
|
263
|
+
finally {
|
|
264
|
+
await client.end()
|
|
265
|
+
client = null
|
|
266
|
+
}
|
|
267
|
+
// console.log('res', res)
|
|
268
|
+
|
|
269
|
+
//check
|
|
270
|
+
if (isErr) {
|
|
271
|
+
return Promise.reject(res)
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
return res
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* 查詢數據
|
|
279
|
+
*
|
|
280
|
+
* @memberOf WOrmPostgresql
|
|
281
|
+
* @param {Object} [find={}] 輸入查詢條件物件
|
|
282
|
+
* @param {Object} [order={}] 輸入排序條件物件
|
|
283
|
+
* @returns {Promise} 回傳Promise,resolve回傳數據,reject回傳錯誤訊息
|
|
284
|
+
*/
|
|
285
|
+
async function select(find = {}, order = {}) {
|
|
286
|
+
let isErr = false
|
|
287
|
+
let res = null
|
|
288
|
+
|
|
289
|
+
//client
|
|
290
|
+
let client = new PgClient({ connectionString })
|
|
291
|
+
|
|
292
|
+
//connect
|
|
293
|
+
try {
|
|
294
|
+
|
|
295
|
+
//connect
|
|
296
|
+
await client.connect()
|
|
297
|
+
|
|
298
|
+
}
|
|
299
|
+
catch (err) {
|
|
300
|
+
isErr = true
|
|
301
|
+
res = err
|
|
302
|
+
client = null
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
//check
|
|
306
|
+
if (isErr) {
|
|
307
|
+
return Promise.reject(res)
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
try {
|
|
311
|
+
|
|
312
|
+
//mr
|
|
313
|
+
let mr = mongoSql.sql({
|
|
314
|
+
type: 'select',
|
|
315
|
+
table: cl,
|
|
316
|
+
where: find,
|
|
317
|
+
// limit: 10,
|
|
318
|
+
order,
|
|
319
|
+
})
|
|
320
|
+
// console.log('mr', mr)
|
|
321
|
+
// console.log('mr.query', mr.query)
|
|
322
|
+
// console.log('mr.values', mr.values)
|
|
323
|
+
|
|
324
|
+
//select
|
|
325
|
+
let r = await client.query(mr.query, mr.values)
|
|
326
|
+
// console.log('r', r)
|
|
327
|
+
|
|
328
|
+
//res
|
|
329
|
+
res = get(r, 'rows')
|
|
330
|
+
|
|
331
|
+
//check
|
|
332
|
+
if (!isarr(res)) {
|
|
333
|
+
isErr = true
|
|
334
|
+
res = `can not select by find[${JSON.stringify(find)}]`
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
}
|
|
338
|
+
catch (err) {
|
|
339
|
+
isErr = true
|
|
340
|
+
res = err
|
|
341
|
+
}
|
|
342
|
+
finally {
|
|
343
|
+
await client.end()
|
|
344
|
+
client = null
|
|
345
|
+
}
|
|
346
|
+
// console.log('res', res)
|
|
347
|
+
|
|
348
|
+
//check
|
|
349
|
+
if (isErr) {
|
|
350
|
+
return Promise.reject(res)
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
return res
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* 插入數據
|
|
358
|
+
*
|
|
359
|
+
* @memberOf WOrmPostgresql
|
|
360
|
+
* @param {Object|Array} data 輸入數據物件或陣列
|
|
361
|
+
* @returns {Promise} 回傳Promise,resolve回傳插入結果,reject回傳錯誤訊息
|
|
362
|
+
*/
|
|
363
|
+
async function insert(data) {
|
|
364
|
+
let isErr = false
|
|
365
|
+
let res = null
|
|
366
|
+
|
|
367
|
+
//cloneDeep
|
|
368
|
+
data = cloneDeep(data)
|
|
369
|
+
|
|
370
|
+
//client
|
|
371
|
+
let client = new PgClient({ connectionString })
|
|
372
|
+
|
|
373
|
+
//connect
|
|
374
|
+
try {
|
|
375
|
+
|
|
376
|
+
//connect
|
|
377
|
+
await client.connect()
|
|
378
|
+
|
|
379
|
+
}
|
|
380
|
+
catch (err) {
|
|
381
|
+
isErr = true
|
|
382
|
+
res = err
|
|
383
|
+
client = null
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
//check
|
|
387
|
+
if (isErr) {
|
|
388
|
+
return Promise.reject(res)
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
try {
|
|
392
|
+
|
|
393
|
+
//check
|
|
394
|
+
if (!isarr(data)) {
|
|
395
|
+
data = [data]
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
//check time
|
|
399
|
+
data = map(data, function(v, k) {
|
|
400
|
+
if (!isDate(v.time)) {
|
|
401
|
+
throw new Error(`invalid data[${k}].time[${v.time}]`)
|
|
402
|
+
}
|
|
403
|
+
return v
|
|
404
|
+
})
|
|
405
|
+
|
|
406
|
+
//mr
|
|
407
|
+
let mr = mongoSql.sql({
|
|
408
|
+
type: 'insert',
|
|
409
|
+
table: cl,
|
|
410
|
+
values: data,
|
|
411
|
+
})
|
|
412
|
+
// console.log('mr', mr)
|
|
413
|
+
// console.log('mr.query', mr.query)
|
|
414
|
+
// console.log('mr.values', mr.values)
|
|
415
|
+
|
|
416
|
+
//nAll, nInsert
|
|
417
|
+
let nAll = size(data)
|
|
418
|
+
let nInsert = nAll //一次插入全部數據加速, 但也因此沒法個別處理conflict, 無法個別計算已插入數量
|
|
419
|
+
|
|
420
|
+
//insert
|
|
421
|
+
await client.query(mr.query, mr.values)
|
|
422
|
+
.then(() => {
|
|
423
|
+
|
|
424
|
+
//res
|
|
425
|
+
res = {
|
|
426
|
+
n: nAll,
|
|
427
|
+
nInserted: nInsert,
|
|
428
|
+
ok: 1,
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
//emit
|
|
432
|
+
ee.emit('change', 'insert', data, res)
|
|
433
|
+
|
|
434
|
+
})
|
|
435
|
+
.catch((err) => {
|
|
436
|
+
isErr = true
|
|
437
|
+
res = err.message
|
|
438
|
+
})
|
|
439
|
+
|
|
440
|
+
}
|
|
441
|
+
catch (err) {
|
|
442
|
+
isErr = true
|
|
443
|
+
res = err
|
|
444
|
+
}
|
|
445
|
+
finally {
|
|
446
|
+
await client.end()
|
|
447
|
+
client = null
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
//check
|
|
451
|
+
if (isErr) {
|
|
452
|
+
return Promise.reject(res)
|
|
453
|
+
}
|
|
454
|
+
|
|
455
|
+
return res
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
/**
|
|
459
|
+
* 儲存數據
|
|
460
|
+
*
|
|
461
|
+
* @memberOf WOrmPostgresql
|
|
462
|
+
* @param {Object|Array} data 輸入數據物件或陣列
|
|
463
|
+
* @param {Object} [option={}] 輸入設定物件,預設為{}
|
|
464
|
+
* @param {boolean} [option.autoInsert=true] 輸入是否於儲存時發現原本無數據,則自動改以插入處理,預設為true
|
|
465
|
+
* @returns {Promise} 回傳Promise,resolve回傳儲存結果,reject回傳錯誤訊息
|
|
466
|
+
*/
|
|
467
|
+
async function save(data, option = {}) {
|
|
468
|
+
let isErr = false
|
|
469
|
+
let res = null
|
|
470
|
+
|
|
471
|
+
//cloneDeep
|
|
472
|
+
data = cloneDeep(data)
|
|
473
|
+
|
|
474
|
+
//autoInsert
|
|
475
|
+
let autoInsert = get(option, 'autoInsert', true)
|
|
476
|
+
|
|
477
|
+
//client
|
|
478
|
+
let client = new PgClient({ connectionString })
|
|
479
|
+
|
|
480
|
+
//connect
|
|
481
|
+
try {
|
|
482
|
+
|
|
483
|
+
//connect
|
|
484
|
+
await client.connect()
|
|
485
|
+
|
|
486
|
+
}
|
|
487
|
+
catch (err) {
|
|
488
|
+
isErr = true
|
|
489
|
+
res = err
|
|
490
|
+
client = null
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
//check
|
|
494
|
+
if (isErr) {
|
|
495
|
+
return Promise.reject(res)
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
try {
|
|
499
|
+
|
|
500
|
+
//check
|
|
501
|
+
if (!isarr(data)) {
|
|
502
|
+
data = [data]
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
//check time
|
|
506
|
+
data = map(data, function(v, k) {
|
|
507
|
+
if (!isDate(v.time)) {
|
|
508
|
+
throw new Error(`invalid data[${k}].time[${v.time}]`)
|
|
509
|
+
}
|
|
510
|
+
return v
|
|
511
|
+
})
|
|
512
|
+
|
|
513
|
+
//pmSeries
|
|
514
|
+
res = await pmSeries(data, async(v) => {
|
|
515
|
+
|
|
516
|
+
//rest
|
|
517
|
+
let rest = null
|
|
518
|
+
|
|
519
|
+
//_v
|
|
520
|
+
let _v = null
|
|
521
|
+
if (true) {
|
|
522
|
+
|
|
523
|
+
//mr
|
|
524
|
+
let mr = mongoSql.sql({
|
|
525
|
+
type: 'select',
|
|
526
|
+
table: cl,
|
|
527
|
+
where: {
|
|
528
|
+
time: v.time,
|
|
529
|
+
},
|
|
530
|
+
// limit: 10,
|
|
531
|
+
// order,
|
|
532
|
+
})
|
|
533
|
+
// console.log('mr', mr)
|
|
534
|
+
// console.log('mr.query', mr.query)
|
|
535
|
+
// console.log('mr.values', mr.values)
|
|
536
|
+
|
|
537
|
+
//select
|
|
538
|
+
let r = await client.query(mr.query, mr.values)
|
|
539
|
+
// console.log('r', r)
|
|
540
|
+
|
|
541
|
+
//rows
|
|
542
|
+
let rows = get(r, 'rows')
|
|
543
|
+
// console.log('rows', rows)
|
|
544
|
+
|
|
545
|
+
//_v
|
|
546
|
+
_v = get(rows, 0, null)
|
|
547
|
+
// console.log('_v', _v)
|
|
548
|
+
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
//check
|
|
552
|
+
if (iseobj(_v)) {
|
|
553
|
+
//存在
|
|
554
|
+
|
|
555
|
+
//_vt
|
|
556
|
+
let _vt = omit(_v, 'time')
|
|
557
|
+
// console.log('_vt', _vt)
|
|
558
|
+
|
|
559
|
+
//vt
|
|
560
|
+
let vt = omit(v, 'time')
|
|
561
|
+
// console.log('vt', vt)
|
|
562
|
+
|
|
563
|
+
if (isEqual(_vt, vt)) {
|
|
564
|
+
//相同時不更新
|
|
565
|
+
|
|
566
|
+
//rest
|
|
567
|
+
rest = {
|
|
568
|
+
n: 1,
|
|
569
|
+
nModified: 0,
|
|
570
|
+
ok: 1,
|
|
571
|
+
}
|
|
572
|
+
// console.log('相同時不更新', rest, v)
|
|
573
|
+
|
|
574
|
+
}
|
|
575
|
+
else {
|
|
576
|
+
//不相同時須更新
|
|
577
|
+
|
|
578
|
+
//mr
|
|
579
|
+
let mr = mongoSql.sql({
|
|
580
|
+
type: 'insert',
|
|
581
|
+
table: cl,
|
|
582
|
+
values: v,
|
|
583
|
+
})
|
|
584
|
+
// console.log('mr', mr)
|
|
585
|
+
// console.log('mr.query', mr.query)
|
|
586
|
+
// console.log('mr.values', mr.values)
|
|
587
|
+
|
|
588
|
+
//添加conflict
|
|
589
|
+
let conflict = genConflictSQL(v)
|
|
590
|
+
|
|
591
|
+
//sql
|
|
592
|
+
let sql = `${mr.query} ${conflict}`
|
|
593
|
+
|
|
594
|
+
//save
|
|
595
|
+
await client.query(sql, mr.values)
|
|
596
|
+
.then(() => {
|
|
597
|
+
|
|
598
|
+
//rest
|
|
599
|
+
rest = {
|
|
600
|
+
n: 1,
|
|
601
|
+
nModified: 1,
|
|
602
|
+
ok: 1,
|
|
603
|
+
}
|
|
604
|
+
// console.log('不相同時須更新', rest, vt)
|
|
605
|
+
|
|
606
|
+
})
|
|
607
|
+
.catch((err) => {
|
|
608
|
+
|
|
609
|
+
//rest
|
|
610
|
+
rest = {
|
|
611
|
+
n: 1,
|
|
612
|
+
nModified: 0,
|
|
613
|
+
ok: 0,
|
|
614
|
+
err: err.message,
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
})
|
|
618
|
+
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
else {
|
|
622
|
+
//不存在
|
|
623
|
+
|
|
624
|
+
//rest
|
|
625
|
+
rest = {
|
|
626
|
+
n: 0,
|
|
627
|
+
nModified: 0,
|
|
628
|
+
ok: 1,
|
|
629
|
+
}
|
|
630
|
+
// console.log('不存在', rest, v)
|
|
631
|
+
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
//autoInsert
|
|
635
|
+
if (autoInsert && rest.n === 0) {
|
|
636
|
+
//之前不存在(rest.n)且可自動插入(autoInsert=true)
|
|
637
|
+
|
|
638
|
+
//mr
|
|
639
|
+
let mr = mongoSql.sql({
|
|
640
|
+
type: 'insert',
|
|
641
|
+
table: cl,
|
|
642
|
+
values: v,
|
|
643
|
+
})
|
|
644
|
+
// console.log('mr', mr)
|
|
645
|
+
// console.log('mr.query', mr.query)
|
|
646
|
+
// console.log('mr.values', mr.values)
|
|
647
|
+
|
|
648
|
+
//save
|
|
649
|
+
await client.query(mr.query, mr.values)
|
|
650
|
+
.then(() => {
|
|
651
|
+
|
|
652
|
+
//rest
|
|
653
|
+
rest = {
|
|
654
|
+
n: 1,
|
|
655
|
+
nInserted: 1,
|
|
656
|
+
ok: 1,
|
|
657
|
+
}
|
|
658
|
+
// console.log('之前不存在且可自動插入', rest, v)
|
|
659
|
+
|
|
660
|
+
})
|
|
661
|
+
.catch((err) => {
|
|
662
|
+
|
|
663
|
+
//rest
|
|
664
|
+
rest = {
|
|
665
|
+
n: 1,
|
|
666
|
+
nInserted: 0,
|
|
667
|
+
ok: 0,
|
|
668
|
+
err: err.message,
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
})
|
|
672
|
+
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
return rest
|
|
676
|
+
})
|
|
677
|
+
|
|
678
|
+
//emit
|
|
679
|
+
ee.emit('change', 'save', data, res)
|
|
680
|
+
|
|
681
|
+
}
|
|
682
|
+
catch (err) {
|
|
683
|
+
isErr = true
|
|
684
|
+
res = err
|
|
685
|
+
}
|
|
686
|
+
finally {
|
|
687
|
+
await client.end()
|
|
688
|
+
client = null
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
//check
|
|
692
|
+
if (isErr) {
|
|
693
|
+
return Promise.reject(res)
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
return res
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
/**
|
|
700
|
+
* 刪除數據
|
|
701
|
+
*
|
|
702
|
+
* @memberOf WOrmPostgresql
|
|
703
|
+
* @param {Object|Array} data 輸入數據物件或陣列
|
|
704
|
+
* @returns {Promise} 回傳Promise,resolve回傳刪除結果,reject回傳錯誤訊息
|
|
705
|
+
*/
|
|
706
|
+
async function del(data) {
|
|
707
|
+
let isErr = false
|
|
708
|
+
let res = null
|
|
709
|
+
|
|
710
|
+
//cloneDeep
|
|
711
|
+
data = cloneDeep(data)
|
|
712
|
+
|
|
713
|
+
//client
|
|
714
|
+
let client = new PgClient({ connectionString })
|
|
715
|
+
|
|
716
|
+
//connect
|
|
717
|
+
try {
|
|
718
|
+
|
|
719
|
+
//connect
|
|
720
|
+
await client.connect()
|
|
721
|
+
|
|
722
|
+
}
|
|
723
|
+
catch (err) {
|
|
724
|
+
isErr = true
|
|
725
|
+
res = err
|
|
726
|
+
client = null
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
//check
|
|
730
|
+
if (isErr) {
|
|
731
|
+
return Promise.reject(res)
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
try {
|
|
735
|
+
|
|
736
|
+
// //database, collection
|
|
737
|
+
// let database = client.db(opt.db)
|
|
738
|
+
// let collection = database.collection(opt.cl)
|
|
739
|
+
|
|
740
|
+
//check
|
|
741
|
+
if (!isarr(data)) {
|
|
742
|
+
data = [data]
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
//check time
|
|
746
|
+
data = map(data, function(v, k) {
|
|
747
|
+
if (!isDate(v.time)) {
|
|
748
|
+
throw new Error(`invalid data[${k}].time[${v.time}]`)
|
|
749
|
+
}
|
|
750
|
+
return v
|
|
751
|
+
})
|
|
752
|
+
|
|
753
|
+
//pmSeries
|
|
754
|
+
res = await pmSeries(data, async(v) => {
|
|
755
|
+
|
|
756
|
+
//rest
|
|
757
|
+
let rest = null
|
|
758
|
+
|
|
759
|
+
//mr
|
|
760
|
+
let mr = mongoSql.sql({
|
|
761
|
+
type: 'delete',
|
|
762
|
+
table: cl,
|
|
763
|
+
where: {
|
|
764
|
+
time: v.time,
|
|
765
|
+
},
|
|
766
|
+
})
|
|
767
|
+
// console.log('mr', mr)
|
|
768
|
+
// console.log('mr.query', mr.query)
|
|
769
|
+
// console.log('mr.values', mr.values)
|
|
770
|
+
|
|
771
|
+
//del
|
|
772
|
+
await client.query(mr.query, mr.values)
|
|
773
|
+
.then((r) => {
|
|
774
|
+
|
|
775
|
+
//res
|
|
776
|
+
rest = {
|
|
777
|
+
n: 1,
|
|
778
|
+
nDeleted: r.rowCount,
|
|
779
|
+
ok: 1,
|
|
780
|
+
}
|
|
781
|
+
|
|
782
|
+
})
|
|
783
|
+
.catch((err) => {
|
|
784
|
+
|
|
785
|
+
//rest
|
|
786
|
+
rest = {
|
|
787
|
+
n: 1,
|
|
788
|
+
nDeleted: 0,
|
|
789
|
+
ok: 0,
|
|
790
|
+
err: err.message,
|
|
791
|
+
}
|
|
792
|
+
|
|
793
|
+
})
|
|
794
|
+
|
|
795
|
+
return rest
|
|
796
|
+
})
|
|
797
|
+
|
|
798
|
+
//emit
|
|
799
|
+
ee.emit('change', 'del', data, res)
|
|
800
|
+
|
|
801
|
+
}
|
|
802
|
+
catch (err) {
|
|
803
|
+
isErr = true
|
|
804
|
+
res = err
|
|
805
|
+
}
|
|
806
|
+
finally {
|
|
807
|
+
await client.end()
|
|
808
|
+
client = null
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
//check
|
|
812
|
+
if (isErr) {
|
|
813
|
+
return Promise.reject(res)
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
return res
|
|
817
|
+
}
|
|
818
|
+
|
|
819
|
+
/**
|
|
820
|
+
* 刪除全部數據,需與del分開,避免未傳數據導致直接刪除全表
|
|
821
|
+
*
|
|
822
|
+
* @memberOf WOrmPostgresql
|
|
823
|
+
* @param {Object} [find={}] 輸入刪除條件物件
|
|
824
|
+
* @returns {Promise} 回傳Promise,resolve回傳刪除結果,reject回傳錯誤訊息
|
|
825
|
+
*/
|
|
826
|
+
async function delAll(find = {}) {
|
|
827
|
+
let isErr = false
|
|
828
|
+
let res = null
|
|
829
|
+
|
|
830
|
+
//client
|
|
831
|
+
let client = new PgClient({ connectionString })
|
|
832
|
+
|
|
833
|
+
//connect
|
|
834
|
+
try {
|
|
835
|
+
|
|
836
|
+
//connect
|
|
837
|
+
await client.connect()
|
|
838
|
+
|
|
839
|
+
}
|
|
840
|
+
catch (err) {
|
|
841
|
+
isErr = true
|
|
842
|
+
res = err
|
|
843
|
+
client = null
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
//check
|
|
847
|
+
if (isErr) {
|
|
848
|
+
return Promise.reject(res)
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
try {
|
|
852
|
+
|
|
853
|
+
// //database, collection
|
|
854
|
+
// let database = client.db(opt.db)
|
|
855
|
+
// let collection = database.collection(opt.cl)
|
|
856
|
+
|
|
857
|
+
// //deleteMany
|
|
858
|
+
// res = await collection.deleteMany(find)
|
|
859
|
+
|
|
860
|
+
// //res
|
|
861
|
+
// res = {
|
|
862
|
+
// n: res.deletedCount,
|
|
863
|
+
// nDeleted: res.deletedCount,
|
|
864
|
+
// ok: res.acknowledged ? 1 : 0,
|
|
865
|
+
// }
|
|
866
|
+
|
|
867
|
+
//mr
|
|
868
|
+
let mr = mongoSql.sql({
|
|
869
|
+
type: 'delete',
|
|
870
|
+
table: cl,
|
|
871
|
+
where: find,
|
|
872
|
+
})
|
|
873
|
+
// console.log('mr', mr)
|
|
874
|
+
// console.log('mr.query', mr.query)
|
|
875
|
+
// console.log('mr.values', mr.values)
|
|
876
|
+
|
|
877
|
+
//delAll
|
|
878
|
+
await client.query(mr.query, mr.values)
|
|
879
|
+
.then((r) => {
|
|
880
|
+
|
|
881
|
+
//res
|
|
882
|
+
res = {
|
|
883
|
+
n: r.rowCount,
|
|
884
|
+
nDeleted: r.rowCount,
|
|
885
|
+
ok: 1,
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
//emit
|
|
889
|
+
ee.emit('change', 'delAll', null, res)
|
|
890
|
+
|
|
891
|
+
})
|
|
892
|
+
.catch((err) => {
|
|
893
|
+
isErr = true
|
|
894
|
+
res = err.message
|
|
895
|
+
})
|
|
896
|
+
|
|
897
|
+
}
|
|
898
|
+
catch (err) {
|
|
899
|
+
isErr = true
|
|
900
|
+
res = err
|
|
901
|
+
}
|
|
902
|
+
finally {
|
|
903
|
+
await client.end()
|
|
904
|
+
client = null
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
//check
|
|
908
|
+
if (isErr) {
|
|
909
|
+
return Promise.reject(res)
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
return res
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
//save
|
|
916
|
+
ee.createTable = createTable
|
|
917
|
+
ee.select = select
|
|
918
|
+
ee.insert = insert
|
|
919
|
+
ee.save = save
|
|
920
|
+
ee.del = del
|
|
921
|
+
ee.delAll = delAll
|
|
922
|
+
|
|
923
|
+
return ee
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
|
|
927
|
+
export default WOrmPostgresql
|
|
928
|
+
</code></pre>
|
|
929
|
+
</article>
|
|
930
|
+
</section>
|
|
931
|
+
|
|
932
|
+
|
|
933
|
+
|
|
934
|
+
|
|
935
|
+
|
|
936
|
+
|
|
937
|
+
</div>
|
|
938
|
+
|
|
939
|
+
<br class="clear">
|
|
940
|
+
|
|
941
|
+
<footer>
|
|
942
|
+
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.4</a> on Sun Mar 23 2025 21:47:56 GMT+0800 (台北標準時間) using the <a href="https://github.com/clenemt/docdash">docdash</a> theme.
|
|
943
|
+
</footer>
|
|
944
|
+
|
|
945
|
+
<script>prettyPrint();</script>
|
|
946
|
+
<script src="scripts/polyfill.js"></script>
|
|
947
|
+
<script src="scripts/linenumber.js"></script>
|
|
948
|
+
|
|
949
|
+
|
|
950
|
+
|
|
951
|
+
</body>
|
|
952
|
+
</html>
|