meadow 2.0.23 → 2.0.27
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 +110 -141
- package/docs/README.md +34 -230
- package/docs/_cover.md +14 -0
- package/docs/_sidebar.md +44 -12
- package/docs/_topbar.md +5 -0
- package/docs/api/doCount.md +109 -0
- package/docs/api/doCreate.md +132 -0
- package/docs/api/doDelete.md +101 -0
- package/docs/api/doRead.md +122 -0
- package/docs/api/doReads.md +136 -0
- package/docs/api/doUndelete.md +98 -0
- package/docs/api/doUpdate.md +129 -0
- package/docs/api/getRoleName.md +84 -0
- package/docs/api/loadFromPackage.md +153 -0
- package/docs/api/marshalRecordFromSourceToObject.md +92 -0
- package/docs/api/query.md +133 -0
- package/docs/api/rawQueries.md +197 -0
- package/docs/api/reference.md +117 -0
- package/docs/api/setAuthorizer.md +103 -0
- package/docs/api/setDefault.md +90 -0
- package/docs/api/setDefaultIdentifier.md +84 -0
- package/docs/api/setDomain.md +56 -0
- package/docs/api/setIDUser.md +91 -0
- package/docs/api/setJsonSchema.md +92 -0
- package/docs/api/setProvider.md +87 -0
- package/docs/api/setSchema.md +107 -0
- package/docs/api/setScope.md +68 -0
- package/docs/api/validateObject.md +119 -0
- package/docs/architecture.md +316 -0
- package/docs/audit-tracking.md +226 -0
- package/docs/configuration.md +317 -0
- package/docs/providers/meadow-endpoints.md +306 -0
- package/docs/providers/mongodb.md +319 -0
- package/docs/providers/postgresql.md +312 -0
- package/docs/providers/rocksdb.md +297 -0
- package/docs/query-dsl.md +269 -0
- package/docs/quick-start.md +384 -0
- package/docs/raw-queries.md +193 -0
- package/docs/retold-catalog.json +61 -1
- package/docs/retold-keyword-index.json +15860 -4839
- package/docs/soft-deletes.md +224 -0
- package/package.json +44 -13
- package/scripts/bookstore-seed-postgresql.sql +135 -0
- package/scripts/dgraph-test-db.sh +144 -0
- package/scripts/meadow-test-cleanup.sh +5 -1
- package/scripts/mongodb-test-db.sh +98 -0
- package/scripts/postgresql-test-db.sh +124 -0
- package/scripts/solr-test-db.sh +135 -0
- package/source/Meadow.js +5 -0
- package/source/providers/Meadow-Provider-DGraph.js +679 -0
- package/source/providers/Meadow-Provider-MeadowEndpoints.js +1 -1
- package/source/providers/Meadow-Provider-MongoDB.js +527 -0
- package/source/providers/Meadow-Provider-PostgreSQL.js +361 -0
- package/source/providers/Meadow-Provider-RocksDB.js +1300 -0
- package/source/providers/Meadow-Provider-Solr.js +726 -0
- package/test/Meadow-Provider-DGraph_tests.js +741 -0
- package/test/Meadow-Provider-MongoDB_tests.js +661 -0
- package/test/Meadow-Provider-PostgreSQL_tests.js +787 -0
- package/test/Meadow-Provider-RocksDB_tests.js +887 -0
- package/test/Meadow-Provider-SQLiteBrowser-Headless_tests.js +657 -0
- package/test/Meadow-Provider-SQLiteBrowser_tests.js +895 -0
- package/test/Meadow-Provider-Solr_tests.js +679 -0
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
# Soft Deletes
|
|
2
|
+
|
|
3
|
+
Meadow supports soft deletes (logical deletion) out of the box. When enabled, deleting a record marks it as deleted rather than removing it from the database. This preserves data for audit trails, recovery, and referential integrity.
|
|
4
|
+
|
|
5
|
+
## The Deleted Column
|
|
6
|
+
|
|
7
|
+
Soft deletes are activated by including a column with type `'Deleted'` in your schema:
|
|
8
|
+
|
|
9
|
+
```javascript
|
|
10
|
+
var tmpSchema =
|
|
11
|
+
[
|
|
12
|
+
{ Column: 'IDBook', Type: 'AutoIdentity' },
|
|
13
|
+
{ Column: 'GUIDBook', Type: 'AutoGUID' },
|
|
14
|
+
{ Column: 'Title', Type: 'String', Size: '255' },
|
|
15
|
+
{ Column: 'CreateDate', Type: 'CreateDate' },
|
|
16
|
+
{ Column: 'CreatingIDUser', Type: 'CreateIDUser' },
|
|
17
|
+
{ Column: 'UpdateDate', Type: 'UpdateDate' },
|
|
18
|
+
{ Column: 'UpdatingIDUser', Type: 'UpdateIDUser' },
|
|
19
|
+
{ Column: 'Deleted', Type: 'Deleted' },
|
|
20
|
+
{ Column: 'DeleteDate', Type: 'DeleteDate' },
|
|
21
|
+
{ Column: 'DeletingIDUser', Type: 'DeleteIDUser' }
|
|
22
|
+
];
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
The `Deleted` column should be an integer (typically `TINYINT` in MySQL) with a default value of `0`. A value of `0` means the record is active; `1` means it is deleted.
|
|
26
|
+
|
|
27
|
+
The corresponding default object should initialize `Deleted` to `0`:
|
|
28
|
+
|
|
29
|
+
```javascript
|
|
30
|
+
var tmpDefault =
|
|
31
|
+
{
|
|
32
|
+
IDBook: null,
|
|
33
|
+
GUIDBook: '',
|
|
34
|
+
Title: '',
|
|
35
|
+
CreateDate: false,
|
|
36
|
+
CreatingIDUser: 0,
|
|
37
|
+
UpdateDate: false,
|
|
38
|
+
UpdatingIDUser: 0,
|
|
39
|
+
Deleted: 0,
|
|
40
|
+
DeleteDate: false,
|
|
41
|
+
DeletingIDUser: 0
|
|
42
|
+
};
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## How doDelete Generates UPDATE Instead of DELETE
|
|
46
|
+
|
|
47
|
+
When FoxHound detects a `Deleted` column in the schema, the `buildDeleteQuery` method generates an `UPDATE` statement instead of a `DELETE` statement. For example, calling `doDelete` with a filter on `IDBook = 1` produces SQL equivalent to:
|
|
48
|
+
|
|
49
|
+
```sql
|
|
50
|
+
UPDATE Book
|
|
51
|
+
SET Deleted = 1, DeleteDate = NOW(), DeletingIDUser = :IDUser
|
|
52
|
+
WHERE IDBook = :IDBook
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
This means the record remains in the database but is flagged as deleted.
|
|
56
|
+
|
|
57
|
+
```javascript
|
|
58
|
+
tmpBookDAL.setIDUser(42);
|
|
59
|
+
|
|
60
|
+
var tmpQuery = tmpBookDAL.query
|
|
61
|
+
.addFilter('IDBook', 1);
|
|
62
|
+
|
|
63
|
+
tmpBookDAL.doDelete(tmpQuery,
|
|
64
|
+
function (pError, pQuery, pResult)
|
|
65
|
+
{
|
|
66
|
+
// The record is not removed from the database.
|
|
67
|
+
// Instead: Deleted = 1, DeleteDate = NOW(), DeletingIDUser = 42
|
|
68
|
+
console.log('Affected rows:', pResult);
|
|
69
|
+
});
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## Automatic Query Filtering
|
|
73
|
+
|
|
74
|
+
When a schema contains a `Deleted` column, FoxHound automatically appends `WHERE Deleted = 0` to all read queries. This means soft-deleted records are invisible by default:
|
|
75
|
+
|
|
76
|
+
```javascript
|
|
77
|
+
// This query automatically excludes deleted records
|
|
78
|
+
tmpBookDAL.doReads(tmpBookDAL.query.setCap(100),
|
|
79
|
+
function (pError, pQuery, pRecords)
|
|
80
|
+
{
|
|
81
|
+
// pRecords contains only records where Deleted = 0
|
|
82
|
+
});
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
The same automatic filtering applies to `doRead`, `doReads`, and `doCount` operations. You do not need to add `Deleted = 0` filters manually.
|
|
86
|
+
|
|
87
|
+
## Viewing Deleted Records
|
|
88
|
+
|
|
89
|
+
To include soft-deleted records in your results, disable delete tracking on the query with `setDisableDeleteTracking(true)`:
|
|
90
|
+
|
|
91
|
+
```javascript
|
|
92
|
+
var tmpQuery = tmpBookDAL.query
|
|
93
|
+
.setDisableDeleteTracking(true)
|
|
94
|
+
.setCap(100);
|
|
95
|
+
|
|
96
|
+
tmpBookDAL.doReads(tmpQuery,
|
|
97
|
+
function (pError, pQuery, pRecords)
|
|
98
|
+
{
|
|
99
|
+
// pRecords includes both active and soft-deleted records
|
|
100
|
+
for (var i = 0; i < pRecords.length; i++)
|
|
101
|
+
{
|
|
102
|
+
var tmpStatus = pRecords[i].Deleted ? 'DELETED' : 'ACTIVE';
|
|
103
|
+
console.log(tmpStatus, '-', pRecords[i].Title);
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
To retrieve only deleted records, combine `setDisableDeleteTracking` with a filter on the `Deleted` column:
|
|
109
|
+
|
|
110
|
+
```javascript
|
|
111
|
+
var tmpQuery = tmpBookDAL.query
|
|
112
|
+
.setDisableDeleteTracking(true)
|
|
113
|
+
.addFilter('Deleted', 1);
|
|
114
|
+
|
|
115
|
+
tmpBookDAL.doReads(tmpQuery,
|
|
116
|
+
function (pError, pQuery, pRecords)
|
|
117
|
+
{
|
|
118
|
+
// pRecords contains only soft-deleted records
|
|
119
|
+
console.log('Deleted books:', pRecords.length);
|
|
120
|
+
});
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Restoring Deleted Records with doUndelete
|
|
124
|
+
|
|
125
|
+
The `doUndelete` method restores a soft-deleted record by setting `Deleted` back to `0`. FoxHound generates an `UPDATE` statement equivalent to:
|
|
126
|
+
|
|
127
|
+
```sql
|
|
128
|
+
UPDATE Book
|
|
129
|
+
SET Deleted = 0
|
|
130
|
+
WHERE IDBook = :IDBook
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
```javascript
|
|
134
|
+
var tmpQuery = tmpBookDAL.query
|
|
135
|
+
.addFilter('IDBook', 1);
|
|
136
|
+
|
|
137
|
+
tmpBookDAL.doUndelete(tmpQuery,
|
|
138
|
+
function (pError, pQuery, pResult)
|
|
139
|
+
{
|
|
140
|
+
console.log('Restored record, affected rows:', pResult);
|
|
141
|
+
// The record is now visible in normal queries again
|
|
142
|
+
});
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
After undelete, the record appears in standard queries that have the default `Deleted = 0` filter.
|
|
146
|
+
|
|
147
|
+
## DeleteDate and DeletingIDUser Columns
|
|
148
|
+
|
|
149
|
+
For a complete audit trail of deletions, include `DeleteDate` and `DeletingIDUser` columns alongside the `Deleted` column:
|
|
150
|
+
|
|
151
|
+
| Column Type | Purpose | Value on Delete | Value on Undelete |
|
|
152
|
+
|------------|---------|-----------------|-------------------|
|
|
153
|
+
| `Deleted` | Deletion flag | `1` | `0` |
|
|
154
|
+
| `DeleteDate` | When the record was deleted | `NOW()` | Not changed |
|
|
155
|
+
| `DeleteIDUser` | Who deleted the record | Current user ID | Not changed |
|
|
156
|
+
|
|
157
|
+
Note that `doUndelete` does not clear `DeleteDate` or `DeletingIDUser`. These columns retain their values from the last delete operation, providing a historical record even after restoration.
|
|
158
|
+
|
|
159
|
+
```javascript
|
|
160
|
+
// Full schema with delete tracking
|
|
161
|
+
var tmpSchema =
|
|
162
|
+
[
|
|
163
|
+
{ Column: 'IDBook', Type: 'AutoIdentity' },
|
|
164
|
+
{ Column: 'GUIDBook', Type: 'AutoGUID' },
|
|
165
|
+
{ Column: 'Title', Type: 'String', Size: '255' },
|
|
166
|
+
{ Column: 'Deleted', Type: 'Deleted' },
|
|
167
|
+
{ Column: 'DeleteDate', Type: 'DeleteDate' },
|
|
168
|
+
{ Column: 'DeletingIDUser', Type: 'DeleteIDUser' }
|
|
169
|
+
];
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## Hard Delete (No Deleted Column)
|
|
173
|
+
|
|
174
|
+
If your schema does not include a column with type `'Deleted'`, then `doDelete` performs a true SQL `DELETE` statement. The record is permanently removed from the database:
|
|
175
|
+
|
|
176
|
+
```javascript
|
|
177
|
+
// Schema without a Deleted column
|
|
178
|
+
var tmpSchema =
|
|
179
|
+
[
|
|
180
|
+
{ Column: 'IDLog', Type: 'AutoIdentity' },
|
|
181
|
+
{ Column: 'GUIDLog', Type: 'AutoGUID' },
|
|
182
|
+
{ Column: 'Message', Type: 'String', Size: '1024' },
|
|
183
|
+
{ Column: 'CreateDate', Type: 'CreateDate' }
|
|
184
|
+
];
|
|
185
|
+
|
|
186
|
+
var tmpLogDAL = libMeadow.new(_Fable, 'Log')
|
|
187
|
+
.setProvider('MySQL')
|
|
188
|
+
.setDefaultIdentifier('IDLog')
|
|
189
|
+
.setSchema(tmpSchema);
|
|
190
|
+
|
|
191
|
+
var tmpQuery = tmpLogDAL.query
|
|
192
|
+
.addFilter('IDLog', 500);
|
|
193
|
+
|
|
194
|
+
tmpLogDAL.doDelete(tmpQuery,
|
|
195
|
+
function (pError, pQuery, pResult)
|
|
196
|
+
{
|
|
197
|
+
// The record is permanently removed from the database.
|
|
198
|
+
// This is a true DELETE FROM statement.
|
|
199
|
+
console.log('Permanently deleted, affected rows:', pResult);
|
|
200
|
+
});
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
With hard deletes:
|
|
204
|
+
|
|
205
|
+
- There is no automatic `Deleted = 0` filter on read queries.
|
|
206
|
+
- `doUndelete` has no meaningful effect (there is nothing to restore).
|
|
207
|
+
- Deleted data cannot be recovered through Meadow.
|
|
208
|
+
|
|
209
|
+
## Choosing Between Soft and Hard Deletes
|
|
210
|
+
|
|
211
|
+
Use **soft deletes** when:
|
|
212
|
+
|
|
213
|
+
- You need audit trails showing who deleted what and when.
|
|
214
|
+
- Users should be able to recover accidentally deleted records.
|
|
215
|
+
- Referential integrity depends on records existing even when "removed".
|
|
216
|
+
- Compliance requirements mandate data retention.
|
|
217
|
+
|
|
218
|
+
Use **hard deletes** when:
|
|
219
|
+
|
|
220
|
+
- Storage space is a concern and deleted data has no value.
|
|
221
|
+
- Privacy regulations require actual data removal (e.g., GDPR right to erasure).
|
|
222
|
+
- The table is for transient data (logs, sessions, caches) that has no recovery need.
|
|
223
|
+
|
|
224
|
+
Most Retold applications use soft deletes for business entities and hard deletes for ephemeral data.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "meadow",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.27",
|
|
4
4
|
"description": "A data access library.",
|
|
5
5
|
"main": "source/Meadow.js",
|
|
6
6
|
"scripts": {
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"coverage": "npx quack coverage",
|
|
9
9
|
"test": "npx quack test",
|
|
10
10
|
"tests": "npx quack test -g",
|
|
11
|
-
"build": "npx quack build
|
|
11
|
+
"build": "npx quack build",
|
|
12
12
|
"docker-dev-build": "docker build ./ -f Dockerfile_LUXURYCode -t retold/meadow:local",
|
|
13
13
|
"docker-dev-run": "docker run -it -d --name meadow-dev -p 12342:8080 -p 12106:3306 -v \"$PWD/.config:/home/coder/.config\" -v \"$PWD:/home/coder/meadow\" -u \"$(id -u):$(id -g)\" -e \"DOCKER_USER=$USER\" retold/meadow:local",
|
|
14
14
|
"docker-dev-shell": "docker exec -it meadow-dev /bin/bash",
|
|
@@ -22,8 +22,29 @@
|
|
|
22
22
|
"docker-mssql-status": "./scripts/mssql-test-db.sh status",
|
|
23
23
|
"test-mssql": "./scripts/mssql-test-db.sh start && npx quack test -g Meadow-Provider-MSSQL",
|
|
24
24
|
"test-mssql-all": "./scripts/mssql-test-db.sh start && npx mocha -u tdd --exit -R spec",
|
|
25
|
-
"
|
|
26
|
-
"docker-
|
|
25
|
+
"docker-postgresql-start": "./scripts/postgresql-test-db.sh start",
|
|
26
|
+
"docker-postgresql-stop": "./scripts/postgresql-test-db.sh stop",
|
|
27
|
+
"docker-postgresql-status": "./scripts/postgresql-test-db.sh status",
|
|
28
|
+
"test-postgresql": "./scripts/postgresql-test-db.sh start && npx quack test -g Meadow-Provider-PostgreSQL",
|
|
29
|
+
"test-postgresql-all": "./scripts/postgresql-test-db.sh start && npx mocha -u tdd --exit -R spec",
|
|
30
|
+
"docker-mongodb-start": "./scripts/mongodb-test-db.sh start",
|
|
31
|
+
"docker-mongodb-stop": "./scripts/mongodb-test-db.sh stop",
|
|
32
|
+
"docker-mongodb-status": "./scripts/mongodb-test-db.sh status",
|
|
33
|
+
"test-mongodb": "./scripts/mongodb-test-db.sh start && npx quack test -g Meadow-Provider-MongoDB",
|
|
34
|
+
"docker-solr-start": "./scripts/solr-test-db.sh start",
|
|
35
|
+
"docker-solr-stop": "./scripts/solr-test-db.sh stop",
|
|
36
|
+
"docker-solr-status": "./scripts/solr-test-db.sh status",
|
|
37
|
+
"test-solr": "./scripts/solr-test-db.sh start && npx quack test -g Meadow-Provider-Solr",
|
|
38
|
+
"docker-dgraph-start": "./scripts/dgraph-test-db.sh start",
|
|
39
|
+
"docker-dgraph-stop": "./scripts/dgraph-test-db.sh stop",
|
|
40
|
+
"docker-dgraph-status": "./scripts/dgraph-test-db.sh status",
|
|
41
|
+
"test-dgraph": "./scripts/dgraph-test-db.sh start && npx quack test -g Meadow-Provider-DGraph",
|
|
42
|
+
"test-alasql": "npx quack test -g Meadow-Provider-ALASQL",
|
|
43
|
+
"test-sqlite-browser": "npx quack test -g Meadow-Provider-SQLiteBrowser",
|
|
44
|
+
"test-sqlite-browser-headless": "npx mocha -u tdd --exit --timeout 60000 test/Meadow-Provider-SQLiteBrowser-Headless_tests.js",
|
|
45
|
+
"test-all-providers": "./scripts/mysql-test-db.sh start && ./scripts/mssql-test-db.sh start && ./scripts/postgresql-test-db.sh start && ./scripts/mongodb-test-db.sh start && ./scripts/solr-test-db.sh start && ./scripts/dgraph-test-db.sh start && npx mocha -u tdd --exit -R spec",
|
|
46
|
+
"docker-cleanup": "./scripts/meadow-test-cleanup.sh",
|
|
47
|
+
"test-cleanup": "./scripts/meadow-test-cleanup.sh"
|
|
27
48
|
},
|
|
28
49
|
"mocha": {
|
|
29
50
|
"diff": true,
|
|
@@ -58,19 +79,29 @@
|
|
|
58
79
|
},
|
|
59
80
|
"homepage": "https://github.com/stevenvelozo/meadow",
|
|
60
81
|
"devDependencies": {
|
|
61
|
-
"alasql": "^4.
|
|
82
|
+
"alasql": "^4.17.0",
|
|
62
83
|
"better-sqlite3": "^12.6.2",
|
|
63
|
-
"
|
|
84
|
+
"dgraph-js-http": "^21.3.0",
|
|
85
|
+
"fable": "^3.1.63",
|
|
64
86
|
"gulp-util": "^3.0.8",
|
|
65
|
-
"meadow-connection-
|
|
66
|
-
"meadow-connection-
|
|
67
|
-
"meadow-connection-
|
|
68
|
-
"
|
|
69
|
-
"
|
|
87
|
+
"meadow-connection-dgraph": "^1.0.2",
|
|
88
|
+
"meadow-connection-mongodb": "^1.0.2",
|
|
89
|
+
"meadow-connection-mssql": "^1.0.15",
|
|
90
|
+
"meadow-connection-mysql": "^1.0.13",
|
|
91
|
+
"meadow-connection-postgresql": "^1.0.1",
|
|
92
|
+
"meadow-connection-rocksdb": "^0.0.2",
|
|
93
|
+
"meadow-connection-solr": "^1.0.2",
|
|
94
|
+
"meadow-connection-sqlite": "^1.0.17",
|
|
95
|
+
"meadow-connection-sqlite-browser": "^1.0.0",
|
|
96
|
+
"mongodb": "^6.12.0",
|
|
97
|
+
"mysql2": "^3.18.2",
|
|
98
|
+
"puppeteer": "^24.38.0",
|
|
99
|
+
"quackage": "^1.0.60",
|
|
100
|
+
"solr-client": "^0.9.0"
|
|
70
101
|
},
|
|
71
102
|
"dependencies": {
|
|
72
|
-
"async": "3.2.
|
|
73
|
-
"foxhound": "^2.0.
|
|
103
|
+
"async": "3.2.6",
|
|
104
|
+
"foxhound": "^2.0.22",
|
|
74
105
|
"is-my-json-valid": "2.20.6",
|
|
75
106
|
"simple-get": "^4.0.1"
|
|
76
107
|
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
-- Bookstore Schema and Seed Data for Meadow PostgreSQL Tests
|
|
2
|
+
-- PostgreSQL variant of bookstore-seed.sql
|
|
3
|
+
|
|
4
|
+
-- Schema
|
|
5
|
+
|
|
6
|
+
CREATE TABLE IF NOT EXISTS
|
|
7
|
+
Book
|
|
8
|
+
(
|
|
9
|
+
IDBook SERIAL PRIMARY KEY,
|
|
10
|
+
GUIDBook CHAR(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
|
|
11
|
+
CreateDate TIMESTAMP,
|
|
12
|
+
CreatingIDUser INT NOT NULL DEFAULT 0,
|
|
13
|
+
UpdateDate TIMESTAMP,
|
|
14
|
+
UpdatingIDUser INT NOT NULL DEFAULT 0,
|
|
15
|
+
Deleted SMALLINT NOT NULL DEFAULT 0,
|
|
16
|
+
DeleteDate TIMESTAMP,
|
|
17
|
+
DeletingIDUser INT NOT NULL DEFAULT 0,
|
|
18
|
+
Title VARCHAR(200) NOT NULL DEFAULT '',
|
|
19
|
+
Type VARCHAR(32) NOT NULL DEFAULT '',
|
|
20
|
+
Genre VARCHAR(128) NOT NULL DEFAULT '',
|
|
21
|
+
ISBN VARCHAR(64) NOT NULL DEFAULT '',
|
|
22
|
+
Language VARCHAR(12) NOT NULL DEFAULT '',
|
|
23
|
+
ImageURL VARCHAR(254) NOT NULL DEFAULT '',
|
|
24
|
+
PublicationYear INT NOT NULL DEFAULT 0
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
CREATE TABLE IF NOT EXISTS
|
|
28
|
+
BookAuthorJoin
|
|
29
|
+
(
|
|
30
|
+
IDBookAuthorJoin SERIAL PRIMARY KEY,
|
|
31
|
+
GUIDBookAuthorJoin CHAR(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
|
|
32
|
+
IDBook INT NOT NULL DEFAULT 0,
|
|
33
|
+
IDAuthor INT NOT NULL DEFAULT 0
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
CREATE TABLE IF NOT EXISTS
|
|
37
|
+
Author
|
|
38
|
+
(
|
|
39
|
+
IDAuthor SERIAL PRIMARY KEY,
|
|
40
|
+
GUIDAuthor CHAR(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
|
|
41
|
+
CreateDate TIMESTAMP,
|
|
42
|
+
CreatingIDUser INT NOT NULL DEFAULT 0,
|
|
43
|
+
UpdateDate TIMESTAMP,
|
|
44
|
+
UpdatingIDUser INT NOT NULL DEFAULT 0,
|
|
45
|
+
Deleted SMALLINT NOT NULL DEFAULT 0,
|
|
46
|
+
DeleteDate TIMESTAMP,
|
|
47
|
+
DeletingIDUser INT NOT NULL DEFAULT 0,
|
|
48
|
+
Name VARCHAR(200) NOT NULL DEFAULT ''
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
CREATE TABLE IF NOT EXISTS
|
|
52
|
+
BookPrice
|
|
53
|
+
(
|
|
54
|
+
IDBookPrice SERIAL PRIMARY KEY,
|
|
55
|
+
GUIDBookPrice CHAR(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
|
|
56
|
+
CreateDate TIMESTAMP,
|
|
57
|
+
CreatingIDUser INT NOT NULL DEFAULT 0,
|
|
58
|
+
UpdateDate TIMESTAMP,
|
|
59
|
+
UpdatingIDUser INT NOT NULL DEFAULT 0,
|
|
60
|
+
Deleted SMALLINT NOT NULL DEFAULT 0,
|
|
61
|
+
DeleteDate TIMESTAMP,
|
|
62
|
+
DeletingIDUser INT NOT NULL DEFAULT 0,
|
|
63
|
+
Price DECIMAL(8,2),
|
|
64
|
+
StartDate TIMESTAMP,
|
|
65
|
+
EndDate TIMESTAMP,
|
|
66
|
+
Discountable SMALLINT NOT NULL DEFAULT 0,
|
|
67
|
+
CouponCode VARCHAR(16) NOT NULL DEFAULT '',
|
|
68
|
+
IDBook INT NOT NULL DEFAULT 0
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
CREATE TABLE IF NOT EXISTS
|
|
72
|
+
Review
|
|
73
|
+
(
|
|
74
|
+
IDReviews SERIAL PRIMARY KEY,
|
|
75
|
+
GUIDReviews CHAR(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000',
|
|
76
|
+
CreateDate TIMESTAMP,
|
|
77
|
+
CreatingIDUser INT NOT NULL DEFAULT 0,
|
|
78
|
+
UpdateDate TIMESTAMP,
|
|
79
|
+
UpdatingIDUser INT NOT NULL DEFAULT 0,
|
|
80
|
+
Deleted SMALLINT NOT NULL DEFAULT 0,
|
|
81
|
+
DeleteDate TIMESTAMP,
|
|
82
|
+
DeletingIDUser INT NOT NULL DEFAULT 0,
|
|
83
|
+
Text TEXT,
|
|
84
|
+
Rating INT NOT NULL DEFAULT 0,
|
|
85
|
+
IDBook INT NOT NULL DEFAULT 0
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
-- Seed Data: First 20 books from books.csv
|
|
89
|
+
|
|
90
|
+
INSERT INTO Book (Title, Type, Genre, ISBN, Language, ImageURL, PublicationYear, CreateDate, CreatingIDUser, UpdateDate, UpdatingIDUser) VALUES
|
|
91
|
+
('The Hunger Games', 'Paper', 'UNKNOWN', '439023483', 'eng', 'https://images.gr-assets.com/books/1447303603m/2767052.jpg', 2008, NOW(), 99999, NOW(), 99999),
|
|
92
|
+
('Harry Potter and the Philosopher''s Stone', 'Paper', 'UNKNOWN', '439554934', 'eng', 'https://images.gr-assets.com/books/1474154022m/3.jpg', 1997, NOW(), 99999, NOW(), 99999),
|
|
93
|
+
('Twilight', 'Paper', 'UNKNOWN', '316015849', 'en-US', 'https://images.gr-assets.com/books/1361039443m/41865.jpg', 2005, NOW(), 99999, NOW(), 99999),
|
|
94
|
+
('To Kill a Mockingbird', 'Paper', 'UNKNOWN', '61120081', 'eng', 'https://images.gr-assets.com/books/1361975680m/2657.jpg', 1960, NOW(), 99999, NOW(), 99999),
|
|
95
|
+
('The Great Gatsby', 'Paper', 'UNKNOWN', '743273567', 'eng', 'https://images.gr-assets.com/books/1490528560m/4671.jpg', 1925, NOW(), 99999, NOW(), 99999),
|
|
96
|
+
('The Fault in Our Stars', 'Paper', 'UNKNOWN', '525478817', 'eng', 'https://images.gr-assets.com/books/1360206420m/11870085.jpg', 2012, NOW(), 99999, NOW(), 99999),
|
|
97
|
+
('The Hobbit or There and Back Again', 'Paper', 'UNKNOWN', '618260307', 'en-US', 'https://images.gr-assets.com/books/1372847500m/5907.jpg', 1937, NOW(), 99999, NOW(), 99999),
|
|
98
|
+
('The Catcher in the Rye', 'Paper', 'UNKNOWN', '316769177', 'eng', 'https://images.gr-assets.com/books/1398034300m/5107.jpg', 1951, NOW(), 99999, NOW(), 99999),
|
|
99
|
+
('Angels & Demons', 'Paper', 'UNKNOWN', '1416524797', 'en-CA', 'https://images.gr-assets.com/books/1303390735m/960.jpg', 2000, NOW(), 99999, NOW(), 99999),
|
|
100
|
+
('Pride and Prejudice', 'Paper', 'UNKNOWN', '679783261', 'eng', 'https://images.gr-assets.com/books/1320399351m/1885.jpg', 1813, NOW(), 99999, NOW(), 99999),
|
|
101
|
+
('The Kite Runner', 'Paper', 'UNKNOWN', '1594480001', 'eng', 'https://images.gr-assets.com/books/1484565687m/77203.jpg', 2003, NOW(), 99999, NOW(), 99999),
|
|
102
|
+
('Divergent', 'Paper', 'UNKNOWN', '62024035', 'eng', 'https://images.gr-assets.com/books/1328559506m/13335037.jpg', 2011, NOW(), 99999, NOW(), 99999),
|
|
103
|
+
('Nineteen Eighty-Four', 'Paper', 'UNKNOWN', '451524934', 'eng', 'https://images.gr-assets.com/books/1348990566m/5470.jpg', 1949, NOW(), 99999, NOW(), 99999),
|
|
104
|
+
('Animal Farm: A Fairy Story', 'Paper', 'UNKNOWN', '452284244', 'eng', 'https://images.gr-assets.com/books/1424037542m/7613.jpg', 1945, NOW(), 99999, NOW(), 99999),
|
|
105
|
+
('Het Achterhuis: Dagboekbrieven 14 juni 1942 - 1 augustus 1944', 'Paper', 'UNKNOWN', '553296981', 'eng', 'https://images.gr-assets.com/books/1358276407m/48855.jpg', 1947, NOW(), 99999, NOW(), 99999),
|
|
106
|
+
('Män som hatar kvinnor', 'Paper', 'UNKNOWN', '307269752', 'eng', 'https://images.gr-assets.com/books/1327868566m/2429135.jpg', 2005, NOW(), 99999, NOW(), 99999),
|
|
107
|
+
('Catching Fire', 'Paper', 'UNKNOWN', '439023491', 'eng', 'https://images.gr-assets.com/books/1358273780m/6148028.jpg', 2009, NOW(), 99999, NOW(), 99999),
|
|
108
|
+
('Harry Potter and the Prisoner of Azkaban', 'Paper', 'UNKNOWN', '043965548X', 'eng', 'https://images.gr-assets.com/books/1499277281m/5.jpg', 1999, NOW(), 99999, NOW(), 99999),
|
|
109
|
+
('The Fellowship of the Ring', 'Paper', 'UNKNOWN', '618346252', 'eng', 'https://images.gr-assets.com/books/1298411339m/34.jpg', 1954, NOW(), 99999, NOW(), 99999),
|
|
110
|
+
('Mockingjay', 'Paper', 'UNKNOWN', '439023513', 'eng', 'https://images.gr-assets.com/books/1358275419m/7260188.jpg', 2010, NOW(), 99999, NOW(), 99999);
|
|
111
|
+
|
|
112
|
+
-- Seed Data: Authors for the first 20 books
|
|
113
|
+
|
|
114
|
+
INSERT INTO Author (Name, CreateDate, CreatingIDUser, UpdateDate, UpdatingIDUser) VALUES
|
|
115
|
+
('Suzanne Collins', NOW(), 99999, NOW(), 99999),
|
|
116
|
+
('J.K. Rowling', NOW(), 99999, NOW(), 99999),
|
|
117
|
+
('Mary GrandPré', NOW(), 99999, NOW(), 99999),
|
|
118
|
+
('Stephenie Meyer', NOW(), 99999, NOW(), 99999),
|
|
119
|
+
('Harper Lee', NOW(), 99999, NOW(), 99999),
|
|
120
|
+
('F. Scott Fitzgerald', NOW(), 99999, NOW(), 99999),
|
|
121
|
+
('John Green', NOW(), 99999, NOW(), 99999),
|
|
122
|
+
('J.R.R. Tolkien', NOW(), 99999, NOW(), 99999),
|
|
123
|
+
('J.D. Salinger', NOW(), 99999, NOW(), 99999),
|
|
124
|
+
('Dan Brown', NOW(), 99999, NOW(), 99999),
|
|
125
|
+
('Jane Austen', NOW(), 99999, NOW(), 99999),
|
|
126
|
+
('Khaled Hosseini', NOW(), 99999, NOW(), 99999),
|
|
127
|
+
('Veronica Roth', NOW(), 99999, NOW(), 99999),
|
|
128
|
+
('George Orwell', NOW(), 99999, NOW(), 99999),
|
|
129
|
+
('Erich Fromm', NOW(), 99999, NOW(), 99999),
|
|
130
|
+
('Anne Frank', NOW(), 99999, NOW(), 99999),
|
|
131
|
+
('Eleanor Roosevelt', NOW(), 99999, NOW(), 99999),
|
|
132
|
+
('B.M. Mooyaart-Doubleday', NOW(), 99999, NOW(), 99999),
|
|
133
|
+
('Stieg Larsson', NOW(), 99999, NOW(), 99999),
|
|
134
|
+
('Reg Keeland', NOW(), 99999, NOW(), 99999),
|
|
135
|
+
('Rufus Beck', NOW(), 99999, NOW(), 99999);
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# DGraph Test Database Management Script
|
|
3
|
+
#
|
|
4
|
+
# Usage:
|
|
5
|
+
# ./scripts/dgraph-test-db.sh start - Start DGraph container, apply schema, and wait for readiness
|
|
6
|
+
# ./scripts/dgraph-test-db.sh stop - Stop and remove the container
|
|
7
|
+
# ./scripts/dgraph-test-db.sh status - Check if the container is running
|
|
8
|
+
#
|
|
9
|
+
# The container settings match the test configuration in
|
|
10
|
+
# test/Meadow-Provider-DGraph_tests.js:
|
|
11
|
+
# Host: 127.0.0.1, Port: 38080 (HTTP), 39080 (gRPC)
|
|
12
|
+
|
|
13
|
+
CONTAINER_NAME="meadow-dgraph-test"
|
|
14
|
+
DGRAPH_HTTP_PORT="38080"
|
|
15
|
+
DGRAPH_GRPC_PORT="39080"
|
|
16
|
+
DGRAPH_IMAGE="dgraph/standalone:latest"
|
|
17
|
+
|
|
18
|
+
start_dgraph() {
|
|
19
|
+
# Check if container already exists
|
|
20
|
+
if docker ps -a --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
|
|
21
|
+
if docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
|
|
22
|
+
echo "DGraph test container is already running."
|
|
23
|
+
return 0
|
|
24
|
+
else
|
|
25
|
+
echo "Removing stopped container..."
|
|
26
|
+
docker rm "${CONTAINER_NAME}" > /dev/null 2>&1
|
|
27
|
+
fi
|
|
28
|
+
fi
|
|
29
|
+
|
|
30
|
+
echo "Starting DGraph test container..."
|
|
31
|
+
docker run -d \
|
|
32
|
+
--name "${CONTAINER_NAME}" \
|
|
33
|
+
-p "${DGRAPH_HTTP_PORT}:8080" \
|
|
34
|
+
-p "${DGRAPH_GRPC_PORT}:9080" \
|
|
35
|
+
"${DGRAPH_IMAGE}"
|
|
36
|
+
|
|
37
|
+
if [ $? -ne 0 ]; then
|
|
38
|
+
echo "ERROR: Failed to start DGraph container."
|
|
39
|
+
exit 1
|
|
40
|
+
fi
|
|
41
|
+
|
|
42
|
+
echo "Waiting for DGraph to be ready..."
|
|
43
|
+
RETRIES=30
|
|
44
|
+
until curl -sf "http://localhost:${DGRAPH_HTTP_PORT}/health" > /dev/null 2>&1; do
|
|
45
|
+
RETRIES=$((RETRIES - 1))
|
|
46
|
+
if [ $RETRIES -le 0 ]; then
|
|
47
|
+
echo "ERROR: DGraph failed to become ready in time."
|
|
48
|
+
docker logs "${CONTAINER_NAME}" 2>&1 | tail -20
|
|
49
|
+
exit 1
|
|
50
|
+
fi
|
|
51
|
+
echo " ...waiting (${RETRIES} retries left)"
|
|
52
|
+
sleep 2
|
|
53
|
+
done
|
|
54
|
+
|
|
55
|
+
# Apply schema predicates for the FableTest type and MeadowCounter type
|
|
56
|
+
# Note: FableTest fields use unscoped predicate names to match FoxHound DGraph dialect output
|
|
57
|
+
echo "Applying DGraph schema..."
|
|
58
|
+
curl -sf "http://localhost:${DGRAPH_HTTP_PORT}/alter" -d '
|
|
59
|
+
IDAnimal: int @index(int) .
|
|
60
|
+
GUIDAnimal: string .
|
|
61
|
+
CreateDate: string .
|
|
62
|
+
CreatingIDUser: int .
|
|
63
|
+
UpdateDate: string .
|
|
64
|
+
UpdatingIDUser: int .
|
|
65
|
+
Deleted: int @index(int) .
|
|
66
|
+
DeleteDate: string .
|
|
67
|
+
DeletingIDUser: int .
|
|
68
|
+
Name: string @index(exact, term) .
|
|
69
|
+
Type: string @index(exact, term) .
|
|
70
|
+
MeadowCounter.scope: string @index(exact) .
|
|
71
|
+
MeadowCounter.sequence: int .
|
|
72
|
+
|
|
73
|
+
type FableTest {
|
|
74
|
+
IDAnimal
|
|
75
|
+
GUIDAnimal
|
|
76
|
+
CreateDate
|
|
77
|
+
CreatingIDUser
|
|
78
|
+
UpdateDate
|
|
79
|
+
UpdatingIDUser
|
|
80
|
+
Deleted
|
|
81
|
+
DeleteDate
|
|
82
|
+
DeletingIDUser
|
|
83
|
+
Name
|
|
84
|
+
Type
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
type MeadowCounter {
|
|
88
|
+
MeadowCounter.scope
|
|
89
|
+
MeadowCounter.sequence
|
|
90
|
+
}
|
|
91
|
+
' > /dev/null 2>&1
|
|
92
|
+
|
|
93
|
+
if [ $? -ne 0 ]; then
|
|
94
|
+
echo "WARNING: Failed to apply DGraph schema. Tests may fail."
|
|
95
|
+
else
|
|
96
|
+
echo "DGraph schema applied successfully."
|
|
97
|
+
fi
|
|
98
|
+
|
|
99
|
+
echo ""
|
|
100
|
+
echo "DGraph test instance is ready!"
|
|
101
|
+
echo " Container: ${CONTAINER_NAME}"
|
|
102
|
+
echo " HTTP: 127.0.0.1:${DGRAPH_HTTP_PORT}"
|
|
103
|
+
echo " gRPC: 127.0.0.1:${DGRAPH_GRPC_PORT}"
|
|
104
|
+
echo ""
|
|
105
|
+
echo "Run tests with: npm run test-dgraph"
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
stop_dgraph() {
|
|
109
|
+
if docker ps -a --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
|
|
110
|
+
echo "Stopping and removing DGraph test container..."
|
|
111
|
+
docker stop "${CONTAINER_NAME}" > /dev/null 2>&1
|
|
112
|
+
docker rm "${CONTAINER_NAME}" > /dev/null 2>&1
|
|
113
|
+
echo "DGraph test container removed."
|
|
114
|
+
else
|
|
115
|
+
echo "No DGraph test container found."
|
|
116
|
+
fi
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
status_dgraph() {
|
|
120
|
+
if docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
|
|
121
|
+
echo "DGraph test container is running."
|
|
122
|
+
docker ps --filter "name=${CONTAINER_NAME}" --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
|
|
123
|
+
elif docker ps -a --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
|
|
124
|
+
echo "DGraph test container exists but is stopped."
|
|
125
|
+
else
|
|
126
|
+
echo "DGraph test container is not running."
|
|
127
|
+
fi
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
case "${1}" in
|
|
131
|
+
start)
|
|
132
|
+
start_dgraph
|
|
133
|
+
;;
|
|
134
|
+
stop)
|
|
135
|
+
stop_dgraph
|
|
136
|
+
;;
|
|
137
|
+
status)
|
|
138
|
+
status_dgraph
|
|
139
|
+
;;
|
|
140
|
+
*)
|
|
141
|
+
echo "Usage: $0 {start|stop|status}"
|
|
142
|
+
exit 1
|
|
143
|
+
;;
|
|
144
|
+
esac
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
2
|
# Meadow Test Database Cleanup Script
|
|
3
3
|
#
|
|
4
|
-
# Stops and removes
|
|
4
|
+
# Stops and removes all meadow test database containers.
|
|
5
5
|
#
|
|
6
6
|
# Usage:
|
|
7
7
|
# ./scripts/meadow-test-cleanup.sh
|
|
@@ -13,6 +13,10 @@ echo ""
|
|
|
13
13
|
|
|
14
14
|
"${SCRIPT_DIR}/mysql-test-db.sh" stop
|
|
15
15
|
"${SCRIPT_DIR}/mssql-test-db.sh" stop
|
|
16
|
+
"${SCRIPT_DIR}/postgresql-test-db.sh" stop
|
|
17
|
+
"${SCRIPT_DIR}/mongodb-test-db.sh" stop
|
|
18
|
+
"${SCRIPT_DIR}/solr-test-db.sh" stop
|
|
19
|
+
"${SCRIPT_DIR}/dgraph-test-db.sh" stop
|
|
16
20
|
|
|
17
21
|
echo ""
|
|
18
22
|
echo "Cleanup complete."
|