foxhound 2.0.12 → 2.0.15

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.
@@ -0,0 +1,82 @@
1
+ # Pagination
2
+
3
+ FoxHound provides dialect-aware pagination through the `setBegin()` and `setCap()` methods.
4
+
5
+ ## Basic Usage
6
+
7
+ ```javascript
8
+ // Get the first 20 records
9
+ tmpQuery
10
+ .setScope('Books')
11
+ .setCap(20)
12
+ .setDialect('MySQL')
13
+ .buildReadQuery();
14
+
15
+ // MySQL: SELECT ... LIMIT 20;
16
+ // MSSQL: SELECT ... OFFSET 0 ROWS FETCH NEXT 20 ROWS ONLY;
17
+ // SQLite: SELECT ... LIMIT 20;
18
+ ```
19
+
20
+ ## Offset Pagination
21
+
22
+ ```javascript
23
+ // Skip the first 40 records, then get 20
24
+ tmpQuery
25
+ .setScope('Books')
26
+ .setBegin(40)
27
+ .setCap(20)
28
+ .setDialect('MySQL')
29
+ .buildReadQuery();
30
+
31
+ // MySQL: SELECT ... LIMIT 40, 20;
32
+ // MSSQL: SELECT ... OFFSET 40 ROWS FETCH NEXT 20 ROWS ONLY;
33
+ // SQLite: SELECT ... LIMIT 20 OFFSET 40;
34
+ ```
35
+
36
+ ## Methods
37
+
38
+ ### setCap(pCapAmount)
39
+
40
+ Set the maximum number of records to return. Must be a non-negative integer.
41
+
42
+ ```javascript
43
+ tmpQuery.setCap(50); // Return at most 50 rows
44
+ tmpQuery.setCap(false); // Remove the cap (return all rows)
45
+ ```
46
+
47
+ ### setBegin(pBeginAmount)
48
+
49
+ Set the zero-based starting offset. Must be a non-negative integer.
50
+
51
+ ```javascript
52
+ tmpQuery.setBegin(100); // Start at the 101st record
53
+ tmpQuery.setBegin(false); // Remove the offset
54
+ ```
55
+
56
+ ## Page-Based Pagination Helper
57
+
58
+ FoxHound doesn't include a built-in page number helper, but it's easy to calculate:
59
+
60
+ ```javascript
61
+ var tmpPageSize = 20;
62
+ var tmpPageNumber = 3; // Zero-based
63
+
64
+ tmpQuery
65
+ .setBegin(tmpPageNumber * tmpPageSize)
66
+ .setCap(tmpPageSize);
67
+ ```
68
+
69
+ ## Dialect Syntax Comparison
70
+
71
+ | Dialect | Cap Only | Cap + Begin |
72
+ |---------|----------|-------------|
73
+ | **MySQL** | `LIMIT 20` | `LIMIT 40, 20` |
74
+ | **MSSQL** | `OFFSET 0 ROWS FETCH NEXT 20 ROWS ONLY` | `OFFSET 40 ROWS FETCH NEXT 20 ROWS ONLY` |
75
+ | **SQLite** | `LIMIT 20` | `LIMIT 20 OFFSET 40` |
76
+ | **ALASQL** | `LIMIT 20` | `LIMIT 20 FETCH 40` |
77
+
78
+ > **Note:** MSSQL's `OFFSET ... FETCH` syntax requires an `ORDER BY` clause. If you use pagination with MSSQL, be sure to add at least one sort column.
79
+
80
+ ## No Cap, No Pagination
81
+
82
+ If `setCap()` is not called (or is set to `false`), no pagination clause is generated and all matching rows are returned.
@@ -0,0 +1,115 @@
1
+ # Query Building Overview
2
+
3
+ FoxHound builds queries through a two-phase process: **configure** then **build**.
4
+
5
+ ## The Query Lifecycle
6
+
7
+ ```
8
+ Configure ──► Build ──► Access Results
9
+ ```
10
+
11
+ 1. **Configure** — set the scope, fields, filters, sorts, joins, pagination, records, and dialect
12
+ 2. **Build** — call one of the `build*Query()` methods to generate the SQL
13
+ 3. **Access** — read `query.body` for the SQL string and `query.parameters` for bound values
14
+
15
+ ## Creating a Query Instance
16
+
17
+ ```javascript
18
+ var libFoxHound = require('foxhound');
19
+ var tmpQuery = libFoxHound.new(_Fable);
20
+ ```
21
+
22
+ Or, when working through Meadow, the DAL provides a pre-configured query:
23
+
24
+ ```javascript
25
+ var tmpQuery = myMeadow.query;
26
+ ```
27
+
28
+ ## Setting the Scope
29
+
30
+ The scope is the primary table (or collection) the query targets:
31
+
32
+ ```javascript
33
+ tmpQuery.setScope('Books');
34
+ ```
35
+
36
+ ## Setting the Dialect
37
+
38
+ Before building, select which SQL dialect to produce:
39
+
40
+ ```javascript
41
+ tmpQuery.setDialect('MySQL'); // MySQL
42
+ tmpQuery.setDialect('MSSQL'); // Microsoft SQL Server
43
+ tmpQuery.setDialect('SQLite'); // SQLite
44
+ tmpQuery.setDialect('ALASQL'); // ALASQL (in-memory)
45
+ tmpQuery.setDialect('English'); // Human-readable (default)
46
+ ```
47
+
48
+ If no dialect is set, FoxHound defaults to `English`.
49
+
50
+ ## Build Methods
51
+
52
+ | Method | Operation | SQL Pattern |
53
+ |--------|-----------|-------------|
54
+ | `buildCreateQuery()` | Insert a record | `INSERT INTO ... VALUES (...)` |
55
+ | `buildReadQuery()` | Select records | `SELECT ... FROM ... WHERE ...` |
56
+ | `buildUpdateQuery()` | Modify a record | `UPDATE ... SET ... WHERE ...` |
57
+ | `buildDeleteQuery()` | Soft- or hard-delete | `UPDATE ... SET Deleted=1` or `DELETE FROM ...` |
58
+ | `buildUndeleteQuery()` | Restore soft-deleted | `UPDATE ... SET Deleted=0` |
59
+ | `buildCountQuery()` | Count matching rows | `SELECT COUNT(*) AS RowCount FROM ...` |
60
+
61
+ Every build method returns `this` for chaining.
62
+
63
+ ## Reading the Output
64
+
65
+ After building, the generated query is available on the `query` property:
66
+
67
+ ```javascript
68
+ tmpQuery.setScope('Books')
69
+ .setDialect('MySQL')
70
+ .buildReadQuery();
71
+
72
+ console.log(tmpQuery.query.body);
73
+ // => SELECT `Books`.* FROM `Books`;
74
+
75
+ console.log(tmpQuery.query.parameters);
76
+ // => {} (no filters, so no bound parameters)
77
+ ```
78
+
79
+ ## Resetting & Cloning
80
+
81
+ After a query is built, you can reset the parameters for reuse or clone the query to create a variant:
82
+
83
+ ```javascript
84
+ // Reset to default parameters
85
+ tmpQuery.resetParameters();
86
+
87
+ // Clone — copies scope, begin, cap, schema, filters, sorts, and dataElements
88
+ var tmpClone = tmpQuery.clone();
89
+ ```
90
+
91
+ ## Full Example
92
+
93
+ ```javascript
94
+ var libFable = require('fable');
95
+ var libFoxHound = require('foxhound');
96
+
97
+ var _Fable = new libFable({});
98
+ var tmpQuery = libFoxHound.new(_Fable);
99
+
100
+ tmpQuery
101
+ .setScope('Books')
102
+ .setDataElements(['Title', 'Author', 'PublishedYear'])
103
+ .addFilter('Genre', 'Science Fiction')
104
+ .addSort({Column: 'PublishedYear', Direction: 'Descending'})
105
+ .setCap(25)
106
+ .setDialect('MySQL')
107
+ .buildReadQuery();
108
+
109
+ console.log(tmpQuery.query.body);
110
+ // => SELECT `Title`, `Author`, `PublishedYear` FROM `Books`
111
+ // WHERE `Books`.`Genre` = :Genre_w0 ORDER BY PublishedYear DESC LIMIT 25;
112
+
113
+ console.log(tmpQuery.query.parameters);
114
+ // => { Genre_w0: 'Science Fiction' }
115
+ ```
@@ -0,0 +1,81 @@
1
+ # Count Query
2
+
3
+ The Count operation generates a `SELECT COUNT(*)` statement to efficiently count matching rows without returning the full result set.
4
+
5
+ ## Basic Usage
6
+
7
+ ```javascript
8
+ tmpQuery
9
+ .setScope('Books')
10
+ .setDialect('MySQL')
11
+ .buildCountQuery();
12
+
13
+ console.log(tmpQuery.query.body);
14
+ // => SELECT COUNT(*) AS RowCount FROM `Books`;
15
+ ```
16
+
17
+ ## With Filters
18
+
19
+ ```javascript
20
+ tmpQuery
21
+ .setScope('Books')
22
+ .addFilter('Genre', 'Science Fiction')
23
+ .setDialect('MySQL')
24
+ .buildCountQuery();
25
+
26
+ // => SELECT COUNT(*) AS RowCount FROM `Books`
27
+ // WHERE `Books`.`Genre` = :Genre_w0;
28
+ ```
29
+
30
+ ## DISTINCT Count
31
+
32
+ When `setDistinct(true)` is used, the count query counts only unique combinations of the selected fields:
33
+
34
+ ```javascript
35
+ tmpQuery
36
+ .setScope('Books')
37
+ .setDataElements(['Author'])
38
+ .setDistinct(true)
39
+ .setDialect('MySQL')
40
+ .buildCountQuery();
41
+
42
+ // => SELECT COUNT(DISTINCT `Author`) AS RowCount FROM `Books`;
43
+ ```
44
+
45
+ If no fields or schema are available when distinct is requested, FoxHound falls back to a standard `COUNT(*)`.
46
+
47
+ ## With Joins
48
+
49
+ Count queries support joins, so you can count records across related tables:
50
+
51
+ ```javascript
52
+ tmpQuery
53
+ .setScope('Books')
54
+ .addJoin('Authors', 'Authors.IDAuthor', 'Books.IDAuthor')
55
+ .addFilter('Authors.Country', 'USA')
56
+ .setDialect('MySQL')
57
+ .buildCountQuery();
58
+
59
+ // => SELECT COUNT(*) AS RowCount FROM `Books`
60
+ // INNER JOIN Authors ON Authors.IDAuthor = Books.IDAuthor
61
+ // WHERE Authors.Country = :Country_w0;
62
+ ```
63
+
64
+ ## Soft-Delete Awareness
65
+
66
+ Just like Read queries, Count queries automatically exclude soft-deleted records when a schema with a `Deleted` column is present.
67
+
68
+ ## Query Overrides
69
+
70
+ Count queries support query overrides with the same template variables as Read queries. The `OrderBy` and `Limit` variables are always empty strings for count operations.
71
+
72
+ ## Dialect Differences
73
+
74
+ | Dialect | Count Alias |
75
+ |---------|-------------|
76
+ | MySQL | `RowCount` |
77
+ | MSSQL | `Row_Count` |
78
+ | SQLite | `RowCount` |
79
+ | ALASQL | `RowCount` |
80
+
81
+ The alias differs for MSSQL because `RowCount` is a reserved keyword in some SQL Server configurations.
@@ -0,0 +1,66 @@
1
+ # Create Query
2
+
3
+ The Create operation generates an `INSERT INTO` statement from a record object.
4
+
5
+ ## Basic Usage
6
+
7
+ ```javascript
8
+ tmpQuery
9
+ .setScope('Books')
10
+ .addRecord({Title: 'Dune', Author: 'Frank Herbert', PublishedYear: 1965})
11
+ .setDialect('MySQL')
12
+ .buildCreateQuery();
13
+
14
+ console.log(tmpQuery.query.body);
15
+ // => INSERT INTO `Books` ( Title, Author, PublishedYear)
16
+ // VALUES ( :Title_0, :Author_1, :PublishedYear_2);
17
+
18
+ console.log(tmpQuery.query.parameters);
19
+ // => { Title_0: 'Dune', Author_1: 'Frank Herbert', PublishedYear_2: 1965 }
20
+ ```
21
+
22
+ ## Schema-Aware Behavior
23
+
24
+ When a schema is attached to the query, FoxHound automatically handles special column types during INSERT:
25
+
26
+ | Schema Type | Behavior |
27
+ |------------|----------|
28
+ | `AutoIdentity` | Inserts `NULL` (lets the database assign the ID) |
29
+ | `AutoGUID` | Generates a UUID via Fable, unless the record already has a valid GUID |
30
+ | `CreateDate` | Inserts the current timestamp (`NOW(3)` for MySQL, `GETUTCDATE()` for MSSQL) |
31
+ | `CreateIDUser` | Inserts the user ID from `setIDUser()` |
32
+ | `UpdateDate` | Inserts the current timestamp |
33
+ | `UpdateIDUser` | Inserts the user ID |
34
+ | `DeleteDate` | Skipped on insert (when delete tracking is enabled) |
35
+ | `DeleteIDUser` | Skipped on insert (when delete tracking is enabled) |
36
+ | `Deleted` | Included normally (typically defaults to `0`) |
37
+
38
+ ## Setting the User
39
+
40
+ To stamp which user created the record:
41
+
42
+ ```javascript
43
+ tmpQuery.setIDUser(42);
44
+ ```
45
+
46
+ This value is used for any `CreateIDUser`, `UpdateIDUser`, or `DeleteIDUser` schema columns.
47
+
48
+ ## Disabling Auto-Management
49
+
50
+ You can disable automatic column management when you need full control:
51
+
52
+ ```javascript
53
+ tmpQuery.setDisableAutoIdentity(true); // Include identity column value as-is
54
+ tmpQuery.setDisableAutoDateStamp(true); // Don't auto-generate timestamps
55
+ tmpQuery.setDisableAutoUserStamp(true); // Don't auto-stamp user IDs
56
+ tmpQuery.setDisableDeleteTracking(true); // Include delete columns on insert
57
+ ```
58
+
59
+ ## Dialect Differences
60
+
61
+ The INSERT syntax is largely the same across dialects, with a few differences:
62
+
63
+ - **MySQL** — uses backtick-quoted identifiers and `:name` parameters
64
+ - **MSSQL** — uses bracket-quoted identifiers, `@name` parameters, and skips the AutoIdentity column entirely (rather than inserting NULL)
65
+ - **SQLite** — uses backtick-quoted identifiers and `:name` parameters
66
+ - **ALASQL** — same as SQLite
@@ -0,0 +1,82 @@
1
+ # Delete Query
2
+
3
+ FoxHound supports two modes of deletion: **soft delete** (the default when a schema has a `Deleted` column) and **hard delete** (a true `DELETE FROM` statement).
4
+
5
+ ## Soft Delete (Default)
6
+
7
+ When a schema with a `Deleted` column type is present, the delete operation generates an UPDATE that sets the deleted flag:
8
+
9
+ ```javascript
10
+ tmpQuery
11
+ .setScope('Books')
12
+ .addFilter('IDBook', 42)
13
+ .setIDUser(5)
14
+ .setDialect('MySQL')
15
+ .buildDeleteQuery();
16
+
17
+ // => UPDATE `Books` SET Deleted = 1, DeleteDate = NOW(3),
18
+ // UpdateDate = NOW(3), DeleteIDUser = :DeleteIDUser_3
19
+ // WHERE `Books`.`IDBook` = :IDBook_w0;
20
+ ```
21
+
22
+ The soft delete automatically manages these schema columns:
23
+
24
+ | Schema Type | Behavior on Delete |
25
+ |------------|-------------------|
26
+ | `Deleted` | Set to `1` |
27
+ | `DeleteDate` | Set to current timestamp |
28
+ | `UpdateDate` | Set to current timestamp (delete is an update) |
29
+ | `DeleteIDUser` | Set to the value from `setIDUser()` |
30
+
31
+ ## Hard Delete
32
+
33
+ When there is no `Deleted` column in the schema, or when delete tracking is disabled, FoxHound generates a true DELETE:
34
+
35
+ ```javascript
36
+ tmpQuery
37
+ .setScope('TempRecords')
38
+ .addFilter('IDTemp', 99)
39
+ .setDisableDeleteTracking(true)
40
+ .setDialect('MySQL')
41
+ .buildDeleteQuery();
42
+
43
+ // => DELETE FROM `TempRecords` WHERE `TempRecords`.`IDTemp` = :IDTemp_w0;
44
+ ```
45
+
46
+ ## Undelete
47
+
48
+ FoxHound also supports restoring soft-deleted records:
49
+
50
+ ```javascript
51
+ tmpQuery
52
+ .setScope('Books')
53
+ .addFilter('IDBook', 42)
54
+ .setIDUser(5)
55
+ .setDialect('MySQL')
56
+ .buildUndeleteQuery();
57
+
58
+ // => UPDATE `Books` SET Deleted = 0, UpdateDate = NOW(3),
59
+ // UpdateIDUser = :UpdateIDUser_1
60
+ // WHERE `Books`.`IDBook` = :IDBook_w0;
61
+ ```
62
+
63
+ The undelete operation sets:
64
+
65
+ | Schema Type | Behavior on Undelete |
66
+ |------------|---------------------|
67
+ | `Deleted` | Set to `0` |
68
+ | `UpdateDate` | Set to current timestamp |
69
+ | `UpdateIDUser` | Set to the value from `setIDUser()` |
70
+
71
+ If the schema has no `Deleted` column, `buildUndeleteQuery()` produces a no-op (`SELECT NULL;`).
72
+
73
+ ## Dialect Differences
74
+
75
+ The soft-delete and undelete operations use the same timestamp functions as other operations:
76
+
77
+ | Dialect | Timestamp Function |
78
+ |---------|-------------------|
79
+ | MySQL | `NOW(3)` |
80
+ | MSSQL | `GETUTCDATE()` |
81
+ | SQLite | `NOW()` (replaced by the provider with `datetime('now')`) |
82
+ | ALASQL | `NOW()` |
@@ -0,0 +1,138 @@
1
+ # Read Query
2
+
3
+ The Read operation generates a `SELECT` statement with support for field selection, filtering, sorting, joins, pagination, and query overrides.
4
+
5
+ ## Basic Usage
6
+
7
+ ```javascript
8
+ tmpQuery
9
+ .setScope('Books')
10
+ .setDialect('MySQL')
11
+ .buildReadQuery();
12
+
13
+ console.log(tmpQuery.query.body);
14
+ // => SELECT `Books`.* FROM `Books`;
15
+ ```
16
+
17
+ ## Selecting Specific Columns
18
+
19
+ ```javascript
20
+ tmpQuery
21
+ .setScope('Books')
22
+ .setDataElements(['Title', 'Author', 'PublishedYear'])
23
+ .setDialect('MySQL')
24
+ .buildReadQuery();
25
+
26
+ // => SELECT `Title`, `Author`, `PublishedYear` FROM `Books`;
27
+ ```
28
+
29
+ You can also use column aliases with array pairs:
30
+
31
+ ```javascript
32
+ tmpQuery.setDataElements([
33
+ ['Books.Title', 'BookTitle'],
34
+ ['Books.Author', 'AuthorName']
35
+ ]);
36
+
37
+ // => SELECT `Books`.`Title` AS `BookTitle`, `Books`.`Author` AS `AuthorName` FROM `Books`;
38
+ ```
39
+
40
+ ## DISTINCT Results
41
+
42
+ ```javascript
43
+ tmpQuery
44
+ .setScope('Books')
45
+ .setDataElements(['Genre'])
46
+ .setDistinct(true)
47
+ .setDialect('MySQL')
48
+ .buildReadQuery();
49
+
50
+ // => SELECT DISTINCT `Genre` FROM `Books`;
51
+ ```
52
+
53
+ ## With Filters
54
+
55
+ ```javascript
56
+ tmpQuery
57
+ .setScope('Books')
58
+ .addFilter('Genre', 'Science Fiction')
59
+ .addFilter('PublishedYear', 2000, '>')
60
+ .setDialect('MySQL')
61
+ .buildReadQuery();
62
+
63
+ // => SELECT `Books`.* FROM `Books`
64
+ // WHERE `Books`.`Genre` = :Genre_w0
65
+ // AND `Books`.`PublishedYear` > :PublishedYear_w1;
66
+ ```
67
+
68
+ See the [Filters](filters.md) page for full filter documentation.
69
+
70
+ ## With Sorting
71
+
72
+ ```javascript
73
+ tmpQuery
74
+ .setScope('Books')
75
+ .addSort({Column: 'PublishedYear', Direction: 'Descending'})
76
+ .setDialect('MySQL')
77
+ .buildReadQuery();
78
+
79
+ // => SELECT `Books`.* FROM `Books` ORDER BY PublishedYear DESC;
80
+ ```
81
+
82
+ See the [Sorting](sorting.md) page for full sort documentation.
83
+
84
+ ## With Joins
85
+
86
+ ```javascript
87
+ tmpQuery
88
+ .setScope('Books')
89
+ .addJoin('Authors', 'Authors.IDAuthor', 'Books.IDAuthor')
90
+ .setDialect('MySQL')
91
+ .buildReadQuery();
92
+
93
+ // => SELECT `Books`.* FROM `Books`
94
+ // INNER JOIN Authors ON Authors.IDAuthor = Books.IDAuthor;
95
+ ```
96
+
97
+ See the [Joins](joins.md) page for full join documentation.
98
+
99
+ ## With Pagination
100
+
101
+ ```javascript
102
+ tmpQuery
103
+ .setScope('Books')
104
+ .setBegin(20)
105
+ .setCap(10)
106
+ .setDialect('MySQL')
107
+ .buildReadQuery();
108
+
109
+ // => SELECT `Books`.* FROM `Books` LIMIT 20, 10;
110
+ ```
111
+
112
+ See the [Pagination](pagination.md) page for dialect-specific pagination details.
113
+
114
+ ## With Index Hints
115
+
116
+ MySQL and MSSQL support index hints:
117
+
118
+ ```javascript
119
+ tmpQuery.indexHints = ['idx_genre', 'idx_year'];
120
+
121
+ // MySQL: SELECT ... FROM `Books` USE INDEX (idx_genre,idx_year) ...
122
+ // MSSQL: SELECT ... FROM [Books] WITH(INDEX(idx_genre,idx_year)) ...
123
+ ```
124
+
125
+ ## Query Overrides
126
+
127
+ You can supply a custom query template while still benefiting from automatic parameter binding:
128
+
129
+ ```javascript
130
+ tmpQuery.parameters.queryOverride =
131
+ 'SELECT <%= FieldList %> FROM <%= TableName %> <%= Where %> <%= OrderBy %> <%= Limit %>';
132
+ ```
133
+
134
+ See [Query Overrides](query-overrides.md) for details on available template variables.
135
+
136
+ ## Soft-Delete Awareness
137
+
138
+ When a schema with a `Deleted` column is present and delete tracking is enabled (the default), Read queries automatically add a `WHERE Deleted = 0` filter so that soft-deleted records are excluded.
@@ -0,0 +1,56 @@
1
+ # Update Query
2
+
3
+ The Update operation generates an `UPDATE ... SET ... WHERE ...` statement from a record object and filter criteria.
4
+
5
+ ## Basic Usage
6
+
7
+ ```javascript
8
+ tmpQuery
9
+ .setScope('Books')
10
+ .addFilter('IDBook', 42)
11
+ .addRecord({Title: 'Dune Messiah', PublishedYear: 1969})
12
+ .setIDUser(5)
13
+ .setDialect('MySQL')
14
+ .buildUpdateQuery();
15
+
16
+ console.log(tmpQuery.query.body);
17
+ // => UPDATE `Books` SET Title = :Title_0, PublishedYear = :PublishedYear_1
18
+ // WHERE `Books`.`IDBook` = :IDBook_w0;
19
+
20
+ console.log(tmpQuery.query.parameters);
21
+ // => { Title_0: 'Dune Messiah', PublishedYear_1: 1969, IDBook_w0: 42 }
22
+ ```
23
+
24
+ ## Schema-Aware Behavior
25
+
26
+ When a schema is present, FoxHound manages certain columns automatically:
27
+
28
+ | Schema Type | Behavior on Update |
29
+ |------------|-------------------|
30
+ | `AutoIdentity` | **Skipped** — never updated |
31
+ | `CreateDate` | **Skipped** — set only on insert |
32
+ | `CreateIDUser` | **Skipped** — set only on insert |
33
+ | `UpdateDate` | Set to current timestamp automatically |
34
+ | `UpdateIDUser` | Set to the value from `setIDUser()` |
35
+ | `DeleteDate` | **Skipped** — managed by delete operations |
36
+ | `DeleteIDUser` | **Skipped** — managed by delete operations |
37
+
38
+ ## Disabling Auto-Management
39
+
40
+ ```javascript
41
+ tmpQuery.setDisableAutoDateStamp(true); // Don't auto-set UpdateDate
42
+ tmpQuery.setDisableAutoUserStamp(true); // Don't auto-set UpdateIDUser
43
+ ```
44
+
45
+ ## Important Notes
46
+
47
+ - The record passed to `addRecord()` should contain only the columns you want to change — FoxHound generates SET clauses for each key in the record object
48
+ - Always include a filter (usually on the primary key) to avoid updating all rows
49
+ - If the record object is empty or no records have been added, `buildUpdateQuery()` returns `false` for the query body
50
+
51
+ ## Dialect Differences
52
+
53
+ - **MySQL** — backtick-quoted identifiers, `:name` parameters
54
+ - **MSSQL** — bracket-quoted identifiers, `@name` parameters; special handling for `UpdateDate` with `disableAutoDateStamp`
55
+ - **SQLite** — backtick-quoted identifiers, `:name` parameters
56
+ - **ALASQL** — same as SQLite