w-orm-postgresql 1.0.11 → 1.0.13
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/README.md +83 -0
- package/dist/w-orm-postgresql.umd.js +2 -2
- package/dist/w-orm-postgresql.umd.js.map +1 -1
- package/docs/WOrmPostgresql.html +312 -14
- package/docs/WOrmPostgresql.mjs.html +286 -35
- package/docs/index.html +2 -2
- package/g-basic.mjs +83 -0
- package/package.json +1 -1
- package/src/WOrmPostgresql.mjs +284 -33
- package/test/api-postgresql.test.mjs +452 -0
- package/toolg/gDistRollup.mjs +1 -1
|
@@ -4,6 +4,7 @@ import path from 'path'
|
|
|
4
4
|
import pg from 'pg'
|
|
5
5
|
import { execFile, spawn } from 'child_process'
|
|
6
6
|
import { promisify } from 'util'
|
|
7
|
+
import isarr from 'wsemi/src/isarr.mjs'
|
|
7
8
|
import isestr from 'wsemi/src/isestr.mjs'
|
|
8
9
|
import WOrm from '../src/WOrmPostgresql.mjs'
|
|
9
10
|
|
|
@@ -957,6 +958,32 @@ describe('insert nInserted', function() {
|
|
|
957
958
|
let vdup = await wo.selectByPk('2025-02-01T00:05:00Z')
|
|
958
959
|
vget[8] = vdup.name
|
|
959
960
|
|
|
961
|
+
//跨批次之插入
|
|
962
|
+
//欄位數愈多則單一語句可送之筆數愈少, 以21欄之資料表令每批上限為3120筆, 送3200筆即須分為2批
|
|
963
|
+
//其中既有主鍵者跳過而其餘照插, 與insertBulk之全有全無不同
|
|
964
|
+
let clBat = 'insertbatch'
|
|
965
|
+
let woBat = WOrm(genOpt(clBat))
|
|
966
|
+
let vSample = { time: '2000-01-01T00:00:00Z' }
|
|
967
|
+
Array.from({ length: 20 }, (v, k) => k).forEach((k) => {
|
|
968
|
+
vSample[`f${k}`] = 'abc'
|
|
969
|
+
})
|
|
970
|
+
await woBat.createTable(clBat, null, vSample).catch(() => {})
|
|
971
|
+
await woBat.delAll()
|
|
972
|
+
|
|
973
|
+
//genRec
|
|
974
|
+
let genRec = (k) => {
|
|
975
|
+
let v = { time: new Date(Date.UTC(2025, 8, 1, 0, 0, 0) + k * 1000).toISOString() }
|
|
976
|
+
Array.from({ length: 20 }, (v2, k2) => k2).forEach((k2) => {
|
|
977
|
+
v[`f${k2}`] = `v${k}-${k2}`
|
|
978
|
+
})
|
|
979
|
+
return v
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
//先插入末筆之主鍵, 令後續之大批次於第2批撞上該筆
|
|
983
|
+
await woBat.insert(genRec(3199))
|
|
984
|
+
vget[9] = await woBat.insert(Array.from({ length: 3200 }, (v, k) => genRec(k)))
|
|
985
|
+
vget[10] = (await woBat.select()).length
|
|
986
|
+
|
|
960
987
|
})
|
|
961
988
|
|
|
962
989
|
vans[1] = { n: 3, nInserted: 3, ok: 1 }
|
|
@@ -999,6 +1026,16 @@ describe('insert nInserted', function() {
|
|
|
999
1026
|
assert.strict.deepStrictEqual(vget[8], vans[8])
|
|
1000
1027
|
})
|
|
1001
1028
|
|
|
1029
|
+
vans[9] = { n: 3200, nInserted: 3199, ok: 1 }
|
|
1030
|
+
it(`should get ${JSON.stringify(vans[9])} for insert across batches with 1 pk existed`, async function() {
|
|
1031
|
+
assert.strict.deepStrictEqual(vget[9], vans[9])
|
|
1032
|
+
})
|
|
1033
|
+
|
|
1034
|
+
vans[10] = 3200
|
|
1035
|
+
it(`should get ${JSON.stringify(vans[10])} for records after insert across batches`, async function() {
|
|
1036
|
+
assert.strict.deepStrictEqual(vget[10], vans[10])
|
|
1037
|
+
})
|
|
1038
|
+
|
|
1002
1039
|
})
|
|
1003
1040
|
|
|
1004
1041
|
|
|
@@ -1674,6 +1711,421 @@ describe('events', function() {
|
|
|
1674
1711
|
})
|
|
1675
1712
|
|
|
1676
1713
|
|
|
1714
|
+
describe('insertBulk', function() {
|
|
1715
|
+
let vans = {}
|
|
1716
|
+
let vget = {}
|
|
1717
|
+
|
|
1718
|
+
before(async function() {
|
|
1719
|
+
this.timeout(300000)
|
|
1720
|
+
|
|
1721
|
+
//wo
|
|
1722
|
+
let cl = 'bulk'
|
|
1723
|
+
let wo = WOrm(genOpt(cl))
|
|
1724
|
+
|
|
1725
|
+
//createTable
|
|
1726
|
+
await wo.createTable(cl, null, {
|
|
1727
|
+
time: '2000-01-01T00:00:00Z',
|
|
1728
|
+
name: 'abc',
|
|
1729
|
+
value: 0.1,
|
|
1730
|
+
}).catch(() => {})
|
|
1731
|
+
await wo.delAll()
|
|
1732
|
+
|
|
1733
|
+
//genTime, 依序產生不重複之主鍵值
|
|
1734
|
+
let genTime = (k) => {
|
|
1735
|
+
return new Date(Date.UTC(2025, 7, 1, 0, 0, 0) + k * 1000).toISOString()
|
|
1736
|
+
}
|
|
1737
|
+
|
|
1738
|
+
//evChange, evError
|
|
1739
|
+
let evChange = []
|
|
1740
|
+
let evError = []
|
|
1741
|
+
wo.on('change', (mode) => {
|
|
1742
|
+
evChange.push(mode)
|
|
1743
|
+
})
|
|
1744
|
+
wo.on('error', (mode) => {
|
|
1745
|
+
evError.push(mode)
|
|
1746
|
+
})
|
|
1747
|
+
|
|
1748
|
+
//nRec, 取得目前筆數
|
|
1749
|
+
let nRec = async () => {
|
|
1750
|
+
return (await wo.select()).length
|
|
1751
|
+
}
|
|
1752
|
+
|
|
1753
|
+
//無衝突, nInserted須等於n
|
|
1754
|
+
vget[1] = await wo.insertBulk([
|
|
1755
|
+
{ time: genTime(0), name: 'peter', value: 1 },
|
|
1756
|
+
{ time: genTime(1), name: 'rosemary', value: 2 },
|
|
1757
|
+
{ time: genTime(2), name: 'kettle', value: 3 },
|
|
1758
|
+
])
|
|
1759
|
+
vget[2] = await nRec()
|
|
1760
|
+
vget[3] = evChange.slice()
|
|
1761
|
+
|
|
1762
|
+
//撞既有主鍵, 整批reject且不寫入任何一筆
|
|
1763
|
+
evChange = []
|
|
1764
|
+
evError = []
|
|
1765
|
+
vget[4] = await wo.insertBulk([
|
|
1766
|
+
{ time: genTime(10), name: 'new-1', value: 11 },
|
|
1767
|
+
{ time: genTime(0), name: 'conflict', value: 12 },
|
|
1768
|
+
{ time: genTime(11), name: 'new-2', value: 13 },
|
|
1769
|
+
])
|
|
1770
|
+
.then(() => 'resolved')
|
|
1771
|
+
.catch(() => 'rejected')
|
|
1772
|
+
vget[5] = await nRec()
|
|
1773
|
+
vget[6] = evError.slice()
|
|
1774
|
+
vget[7] = evChange.slice()
|
|
1775
|
+
|
|
1776
|
+
//同批含重複主鍵, 亦視為衝突而整批reject
|
|
1777
|
+
evChange = []
|
|
1778
|
+
evError = []
|
|
1779
|
+
vget[8] = await wo.insertBulk([
|
|
1780
|
+
{ time: genTime(20), name: 'dup-1', value: 21 },
|
|
1781
|
+
{ time: genTime(20), name: 'dup-2', value: 22 },
|
|
1782
|
+
{ time: genTime(21), name: 'uniq', value: 23 },
|
|
1783
|
+
])
|
|
1784
|
+
.then(() => 'resolved')
|
|
1785
|
+
.catch(() => 'rejected')
|
|
1786
|
+
vget[9] = await nRec()
|
|
1787
|
+
|
|
1788
|
+
//未帶有效主鍵, 不補值而整批reject
|
|
1789
|
+
vget[10] = await wo.insertBulk([
|
|
1790
|
+
{ time: genTime(30), name: 'ok', value: 31 },
|
|
1791
|
+
{ name: 'no-pk', value: 32 },
|
|
1792
|
+
])
|
|
1793
|
+
.then(() => 'resolved')
|
|
1794
|
+
.catch(() => 'rejected')
|
|
1795
|
+
vget[11] = await nRec()
|
|
1796
|
+
|
|
1797
|
+
//輸入無效
|
|
1798
|
+
vget[12] = await wo.insertBulk(null)
|
|
1799
|
+
|
|
1800
|
+
//單一物件亦回傳單一物件
|
|
1801
|
+
vget[13] = await wo.insertBulk({ time: genTime(40), name: 'single', value: 41 })
|
|
1802
|
+
vget[14] = await nRec()
|
|
1803
|
+
|
|
1804
|
+
//跨批次之回滾
|
|
1805
|
+
//欄位數愈多則單一語句可送之筆數愈少, 以21欄之資料表令每批上限為3120筆,
|
|
1806
|
+
//送3200筆即須分為2批, 末筆撞既有主鍵時第1批已送出, 須由交易回滾方能維持全有全無
|
|
1807
|
+
let clBat = 'bulkbatch'
|
|
1808
|
+
let woBat = WOrm(genOpt(clBat))
|
|
1809
|
+
let vSample = { time: '2000-01-01T00:00:00Z' }
|
|
1810
|
+
Array.from({ length: 20 }, (v, k) => k).forEach((k) => {
|
|
1811
|
+
vSample[`f${k}`] = 'abc'
|
|
1812
|
+
})
|
|
1813
|
+
await woBat.createTable(clBat, null, vSample).catch(() => {})
|
|
1814
|
+
await woBat.delAll()
|
|
1815
|
+
|
|
1816
|
+
//genRec
|
|
1817
|
+
let genRec = (k) => {
|
|
1818
|
+
let v = { time: genTime(k) }
|
|
1819
|
+
Array.from({ length: 20 }, (v2, k2) => k2).forEach((k2) => {
|
|
1820
|
+
v[`f${k2}`] = `v${k}-${k2}`
|
|
1821
|
+
})
|
|
1822
|
+
return v
|
|
1823
|
+
}
|
|
1824
|
+
|
|
1825
|
+
//先插入末筆之主鍵, 令後續之大批次於第2批撞上
|
|
1826
|
+
let kLast = 3199
|
|
1827
|
+
await woBat.insert(genRec(kLast))
|
|
1828
|
+
let nBefore = (await woBat.select()).length
|
|
1829
|
+
|
|
1830
|
+
//3200筆之批次, 末筆與既有衝突
|
|
1831
|
+
vget[15] = await woBat.insertBulk(Array.from({ length: 3200 }, (v, k) => genRec(k)))
|
|
1832
|
+
.then(() => 'resolved')
|
|
1833
|
+
.catch(() => 'rejected')
|
|
1834
|
+
|
|
1835
|
+
//失敗後資料表不得有任何新增
|
|
1836
|
+
vget[16] = (await woBat.select()).length - nBefore
|
|
1837
|
+
|
|
1838
|
+
//跨批次且無衝突者須全數寫入
|
|
1839
|
+
await woBat.delAll()
|
|
1840
|
+
vget[17] = await woBat.insertBulk(Array.from({ length: 3200 }, (v, k) => genRec(k)))
|
|
1841
|
+
vget[18] = (await woBat.select()).length
|
|
1842
|
+
|
|
1843
|
+
})
|
|
1844
|
+
|
|
1845
|
+
vans[1] = { n: 3, nInserted: 3, ok: 1 }
|
|
1846
|
+
it(`should get ${JSON.stringify(vans[1])} for insertBulk without conflict`, async function() {
|
|
1847
|
+
assert.strict.deepStrictEqual(vget[1], vans[1])
|
|
1848
|
+
})
|
|
1849
|
+
|
|
1850
|
+
vans[2] = 3
|
|
1851
|
+
it(`should get ${JSON.stringify(vans[2])} for records after insertBulk without conflict`, async function() {
|
|
1852
|
+
assert.strict.deepStrictEqual(vget[2], vans[2])
|
|
1853
|
+
})
|
|
1854
|
+
|
|
1855
|
+
vans[3] = ['insertBulk']
|
|
1856
|
+
it(`should get ${JSON.stringify(vans[3])} for change modes by insertBulk`, async function() {
|
|
1857
|
+
assert.strict.deepStrictEqual(vget[3], vans[3])
|
|
1858
|
+
})
|
|
1859
|
+
|
|
1860
|
+
vans[4] = 'rejected'
|
|
1861
|
+
it(`should get ${JSON.stringify(vans[4])} for insertBulk with pk existed`, async function() {
|
|
1862
|
+
assert.strict.deepStrictEqual(vget[4], vans[4])
|
|
1863
|
+
})
|
|
1864
|
+
|
|
1865
|
+
vans[5] = 3
|
|
1866
|
+
it(`should get ${JSON.stringify(vans[5])} for records after insertBulk with pk existed`, async function() {
|
|
1867
|
+
assert.strict.deepStrictEqual(vget[5], vans[5])
|
|
1868
|
+
})
|
|
1869
|
+
|
|
1870
|
+
vans[6] = ['insertBulk']
|
|
1871
|
+
it(`should get ${JSON.stringify(vans[6])} for error modes by insertBulk with pk existed`, async function() {
|
|
1872
|
+
assert.strict.deepStrictEqual(vget[6], vans[6])
|
|
1873
|
+
})
|
|
1874
|
+
|
|
1875
|
+
vans[7] = []
|
|
1876
|
+
it(`should get ${JSON.stringify(vans[7])} for change modes by insertBulk rejected`, async function() {
|
|
1877
|
+
assert.strict.deepStrictEqual(vget[7], vans[7])
|
|
1878
|
+
})
|
|
1879
|
+
|
|
1880
|
+
vans[8] = 'rejected'
|
|
1881
|
+
it(`should get ${JSON.stringify(vans[8])} for insertBulk with duplicated pk in same batch`, async function() {
|
|
1882
|
+
assert.strict.deepStrictEqual(vget[8], vans[8])
|
|
1883
|
+
})
|
|
1884
|
+
|
|
1885
|
+
vans[9] = 3
|
|
1886
|
+
it(`should get ${JSON.stringify(vans[9])} for records after insertBulk with duplicated pk`, async function() {
|
|
1887
|
+
assert.strict.deepStrictEqual(vget[9], vans[9])
|
|
1888
|
+
})
|
|
1889
|
+
|
|
1890
|
+
vans[10] = 'rejected'
|
|
1891
|
+
it(`should get ${JSON.stringify(vans[10])} for insertBulk without valid pk`, async function() {
|
|
1892
|
+
assert.strict.deepStrictEqual(vget[10], vans[10])
|
|
1893
|
+
})
|
|
1894
|
+
|
|
1895
|
+
vans[11] = 3
|
|
1896
|
+
it(`should get ${JSON.stringify(vans[11])} for records after insertBulk without valid pk`, async function() {
|
|
1897
|
+
assert.strict.deepStrictEqual(vget[11], vans[11])
|
|
1898
|
+
})
|
|
1899
|
+
|
|
1900
|
+
vans[12] = { n: 0, nInserted: 0, ok: 1 }
|
|
1901
|
+
it(`should get ${JSON.stringify(vans[12])} for insertBulk with invalid data`, async function() {
|
|
1902
|
+
assert.strict.deepStrictEqual(vget[12], vans[12])
|
|
1903
|
+
})
|
|
1904
|
+
|
|
1905
|
+
vans[13] = { n: 1, nInserted: 1, ok: 1 }
|
|
1906
|
+
it(`should get ${JSON.stringify(vans[13])} for insertBulk with single object`, async function() {
|
|
1907
|
+
assert.strict.deepStrictEqual(vget[13], vans[13])
|
|
1908
|
+
})
|
|
1909
|
+
|
|
1910
|
+
vans[14] = 4
|
|
1911
|
+
it(`should get ${JSON.stringify(vans[14])} for records after insertBulk with single object`, async function() {
|
|
1912
|
+
assert.strict.deepStrictEqual(vget[14], vans[14])
|
|
1913
|
+
})
|
|
1914
|
+
|
|
1915
|
+
vans[15] = 'rejected'
|
|
1916
|
+
it(`should get ${JSON.stringify(vans[15])} for insertBulk across batches with pk existed`, async function() {
|
|
1917
|
+
assert.strict.deepStrictEqual(vget[15], vans[15])
|
|
1918
|
+
})
|
|
1919
|
+
|
|
1920
|
+
vans[16] = 0
|
|
1921
|
+
it(`should get ${JSON.stringify(vans[16])} for increment of records after insertBulk across batches failed`, async function() {
|
|
1922
|
+
assert.strict.deepStrictEqual(vget[16], vans[16])
|
|
1923
|
+
})
|
|
1924
|
+
|
|
1925
|
+
vans[17] = { n: 3200, nInserted: 3200, ok: 1 }
|
|
1926
|
+
it(`should get ${JSON.stringify(vans[17])} for insertBulk across batches without conflict`, async function() {
|
|
1927
|
+
assert.strict.deepStrictEqual(vget[17], vans[17])
|
|
1928
|
+
})
|
|
1929
|
+
|
|
1930
|
+
vans[18] = 3200
|
|
1931
|
+
it(`should get ${JSON.stringify(vans[18])} for records after insertBulk across batches`, async function() {
|
|
1932
|
+
assert.strict.deepStrictEqual(vget[18], vans[18])
|
|
1933
|
+
})
|
|
1934
|
+
|
|
1935
|
+
})
|
|
1936
|
+
|
|
1937
|
+
|
|
1938
|
+
describe('insert returnList', function() {
|
|
1939
|
+
let vans = {}
|
|
1940
|
+
let vget = {}
|
|
1941
|
+
|
|
1942
|
+
before(async function() {
|
|
1943
|
+
this.timeout(180000)
|
|
1944
|
+
|
|
1945
|
+
//wo
|
|
1946
|
+
let cl = 'retlist'
|
|
1947
|
+
let wo = WOrm(genOpt(cl))
|
|
1948
|
+
|
|
1949
|
+
//createTable
|
|
1950
|
+
await wo.createTable(cl, null, {
|
|
1951
|
+
time: '2000-01-01T00:00:00Z',
|
|
1952
|
+
name: 'abc',
|
|
1953
|
+
value: 0.1,
|
|
1954
|
+
}).catch(() => {})
|
|
1955
|
+
await wo.delAll()
|
|
1956
|
+
|
|
1957
|
+
//genRec
|
|
1958
|
+
let genRec = (k) => {
|
|
1959
|
+
return {
|
|
1960
|
+
time: new Date(Date.UTC(2025, 9, 1, 0, 0, 0) + k * 1000).toISOString(),
|
|
1961
|
+
name: `n${k}`,
|
|
1962
|
+
value: k,
|
|
1963
|
+
}
|
|
1964
|
+
}
|
|
1965
|
+
|
|
1966
|
+
//evChange
|
|
1967
|
+
let evChange = []
|
|
1968
|
+
wo.on('change', (mode, data, res) => {
|
|
1969
|
+
evChange.push(res)
|
|
1970
|
+
})
|
|
1971
|
+
|
|
1972
|
+
//先插入第1與第3筆, 令後續之批次呈現[新,舊,新,舊,新]之交錯
|
|
1973
|
+
await wo.insert([genRec(1), genRec(3)])
|
|
1974
|
+
|
|
1975
|
+
//returnList為true, 須與輸入等長保序且對位正確
|
|
1976
|
+
evChange = []
|
|
1977
|
+
vget[1] = await wo.insert([genRec(0), genRec(1), genRec(2), genRec(3), genRec(4)], { returnList: true })
|
|
1978
|
+
vget[2] = vget[1].map((v) => v.nInserted)
|
|
1979
|
+
vget[3] = vget[1].length
|
|
1980
|
+
vget[4] = Object.keys(vget[1][0]).sort()
|
|
1981
|
+
vget[5] = vget[1].filter((v) => v.nInserted === 1).length
|
|
1982
|
+
|
|
1983
|
+
//change事件之res即本次實際回傳值
|
|
1984
|
+
vget[6] = isarr(evChange[0]) ? evChange[0].length : null
|
|
1985
|
+
|
|
1986
|
+
//聚合模式之nInserted須等於逐筆模式之filter計數
|
|
1987
|
+
await wo.delAll()
|
|
1988
|
+
await wo.insert([genRec(1), genRec(3)])
|
|
1989
|
+
vget[7] = await wo.insert([genRec(0), genRec(1), genRec(2), genRec(3), genRec(4)])
|
|
1990
|
+
|
|
1991
|
+
//同批含重複主鍵, 僅首次出現者之nInserted為1
|
|
1992
|
+
await wo.delAll()
|
|
1993
|
+
vget[8] = (await wo.insert([genRec(10), genRec(10), genRec(11)], { returnList: true })).map((v) => v.nInserted)
|
|
1994
|
+
|
|
1995
|
+
//輸入無效, returnList為true回傳空陣列, 為false回傳聚合物件
|
|
1996
|
+
vget[9] = await wo.insert(null, { returnList: true })
|
|
1997
|
+
vget[10] = await wo.insert(null)
|
|
1998
|
+
|
|
1999
|
+
//單一物件輸入亦回傳長度1之陣列
|
|
2000
|
+
await wo.delAll()
|
|
2001
|
+
vget[11] = await wo.insert(genRec(20), { returnList: true })
|
|
2002
|
+
|
|
2003
|
+
//returnList為false時形狀不變
|
|
2004
|
+
vget[12] = await wo.insert(genRec(21))
|
|
2005
|
+
|
|
2006
|
+
//文字主鍵之型別分流, 主鍵非時間戳者不得誤判
|
|
2007
|
+
let clC = 'retlistcode'
|
|
2008
|
+
let woC = WOrm({
|
|
2009
|
+
...genOpt(clC),
|
|
2010
|
+
pk: 'code',
|
|
2011
|
+
})
|
|
2012
|
+
await woC.createTable(clC, null, {
|
|
2013
|
+
code: 'abc',
|
|
2014
|
+
name: 'abc',
|
|
2015
|
+
value: 0.1,
|
|
2016
|
+
}).catch(() => {})
|
|
2017
|
+
await woC.delAll()
|
|
2018
|
+
await woC.insert([
|
|
2019
|
+
{ code: 'c1', name: 'n1', value: 1 },
|
|
2020
|
+
{ code: 'c3', name: 'n3', value: 3 },
|
|
2021
|
+
])
|
|
2022
|
+
vget[13] = (await woC.insert([
|
|
2023
|
+
{ code: 'c0', name: 'n0', value: 0 },
|
|
2024
|
+
{ code: 'c1', name: 'n1', value: 1 },
|
|
2025
|
+
{ code: 'c2', name: 'n2', value: 2 },
|
|
2026
|
+
{ code: 'c3', name: 'n3', value: 3 },
|
|
2027
|
+
{ code: 'c4', name: 'n4', value: 4 },
|
|
2028
|
+
], { returnList: true })).map((v) => v.nInserted)
|
|
2029
|
+
|
|
2030
|
+
//文字主鍵而值形如日期者, 不得因正規化而碰撞
|
|
2031
|
+
let clD = 'retlistdate'
|
|
2032
|
+
let woD = WOrm({
|
|
2033
|
+
...genOpt(clD),
|
|
2034
|
+
pk: 'code',
|
|
2035
|
+
})
|
|
2036
|
+
await woD.createTable(clD, null, {
|
|
2037
|
+
code: 'abc',
|
|
2038
|
+
name: 'abc',
|
|
2039
|
+
value: 0.1,
|
|
2040
|
+
}).catch(() => {})
|
|
2041
|
+
await woD.delAll()
|
|
2042
|
+
await woD.insert({ code: '2025', name: 'y', value: 1 })
|
|
2043
|
+
vget[14] = (await woD.insert([
|
|
2044
|
+
{ code: '2025', name: 'y', value: 1 },
|
|
2045
|
+
{ code: '2025-01-01', name: 'd', value: 2 },
|
|
2046
|
+
], { returnList: true })).map((v) => v.nInserted)
|
|
2047
|
+
|
|
2048
|
+
})
|
|
2049
|
+
|
|
2050
|
+
vans[1] = [
|
|
2051
|
+
{ n: 1, nInserted: 1, ok: 1 },
|
|
2052
|
+
{ n: 1, nInserted: 0, ok: 1 },
|
|
2053
|
+
{ n: 1, nInserted: 1, ok: 1 },
|
|
2054
|
+
{ n: 1, nInserted: 0, ok: 1 },
|
|
2055
|
+
{ n: 1, nInserted: 1, ok: 1 },
|
|
2056
|
+
]
|
|
2057
|
+
it(`should get ${JSON.stringify(vans[1])} for insert with returnList`, async function() {
|
|
2058
|
+
assert.strict.deepStrictEqual(vget[1], vans[1])
|
|
2059
|
+
})
|
|
2060
|
+
|
|
2061
|
+
vans[2] = [1, 0, 1, 0, 1]
|
|
2062
|
+
it(`should get ${JSON.stringify(vans[2])} for nInserted in order by insert with returnList`, async function() {
|
|
2063
|
+
assert.strict.deepStrictEqual(vget[2], vans[2])
|
|
2064
|
+
})
|
|
2065
|
+
|
|
2066
|
+
vans[3] = 5
|
|
2067
|
+
it(`should get ${JSON.stringify(vans[3])} for length of insert with returnList`, async function() {
|
|
2068
|
+
assert.strict.deepStrictEqual(vget[3], vans[3])
|
|
2069
|
+
})
|
|
2070
|
+
|
|
2071
|
+
vans[4] = ['n', 'nInserted', 'ok']
|
|
2072
|
+
it(`should get ${JSON.stringify(vans[4])} for keys of each element by insert with returnList`, async function() {
|
|
2073
|
+
assert.strict.deepStrictEqual(vget[4], vans[4])
|
|
2074
|
+
})
|
|
2075
|
+
|
|
2076
|
+
vans[5] = 3
|
|
2077
|
+
it(`should get ${JSON.stringify(vans[5])} for count of nInserted===1 by insert with returnList`, async function() {
|
|
2078
|
+
assert.strict.deepStrictEqual(vget[5], vans[5])
|
|
2079
|
+
})
|
|
2080
|
+
|
|
2081
|
+
vans[6] = 5
|
|
2082
|
+
it(`should get ${JSON.stringify(vans[6])} for length of res in change event by insert with returnList`, async function() {
|
|
2083
|
+
assert.strict.deepStrictEqual(vget[6], vans[6])
|
|
2084
|
+
})
|
|
2085
|
+
|
|
2086
|
+
vans[7] = { n: 5, nInserted: 3, ok: 1 }
|
|
2087
|
+
it(`should get ${JSON.stringify(vans[7])} for insert without returnList on same input`, async function() {
|
|
2088
|
+
assert.strict.deepStrictEqual(vget[7], vans[7])
|
|
2089
|
+
})
|
|
2090
|
+
|
|
2091
|
+
vans[8] = [1, 0, 1]
|
|
2092
|
+
it(`should get ${JSON.stringify(vans[8])} for duplicated pk in same batch by insert with returnList`, async function() {
|
|
2093
|
+
assert.strict.deepStrictEqual(vget[8], vans[8])
|
|
2094
|
+
})
|
|
2095
|
+
|
|
2096
|
+
vans[9] = []
|
|
2097
|
+
it(`should get ${JSON.stringify(vans[9])} for insert with invalid data and returnList`, async function() {
|
|
2098
|
+
assert.strict.deepStrictEqual(vget[9], vans[9])
|
|
2099
|
+
})
|
|
2100
|
+
|
|
2101
|
+
vans[10] = { n: 0, nInserted: 0, ok: 1 }
|
|
2102
|
+
it(`should get ${JSON.stringify(vans[10])} for insert with invalid data and without returnList`, async function() {
|
|
2103
|
+
assert.strict.deepStrictEqual(vget[10], vans[10])
|
|
2104
|
+
})
|
|
2105
|
+
|
|
2106
|
+
vans[11] = [{ n: 1, nInserted: 1, ok: 1 }]
|
|
2107
|
+
it(`should get ${JSON.stringify(vans[11])} for insert with single object and returnList`, async function() {
|
|
2108
|
+
assert.strict.deepStrictEqual(vget[11], vans[11])
|
|
2109
|
+
})
|
|
2110
|
+
|
|
2111
|
+
vans[12] = { n: 1, nInserted: 1, ok: 1 }
|
|
2112
|
+
it(`should get ${JSON.stringify(vans[12])} for insert with single object and without returnList`, async function() {
|
|
2113
|
+
assert.strict.deepStrictEqual(vget[12], vans[12])
|
|
2114
|
+
})
|
|
2115
|
+
|
|
2116
|
+
vans[13] = [1, 0, 1, 0, 1]
|
|
2117
|
+
it(`should get ${JSON.stringify(vans[13])} for insert with returnList by custom text pk`, async function() {
|
|
2118
|
+
assert.strict.deepStrictEqual(vget[13], vans[13])
|
|
2119
|
+
})
|
|
2120
|
+
|
|
2121
|
+
vans[14] = [0, 1]
|
|
2122
|
+
it(`should get ${JSON.stringify(vans[14])} for insert with returnList by text pk looking like date`, async function() {
|
|
2123
|
+
assert.strict.deepStrictEqual(vget[14], vans[14])
|
|
2124
|
+
})
|
|
2125
|
+
|
|
2126
|
+
})
|
|
2127
|
+
|
|
2128
|
+
|
|
1677
2129
|
//runProc, 另起行程對同一資料表操作, 用於驗證跨行程之原子性
|
|
1678
2130
|
//子行程以--input-type=module執行, 並以pathToFileURL轉換src路徑, 避免專案路徑含非ASCII字元而無法import
|
|
1679
2131
|
function runProc(tag, opt, mode, payload) {
|