meadow 2.0.22 → 2.0.26

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.
Files changed (59) hide show
  1. package/README.md +110 -141
  2. package/docs/README.md +34 -230
  3. package/docs/_cover.md +14 -0
  4. package/docs/_sidebar.md +44 -12
  5. package/docs/_topbar.md +5 -0
  6. package/docs/api/doCount.md +109 -0
  7. package/docs/api/doCreate.md +132 -0
  8. package/docs/api/doDelete.md +101 -0
  9. package/docs/api/doRead.md +122 -0
  10. package/docs/api/doReads.md +136 -0
  11. package/docs/api/doUndelete.md +98 -0
  12. package/docs/api/doUpdate.md +129 -0
  13. package/docs/api/getRoleName.md +84 -0
  14. package/docs/api/loadFromPackage.md +153 -0
  15. package/docs/api/marshalRecordFromSourceToObject.md +92 -0
  16. package/docs/api/query.md +133 -0
  17. package/docs/api/rawQueries.md +197 -0
  18. package/docs/api/reference.md +117 -0
  19. package/docs/api/setAuthorizer.md +103 -0
  20. package/docs/api/setDefault.md +90 -0
  21. package/docs/api/setDefaultIdentifier.md +84 -0
  22. package/docs/api/setDomain.md +56 -0
  23. package/docs/api/setIDUser.md +91 -0
  24. package/docs/api/setJsonSchema.md +92 -0
  25. package/docs/api/setProvider.md +87 -0
  26. package/docs/api/setSchema.md +107 -0
  27. package/docs/api/setScope.md +68 -0
  28. package/docs/api/validateObject.md +119 -0
  29. package/docs/architecture.md +316 -0
  30. package/docs/audit-tracking.md +226 -0
  31. package/docs/configuration.md +317 -0
  32. package/docs/providers/meadow-endpoints.md +306 -0
  33. package/docs/providers/mongodb.md +319 -0
  34. package/docs/providers/postgresql.md +312 -0
  35. package/docs/providers/rocksdb.md +297 -0
  36. package/docs/query-dsl.md +269 -0
  37. package/docs/quick-start.md +384 -0
  38. package/docs/raw-queries.md +193 -0
  39. package/docs/retold-catalog.json +61 -1
  40. package/docs/retold-keyword-index.json +15860 -4839
  41. package/docs/soft-deletes.md +224 -0
  42. package/package.json +44 -27
  43. package/scripts/bookstore-seed-postgresql.sql +135 -0
  44. package/scripts/dgraph-test-db.sh +144 -0
  45. package/scripts/meadow-test-cleanup.sh +5 -1
  46. package/scripts/mongodb-test-db.sh +98 -0
  47. package/scripts/postgresql-test-db.sh +124 -0
  48. package/scripts/solr-test-db.sh +135 -0
  49. package/source/Meadow.js +5 -0
  50. package/source/providers/Meadow-Provider-DGraph.js +679 -0
  51. package/source/providers/Meadow-Provider-MongoDB.js +527 -0
  52. package/source/providers/Meadow-Provider-PostgreSQL.js +361 -0
  53. package/source/providers/Meadow-Provider-RocksDB.js +1300 -0
  54. package/source/providers/Meadow-Provider-Solr.js +726 -0
  55. package/test/Meadow-Provider-DGraph_tests.js +741 -0
  56. package/test/Meadow-Provider-MongoDB_tests.js +661 -0
  57. package/test/Meadow-Provider-PostgreSQL_tests.js +787 -0
  58. package/test/Meadow-Provider-RocksDB_tests.js +887 -0
  59. package/test/Meadow-Provider-Solr_tests.js +679 -0
@@ -0,0 +1,297 @@
1
+ # RocksDB Provider
2
+
3
+ > Embedded key-value store for high-throughput scenarios with in-memory filtering
4
+
5
+ The RocksDB provider connects Meadow to [RocksDB](https://rocksdb.org/), a high-performance embedded key-value store. Unlike SQL-based providers, RocksDB does not use a FoxHound dialect for query generation. Instead, records are stored as key-value pairs and all filtering is performed in-memory after a full scan. Direct key lookups are O(1), making this provider ideal for high-throughput scenarios where reads are primarily by key.
6
+
7
+ ## Setup
8
+
9
+ ### Install Dependencies
10
+
11
+ ```bash
12
+ npm install meadow meadow-connection-rocksdb
13
+ ```
14
+
15
+ ### Register the Connection
16
+
17
+ ```javascript
18
+ const libFable = require('fable').new(
19
+ {
20
+ RocksDB:
21
+ {
22
+ RocksDBFolder: './data/rocksdb',
23
+ KeyMode: 'GUID'
24
+ }
25
+ });
26
+
27
+ const libMeadowConnectionRocksDB = require('meadow-connection-rocksdb');
28
+
29
+ // Register the connection service
30
+ libFable.serviceManager.addServiceType('MeadowRocksDBProvider', libMeadowConnectionRocksDB);
31
+ libFable.serviceManager.instantiateServiceProvider('MeadowRocksDBProvider');
32
+ ```
33
+
34
+ ### Create a Meadow DAL
35
+
36
+ ```javascript
37
+ const libMeadow = require('meadow');
38
+
39
+ const meadow = libMeadow.new(libFable, 'Book')
40
+ .setProvider('RocksDB')
41
+ .setDefaultIdentifier('IDBook')
42
+ .setSchema([
43
+ { Column: 'IDBook', Type: 'AutoIdentity' },
44
+ { Column: 'GUIDBook', Type: 'AutoGUID' },
45
+ { Column: 'Title', Type: 'String', Size: '255' },
46
+ { Column: 'Author', Type: 'String', Size: '128' },
47
+ { Column: 'CreateDate', Type: 'CreateDate' },
48
+ { Column: 'CreatingIDUser', Type: 'CreateIDUser' },
49
+ { Column: 'UpdateDate', Type: 'UpdateDate' },
50
+ { Column: 'UpdatingIDUser', Type: 'UpdateIDUser' },
51
+ { Column: 'DeleteDate', Type: 'DeleteDate' },
52
+ { Column: 'DeletingIDUser', Type: 'DeleteIDUser' },
53
+ { Column: 'Deleted', Type: 'Deleted' }
54
+ ]);
55
+ ```
56
+
57
+ ## Connection Management
58
+
59
+ ### Connection Configuration
60
+
61
+ | Setting | Type | Default | Description |
62
+ |---------|------|---------|-------------|
63
+ | `RocksDB.RocksDBFolder` | string | -- | Filesystem path to the RocksDB data directory |
64
+ | `RocksDB.KeyMode` | string | `'GUID'` | Key generation strategy: `'GUID'` or `'ID'` |
65
+
66
+ ### Key Modes
67
+
68
+ The `KeyMode` setting determines how records are keyed in the store:
69
+
70
+ | Mode | Key Format | Description |
71
+ |------|------------|-------------|
72
+ | `GUID` | `M-E-{Scope}-{GUID}` | Keys use the record's GUID (default) |
73
+ | `ID` | `M-EBI-{Scope}-{ID}` | Keys use the record's integer identity |
74
+
75
+ For example, with a `Book` scope:
76
+
77
+ ```
78
+ GUID mode: M-E-Book-a1b2c3d4-e5f6-7890-abcd-ef1234567890
79
+ ID mode: M-EBI-Book-42
80
+ ```
81
+
82
+ ## Storage Model
83
+
84
+ ### Key-Value Architecture
85
+
86
+ RocksDB is a key-value store, not a relational database. Each Meadow record is serialized as a JSON value stored under a structured key. This has important implications:
87
+
88
+ - **No SQL dialect** -- The provider does not use FoxHound for query generation
89
+ - **No JOINs** -- Cross-entity queries are not supported
90
+ - **No aggregations** -- Beyond COUNT, no aggregate functions are available
91
+ - **In-memory filtering** -- All filter operations require scanning records and evaluating filters in memory
92
+
93
+ ### Direct Key Lookup
94
+
95
+ When reading a record by its primary key (GUID or ID depending on KeyMode), the provider performs a direct key lookup against RocksDB. This is an O(1) operation and is extremely fast regardless of the total number of records in the store.
96
+
97
+ ### In-Memory Filter Engine
98
+
99
+ For queries with filters, sorts, or pagination, the provider:
100
+
101
+ 1. Scans all records in the scope prefix range
102
+ 2. Deserializes each record from JSON
103
+ 3. Evaluates filter conditions against each record in memory
104
+ 4. Applies sorting in memory
105
+ 5. Applies pagination (begin/cap) in memory
106
+ 6. Returns the matching result set
107
+
108
+ This means that filtered reads scale linearly with the total number of records in the scope. For large datasets with complex filter requirements, consider a SQL-based provider instead.
109
+
110
+ ## CRUD Operations
111
+
112
+ ### Create
113
+
114
+ Serializes the record as JSON and stores it under the generated key.
115
+
116
+ ```javascript
117
+ meadow.doCreate(
118
+ meadow.query.addRecord({ Title: 'Dune', Author: 'Frank Herbert' }),
119
+ (pError, pCreateQuery, pReadQuery, pRecord) =>
120
+ {
121
+ console.log('New ID:', pRecord.IDBook);
122
+ console.log('Stored with key: M-E-Book-' + pRecord.GUIDBook);
123
+ });
124
+ ```
125
+
126
+ ### Read
127
+
128
+ Performs a direct key lookup when filtering by the primary key, or an in-memory scan for other filters.
129
+
130
+ ```javascript
131
+ // Direct key lookup (O(1))
132
+ meadow.doRead(
133
+ meadow.query.addFilter('IDBook', 42),
134
+ (pError, pQuery, pRecord) =>
135
+ {
136
+ console.log('Title:', pRecord.Title);
137
+ });
138
+
139
+ // In-memory filtered scan
140
+ meadow.doReads(
141
+ meadow.query.setCap(25).setBegin(0).addFilter('Author', 'Frank Herbert', '='),
142
+ (pError, pQuery, pRecords) =>
143
+ {
144
+ pRecords.forEach((pBook) => console.log(pBook.Title));
145
+ });
146
+ ```
147
+
148
+ ### Update
149
+
150
+ Reads the existing record by key, merges the updated fields, and writes the updated record back.
151
+
152
+ ```javascript
153
+ meadow.doUpdate(
154
+ meadow.query
155
+ .addFilter('IDBook', 42)
156
+ .addRecord({ Title: 'Updated Title' }),
157
+ (pError, pUpdateQuery, pReadQuery, pRecord) =>
158
+ {
159
+ console.log('Updated:', pRecord.Title);
160
+ });
161
+ ```
162
+
163
+ ### Delete
164
+
165
+ Executes a soft delete by setting the Deleted flag on the stored record.
166
+
167
+ ```javascript
168
+ meadow.doDelete(
169
+ meadow.query.addFilter('IDBook', 42),
170
+ (pError, pQuery, pResult) =>
171
+ {
172
+ console.log('Deleted records:', pResult);
173
+ });
174
+ ```
175
+
176
+ ### Undelete
177
+
178
+ Reverses a soft delete by clearing the Deleted flag.
179
+
180
+ ```javascript
181
+ meadow.doUndelete(
182
+ meadow.query.addFilter('IDBook', 42),
183
+ (pError, pQuery, pResult) =>
184
+ {
185
+ console.log('Restored records:', pResult);
186
+ });
187
+ ```
188
+
189
+ ### Count
190
+
191
+ Scans the scope prefix and counts matching records in memory.
192
+
193
+ ```javascript
194
+ meadow.doCount(
195
+ meadow.query,
196
+ (pError, pQuery, pCount) =>
197
+ {
198
+ console.log('Total books:', pCount);
199
+ });
200
+ ```
201
+
202
+ ## Limitations
203
+
204
+ | Feature | Supported | Notes |
205
+ |---------|-----------|-------|
206
+ | Direct key lookup | Yes | O(1) performance |
207
+ | Filtered reads | Yes | In-memory post-scan filtering |
208
+ | Sorting | Yes | In-memory after scan |
209
+ | Pagination (begin/cap) | Yes | In-memory after scan |
210
+ | COUNT | Yes | In-memory count after scan |
211
+ | JOINs | No | Not supported in key-value model |
212
+ | Aggregations (SUM, AVG) | No | Only COUNT is available |
213
+ | FoxHound dialect | No | Provider uses its own filter engine |
214
+
215
+ ## When to Use RocksDB
216
+
217
+ | Use Case | Recommendation |
218
+ |----------|---------------|
219
+ | High-throughput key lookups | Excellent -- O(1) reads by key |
220
+ | Embedded applications | Excellent -- no server process required |
221
+ | Write-heavy workloads | Good -- RocksDB is optimized for writes |
222
+ | Complex filtered queries | Consider SQL providers instead |
223
+ | JOIN-heavy data models | Use MySQL, MSSQL, or PostgreSQL |
224
+ | Browser applications | Use ALASQL provider instead |
225
+
226
+ ## Full Setup Example
227
+
228
+ A complete working example using RocksDB for local key-value storage:
229
+
230
+ ```javascript
231
+ const libFable = require('fable').new(
232
+ {
233
+ RocksDB:
234
+ {
235
+ RocksDBFolder: './data/bookstore',
236
+ KeyMode: 'GUID'
237
+ }
238
+ });
239
+
240
+ const libMeadow = require('meadow');
241
+ const libMeadowConnectionRocksDB = require('meadow-connection-rocksdb');
242
+
243
+ // Register the connection service
244
+ libFable.serviceManager.addServiceType('MeadowRocksDBProvider', libMeadowConnectionRocksDB);
245
+ libFable.serviceManager.instantiateServiceProvider('MeadowRocksDBProvider');
246
+
247
+ // Create the DAL
248
+ const meadow = libMeadow.new(libFable, 'Book')
249
+ .setProvider('RocksDB')
250
+ .setDefaultIdentifier('IDBook')
251
+ .setSchema([
252
+ { Column: 'IDBook', Type: 'AutoIdentity' },
253
+ { Column: 'GUIDBook', Type: 'AutoGUID' },
254
+ { Column: 'Title', Type: 'String', Size: '255' },
255
+ { Column: 'Author', Type: 'String', Size: '128' },
256
+ { Column: 'CreateDate', Type: 'CreateDate' },
257
+ { Column: 'CreatingIDUser', Type: 'CreateIDUser' },
258
+ { Column: 'UpdateDate', Type: 'UpdateDate' },
259
+ { Column: 'UpdatingIDUser', Type: 'UpdateIDUser' },
260
+ { Column: 'DeleteDate', Type: 'DeleteDate' },
261
+ { Column: 'DeletingIDUser', Type: 'DeleteIDUser' },
262
+ { Column: 'Deleted', Type: 'Deleted' }
263
+ ]);
264
+
265
+ // Insert a record
266
+ meadow.doCreate(
267
+ meadow.query.addRecord({ Title: 'Dune', Author: 'Frank Herbert' }),
268
+ (pError, pCreateQuery, pReadQuery, pRecord) =>
269
+ {
270
+ console.log('Created book with ID:', pRecord.IDBook);
271
+ console.log('GUID:', pRecord.GUIDBook);
272
+ console.log('Key: M-E-Book-' + pRecord.GUIDBook);
273
+
274
+ // Direct key lookup
275
+ meadow.doRead(
276
+ meadow.query.addFilter('IDBook', pRecord.IDBook),
277
+ (pError, pQuery, pRecord) =>
278
+ {
279
+ console.log('Read back:', pRecord.Title, 'by', pRecord.Author);
280
+ });
281
+ });
282
+ ```
283
+
284
+ ## Error Handling
285
+
286
+ All operations follow the same error handling pattern:
287
+
288
+ - Storage errors are stored in `pQuery.parameters.result.error`
289
+ - Key generation or serialization failures are logged as warnings
290
+ - File system errors (e.g., missing RocksDBFolder) bubble through the callback
291
+
292
+ ## Related Documentation
293
+
294
+ - [Providers Overview](providers/README.md) -- Comparison of all providers
295
+ - [SQLite Provider](providers/sqlite.md) -- Embedded SQL alternative
296
+ - [ALASQL Provider](providers/alasql.md) -- In-memory SQL alternative
297
+ - [meadow-connection-rocksdb](https://github.com/stevenvelozo/meadow-connection-rocksdb) -- Connection module source
@@ -0,0 +1,269 @@
1
+ # Query DSL
2
+
3
+ Meadow uses [FoxHound](https://github.com/stevenvelozo/foxhound) as its query DSL. FoxHound provides a fluent, chainable API for building database queries without writing raw SQL. Meadow wraps FoxHound and manages query lifecycle, cloning, and schema injection.
4
+
5
+ ## Getting a Query
6
+
7
+ Access a new query through the `meadow.query` property:
8
+
9
+ ```javascript
10
+ var tmpQuery = tmpBookDAL.query;
11
+ ```
12
+
13
+ Every access to `.query` returns a fresh, independent clone of the internal FoxHound instance. The clone comes pre-configured with the Meadow entity scope and schema.
14
+
15
+ ## Query Cloning and Isolation
16
+
17
+ Each call to `meadow.query` produces an isolated query object. Configuring one query never affects another:
18
+
19
+ ```javascript
20
+ var tmpQueryA = tmpBookDAL.query
21
+ .addFilter('Author', 'Asimov')
22
+ .setCap(10);
23
+
24
+ var tmpQueryB = tmpBookDAL.query
25
+ .addFilter('Author', 'Herbert')
26
+ .setCap(50);
27
+
28
+ // tmpQueryA and tmpQueryB are completely independent.
29
+ // tmpQueryA filters for Asimov with cap 10.
30
+ // tmpQueryB filters for Herbert with cap 50.
31
+ ```
32
+
33
+ This isolation is critical for concurrent operations. You can safely build multiple queries in parallel without state leakage.
34
+
35
+ ## Filtering
36
+
37
+ Add filters to constrain which records are returned. The `addFilter` method accepts a column name, a value, and an optional operator.
38
+
39
+ ### Basic Syntax
40
+
41
+ ```javascript
42
+ // Equality (default operator)
43
+ tmpQuery.addFilter('Author', 'Frank Herbert');
44
+
45
+ // With explicit operator
46
+ tmpQuery.addFilter('YearPublished', 1960, '>=');
47
+ ```
48
+
49
+ ### Supported Operators
50
+
51
+ | Operator | Description | Example |
52
+ |----------|-------------|---------|
53
+ | `=` | Equal to (default) | `addFilter('Status', 'Active')` |
54
+ | `!=` | Not equal to | `addFilter('Status', 'Deleted', '!=')` |
55
+ | `>` | Greater than | `addFilter('Price', 10, '>')` |
56
+ | `<` | Less than | `addFilter('Price', 100, '<')` |
57
+ | `>=` | Greater than or equal | `addFilter('YearPublished', 2000, '>=')` |
58
+ | `<=` | Less than or equal | `addFilter('YearPublished', 2020, '<=')` |
59
+ | `LIKE` | Pattern match | `addFilter('Title', '%Dune%', 'LIKE')` |
60
+ | `IN` | Value in set | `addFilter('IDBook', '1,2,3', 'IN')` |
61
+
62
+ ### Combining Filters
63
+
64
+ Multiple filters are combined with `AND` logic:
65
+
66
+ ```javascript
67
+ var tmpQuery = tmpBookDAL.query
68
+ .addFilter('Author', 'Frank Herbert')
69
+ .addFilter('YearPublished', 1965, '>=')
70
+ .addFilter('YearPublished', 1985, '<=');
71
+ ```
72
+
73
+ This generates a query equivalent to:
74
+
75
+ ```sql
76
+ WHERE Author = 'Frank Herbert'
77
+ AND YearPublished >= 1965
78
+ AND YearPublished <= 1985
79
+ AND Deleted = 0
80
+ ```
81
+
82
+ Note that `Deleted = 0` is added automatically when the schema contains a `Deleted` column. See [Soft Deletes](soft-deletes.md) for details.
83
+
84
+ ## Pagination
85
+
86
+ Control result set size and offset with `setCap` and `setBegin`.
87
+
88
+ ### setCap(n)
89
+
90
+ Limits the number of records returned:
91
+
92
+ ```javascript
93
+ // Return at most 25 records
94
+ var tmpQuery = tmpBookDAL.query
95
+ .setCap(25);
96
+ ```
97
+
98
+ ### setBegin(n)
99
+
100
+ Sets the starting offset for pagination:
101
+
102
+ ```javascript
103
+ // Skip the first 50 records, return the next 25
104
+ var tmpQuery = tmpBookDAL.query
105
+ .setCap(25)
106
+ .setBegin(50);
107
+ ```
108
+
109
+ ### Pagination Example
110
+
111
+ ```javascript
112
+ var tmpPageSize = 20;
113
+ var tmpPageNumber = 3;
114
+
115
+ var tmpQuery = tmpBookDAL.query
116
+ .setCap(tmpPageSize)
117
+ .setBegin(tmpPageSize * tmpPageNumber);
118
+
119
+ tmpBookDAL.doReads(tmpQuery,
120
+ function (pError, pQuery, pRecords)
121
+ {
122
+ console.log('Page', tmpPageNumber, ':', pRecords.length, 'records');
123
+ });
124
+ ```
125
+
126
+ ## Sorting
127
+
128
+ Add sort directives with `addSort`. Each sort directive is an object with `Column` and `Direction` properties.
129
+
130
+ ```javascript
131
+ var tmpQuery = tmpBookDAL.query
132
+ .addSort({ Column: 'Author', Direction: 'ASC' })
133
+ .addSort({ Column: 'Title', Direction: 'DESC' });
134
+ ```
135
+
136
+ Sort directives are applied in the order they are added.
137
+
138
+ ## Column Selection
139
+
140
+ Restrict which columns are returned with `setDataElements`. This is useful for performance when you only need specific fields.
141
+
142
+ ```javascript
143
+ var tmpQuery = tmpBookDAL.query
144
+ .setDataElements(['IDBook', 'Title', 'Author']);
145
+
146
+ tmpBookDAL.doReads(tmpQuery,
147
+ function (pError, pQuery, pRecords)
148
+ {
149
+ // Each record only contains IDBook, Title, and Author
150
+ });
151
+ ```
152
+
153
+ ## Distinct
154
+
155
+ Return only unique rows with `setDistinct`:
156
+
157
+ ```javascript
158
+ var tmpQuery = tmpBookDAL.query
159
+ .setDataElements(['Author'])
160
+ .setDistinct(true);
161
+
162
+ tmpBookDAL.doReads(tmpQuery,
163
+ function (pError, pQuery, pRecords)
164
+ {
165
+ // Returns unique authors only
166
+ });
167
+ ```
168
+
169
+ ## Record Attachment
170
+
171
+ Attach a record to the query for create and update operations using `addRecord`:
172
+
173
+ ```javascript
174
+ // For doCreate
175
+ var tmpQuery = tmpBookDAL.query
176
+ .addRecord(
177
+ {
178
+ Title: 'Neuromancer',
179
+ Author: 'William Gibson',
180
+ YearPublished: 1984
181
+ });
182
+
183
+ tmpBookDAL.doCreate(tmpQuery,
184
+ function (pError, pCreateQuery, pReadQuery, pRecord)
185
+ {
186
+ console.log('Created:', pRecord.IDBook);
187
+ });
188
+
189
+ // For doUpdate (must include the default identifier)
190
+ var tmpQuery = tmpBookDAL.query
191
+ .addRecord(
192
+ {
193
+ IDBook: 5,
194
+ Title: 'Neuromancer (Anniversary Edition)'
195
+ });
196
+
197
+ tmpBookDAL.doUpdate(tmpQuery,
198
+ function (pError, pUpdateQuery, pReadQuery, pRecord)
199
+ {
200
+ console.log('Updated:', pRecord.Title);
201
+ });
202
+ ```
203
+
204
+ For updates, the record must include the default identifier column (e.g. `IDBook`). Meadow automatically adds a filter on this column to ensure only the intended record is updated.
205
+
206
+ ## Delete Tracking Control
207
+
208
+ By default, queries exclude records where `Deleted = 1`. To include deleted records in your results, disable delete tracking on the query:
209
+
210
+ ```javascript
211
+ var tmpQuery = tmpBookDAL.query
212
+ .setDisableDeleteTracking(true);
213
+
214
+ tmpBookDAL.doReads(tmpQuery,
215
+ function (pError, pQuery, pRecords)
216
+ {
217
+ // pRecords includes both active and soft-deleted records
218
+ });
219
+ ```
220
+
221
+ ## User Identity
222
+
223
+ The user identity attached to a query is used for auto-stamping `CreateIDUser`, `UpdateIDUser`, and `DeleteIDUser` columns.
224
+
225
+ ### Setting User Identity on the DAL
226
+
227
+ The preferred approach is to set the user ID on the Meadow instance, which applies to all queries:
228
+
229
+ ```javascript
230
+ tmpBookDAL.setIDUser(42);
231
+ ```
232
+
233
+ ### Setting User Identity Per Query
234
+
235
+ Override the user identity on an individual query:
236
+
237
+ ```javascript
238
+ var tmpQuery = tmpBookDAL.query;
239
+ tmpQuery.query.IDUser = 99;
240
+ ```
241
+
242
+ The per-query value takes precedence over the DAL-level value.
243
+
244
+ ### Disabling Auto-Stamps
245
+
246
+ To prevent automatic date and user stamps on a query, set the disable flags:
247
+
248
+ ```javascript
249
+ var tmpQuery = tmpBookDAL.query
250
+ .addRecord(
251
+ {
252
+ IDBook: 5,
253
+ Title: 'Manual Update'
254
+ });
255
+
256
+ // Prevent automatic UpdateDate stamping
257
+ tmpQuery.query.disableAutoDateStamp = true;
258
+
259
+ // Prevent automatic UpdatingIDUser stamping
260
+ tmpQuery.query.disableAutoUserStamp = true;
261
+
262
+ tmpBookDAL.doUpdate(tmpQuery,
263
+ function (pError, pUpdateQuery, pReadQuery, pRecord)
264
+ {
265
+ // UpdateDate and UpdatingIDUser were not changed
266
+ });
267
+ ```
268
+
269
+ See [Audit Tracking](audit-tracking.md) for more details on how auto-stamping works.