"outDir"
defines where your zapatos
folder will be created, relative to the project root. If not specified, it defaults to the project root, i.e. "."
.
@@ -534,14 +534,16 @@
}
Wildcard table options have lower precedence than named table options. The default values, should you want to restore them for named tables, are "insert": "auto"
and "update": "auto"
. Note that "*"
is only supported as the whole key — you can’t use a *
to match parts of schema or table names — and isn’t supported for column names.
-"schemaJSDoc"
is a boolean that turns JSDoc comments for each column in the generated schema on (the default) or off. JSDoc comments enable per-column VS Code pop-ups giving details of Postgres data type, default value and so on. They also make the schema file longer and less readable.
+-
+
"schemaJSDoc"
is a boolean that turns JSDoc comments for each column in the generated schema on (the default) or off. JSDoc comments enable per-column VS Code pop-ups giving details of Postgres data type, default value and so on. They also make the schema file longer and less readable.
+
+-
+
customJSONParsingForLargeNumbers
changes the types for bigint
/int8
and numeric
/decimal
values to reflect the use of custom JSON parsing to maintain precision.
+
In summary, the expected structure is defined like so:
-export interface RequiredConfig {
+export interface OptionalConfig {
db: pg.ClientConfig;
-}
-
-export interface OptionalConfig {
outDir: string;
outExt: string;
schemas: SchemaRules;
@@ -551,6 +553,7 @@
customTypesTransform: 'PgMy_type' | 'my_type' | 'PgMyType' | ((s: string) => string);
columnOptions: ColumnOptions;
schemaJSDoc: boolean;
+ customJSONParsingForLargeNumbers: boolean;
}
interface SchemaRules {
@@ -567,9 +570,7 @@
update?: 'auto' | 'excluded';
};
};
-}
-
-export type Config = RequiredConfig & Partial<OptionalConfig>;
+}
Environment variables
All values in zapatosconfig.json
can have environment variables (Node’s process.env.SOMETHING
) interpolated via handlebars-style doubly-curly-brackets {{variables}}
.
This is likely most useful for the database connection details. For example, on Heroku you might configure your database as:
@@ -624,7 +625,7 @@ Import it
import type * as c from 'zapatos/custom';
The paths zapatos/db
and zapatos/generate
point to real folders in node_modules
. Although they look like file paths, zapatos/schema
and zapatos/custom
are actually the names of ambient modules declared in the generated files in your source tree: zapatos/schema.d.ts
and zapatos/custom/*.d.ts
.
User guide
-
+
sql
tagged template strings
Arbitrary queries are written using the tagged template function sql
, which returns SQLFragment
class instances.
The sql
function is generic, having two type variables. For example:
@@ -679,10 +680,10 @@ sql
tagged template stringsSELECT random()
[
{
- "random": 0.7165549267636955
+ "random": 0.3749941670395458
}
]
-0.7165549267636955
+0.3749941670395458
Interpolations
is never
because nothing needs to be interpolated in this query, and the RunResult
type says that the query will return one row comprising one numeric column, named random
. The random
TypeScript variable we initialize will of course be typed as a number
.
If you’re happy to have your types tied down a little less tightly, it also works to wholly omit the type variables in this particular query, falling back on their defaults:
@@ -822,7 +823,7 @@ Whereable
"id": 1000,
"authorId": 1000,
"title": "Northern Lights",
- "createdAt": "2023-11-16T11:27:47.848Z"
+ "createdAt": "2023-11-24T14:16:32.554Z"
}
]
@@ -848,7 +849,7 @@ Whereable
"id": 1000,
"authorId": 1000,
"title": "Northern Lights",
- "createdAt": "2023-11-16T11:27:47.848Z"
+ "createdAt": "2023-11-24T14:16:32.554Z"
}
]
@@ -874,7 +875,7 @@ Whereable
"id": 1000,
"authorId": 1000,
"title": "Northern Lights",
- "createdAt": "2023-11-16T11:27:47.848Z"
+ "createdAt": "2023-11-24T14:16:32.554Z"
}
]
@@ -935,10 +936,10 @@ parent(columnName?: string):
SQLFragment
SQLFragment<RunResult>
class instances are what is returned by the sql
tagged template function — you’re unlikely ever to contruct them directly with new
. They take on the RunResult
type variable from the sql
template function that constructs them.
You can interpolate them into other sql
tagged template strings, or call/access the following properties on them:
-
+
prepared(name: string): this
The prepared
function causes a name
property to be added to the compiled SQL query object that’s passed to pg
, and this instructs Postgres to treat it as a prepared statement. You can specify a prepared statement name as the function’s argument, or let it default to "_zapatos_prepared_N"
(where N is a sequence number). This name appears in the Postgres logs.
-
+
async run(queryable: Queryable, force = false): Promise<RunResult>
The run
function compiles, executes, and returns the transformed result of the query represented by this SQLFragment
. The awaited
return value is typed according to the SQLFragment
’s RunResult
type variable.
Taking that one step at a time:
@@ -955,7 +956,7 @@ async
Examples of the run
function are scattered throughout this documentation.
The force
parameter is relevant only if this SQLFragment
has been marked as a no-op: at present, Zapatos does this automatically if you pass an empty array to insert
or upsert
. By default, the database will not be disturbed in such cases, but you can force a no-op query to actually be run against the database — perhaps for logging or triggering reasons — by setting force
to true
.
-
+
compile(): SQLQuery
The compile
function recursively transforms this SQLFragment
and its interpolated values into a SQLQuery
object ({ text: string; values: any[]; }
) that can be passed straight to the pg
module. It is called without arguments (the arguments it can take are for internal use).
For example:
@@ -973,7 +974,7 @@ compile(): SQLQuery
}
You may never need this function. Use it if and when you want to see the SQL that would be executed by the run
function, without in fact executing it.
-
+
When you call run
, the function stored in this property is applied to the QueryResult
object returned by pg
, in order to produce the result that the run
function ultimately returns.
By default, the QueryResult
’s rows
property (which is an array) is returned: that is, the default implementation is just qr => qr.rows
. However, the shortcut functions supply their own runResultTransform
implementations in order to match their declared RunResult
types.
@@ -989,7 +990,7 @@ Note that the RunResult
type variable on the sql
template function (in this case, Date
) must reflect the type of the transformed result, not what comes straight back from pg
(which in this case is roughly { rows: [{ now: Date }] }
).
If a SQLFragment
does not have run
called on it directly — for example, if it is instead interpolated into another SQLFragment
, or given as the value of the lateral
option to the select
shortcut — then the runResultTransform
function is never applied.
@@ -1015,7 +1016,7 @@ Manual joins using Postgres
"id": 1000,
"authorId": 1000,
"title": "Northern Lights",
- "createdAt": "2023-11-16T11:27:47.848Z",
+ "createdAt": "2023-11-24T14:16:32.554Z",
"author": {
"id": 1000,
"name": "Philip Pullman",
@@ -1026,7 +1027,7 @@ Manual joins using Postgres
"id": 1001,
"authorId": 1000,
"title": "The Subtle Knife",
- "createdAt": "2023-11-16T11:27:47.849Z",
+ "createdAt": "2023-11-24T14:16:32.555Z",
"author": {
"id": 1000,
"name": "Philip Pullman",
@@ -1037,7 +1038,7 @@ Manual joins using Postgres
"id": 1002,
"authorId": 1000,
"title": "The Amber Spyglass",
- "createdAt": "2023-11-16T11:27:47.849Z",
+ "createdAt": "2023-11-24T14:16:32.556Z",
"author": {
"id": 1000,
"name": "Philip Pullman",
@@ -1048,7 +1049,7 @@ Manual joins using Postgres
"id": 1003,
"authorId": 1001,
"title": "The Curious Incident of the Dog in the Night-Time",
- "createdAt": "2023-11-16T11:27:47.854Z",
+ "createdAt": "2023-11-24T14:16:32.560Z",
"author": {
"id": 1001,
"name": "Mark Haddon",
@@ -1059,7 +1060,7 @@ Manual joins using Postgres
"id": 1004,
"authorId": 1002,
"title": "Holes",
- "createdAt": "2023-11-16T11:27:47.856Z",
+ "createdAt": "2023-11-24T14:16:32.561Z",
"author": {
"id": 1002,
"name": "Louis Sachar",
@@ -1095,19 +1096,19 @@ Manual joins using Postgres
"id": 1000,
"title": "Northern Lights",
"authorId": 1000,
- "createdAt": "2023-11-16T11:27:47.847734+00:00"
+ "createdAt": "2023-11-24T14:16:32.554126+00:00"
},
{
"id": 1001,
"title": "The Subtle Knife",
"authorId": 1000,
- "createdAt": "2023-11-16T11:27:47.848612+00:00"
+ "createdAt": "2023-11-24T14:16:32.555064+00:00"
},
{
"id": 1002,
"title": "The Amber Spyglass",
"authorId": 1000,
- "createdAt": "2023-11-16T11:27:47.849159+00:00"
+ "createdAt": "2023-11-24T14:16:32.555565+00:00"
}
]
},
@@ -1120,7 +1121,7 @@ Manual joins using Postgres
"id": 1003,
"title": "The Curious Incident of the Dog in the Night-Time",
"authorId": 1001,
- "createdAt": "2023-11-16T11:27:47.854358+00:00"
+ "createdAt": "2023-11-24T14:16:32.560168+00:00"
}
]
},
@@ -1133,7 +1134,7 @@ Manual joins using Postgres
"id": 1004,
"title": "Holes",
"authorId": 1002,
- "createdAt": "2023-11-16T11:27:47.855953+00:00"
+ "createdAt": "2023-11-24T14:16:32.561336+00:00"
}
]
}
@@ -1171,19 +1172,19 @@ Manual joins using Postgres
"id": 1000,
"authorId": 1000,
"title": "Northern Lights",
- "createdAt": "2023-11-16T11:27:47.847734+00:00"
+ "createdAt": "2023-11-24T14:16:32.554126+00:00"
},
{
"id": 1001,
"authorId": 1000,
"title": "The Subtle Knife",
- "createdAt": "2023-11-16T11:27:47.848612+00:00"
+ "createdAt": "2023-11-24T14:16:32.555064+00:00"
},
{
"id": 1002,
"authorId": 1000,
"title": "The Amber Spyglass",
- "createdAt": "2023-11-16T11:27:47.849159+00:00"
+ "createdAt": "2023-11-24T14:16:32.555565+00:00"
}
]
},
@@ -1196,7 +1197,7 @@ Manual joins using Postgres
"id": 1003,
"authorId": 1001,
"title": "The Curious Incident of the Dog in the Night-Time",
- "createdAt": "2023-11-16T11:27:47.854358+00:00"
+ "createdAt": "2023-11-24T14:16:32.560168+00:00"
}
]
},
@@ -1209,7 +1210,7 @@ Manual joins using Postgres
"id": 1004,
"authorId": 1002,
"title": "Holes",
- "createdAt": "2023-11-16T11:27:47.855953+00:00"
+ "createdAt": "2023-11-24T14:16:32.561336+00:00"
}
]
},
@@ -1313,13 +1314,13 @@ insert
"id": 1,
"title": "A Brief History of Time",
"authorId": 5,
- "createdAt": "2023-11-16T11:27:59.270781+00:00"
+ "createdAt": "2023-11-24T14:16:44.656638+00:00"
},
{
"id": 2,
"title": "My Brief History",
"authorId": 5,
- "createdAt": "2023-11-16T11:27:59.270781+00:00"
+ "createdAt": "2023-11-24T14:16:44.656638+00:00"
}
]
INSERT INTO "tags" ("bookId", "tag")
@@ -1414,7 +1415,7 @@ update
[
{
"email": "me@privacy.net",
- "lastFailedLogin": "2023-11-16T11:28:00.438215+00:00",
+ "lastFailedLogin": "2023-11-24T14:16:45.84291+00:00",
"consecutiveFailedLogins": 1
}
]
@@ -1562,7 +1563,7 @@ INSERT ... ON CONFLICT ... DO NOT
{
"code": "XYE953ZVU767",
"$action": "INSERT",
- "redeemedAt": "2023-11-16T11:28:01.184917+00:00"
+ "redeemedAt": "2023-11-24T14:16:46.716498+00:00"
}
INSERT INTO "usedVoucherCodes" ("code")
VALUES ($1)
@@ -1694,43 +1695,43 @@ select
, select
"id": 1000,
"title": "Northern Lights",
"authorId": 1000,
- "createdAt": "2023-11-16T11:27:47.847734+00:00"
+ "createdAt": "2023-11-24T14:16:32.554126+00:00"
},
{
"id": 1001,
"title": "The Subtle Knife",
"authorId": 1000,
- "createdAt": "2023-11-16T11:27:47.848612+00:00"
+ "createdAt": "2023-11-24T14:16:32.555064+00:00"
},
{
"id": 1002,
"title": "The Amber Spyglass",
"authorId": 1000,
- "createdAt": "2023-11-16T11:27:47.849159+00:00"
+ "createdAt": "2023-11-24T14:16:32.555565+00:00"
},
{
"id": 1003,
"title": "The Curious Incident of the Dog in the Night-Time",
"authorId": 1001,
- "createdAt": "2023-11-16T11:27:47.854358+00:00"
+ "createdAt": "2023-11-24T14:16:32.560168+00:00"
},
{
"id": 1,
"title": "A Brief History of Time",
"authorId": 5,
- "createdAt": "2023-11-16T11:27:59.270781+00:00"
+ "createdAt": "2023-11-24T14:16:44.656638+00:00"
},
{
"id": 2,
"title": "My Brief History",
"authorId": 5,
- "createdAt": "2023-11-16T11:27:59.270781+00:00"
+ "createdAt": "2023-11-24T14:16:44.656638+00:00"
},
{
"id": 3,
"title": "The Universe in a Nutshell",
"authorId": 5,
- "createdAt": "2023-11-16T11:27:59.2759+00:00"
+ "createdAt": "2023-11-24T14:16:44.661499+00:00"
}
]
@@ -1748,19 +1749,19 @@ select
, select
"id": 1000,
"title": "Northern Lights",
"authorId": 1000,
- "createdAt": "2023-11-16T11:27:47.847734+00:00"
+ "createdAt": "2023-11-24T14:16:32.554126+00:00"
},
{
"id": 1001,
"title": "The Subtle Knife",
"authorId": 1000,
- "createdAt": "2023-11-16T11:27:47.848612+00:00"
+ "createdAt": "2023-11-24T14:16:32.555064+00:00"
},
{
"id": 1002,
"title": "The Amber Spyglass",
"authorId": 1000,
- "createdAt": "2023-11-16T11:27:47.849159+00:00"
+ "createdAt": "2023-11-24T14:16:32.555565+00:00"
}
]
@@ -1814,7 +1815,7 @@ select
, select
"id": 1003,
"title": "The Curious Incident of the Dog in the Night-Time",
"authorId": 1001,
- "createdAt": "2023-11-16T11:27:47.854358+00:00"
+ "createdAt": "2023-11-24T14:16:32.560168+00:00"
}
]
@@ -1837,7 +1838,7 @@ select
, select
"id": 1003,
"title": "The Curious Incident of the Dog in the Night-Time",
"authorId": 1001,
- "createdAt": "2023-11-16T11:27:47.854358+00:00"
+ "createdAt": "2023-11-24T14:16:32.560168+00:00"
}
]
@@ -1859,7 +1860,7 @@ select
, select
"id": 1,
"title": "A Brief History of Time",
"authorId": 5,
- "createdAt": "2023-11-16T11:27:59.270781+00:00"
+ "createdAt": "2023-11-24T14:16:44.656638+00:00"
}
]
@@ -1927,7 +1928,7 @@ order
, limit
and "id": 1,
"title": "A Brief History of Time",
"authorId": 5,
- "createdAt": "2023-11-16T11:27:59.270781+00:00"
+ "createdAt": "2023-11-24T14:16:44.656638+00:00"
}
]
@@ -1947,7 +1948,7 @@ order
, limit
and "id": 1,
"title": "A Brief History of Time",
"authorId": 5,
- "createdAt": "2023-11-16T11:27:59.270781+00:00"
+ "createdAt": "2023-11-24T14:16:44.656638+00:00"
}
The { limit: 1 }
option is now applied automatically. And the return type following await
needs no destructuring and is now, correctly, JSONSelectable | undefined
.
@@ -2000,7 +2001,7 @@ lateral
property maps
"isLiving": true
},
"authorId": 1000,
- "createdAt": "2023-11-16T11:27:47.847734+00:00"
+ "createdAt": "2023-11-24T14:16:32.554126+00:00"
},
{
"id": 1001,
@@ -2021,7 +2022,7 @@ lateral
property maps
"isLiving": true
},
"authorId": 1000,
- "createdAt": "2023-11-16T11:27:47.848612+00:00"
+ "createdAt": "2023-11-24T14:16:32.555064+00:00"
},
{
"id": 1002,
@@ -2042,7 +2043,7 @@ lateral
property maps
"isLiving": true
},
"authorId": 1000,
- "createdAt": "2023-11-16T11:27:47.849159+00:00"
+ "createdAt": "2023-11-24T14:16:32.555565+00:00"
},
{
"id": 1003,
@@ -2059,7 +2060,7 @@ lateral
property maps
"isLiving": true
},
"authorId": 1001,
- "createdAt": "2023-11-16T11:27:47.854358+00:00"
+ "createdAt": "2023-11-24T14:16:32.560168+00:00"
},
{
"id": 1,
@@ -2076,7 +2077,7 @@ lateral
property maps
"isLiving": false
},
"authorId": 5,
- "createdAt": "2023-11-16T11:27:59.270781+00:00"
+ "createdAt": "2023-11-24T14:16:44.656638+00:00"
},
{
"id": 2,
@@ -2097,7 +2098,7 @@ lateral
property maps
"isLiving": false
},
"authorId": 5,
- "createdAt": "2023-11-16T11:27:59.270781+00:00"
+ "createdAt": "2023-11-24T14:16:44.656638+00:00"
},
{
"id": 3,
@@ -2109,7 +2110,7 @@ lateral
property maps
"isLiving": false
},
"authorId": 5,
- "createdAt": "2023-11-16T11:27:59.2759+00:00"
+ "createdAt": "2023-11-24T14:16:44.661499+00:00"
}
]
@@ -2160,7 +2161,7 @@ lateral
property maps
],
"title": "Northern Lights",
"authorId": 1000,
- "createdAt": "2023-11-16T11:27:47.847734+00:00"
+ "createdAt": "2023-11-24T14:16:32.554126+00:00"
},
{
"id": 1001,
@@ -2174,7 +2175,7 @@ lateral
property maps
],
"title": "The Subtle Knife",
"authorId": 1000,
- "createdAt": "2023-11-16T11:27:47.848612+00:00"
+ "createdAt": "2023-11-24T14:16:32.555064+00:00"
},
{
"id": 1002,
@@ -2188,7 +2189,7 @@ lateral
property maps
],
"title": "The Amber Spyglass",
"authorId": 1000,
- "createdAt": "2023-11-16T11:27:47.849159+00:00"
+ "createdAt": "2023-11-24T14:16:32.555565+00:00"
}
],
"isLiving": true
@@ -2206,7 +2207,7 @@ lateral
property maps
],
"title": "The Curious Incident of the Dog in the Night-Time",
"authorId": 1001,
- "createdAt": "2023-11-16T11:27:47.854358+00:00"
+ "createdAt": "2023-11-24T14:16:32.560168+00:00"
}
],
"isLiving": true
@@ -2254,7 +2255,7 @@ lateral
property maps
],
"title": "A Brief History of Time",
"authorId": 5,
- "createdAt": "2023-11-16T11:27:59.270781+00:00"
+ "createdAt": "2023-11-24T14:16:44.656638+00:00"
},
{
"id": 2,
@@ -2268,14 +2269,14 @@ lateral
property maps
],
"title": "My Brief History",
"authorId": 5,
- "createdAt": "2023-11-16T11:27:59.270781+00:00"
+ "createdAt": "2023-11-24T14:16:44.656638+00:00"
},
{
"id": 3,
"tags": [],
"title": "The Universe in a Nutshell",
"authorId": 5,
- "createdAt": "2023-11-16T11:27:59.2759+00:00"
+ "createdAt": "2023-11-24T14:16:44.661499+00:00"
}
],
"isLiving": false
@@ -2749,46 +2750,46 @@ distinct
FROM "books") AS "sq_books"
[
{
- "id": 2,
- "title": "My Brief History",
+ "id": 3,
+ "title": "The Universe in a Nutshell",
"authorId": 5,
- "createdAt": "2023-11-16T11:27:59.270781+00:00"
+ "createdAt": "2023-11-24T14:16:44.661499+00:00"
},
{
"id": 1000,
"title": "Northern Lights",
"authorId": 1000,
- "createdAt": "2023-11-16T11:27:47.847734+00:00"
+ "createdAt": "2023-11-24T14:16:32.554126+00:00"
},
{
- "id": 1,
- "title": "A Brief History of Time",
+ "id": 2,
+ "title": "My Brief History",
"authorId": 5,
- "createdAt": "2023-11-16T11:27:59.270781+00:00"
+ "createdAt": "2023-11-24T14:16:44.656638+00:00"
},
{
- "id": 1002,
- "title": "The Amber Spyglass",
- "authorId": 1000,
- "createdAt": "2023-11-16T11:27:47.849159+00:00"
- },
- {
- "id": 3,
- "title": "The Universe in a Nutshell",
- "authorId": 5,
- "createdAt": "2023-11-16T11:27:59.2759+00:00"
+ "id": 1003,
+ "title": "The Curious Incident of the Dog in the Night-Time",
+ "authorId": 1001,
+ "createdAt": "2023-11-24T14:16:32.560168+00:00"
},
{
"id": 1001,
"title": "The Subtle Knife",
"authorId": 1000,
- "createdAt": "2023-11-16T11:27:47.848612+00:00"
+ "createdAt": "2023-11-24T14:16:32.555064+00:00"
},
{
- "id": 1003,
- "title": "The Curious Incident of the Dog in the Night-Time",
- "authorId": 1001,
- "createdAt": "2023-11-16T11:27:47.854358+00:00"
+ "id": 1002,
+ "title": "The Amber Spyglass",
+ "authorId": 1000,
+ "createdAt": "2023-11-24T14:16:32.555565+00:00"
+ },
+ {
+ "id": 1,
+ "title": "A Brief History of Time",
+ "authorId": 5,
+ "createdAt": "2023-11-24T14:16:44.656638+00:00"
}
]
SELECT coalesce(jsonb_agg(result), '[]') AS result
@@ -2800,43 +2801,43 @@ distinct
"id": 1,
"title": "A Brief History of Time",
"authorId": 5,
- "createdAt": "2023-11-16T11:27:59.270781+00:00"
+ "createdAt": "2023-11-24T14:16:44.656638+00:00"
},
{
"id": 2,
"title": "My Brief History",
"authorId": 5,
- "createdAt": "2023-11-16T11:27:59.270781+00:00"
+ "createdAt": "2023-11-24T14:16:44.656638+00:00"
},
{
"id": 1000,
"title": "Northern Lights",
"authorId": 1000,
- "createdAt": "2023-11-16T11:27:47.847734+00:00"
+ "createdAt": "2023-11-24T14:16:32.554126+00:00"
},
{
"id": 1002,
"title": "The Amber Spyglass",
"authorId": 1000,
- "createdAt": "2023-11-16T11:27:47.849159+00:00"
+ "createdAt": "2023-11-24T14:16:32.555565+00:00"
},
{
"id": 1003,
"title": "The Curious Incident of the Dog in the Night-Time",
"authorId": 1001,
- "createdAt": "2023-11-16T11:27:47.854358+00:00"
+ "createdAt": "2023-11-24T14:16:32.560168+00:00"
},
{
"id": 1001,
"title": "The Subtle Knife",
"authorId": 1000,
- "createdAt": "2023-11-16T11:27:47.848612+00:00"
+ "createdAt": "2023-11-24T14:16:32.555064+00:00"
},
{
"id": 3,
"title": "The Universe in a Nutshell",
"authorId": 5,
- "createdAt": "2023-11-16T11:27:59.2759+00:00"
+ "createdAt": "2023-11-24T14:16:44.661499+00:00"
}
]
SELECT coalesce(jsonb_agg(result), '[]') AS result
@@ -2848,43 +2849,43 @@ distinct
"id": 1,
"title": "A Brief History of Time",
"authorId": 5,
- "createdAt": "2023-11-16T11:27:59.270781+00:00"
+ "createdAt": "2023-11-24T14:16:44.656638+00:00"
},
{
"id": 2,
"title": "My Brief History",
"authorId": 5,
- "createdAt": "2023-11-16T11:27:59.270781+00:00"
+ "createdAt": "2023-11-24T14:16:44.656638+00:00"
},
{
"id": 1000,
"title": "Northern Lights",
"authorId": 1000,
- "createdAt": "2023-11-16T11:27:47.847734+00:00"
+ "createdAt": "2023-11-24T14:16:32.554126+00:00"
},
{
"id": 1002,
"title": "The Amber Spyglass",
"authorId": 1000,
- "createdAt": "2023-11-16T11:27:47.849159+00:00"
+ "createdAt": "2023-11-24T14:16:32.555565+00:00"
},
{
"id": 1003,
"title": "The Curious Incident of the Dog in the Night-Time",
"authorId": 1001,
- "createdAt": "2023-11-16T11:27:47.854358+00:00"
+ "createdAt": "2023-11-24T14:16:32.560168+00:00"
},
{
"id": 1001,
"title": "The Subtle Knife",
"authorId": 1000,
- "createdAt": "2023-11-16T11:27:47.848612+00:00"
+ "createdAt": "2023-11-24T14:16:32.555064+00:00"
},
{
"id": 3,
"title": "The Universe in a Nutshell",
"authorId": 5,
- "createdAt": "2023-11-16T11:27:59.2759+00:00"
+ "createdAt": "2023-11-24T14:16:44.661499+00:00"
}
]
SELECT coalesce(jsonb_agg(result), '[]') AS result
@@ -2896,43 +2897,43 @@ distinct
"id": 1,
"title": "A Brief History of Time",
"authorId": 5,
- "createdAt": "2023-11-16T11:27:59.270781+00:00"
+ "createdAt": "2023-11-24T14:16:44.656638+00:00"
},
{
"id": 2,
"title": "My Brief History",
"authorId": 5,
- "createdAt": "2023-11-16T11:27:59.270781+00:00"
+ "createdAt": "2023-11-24T14:16:44.656638+00:00"
},
{
"id": 1000,
"title": "Northern Lights",
"authorId": 1000,
- "createdAt": "2023-11-16T11:27:47.847734+00:00"
+ "createdAt": "2023-11-24T14:16:32.554126+00:00"
},
{
"id": 1002,
"title": "The Amber Spyglass",
"authorId": 1000,
- "createdAt": "2023-11-16T11:27:47.849159+00:00"
+ "createdAt": "2023-11-24T14:16:32.555565+00:00"
},
{
"id": 1003,
"title": "The Curious Incident of the Dog in the Night-Time",
"authorId": 1001,
- "createdAt": "2023-11-16T11:27:47.854358+00:00"
+ "createdAt": "2023-11-24T14:16:32.560168+00:00"
},
{
"id": 1001,
"title": "The Subtle Knife",
"authorId": 1000,
- "createdAt": "2023-11-16T11:27:47.848612+00:00"
+ "createdAt": "2023-11-24T14:16:32.555064+00:00"
},
{
"id": 3,
"title": "The Universe in a Nutshell",
"authorId": 5,
- "createdAt": "2023-11-16T11:27:59.2759+00:00"
+ "createdAt": "2023-11-24T14:16:44.661499+00:00"
}
]
@@ -3091,12 +3092,12 @@ JSONSelectable
s1: '2012-06-01T12:34:00.000Z',
s2: '2012-06-01T00:00:00.000',
s3: '2012-06-01',
- s4: null
+ s4: '2012-10-09T02:34:00.000Z'
}
-
-
int8
columns are returned as string values (of template string type `${number}`
) in a Selectable
, but as numbers in a JSONSelectable
. This reflects how Postgres natively converts int8
to JSON, and means these values could overflow Number.MAX_SAFE_INTEGER
.
+bigint
/int8
and numeric
/decimal
columns are returned as string values (of template string type `${number}`
) in a Selectable
, but as numbers in a JSONSelectable
. This point is discussed in the next section.
-
bytea
columns are returned as ByteArrayString
, defined as `\\x{string}`
. A toBuffer()
function is provided for use with these. For performance and memory reasons, this should not be used for large objects: in that case, consider something like pg-large-object instead.
@@ -3185,6 +3186,12 @@ JSONSelectable
alsoTsTz: '1989-11-09T17:53:00.000+00:00'
}
+Custom JSON parsing for bigint
and numeric
+All numeric values are returned as ordinary numbers in Postgres’ JSON types. That means bigint
/int8
values could exceed Number.MAX_SAFE_INTEGER
(becoming different integers in the process), and numeric
/decimal
values could overflow Number.MAX_VALUE
or lose precision. I have written about this issue in more detail elsewhere.
+If your database includes any bigint
/int8
or numeric
/decimal
columns, a warning will therefore be printed at schema-generation time (since version 6.3).
+To suppress the warning, and change the TypeScript types for these columns in JSONSelectable
s from number
to number | string
, set customJSONParsingForLargeNumbers: true
in zapatosconfig.json
.
+At the same time, be sure to call db.enableCustomJSONParsingForLargeNumbers(pg)
in your code before running any queries. This switches node-postgres JSON parsing to use my json-custom-numbers package, and return as strings any values not representable as a JS number.
+When using these string | number
values in code, you will likely want to convert integers to BigInt
and decimals to a third-party decimal format such as big.js at the earliest opportunity.
transaction
export enum IsolationLevel {
@@ -3295,16 +3302,10 @@ transaction
console.log(`Leave booked for:
Annabel – ${leaveBookedForAnnabel}
Brian – ${leaveBookedForBrian}`);
-
Transaction 1
-
START TRANSACTION ISOLATION LEVEL SERIALIZABLE
Transaction 0
START TRANSACTION ISOLATION LEVEL SERIALIZABLE
Transaction 1
-
SELECT count("shifts".*) AS result
-FROM "shifts"
-WHERE ("day" = $1
- AND ("doctorId" != $2))
-
["2020-12-25", 2]
+
START TRANSACTION ISOLATION LEVEL SERIALIZABLE
Transaction 0
SELECT count("shifts".*) AS result
FROM "shifts"
@@ -3312,12 +3313,10 @@ transaction
AND ("doctorId" != $2))
["2020-12-25", 1]
Transaction 1
-
1
-
Transaction 1
-
DELETE FROM "shifts"
+SELECT count("shifts".*) AS result
+FROM "shifts"
WHERE ("day" = $1
- AND "doctorId" = $2)
-RETURNING to_jsonb ("shifts".*) AS result
+ AND ("doctorId" != $2))
["2020-12-25", 2]
Transaction 0
1
@@ -3328,44 +3327,52 @@
transaction
RETURNING to_jsonb ("shifts".*) AS result
["2020-12-25", 1]
Transaction 1
+
1
+
Transaction 1
+
DELETE FROM "shifts"
+WHERE ("day" = $1
+ AND "doctorId" = $2)
+RETURNING to_jsonb ("shifts".*) AS result
+
["2020-12-25", 2]
+
Transaction 0
[
{
"day": "2020-12-25",
- "doctorId": 2
+ "doctorId": 1
}
]
-
Transaction 1
-
COMMIT
Transaction 0
+
COMMIT
+
Transaction 1
[
{
"day": "2020-12-25",
- "doctorId": 1
+ "doctorId": 2
}
]
-
Transaction 0
+
Transaction 1
COMMIT
-
Transaction 0
+
Transaction 1
ROLLBACK
-
Transaction 0
-
Transaction rollback (code 40001) on attempt 1 of 5, retrying in 75ms
-
Transaction 0
+
Transaction 1
+
Transaction rollback (code 40001) on attempt 1 of 5, retrying in 114ms
+
Transaction 1
Retrying transaction, attempt 2 of 5
-
Transaction 0
+
Transaction 1
START TRANSACTION ISOLATION LEVEL SERIALIZABLE
-
Transaction 0
+
Transaction 1
SELECT count("shifts".*) AS result
FROM "shifts"
WHERE ("day" = $1
AND ("doctorId" != $2))
-
["2020-12-25", 1]
-
Transaction 0
+
["2020-12-25", 2]
+
Transaction 1
0
-
Transaction 0
+
Transaction 1
COMMIT
Leave booked for:
- Annabel – false
- Brian – true
+
Annabel – true
+
Brian – false
Expanding the results, we see that one of the requests is retried and then fails — as it must to retain one doctor on shift — thanks to the SERIALIZABLE
isolation. REPEATABLE READ
, which is one isolation level weaker, wouldn’t help here.
Transaction isolation shortcuts
@@ -3834,6 +3841,8 @@ Casting Parameters
to JSON
About Zapatos
Changes
This change list is not comprehensive. For a complete version history, please see the commit list.
+6.3
+Added support for large and precise numbers — bigint
and numeric
/decimal
— returned as JSON.
6.2
Return type for certain embedded SQLFragments
now matches the null
actually returned (previously typed as undefined
). Fix for and
and or
types. Corrected package.json
key order. Exporting mapWithSeparator
.
6.0
diff --git a/docs/zapatos-bundle.js b/docs/zapatos-bundle.js
index cffe487..7dcbcb0 100644
--- a/docs/zapatos-bundle.js
+++ b/docs/zapatos-bundle.js
@@ -1 +1 @@
-const zapatosBundle = {"custom/PgGeometry.d.ts":"/*\n** Please edit this file as needed **\nIt's been generated by Zapatos as a custom type definition placeholder, and won't be overwritten\n*/\n\ndeclare module 'zapatos/custom' {\n export type PgGeometry = any; // replace with your custom type or interface as desired\n}\n","custom/index.d.ts":"/*\n** DON'T EDIT THIS FILE **\nIt's been generated by Zapatos, and is liable to be overwritten\n\nZapatos: https://jawj.github.io/zapatos/\nCopyright (C) 2020 - 2022 George MacKerron\nReleased under the MIT licence: see LICENCE file\n*/\n\n// this empty declaration appears to fix relative imports in other custom type files\ndeclare module 'zapatos/custom' { }\n","schema.d.ts":"/*\n** DON'T EDIT THIS FILE **\nIt's been generated by Zapatos, and is liable to be overwritten\n\nZapatos: https://jawj.github.io/zapatos/\nCopyright (C) 2020 - 2022 George MacKerron\nReleased under the MIT licence: see LICENCE file\n*/\n\ndeclare module 'zapatos/schema' {\n\n import type * as db from 'zapatos/db';\n import type * as c from 'zapatos/custom';\n\n // got a type error on schemaVersionCanary below? update by running `npx zapatos`\n export interface schemaVersionCanary extends db.SchemaVersionCanary { version: 104 }\n\n\n /* === schema: public === */\n\n /* --- enums --- */\n\n export type appleEnvironment = 'PROD' | 'Sandbox';\n export namespace every {\n export type appleEnvironment = ['PROD', 'Sandbox'];\n }\n\n /* --- tables --- */\n\n /**\n * **appleTransactions**\n * - Table in database\n */\n export namespace appleTransactions {\n export type Table = 'appleTransactions';\n export interface Selectable {\n /**\n * **appleTransactions.environment**\n * - `appleEnvironment` in database\n * - `NOT NULL`, no default\n */\n environment: appleEnvironment;\n /**\n * **appleTransactions.originalTransactionId**\n * - `text` in database\n * - `NOT NULL`, no default\n */\n originalTransactionId: string;\n /**\n * **appleTransactions.accountId**\n * - `int4` in database\n * - `NOT NULL`, no default\n */\n accountId: number;\n /**\n * **appleTransactions.latestReceiptData**\n * - `text` in database\n * - Nullable, no default\n */\n latestReceiptData: string | null;\n }\n export interface JSONSelectable {\n /**\n * **appleTransactions.environment**\n * - `appleEnvironment` in database\n * - `NOT NULL`, no default\n */\n environment: appleEnvironment;\n /**\n * **appleTransactions.originalTransactionId**\n * - `text` in database\n * - `NOT NULL`, no default\n */\n originalTransactionId: string;\n /**\n * **appleTransactions.accountId**\n * - `int4` in database\n * - `NOT NULL`, no default\n */\n accountId: number;\n /**\n * **appleTransactions.latestReceiptData**\n * - `text` in database\n * - Nullable, no default\n */\n latestReceiptData: string | null;\n }\n export interface Whereable {\n /**\n * **appleTransactions.environment**\n * - `appleEnvironment` in database\n * - `NOT NULL`, no default\n */\n environment?: appleEnvironment | db.Parameter | db.SQLFragment | db.ParentColumn | db.SQLFragment | db.SQLFragment | db.ParentColumn>;\n /**\n * **appleTransactions.originalTransactionId**\n * - `text` in database\n * - `NOT NULL`, no default\n */\n originalTransactionId?: string | db.Parameter | db.SQLFragment | db.ParentColumn | db.SQLFragment | db.SQLFragment | db.ParentColumn>;\n /**\n * **appleTransactions.accountId**\n * - `int4` in database\n * - `NOT NULL`, no default\n */\n accountId?: number | db.Parameter | db.SQLFragment | db.ParentColumn | db.SQLFragment | db.SQLFragment | db.ParentColumn>;\n /**\n * **appleTransactions.latestReceiptData**\n * - `text` in database\n * - Nullable, no default\n */\n latestReceiptData?: string | db.Parameter | db.SQLFragment | db.ParentColumn | db.SQLFragment | db.SQLFragment | db.ParentColumn>;\n }\n export interface Insertable {\n /**\n * **appleTransactions.environment**\n * - `appleEnvironment` in database\n * - `NOT NULL`, no default\n */\n environment: appleEnvironment | db.Parameter | db.SQLFragment;\n /**\n * **appleTransactions.originalTransactionId**\n * - `text` in database\n * - `NOT NULL`, no default\n */\n originalTransactionId: string | db.Parameter | db.SQLFragment;\n /**\n * **appleTransactions.accountId**\n * - `int4` in database\n * - `NOT NULL`, no default\n */\n accountId: number | db.Parameter | db.SQLFragment;\n /**\n * **appleTransactions.latestReceiptData**\n * - `text` in database\n * - Nullable, no default\n */\n latestReceiptData?: string | db.Parameter | null | db.DefaultType | db.SQLFragment;\n }\n export interface Updatable {\n /**\n * **appleTransactions.environment**\n * - `appleEnvironment` in database\n * - `NOT NULL`, no default\n */\n environment?: appleEnvironment | db.Parameter | db.SQLFragment | db.SQLFragment | db.SQLFragment>;\n /**\n * **appleTransactions.originalTransactionId**\n * - `text` in database\n * - `NOT NULL`, no default\n */\n originalTransactionId?: string | db.Parameter | db.SQLFragment | db.SQLFragment | db.SQLFragment>;\n /**\n * **appleTransactions.accountId**\n * - `int4` in database\n * - `NOT NULL`, no default\n */\n accountId?: number | db.Parameter | db.SQLFragment | db.SQLFragment | db.SQLFragment>;\n /**\n * **appleTransactions.latestReceiptData**\n * - `text` in database\n * - Nullable, no default\n */\n latestReceiptData?: string | db.Parameter | null | db.DefaultType | db.SQLFragment | db.SQLFragment | null | db.DefaultType | db.SQLFragment>;\n }\n export type UniqueIndex = 'appleTransactionsPrimaryKey';\n export type Column = keyof Selectable;\n export type OnlyCols = Pick;\n export type SQLExpression = Table | db.ColumnNames | db.ColumnValues | Whereable | Column | db.ParentColumn | db.GenericSQLExpression;\n export type SQL = SQLExpression | SQLExpression[];\n }\n\n /**\n * **arrays**\n * - Table in database\n */\n export namespace arrays {\n export type Table = 'arrays';\n export interface Selectable {\n /**\n * **arrays.jsonValue**\n * - `jsonb` in database\n * - Nullable, no default\n */\n jsonValue: db.JSONValue | null;\n /**\n * **arrays.textArray**\n * - `_text` in database\n * - Nullable, no default\n */\n textArray: string[] | null;\n }\n export interface JSONSelectable {\n /**\n * **arrays.jsonValue**\n * - `jsonb` in database\n * - Nullable, no default\n */\n jsonValue: db.JSONValue | null;\n /**\n * **arrays.textArray**\n * - `_text` in database\n * - Nullable, no default\n */\n textArray: string[] | null;\n }\n export interface Whereable {\n /**\n * **arrays.jsonValue**\n * - `jsonb` in database\n * - Nullable, no default\n */\n jsonValue?: db.JSONValue | db.Parameter | db.SQLFragment | db.ParentColumn | db.SQLFragment | db.SQLFragment | db.ParentColumn>;\n /**\n * **arrays.textArray**\n * - `_text` in database\n * - Nullable, no default\n */\n textArray?: string[] | db.Parameter | db.SQLFragment | db.ParentColumn | db.SQLFragment | db.SQLFragment | db.ParentColumn>;\n }\n export interface Insertable {\n /**\n * **arrays.jsonValue**\n * - `jsonb` in database\n * - Nullable, no default\n */\n jsonValue?: db.JSONValue | db.Parameter | null | db.DefaultType | db.SQLFragment;\n /**\n * **arrays.textArray**\n * - `_text` in database\n * - Nullable, no default\n */\n textArray?: string[] | db.Parameter | null | db.DefaultType | db.SQLFragment;\n }\n export interface Updatable {\n /**\n * **arrays.jsonValue**\n * - `jsonb` in database\n * - Nullable, no default\n */\n jsonValue?: db.JSONValue | db.Parameter | null | db.DefaultType | db.SQLFragment | db.SQLFragment | null | db.DefaultType | db.SQLFragment>;\n /**\n * **arrays.textArray**\n * - `_text` in database\n * - Nullable, no default\n */\n textArray?: string[] | db.Parameter | null | db.DefaultType | db.SQLFragment | db.SQLFragment | null | db.DefaultType | db.SQLFragment>;\n }\n export type UniqueIndex = never;\n export type Column = keyof Selectable;\n export type OnlyCols = Pick;\n export type SQLExpression = Table | db.ColumnNames | db.ColumnValues | Whereable | Column | db.ParentColumn | db.GenericSQLExpression;\n export type SQL = SQLExpression | SQLExpression[];\n }\n\n /**\n * **authors**\n * - Table in database\n */\n export namespace authors {\n export type Table = 'authors';\n export interface Selectable {\n /**\n * **authors.id**\n * - `int4` in database\n * - `NOT NULL`, default: `nextval('authors_id_seq'::regclass)`\n */\n id: number;\n /**\n * **authors.name**\n * - `text` in database\n * - `NOT NULL`, no default\n */\n name: string;\n /**\n * **authors.isLiving**\n * - `bool` in database\n * - Nullable, no default\n */\n isLiving: boolean | null;\n }\n export interface JSONSelectable {\n /**\n * **authors.id**\n * - `int4` in database\n * - `NOT NULL`, default: `nextval('authors_id_seq'::regclass)`\n */\n id: number;\n /**\n * **authors.name**\n * - `text` in database\n * - `NOT NULL`, no default\n */\n name: string;\n /**\n * **authors.isLiving**\n * - `bool` in database\n * - Nullable, no default\n */\n isLiving: boolean | null;\n }\n export interface Whereable {\n /**\n * **authors.id**\n * - `int4` in database\n * - `NOT NULL`, default: `nextval('authors_id_seq'::regclass)`\n */\n id?: number | db.Parameter | db.SQLFragment | db.ParentColumn | db.SQLFragment | db.SQLFragment | db.ParentColumn>;\n /**\n * **authors.name**\n * - `text` in database\n * - `NOT NULL`, no default\n */\n name?: string | db.Parameter | db.SQLFragment | db.ParentColumn | db.SQLFragment | db.SQLFragment | db.ParentColumn>;\n /**\n * **authors.isLiving**\n * - `bool` in database\n * - Nullable, no default\n */\n isLiving?: boolean | db.Parameter | db.SQLFragment | db.ParentColumn | db.SQLFragment | db.SQLFragment | db.ParentColumn>;\n }\n export interface Insertable {\n /**\n * **authors.id**\n * - `int4` in database\n * - `NOT NULL`, default: `nextval('authors_id_seq'::regclass)`\n */\n id?: number | db.Parameter | db.DefaultType | db.SQLFragment;\n /**\n * **authors.name**\n * - `text` in database\n * - `NOT NULL`, no default\n */\n name: string | db.Parameter | db.SQLFragment;\n /**\n * **authors.isLiving**\n * - `bool` in database\n * - Nullable, no default\n */\n isLiving?: boolean | db.Parameter | null | db.DefaultType | db.SQLFragment;\n }\n export interface Updatable {\n /**\n * **authors.id**\n * - `int4` in database\n * - `NOT NULL`, default: `nextval('authors_id_seq'::regclass)`\n */\n id?: number | db.Parameter | db.DefaultType | db.SQLFragment | db.SQLFragment | db.DefaultType | db.SQLFragment>;\n /**\n * **authors.name**\n * - `text` in database\n * - `NOT NULL`, no default\n */\n name?: string | db.Parameter | db.SQLFragment | db.SQLFragment | db.SQLFragment>;\n /**\n * **authors.isLiving**\n * - `bool` in database\n * - Nullable, no default\n */\n isLiving?: boolean | db.Parameter | null | db.DefaultType | db.SQLFragment | db.SQLFragment | null | db.DefaultType | db.SQLFragment>;\n }\n export type UniqueIndex = 'authors_pkey';\n export type Column = keyof Selectable;\n export type OnlyCols = Pick;\n export type SQLExpression = Table | db.ColumnNames | db.ColumnValues | Whereable | Column | db.ParentColumn | db.GenericSQLExpression;\n export type SQL = SQLExpression | SQLExpression[];\n }\n\n /**\n * **bankAccounts**\n * - Table in database\n */\n export namespace bankAccounts {\n export type Table = 'bankAccounts';\n export interface Selectable {\n /**\n * **bankAccounts.id**\n * - `int4` in database\n * - `NOT NULL`, default: `nextval('\"bankAccounts_id_seq\"'::regclass)`\n */\n id: number;\n /**\n * **bankAccounts.balance**\n * - `int4` in database\n * - `NOT NULL`, default: `0`\n */\n balance: number;\n }\n export interface JSONSelectable {\n /**\n * **bankAccounts.id**\n * - `int4` in database\n * - `NOT NULL`, default: `nextval('\"bankAccounts_id_seq\"'::regclass)`\n */\n id: number;\n /**\n * **bankAccounts.balance**\n * - `int4` in database\n * - `NOT NULL`, default: `0`\n */\n balance: number;\n }\n export interface Whereable {\n /**\n * **bankAccounts.id**\n * - `int4` in database\n * - `NOT NULL`, default: `nextval('\"bankAccounts_id_seq\"'::regclass)`\n */\n id?: number | db.Parameter | db.SQLFragment | db.ParentColumn | db.SQLFragment | db.SQLFragment | db.ParentColumn>;\n /**\n * **bankAccounts.balance**\n * - `int4` in database\n * - `NOT NULL`, default: `0`\n */\n balance?: number | db.Parameter | db.SQLFragment | db.ParentColumn | db.SQLFragment | db.SQLFragment | db.ParentColumn>;\n }\n export interface Insertable {\n /**\n * **bankAccounts.id**\n * - `int4` in database\n * - `NOT NULL`, default: `nextval('\"bankAccounts_id_seq\"'::regclass)`\n */\n id?: number | db.Parameter | db.DefaultType | db.SQLFragment;\n /**\n * **bankAccounts.balance**\n * - `int4` in database\n * - `NOT NULL`, default: `0`\n */\n balance?: number | db.Parameter | db.DefaultType | db.SQLFragment;\n }\n export interface Updatable {\n /**\n * **bankAccounts.id**\n * - `int4` in database\n * - `NOT NULL`, default: `nextval('\"bankAccounts_id_seq\"'::regclass)`\n */\n id?: number | db.Parameter | db.DefaultType | db.SQLFragment | db.SQLFragment | db.DefaultType | db.SQLFragment>;\n /**\n * **bankAccounts.balance**\n * - `int4` in database\n * - `NOT NULL`, default: `0`\n */\n balance?: number | db.Parameter | db.DefaultType | db.SQLFragment | db.SQLFragment | db.DefaultType | db.SQLFragment>;\n }\n export type UniqueIndex = 'bankAccounts_pkey';\n export type Column = keyof Selectable;\n export type OnlyCols = Pick;\n export type SQLExpression = Table | db.ColumnNames | db.ColumnValues | Whereable | Column | db.ParentColumn | db.GenericSQLExpression;\n export type SQL = SQLExpression | SQLExpression[];\n }\n\n /**\n * **books**\n * - Table in database\n */\n export namespace books {\n export type Table = 'books';\n export interface Selectable {\n /**\n * **books.id**\n * - `int4` in database\n * - `NOT NULL`, default: `nextval('books_id_seq'::regclass)`\n */\n id: number;\n /**\n * **books.authorId**\n * - `int4` in database\n * - `NOT NULL`, no default\n */\n authorId: number;\n /**\n * **books.title**\n * - `text` in database\n * - Nullable, no default\n */\n title: string | null;\n /**\n * **books.createdAt**\n * - `timestamptz` in database\n * - `NOT NULL`, default: `now()`\n */\n createdAt: Date;\n }\n export interface JSONSelectable {\n /**\n * **books.id**\n * - `int4` in database\n * - `NOT NULL`, default: `nextval('books_id_seq'::regclass)`\n */\n id: number;\n /**\n * **books.authorId**\n * - `int4` in database\n * - `NOT NULL`, no default\n */\n authorId: number;\n /**\n * **books.title**\n * - `text` in database\n * - Nullable, no default\n */\n title: string | null;\n /**\n * **books.createdAt**\n * - `timestamptz` in database\n * - `NOT NULL`, default: `now()`\n */\n createdAt: db.TimestampTzString;\n }\n export interface Whereable {\n /**\n * **books.id**\n * - `int4` in database\n * - `NOT NULL`, default: `nextval('books_id_seq'::regclass)`\n */\n id?: number | db.Parameter | db.SQLFragment | db.ParentColumn | db.SQLFragment | db.SQLFragment | db.ParentColumn>;\n /**\n * **books.authorId**\n * - `int4` in database\n * - `NOT NULL`, no default\n */\n authorId?: number | db.Parameter | db.SQLFragment | db.ParentColumn | db.SQLFragment | db.SQLFragment | db.ParentColumn>;\n /**\n * **books.title**\n * - `text` in database\n * - Nullable, no default\n */\n title?: string | db.Parameter | db.SQLFragment | db.ParentColumn | db.SQLFragment | db.SQLFragment | db.ParentColumn>;\n /**\n * **books.createdAt**\n * - `timestamptz` in database\n * - `NOT NULL`, default: `now()`\n */\n createdAt?: (db.TimestampTzString | Date) | db.Parameter<(db.TimestampTzString | Date)> | db.SQLFragment | db.ParentColumn | db.SQLFragment | db.SQLFragment | db.ParentColumn>;\n }\n export interface Insertable {\n /**\n * **books.id**\n * - `int4` in database\n * - `NOT NULL`, default: `nextval('books_id_seq'::regclass)`\n */\n id?: number | db.Parameter | db.DefaultType | db.SQLFragment;\n /**\n * **books.authorId**\n * - `int4` in database\n * - `NOT NULL`, no default\n */\n authorId: number | db.Parameter | db.SQLFragment;\n /**\n * **books.title**\n * - `text` in database\n * - Nullable, no default\n */\n title?: string | db.Parameter | null | db.DefaultType | db.SQLFragment;\n /**\n * **books.createdAt**\n * - `timestamptz` in database\n * - `NOT NULL`, default: `now()`\n */\n createdAt?: (db.TimestampTzString | Date) | db.Parameter<(db.TimestampTzString | Date)> | db.DefaultType | db.SQLFragment;\n }\n export interface Updatable {\n /**\n * **books.id**\n * - `int4` in database\n * - `NOT NULL`, default: `nextval('books_id_seq'::regclass)`\n */\n id?: number | db.Parameter | db.DefaultType | db.SQLFragment | db.SQLFragment | db.DefaultType | db.SQLFragment>;\n /**\n * **books.authorId**\n * - `int4` in database\n * - `NOT NULL`, no default\n */\n authorId?: number | db.Parameter | db.SQLFragment | db.SQLFragment | db.SQLFragment>;\n /**\n * **books.title**\n * - `text` in database\n * - Nullable, no default\n */\n title?: string | db.Parameter | null | db.DefaultType | db.SQLFragment | db.SQLFragment | null | db.DefaultType | db.SQLFragment>;\n /**\n * **books.createdAt**\n * - `timestamptz` in database\n * - `NOT NULL`, default: `now()`\n */\n createdAt?: (db.TimestampTzString | Date) | db.Parameter<(db.TimestampTzString | Date)> | db.DefaultType | db.SQLFragment | db.SQLFragment | db.DefaultType | db.SQLFragment>;\n }\n export type UniqueIndex = 'books_pkey';\n export type Column = keyof Selectable;\n export type OnlyCols = Pick;\n export type SQLExpression = Table | db.ColumnNames | db.ColumnValues | Whereable | Column | db.ParentColumn | db.GenericSQLExpression;\n export type SQL = SQLExpression | SQLExpression[];\n }\n\n /**\n * **doctors**\n * - Table in database\n */\n export namespace doctors {\n export type Table = 'doctors';\n export interface Selectable {\n /**\n * **doctors.id**\n * - `int4` in database\n * - `NOT NULL`, default: `nextval('doctors_id_seq'::regclass)`\n */\n id: number;\n /**\n * **doctors.name**\n * - `text` in database\n * - `NOT NULL`, no default\n */\n name: string;\n }\n export interface JSONSelectable {\n /**\n * **doctors.id**\n * - `int4` in database\n * - `NOT NULL`, default: `nextval('doctors_id_seq'::regclass)`\n */\n id: number;\n /**\n * **doctors.name**\n * - `text` in database\n * - `NOT NULL`, no default\n */\n name: string;\n }\n export interface Whereable {\n /**\n * **doctors.id**\n * - `int4` in database\n * - `NOT NULL`, default: `nextval('doctors_id_seq'::regclass)`\n */\n id?: number | db.Parameter | db.SQLFragment | db.ParentColumn | db.SQLFragment | db.SQLFragment | db.ParentColumn>;\n /**\n * **doctors.name**\n * - `text` in database\n * - `NOT NULL`, no default\n */\n name?: string | db.Parameter | db.SQLFragment | db.ParentColumn | db.SQLFragment | db.SQLFragment | db.ParentColumn>;\n }\n export interface Insertable {\n /**\n * **doctors.id**\n * - `int4` in database\n * - `NOT NULL`, default: `nextval('doctors_id_seq'::regclass)`\n */\n id?: number | db.Parameter | db.DefaultType | db.SQLFragment;\n /**\n * **doctors.name**\n * - `text` in database\n * - `NOT NULL`, no default\n */\n name: string | db.Parameter | db.SQLFragment;\n }\n export interface Updatable {\n /**\n * **doctors.id**\n * - `int4` in database\n * - `NOT NULL`, default: `nextval('doctors_id_seq'::regclass)`\n */\n id?: number | db.Parameter | db.DefaultType | db.SQLFragment | db.SQLFragment | db.DefaultType | db.SQLFragment>;\n /**\n * **doctors.name**\n * - `text` in database\n * - `NOT NULL`, no default\n */\n name?: string | db.Parameter | db.SQLFragment | db.SQLFragment | db.SQLFragment>;\n }\n export type UniqueIndex = 'doctors_pkey';\n export type Column = keyof Selectable;\n export type OnlyCols = Pick;\n export type SQLExpression = Table | db.ColumnNames | db.ColumnValues | Whereable | Column | db.ParentColumn | db.GenericSQLExpression;\n export type SQL = SQLExpression | SQLExpression[];\n }\n\n /**\n * **emailAuthentication**\n * - Table in database\n */\n export namespace emailAuthentication {\n export type Table = 'emailAuthentication';\n export interface Selectable {\n /**\n * **emailAuthentication.email**\n * - `text` in database\n * - `NOT NULL`, no default\n */\n email: string;\n /**\n * **emailAuthentication.consecutiveFailedLogins**\n * - `int4` in database\n * - `NOT NULL`, default: `0`\n */\n consecutiveFailedLogins: number;\n /**\n * **emailAuthentication.lastFailedLogin**\n * - `timestamptz` in database\n * - Nullable, no default\n */\n lastFailedLogin: Date | null;\n }\n export interface JSONSelectable {\n /**\n * **emailAuthentication.email**\n * - `text` in database\n * - `NOT NULL`, no default\n */\n email: string;\n /**\n * **emailAuthentication.consecutiveFailedLogins**\n * - `int4` in database\n * - `NOT NULL`, default: `0`\n */\n consecutiveFailedLogins: number;\n /**\n * **emailAuthentication.lastFailedLogin**\n * - `timestamptz` in database\n * - Nullable, no default\n */\n lastFailedLogin: db.TimestampTzString | null;\n }\n export interface Whereable {\n /**\n * **emailAuthentication.email**\n * - `text` in database\n * - `NOT NULL`, no default\n */\n email?: string | db.Parameter | db.SQLFragment | db.ParentColumn | db.SQLFragment | db.SQLFragment | db.ParentColumn>;\n /**\n * **emailAuthentication.consecutiveFailedLogins**\n * - `int4` in database\n * - `NOT NULL`, default: `0`\n */\n consecutiveFailedLogins?: number | db.Parameter | db.SQLFragment | db.ParentColumn | db.SQLFragment | db.SQLFragment | db.ParentColumn>;\n /**\n * **emailAuthentication.lastFailedLogin**\n * - `timestamptz` in database\n * - Nullable, no default\n */\n lastFailedLogin?: (db.TimestampTzString | Date) | db.Parameter<(db.TimestampTzString | Date)> | db.SQLFragment | db.ParentColumn | db.SQLFragment | db.SQLFragment | db.ParentColumn>;\n }\n export interface Insertable {\n /**\n * **emailAuthentication.email**\n * - `text` in database\n * - `NOT NULL`, no default\n */\n email: string | db.Parameter | db.SQLFragment;\n /**\n * **emailAuthentication.consecutiveFailedLogins**\n * - `int4` in database\n * - `NOT NULL`, default: `0`\n */\n consecutiveFailedLogins?: number | db.Parameter | db.DefaultType | db.SQLFragment;\n /**\n * **emailAuthentication.lastFailedLogin**\n * - `timestamptz` in database\n * - Nullable, no default\n */\n lastFailedLogin?: (db.TimestampTzString | Date) | db.Parameter<(db.TimestampTzString | Date)> | null | db.DefaultType | db.SQLFragment;\n }\n export interface Updatable {\n /**\n * **emailAuthentication.email**\n * - `text` in database\n * - `NOT NULL`, no default\n */\n email?: string | db.Parameter | db.SQLFragment | db.SQLFragment | db.SQLFragment>;\n /**\n * **emailAuthentication.consecutiveFailedLogins**\n * - `int4` in database\n * - `NOT NULL`, default: `0`\n */\n consecutiveFailedLogins?: number | db.Parameter | db.DefaultType | db.SQLFragment | db.SQLFragment | db.DefaultType | db.SQLFragment>;\n /**\n * **emailAuthentication.lastFailedLogin**\n * - `timestamptz` in database\n * - Nullable, no default\n */\n lastFailedLogin?: (db.TimestampTzString | Date) | db.Parameter<(db.TimestampTzString | Date)> | null | db.DefaultType | db.SQLFragment | db.SQLFragment | null | db.DefaultType | db.SQLFragment>;\n }\n export type UniqueIndex = 'emailAuthentication_pkey';\n export type Column = keyof Selectable;\n export type OnlyCols = Pick;\n export type SQLExpression = Table | db.ColumnNames | db.ColumnValues | Whereable | Column | db.ParentColumn | db.GenericSQLExpression;\n export type SQL = SQLExpression | SQLExpression[];\n }\n\n /**\n * **employees**\n * - Table in database\n */\n export namespace employees {\n export type Table = 'employees';\n export interface Selectable {\n /**\n * **employees.id**\n * - `int4` in database\n * - `NOT NULL`, default: `nextval('employees_id_seq'::regclass)`\n */\n id: number;\n /**\n * **employees.name**\n * - `text` in database\n * - `NOT NULL`, no default\n */\n name: string;\n /**\n * **employees.managerId**\n * - `int4` in database\n * - Nullable, no default\n */\n managerId: number | null;\n }\n export interface JSONSelectable {\n /**\n * **employees.id**\n * - `int4` in database\n * - `NOT NULL`, default: `nextval('employees_id_seq'::regclass)`\n */\n id: number;\n /**\n * **employees.name**\n * - `text` in database\n * - `NOT NULL`, no default\n */\n name: string;\n /**\n * **employees.managerId**\n * - `int4` in database\n * - Nullable, no default\n */\n managerId: number | null;\n }\n export interface Whereable {\n /**\n * **employees.id**\n * - `int4` in database\n * - `NOT NULL`, default: `nextval('employees_id_seq'::regclass)`\n */\n id?: number | db.Parameter | db.SQLFragment | db.ParentColumn | db.SQLFragment | db.SQLFragment | db.ParentColumn>;\n /**\n * **employees.name**\n * - `text` in database\n * - `NOT NULL`, no default\n */\n name?: string | db.Parameter | db.SQLFragment | db.ParentColumn | db.SQLFragment | db.SQLFragment | db.ParentColumn>;\n /**\n * **employees.managerId**\n * - `int4` in database\n * - Nullable, no default\n */\n managerId?: number | db.Parameter | db.SQLFragment | db.ParentColumn | db.SQLFragment | db.SQLFragment | db.ParentColumn>;\n }\n export interface Insertable {\n /**\n * **employees.id**\n * - `int4` in database\n * - `NOT NULL`, default: `nextval('employees_id_seq'::regclass)`\n */\n id?: number | db.Parameter | db.DefaultType | db.SQLFragment;\n /**\n * **employees.name**\n * - `text` in database\n * - `NOT NULL`, no default\n */\n name: string | db.Parameter | db.SQLFragment;\n /**\n * **employees.managerId**\n * - `int4` in database\n * - Nullable, no default\n */\n managerId?: number | db.Parameter | null | db.DefaultType | db.SQLFragment;\n }\n export interface Updatable {\n /**\n * **employees.id**\n * - `int4` in database\n * - `NOT NULL`, default: `nextval('employees_id_seq'::regclass)`\n */\n id?: number | db.Parameter | db.DefaultType | db.SQLFragment | db.SQLFragment | db.DefaultType | db.SQLFragment>;\n /**\n * **employees.name**\n * - `text` in database\n * - `NOT NULL`, no default\n */\n name?: string | db.Parameter | db.SQLFragment | db.SQLFragment | db.SQLFragment>;\n /**\n * **employees.managerId**\n * - `int4` in database\n * - Nullable, no default\n */\n managerId?: number | db.Parameter | null | db.DefaultType | db.SQLFragment | db.SQLFragment | null | db.DefaultType | db.SQLFragment>;\n }\n export type UniqueIndex = 'employees_pkey';\n export type Column = keyof Selectable;\n export type OnlyCols = Pick;\n export type SQLExpression = Table | db.ColumnNames | db.ColumnValues | Whereable | Column | db.ParentColumn | db.GenericSQLExpression;\n export type SQL = SQLExpression | SQLExpression[];\n }\n\n /**\n * **nameCounts**\n * - Table in database\n */\n export namespace nameCounts {\n export type Table = 'nameCounts';\n export interface Selectable {\n /**\n * **nameCounts.name**\n * - `text` in database\n * - `NOT NULL`, no default\n */\n name: string;\n /**\n * **nameCounts.count**\n * - `int4` in database\n * - `NOT NULL`, no default\n */\n count: number;\n }\n export interface JSONSelectable {\n /**\n * **nameCounts.name**\n * - `text` in database\n * - `NOT NULL`, no default\n */\n name: string;\n /**\n * **nameCounts.count**\n * - `int4` in database\n * - `NOT NULL`, no default\n */\n count: number;\n }\n export interface Whereable {\n /**\n * **nameCounts.name**\n * - `text` in database\n * - `NOT NULL`, no default\n */\n name?: string | db.Parameter | db.SQLFragment | db.ParentColumn | db.SQLFragment | db.SQLFragment | db.ParentColumn>;\n /**\n * **nameCounts.count**\n * - `int4` in database\n * - `NOT NULL`, no default\n */\n count?: number | db.Parameter | db.SQLFragment | db.ParentColumn | db.SQLFragment | db.SQLFragment | db.ParentColumn>;\n }\n export interface Insertable {\n /**\n * **nameCounts.name**\n * - `text` in database\n * - `NOT NULL`, no default\n */\n name: string | db.Parameter | db.SQLFragment;\n /**\n * **nameCounts.count**\n * - `int4` in database\n * - `NOT NULL`, no default\n */\n count: number | db.Parameter | db.SQLFragment;\n }\n export interface Updatable {\n /**\n * **nameCounts.name**\n * - `text` in database\n * - `NOT NULL`, no default\n */\n name?: string | db.Parameter | db.SQLFragment | db.SQLFragment | db.SQLFragment>;\n /**\n * **nameCounts.count**\n * - `int4` in database\n * - `NOT NULL`, no default\n */\n count?: number | db.Parameter | db.SQLFragment | db.SQLFragment | db.SQLFragment>;\n }\n export type UniqueIndex = 'nameCounts_pkey';\n export type Column = keyof Selectable;\n export type OnlyCols = Pick;\n export type SQLExpression = Table | db.ColumnNames | db.ColumnValues | Whereable | Column | db.ParentColumn | db.GenericSQLExpression;\n export type SQL = SQLExpression | SQLExpression[];\n }\n\n /**\n * **photos**\n * - Table in database\n */\n export namespace photos {\n export type Table = 'photos';\n export interface Selectable {\n /**\n * **photos.photoId**\n * - `int4` in database\n * - `NOT NULL`, identity column\n */\n photoId: number;\n /**\n * **photos.url**\n * - `text` in database\n * - `NOT NULL`, no default\n */\n url: string;\n }\n export interface JSONSelectable {\n /**\n * **photos.photoId**\n * - `int4` in database\n * - `NOT NULL`, identity column\n */\n photoId: number;\n /**\n * **photos.url**\n * - `text` in database\n * - `NOT NULL`, no default\n */\n url: string;\n }\n export interface Whereable {\n /**\n * **photos.photoId**\n * - `int4` in database\n * - `NOT NULL`, identity column\n */\n photoId?: number | db.Parameter | db.SQLFragment | db.ParentColumn | db.SQLFragment | db.SQLFragment | db.ParentColumn>;\n /**\n * **photos.url**\n * - `text` in database\n * - `NOT NULL`, no default\n */\n url?: string | db.Parameter | db.SQLFragment | db.ParentColumn | db.SQLFragment | db.SQLFragment | db.ParentColumn>;\n }\n export interface Insertable {\n /**\n * **photos.photoId**\n * - `int4` in database\n * - `NOT NULL`, identity column\n */\n photoId?: number | db.Parameter | db.DefaultType | db.SQLFragment;\n /**\n * **photos.url**\n * - `text` in database\n * - `NOT NULL`, no default\n */\n url: string | db.Parameter | db.SQLFragment;\n }\n export interface Updatable {\n /**\n * **photos.photoId**\n * - `int4` in database\n * - `NOT NULL`, identity column\n */\n photoId?: number | db.Parameter | db.DefaultType | db.SQLFragment | db.SQLFragment | db.DefaultType | db.SQLFragment>;\n /**\n * **photos.url**\n * - `text` in database\n * - `NOT NULL`, no default\n */\n url?: string | db.Parameter | db.SQLFragment | db.SQLFragment | db.SQLFragment>;\n }\n export type UniqueIndex = 'photos_pkey';\n export type Column = keyof Selectable;\n export type OnlyCols = Pick;\n export type SQLExpression = Table | db.ColumnNames | db.ColumnValues | Whereable | Column | db.ParentColumn | db.GenericSQLExpression;\n export type SQL = SQLExpression | SQLExpression[];\n }\n\n /**\n * **shifts**\n * - Table in database\n */\n export namespace shifts {\n export type Table = 'shifts';\n export interface Selectable {\n /**\n * **shifts.day**\n * - `date` in database\n * - `NOT NULL`, no default\n */\n day: Date;\n /**\n * **shifts.doctorId**\n * - `int4` in database\n * - `NOT NULL`, no default\n */\n doctorId: number;\n }\n export interface JSONSelectable {\n /**\n * **shifts.day**\n * - `date` in database\n * - `NOT NULL`, no default\n */\n day: db.DateString;\n /**\n * **shifts.doctorId**\n * - `int4` in database\n * - `NOT NULL`, no default\n */\n doctorId: number;\n }\n export interface Whereable {\n /**\n * **shifts.day**\n * - `date` in database\n * - `NOT NULL`, no default\n */\n day?: (db.DateString | Date) | db.Parameter<(db.DateString | Date)> | db.SQLFragment | db.ParentColumn | db.SQLFragment | db.SQLFragment | db.ParentColumn>;\n /**\n * **shifts.doctorId**\n * - `int4` in database\n * - `NOT NULL`, no default\n */\n doctorId?: number | db.Parameter | db.SQLFragment | db.ParentColumn | db.SQLFragment | db.SQLFragment | db.ParentColumn>;\n }\n export interface Insertable {\n /**\n * **shifts.day**\n * - `date` in database\n * - `NOT NULL`, no default\n */\n day: (db.DateString | Date) | db.Parameter<(db.DateString | Date)> | db.SQLFragment;\n /**\n * **shifts.doctorId**\n * - `int4` in database\n * - `NOT NULL`, no default\n */\n doctorId: number | db.Parameter | db.SQLFragment;\n }\n export interface Updatable {\n /**\n * **shifts.day**\n * - `date` in database\n * - `NOT NULL`, no default\n */\n day?: (db.DateString | Date) | db.Parameter<(db.DateString | Date)> | db.SQLFragment | db.SQLFragment | db.SQLFragment>;\n /**\n * **shifts.doctorId**\n * - `int4` in database\n * - `NOT NULL`, no default\n */\n doctorId?: number | db.Parameter | db.SQLFragment | db.SQLFragment | db.SQLFragment>;\n }\n export type UniqueIndex = 'shifts_pkey';\n export type Column = keyof Selectable;\n export type OnlyCols = Pick;\n export type SQLExpression = Table | db.ColumnNames | db.ColumnValues | Whereable | Column | db.ParentColumn | db.GenericSQLExpression;\n export type SQL = SQLExpression | SQLExpression[];\n }\n\n /**\n * **stores**\n * - Table in database\n */\n export namespace stores {\n export type Table = 'stores';\n export interface Selectable {\n /**\n * **stores.id**\n * - `int4` in database\n * - `NOT NULL`, default: `nextval('stores_id_seq'::regclass)`\n */\n id: number;\n /**\n * **stores.name**\n * - `text` in database\n * - `NOT NULL`, no default\n */\n name: string;\n /**\n * **stores.geom**\n * - `geometry` in database\n * - `NOT NULL`, no default\n */\n geom: c.PgGeometry;\n }\n export interface JSONSelectable {\n /**\n * **stores.id**\n * - `int4` in database\n * - `NOT NULL`, default: `nextval('stores_id_seq'::regclass)`\n */\n id: number;\n /**\n * **stores.name**\n * - `text` in database\n * - `NOT NULL`, no default\n */\n name: string;\n /**\n * **stores.geom**\n * - `geometry` in database\n * - `NOT NULL`, no default\n */\n geom: c.PgGeometry;\n }\n export interface Whereable {\n /**\n * **stores.id**\n * - `int4` in database\n * - `NOT NULL`, default: `nextval('stores_id_seq'::regclass)`\n */\n id?: number | db.Parameter | db.SQLFragment | db.ParentColumn | db.SQLFragment | db.SQLFragment | db.ParentColumn>;\n /**\n * **stores.name**\n * - `text` in database\n * - `NOT NULL`, no default\n */\n name?: string | db.Parameter | db.SQLFragment | db.ParentColumn | db.SQLFragment | db.SQLFragment | db.ParentColumn>;\n /**\n * **stores.geom**\n * - `geometry` in database\n * - `NOT NULL`, no default\n */\n geom?: c.PgGeometry | db.Parameter | db.SQLFragment | db.ParentColumn | db.SQLFragment | db.SQLFragment | db.ParentColumn>;\n }\n export interface Insertable {\n /**\n * **stores.id**\n * - `int4` in database\n * - `NOT NULL`, default: `nextval('stores_id_seq'::regclass)`\n */\n id?: number | db.Parameter | db.DefaultType | db.SQLFragment;\n /**\n * **stores.name**\n * - `text` in database\n * - `NOT NULL`, no default\n */\n name: string | db.Parameter | db.SQLFragment;\n /**\n * **stores.geom**\n * - `geometry` in database\n * - `NOT NULL`, no default\n */\n geom: c.PgGeometry | db.Parameter | db.SQLFragment;\n }\n export interface Updatable {\n /**\n * **stores.id**\n * - `int4` in database\n * - `NOT NULL`, default: `nextval('stores_id_seq'::regclass)`\n */\n id?: number | db.Parameter | db.DefaultType | db.SQLFragment | db.SQLFragment | db.DefaultType | db.SQLFragment>;\n /**\n * **stores.name**\n * - `text` in database\n * - `NOT NULL`, no default\n */\n name?: string | db.Parameter | db.SQLFragment | db.SQLFragment | db.SQLFragment>;\n /**\n * **stores.geom**\n * - `geometry` in database\n * - `NOT NULL`, no default\n */\n geom?: c.PgGeometry | db.Parameter | db.SQLFragment | db.SQLFragment | db.SQLFragment>;\n }\n export type UniqueIndex = 'stores_pkey';\n export type Column = keyof Selectable;\n export type OnlyCols = Pick;\n export type SQLExpression = Table | db.ColumnNames | db.ColumnValues | Whereable | Column | db.ParentColumn | db.GenericSQLExpression;\n export type SQL = SQLExpression | SQLExpression[];\n }\n\n /**\n * **subjectPhotos**\n * - Table in database\n */\n export namespace subjectPhotos {\n export type Table = 'subjectPhotos';\n export interface Selectable {\n /**\n * **subjectPhotos.subjectId**\n * - `int4` in database\n * - `NOT NULL`, no default\n */\n subjectId: number;\n /**\n * **subjectPhotos.photoId**\n * - `int4` in database\n * - `NOT NULL`, no default\n */\n photoId: number;\n }\n export interface JSONSelectable {\n /**\n * **subjectPhotos.subjectId**\n * - `int4` in database\n * - `NOT NULL`, no default\n */\n subjectId: number;\n /**\n * **subjectPhotos.photoId**\n * - `int4` in database\n * - `NOT NULL`, no default\n */\n photoId: number;\n }\n export interface Whereable {\n /**\n * **subjectPhotos.subjectId**\n * - `int4` in database\n * - `NOT NULL`, no default\n */\n subjectId?: number | db.Parameter | db.SQLFragment | db.ParentColumn | db.SQLFragment | db.SQLFragment | db.ParentColumn>;\n /**\n * **subjectPhotos.photoId**\n * - `int4` in database\n * - `NOT NULL`, no default\n */\n photoId?: number | db.Parameter | db.SQLFragment | db.ParentColumn | db.SQLFragment | db.SQLFragment | db.ParentColumn>;\n }\n export interface Insertable {\n /**\n * **subjectPhotos.subjectId**\n * - `int4` in database\n * - `NOT NULL`, no default\n */\n subjectId: number | db.Parameter | db.SQLFragment;\n /**\n * **subjectPhotos.photoId**\n * - `int4` in database\n * - `NOT NULL`, no default\n */\n photoId: number | db.Parameter | db.SQLFragment;\n }\n export interface Updatable {\n /**\n * **subjectPhotos.subjectId**\n * - `int4` in database\n * - `NOT NULL`, no default\n */\n subjectId?: number | db.Parameter | db.SQLFragment | db.SQLFragment | db.SQLFragment>;\n /**\n * **subjectPhotos.photoId**\n * - `int4` in database\n * - `NOT NULL`, no default\n */\n photoId?: number | db.Parameter | db.SQLFragment | db.SQLFragment | db.SQLFragment>;\n }\n export type UniqueIndex = 'userphotosunique';\n export type Column = keyof Selectable;\n export type OnlyCols = Pick;\n export type SQLExpression = Table | db.ColumnNames | db.ColumnValues | Whereable | Column | db.ParentColumn | db.GenericSQLExpression;\n export type SQL = SQLExpression | SQLExpression[];\n }\n\n /**\n * **subjects**\n * - Table in database\n */\n export namespace subjects {\n export type Table = 'subjects';\n export interface Selectable {\n /**\n * **subjects.subjectId**\n * - `int4` in database\n * - `NOT NULL`, identity column\n */\n subjectId: number;\n /**\n * **subjects.name**\n * - `text` in database\n * - `NOT NULL`, no default\n */\n name: string;\n }\n export interface JSONSelectable {\n /**\n * **subjects.subjectId**\n * - `int4` in database\n * - `NOT NULL`, identity column\n */\n subjectId: number;\n /**\n * **subjects.name**\n * - `text` in database\n * - `NOT NULL`, no default\n */\n name: string;\n }\n export interface Whereable {\n /**\n * **subjects.subjectId**\n * - `int4` in database\n * - `NOT NULL`, identity column\n */\n subjectId?: number | db.Parameter | db.SQLFragment | db.ParentColumn | db.SQLFragment | db.SQLFragment | db.ParentColumn>;\n /**\n * **subjects.name**\n * - `text` in database\n * - `NOT NULL`, no default\n */\n name?: string | db.Parameter | db.SQLFragment | db.ParentColumn | db.SQLFragment | db.SQLFragment | db.ParentColumn>;\n }\n export interface Insertable {\n /**\n * **subjects.subjectId**\n * - `int4` in database\n * - `NOT NULL`, identity column\n */\n subjectId?: number | db.Parameter | db.DefaultType | db.SQLFragment;\n /**\n * **subjects.name**\n * - `text` in database\n * - `NOT NULL`, no default\n */\n name: string | db.Parameter | db.SQLFragment;\n }\n export interface Updatable {\n /**\n * **subjects.subjectId**\n * - `int4` in database\n * - `NOT NULL`, identity column\n */\n subjectId?: number | db.Parameter | db.DefaultType | db.SQLFragment | db.SQLFragment | db.DefaultType | db.SQLFragment>;\n /**\n * **subjects.name**\n * - `text` in database\n * - `NOT NULL`, no default\n */\n name?: string | db.Parameter | db.SQLFragment | db.SQLFragment | db.SQLFragment>;\n }\n export type UniqueIndex = 'subjects_pkey';\n export type Column = keyof Selectable;\n export type OnlyCols = Pick;\n export type SQLExpression = Table | db.ColumnNames | db.ColumnValues | Whereable | Column | db.ParentColumn | db.GenericSQLExpression;\n export type SQL = SQLExpression | SQLExpression[];\n }\n\n /**\n * **tags**\n * - Table in database\n */\n export namespace tags {\n export type Table = 'tags';\n export interface Selectable {\n /**\n * **tags.tag**\n * - `text` in database\n * - `NOT NULL`, no default\n */\n tag: string;\n /**\n * **tags.bookId**\n * - `int4` in database\n * - `NOT NULL`, no default\n */\n bookId: number;\n }\n export interface JSONSelectable {\n /**\n * **tags.tag**\n * - `text` in database\n * - `NOT NULL`, no default\n */\n tag: string;\n /**\n * **tags.bookId**\n * - `int4` in database\n * - `NOT NULL`, no default\n */\n bookId: number;\n }\n export interface Whereable {\n /**\n * **tags.tag**\n * - `text` in database\n * - `NOT NULL`, no default\n */\n tag?: string | db.Parameter | db.SQLFragment | db.ParentColumn | db.SQLFragment | db.SQLFragment | db.ParentColumn>;\n /**\n * **tags.bookId**\n * - `int4` in database\n * - `NOT NULL`, no default\n */\n bookId?: number | db.Parameter | db.SQLFragment | db.ParentColumn | db.SQLFragment | db.SQLFragment | db.ParentColumn>;\n }\n export interface Insertable {\n /**\n * **tags.tag**\n * - `text` in database\n * - `NOT NULL`, no default\n */\n tag: string | db.Parameter | db.SQLFragment;\n /**\n * **tags.bookId**\n * - `int4` in database\n * - `NOT NULL`, no default\n */\n bookId: number | db.Parameter | db.SQLFragment;\n }\n export interface Updatable {\n /**\n * **tags.tag**\n * - `text` in database\n * - `NOT NULL`, no default\n */\n tag?: string | db.Parameter | db.SQLFragment | db.SQLFragment | db.SQLFragment>;\n /**\n * **tags.bookId**\n * - `int4` in database\n * - `NOT NULL`, no default\n */\n bookId?: number | db.Parameter | db.SQLFragment | db.SQLFragment | db.SQLFragment>;\n }\n export type UniqueIndex = 'tagsUniqueIdx';\n export type Column = keyof Selectable;\n export type OnlyCols = Pick;\n export type SQLExpression = Table | db.ColumnNames | db.ColumnValues | Whereable | Column | db.ParentColumn | db.GenericSQLExpression;\n export type SQL = SQLExpression | SQLExpression[];\n }\n\n /**\n * **usedVoucherCodes**\n * - Table in database\n */\n export namespace usedVoucherCodes {\n export type Table = 'usedVoucherCodes';\n export interface Selectable {\n /**\n * **usedVoucherCodes.code**\n * - `text` in database\n * - `NOT NULL`, no default\n */\n code: string;\n /**\n * **usedVoucherCodes.redeemedAt**\n * - `timestamptz` in database\n * - `NOT NULL`, default: `now()`\n */\n redeemedAt: Date;\n }\n export interface JSONSelectable {\n /**\n * **usedVoucherCodes.code**\n * - `text` in database\n * - `NOT NULL`, no default\n */\n code: string;\n /**\n * **usedVoucherCodes.redeemedAt**\n * - `timestamptz` in database\n * - `NOT NULL`, default: `now()`\n */\n redeemedAt: db.TimestampTzString;\n }\n export interface Whereable {\n /**\n * **usedVoucherCodes.code**\n * - `text` in database\n * - `NOT NULL`, no default\n */\n code?: string | db.Parameter | db.SQLFragment | db.ParentColumn | db.SQLFragment | db.SQLFragment | db.ParentColumn>;\n /**\n * **usedVoucherCodes.redeemedAt**\n * - `timestamptz` in database\n * - `NOT NULL`, default: `now()`\n */\n redeemedAt?: (db.TimestampTzString | Date) | db.Parameter<(db.TimestampTzString | Date)> | db.SQLFragment | db.ParentColumn | db.SQLFragment | db.SQLFragment | db.ParentColumn>;\n }\n export interface Insertable {\n /**\n * **usedVoucherCodes.code**\n * - `text` in database\n * - `NOT NULL`, no default\n */\n code: string | db.Parameter | db.SQLFragment;\n /**\n * **usedVoucherCodes.redeemedAt**\n * - `timestamptz` in database\n * - `NOT NULL`, default: `now()`\n */\n redeemedAt?: (db.TimestampTzString | Date) | db.Parameter<(db.TimestampTzString | Date)> | db.DefaultType | db.SQLFragment;\n }\n export interface Updatable {\n /**\n * **usedVoucherCodes.code**\n * - `text` in database\n * - `NOT NULL`, no default\n */\n code?: string | db.Parameter | db.SQLFragment | db.SQLFragment | db.SQLFragment>;\n /**\n * **usedVoucherCodes.redeemedAt**\n * - `timestamptz` in database\n * - `NOT NULL`, default: `now()`\n */\n redeemedAt?: (db.TimestampTzString | Date) | db.Parameter<(db.TimestampTzString | Date)> | db.DefaultType | db.SQLFragment | db.SQLFragment | db.DefaultType | db.SQLFragment>;\n }\n export type UniqueIndex = 'usedVoucherCodes_pkey';\n export type Column = keyof Selectable;\n export type OnlyCols = Pick;\n export type SQLExpression = Table | db.ColumnNames | db.ColumnValues