diff --git a/.claude/add-a-dialect.md b/.claude/add-a-dialect.md new file mode 100644 index 0000000000..284bbce905 --- /dev/null +++ b/.claude/add-a-dialect.md @@ -0,0 +1,184 @@ +# Adding a new database dialect + +A walkthrough of every file you need to touch, in roughly the order you should touch them. The +SQLite support PR is the cleanest recent reference — every step below points at a SQLite analogue. + +## 0. What the upstream `foundations-jdbc` library must already provide + +`typr` is the code generator; the runtime types and codecs live in the external +`dev.typr.foundations:foundations-jdbc` library. Before you start, make sure that library exposes: + +- A typed types catalogue, e.g. `dev.typr.foundations.XxxTypes` with one entry per declarable type + (integer/varchar/decimal/date/…). Each entry is a `XxxType` carrying the read/write + codec and JSON codec. +- `dev.typr.foundations.connect.XxxConfig` for building a JDBC connection, and + `DatabaseKind.XXX` enum value. +- Scala and Kotlin wrappers: `dev.typr.foundationssc.XxxTypes` and + `dev.typr.foundationskt.XxxTypes`. + +If any of these are missing, send the PR to foundations first. + +## 1. Add a `Dialect` entry + +File: `typr-dsl/src/java/dev/typr/dsl/Dialect.java` — the DSL's per-dialect SQL grammar bits +(identifier quoting, casts, null-safe comparison, LIMIT/OFFSET, tuple-IN support). + +The `Dialect` interface has reasonable defaults for everything except `bigint()`, `quoteIdent()`, +`escapeIdent()`, `typeCast()`, `columnRef()`, `nullSafeEquals()`, `nullSafeNotEquals()` — override +just what differs from the default (PostgreSQL-shaped) behaviour. + +Re-export it in the Scala wrapper at +`typr-dsl-scala/src/scala/dev/typr/dslsc/package.scala`'s `object Dialect`. + +(Kotlin can use the Java static field directly — no wrapper needed.) + +## 2. Define the `db.XxxType` ADT + +File: `typr-codegen/src/scala/typr/db.scala`. + +Add a `sealed trait XxxType extends Type` plus one `case object` (or `case class` for parameterised +types like `Decimal(precision, scale)`) per concrete declarable type. Add `XxxType` to the +`Unknown` mixin trait list at the bottom — that's the fallback for unrecognised JDBC type names. + +## 3. Add `DbType.Xxx` + connection plumbing + +Files: + +- `typr-codegen/src/scala/typr/DbType.scala` — add `case object Xxx extends DbType` returning your + adapter, plus a branch in `detect(...)` and `detectFromDriver(...)`. +- `typr-codegen/src/scala/typr/TypoDataSource.scala` — add a `hikariXxx*(...)` constructor and a + `DatabaseKind.XXX` branch in `hikari(...)`. + +## 4. Write the codegen adapter + +File: `typr-codegen/src/scala/typr/internal/codegen/XxxAdapter.scala`. + +Mirror `DuckDbAdapter` (closest in spirit for most embedded DBs) or `Db2Adapter` (single-schema, +no native arrays). Five layers: + +1. **SQL syntax** — `quoteIdent`, `typeCast`, the various `columnReadCast`/`columnWriteCast` (most + dialects can return `Code.Empty`). +2. **Runtime types** — point at `XxxTypes` / `XxxType` / `XxxText` and pick a `typeFieldName` + (e.g. `xxxType`). +3. **Capabilities** — `supportsArrays`, `supportsReturning`, `supportsCopyStreaming`, the upsert + strategy. +4. **SQL templates** — upsert (`ON CONFLICT` vs `MERGE`), conflict update clause, returning clause. +5. **Schema DDL** — `dropSchemaDdl` / `createSchemaDdl`. For dialects without schemas (SQLite, + embedded DBs), return a SQL comment. + +## 5. Write the metadata-extraction package + +Directory: `typr-codegen/src/scala/typr/internal/xxx/`. Four files: + +- `XxxJdbcMetadata.scala` — wraps `ResultSetMetaData` into `MetadataColumn`. This is essentially + identical across dialects — copy `DuckDbJdbcMetadata` and rename. +- `XxxTypeMapperDb.scala` — maps the declared/JDBC type name string to a `db.XxxType`. Read your + database's reference for type aliases; many dialects accept synonyms (BIGINT/INT8/LONG/…). +- `XxxSqlFileMetadata.scala` — analyses user-supplied `.sql` files using sqlglot. Copy + `DuckDbSqlFileMetadata`; the only dialect-specific bits are (a) how you read the schema (the + catalogue queries) and (b) the sqlglot `dialect` string. +- `XxxMetaDb.scala` — reads tables/columns/PKs/FKs/uniques/views from the database catalogue. + Look at how your DB exposes metadata (information_schema, system catalog views, or PRAGMAs) and + shape the queries to fit. Return a `MetaDb(dbType, relations, enums = Nil, domains = Nil, …)`. + +## 6. Wire all dispatch sites + +These are the files that have one `case DbType.X => …` arm per dialect. Each new dialect needs an +arm added everywhere: + +- `typr-codegen/src/scala/typr/MetaDb.scala` — both the `typeMapperDb` match and the `fromDb` + match. +- `typr-codegen/src/scala/typr/internal/InstanceRequirements.scala` — the heuristic name guess + and the `dbTypeFieldNameFor` map. +- `typr-codegen/src/scala/typr/internal/generate.scala` — the `databaseName` string used as a + TypeDefinition discriminator, **plus** the precision-types case list near the bottom that emits + `PreciseConstraint.*` for `VarChar(Some(n))` etc. +- `typr-codegen/src/scala/typr/internal/codegen/DbLibFoundations.scala` — selectByIds / + deleteByIds bodies. If your DB has no native arrays (most non-Postgres do), fold it into the + existing `case DbType.SqlServer | DbType.DB2 | …` arms rather than copy-pasting. +- `typr-codegen/src/scala/typr/internal/sqlfiles/SqlFileReader.scala` — dispatch to your + `XxxSqlFileMetadata`. +- `typr-codegen/src/scala/typr/internal/TypeMapperJvmNew.scala` — both the `baseType` and the + precise-types match. (`TypeMapperJvmOld` is PostgreSQL-only legacy; skip.) +- `typr-codegen/src/scala/typr/internal/TypeMatcher.scala` — `typeName` (for the matcher's + per-column name string). +- `typr-codegen/src/scala/typr/internal/TypeCompatibilityChecker.scala` — add a `CompatibilityClass` + arm for every Java-equivalent class (String/Boolean/Int/Long/…) so cross-dialect Bridge type + matching works. +- `typr-codegen/src/scala/typr/internal/ComputedTestInserts.scala` — the `case`s for max-length + detection on text columns. +- `typr/src/scala/typr/bridge/TypeSuggester.scala` — group types into the "text/integer/numeric/ + boolean/temporal/uuid/json" buckets the bridge UI uses. + +## 7. CLI wiring + +- `typr-config.schema.json` — add `"xxx"` to the boundary `type` enum and add a `xxxBoundary` + definition (use `duckdbBoundary` as a template for embedded DBs, or `databaseBoundary` for + server-based ones). +- Run `bleep run generate-config-types` to regenerate the typed config classes + (`XxxBoundary.scala` shows up under `typr-codegen/generated-and-checked-in-jsonschema/`). +- `typr/src/scala/typr/cli/config/ConfigParser.scala` — add `Some("xxx") => …` arms for source + *and* boundary parsing, and add `ParsedSource.Xxx` / `ParsedBoundary.Xxx` cases. +- `typr/src/scala/typr/cli/config/ConfigToOptions.scala` — `convertXxxBoundary` + `convertXxxSource`. +- `typr/src/scala/typr/cli/commands/Generate.scala` — `fetchXxxBoundary`, `fetchXxxSource`, + `generateXxxForOutput`, plus the two dispatch sites in `runTwoPhaseGeneration`. Watch for any + driver-specific quirks loading the schema (SQLite's xerial driver, for example, can't run + multi-statement strings in a single `execute()` — the SQLite path splits on `;` first). +- `typr/src/scala/typr/cli/app/MetaDbFetch.scala` — add a `ParsedSource.Xxx` arm + `fetchXxx`. +- `typr/src/scala/typr/cli/app/ConnectionTest.scala` — add a `ParsedSource.Xxx` arm + `tryXxx`, + and include `Xxx` in `isTestable`'s pattern. +- `typr/src/scala/typr/cli/app/LoadedSource.scala` — include `ParsedSource.Xxx` in the database + pattern arm. +- The TUI screens (`SchemaPicker`, `SourceForm`, `SourceList`, `MainMenu`) — fold the new kind + string into the existing `"duckdb" | "xxx"` cases for path-style sources, or use the database + patterns for host/port sources. + +## 8. Build wiring + +- `bleep.yaml` — add three tester project entries (`testers/xxx/java`, `testers/xxx/kotlin`, + `testers/xxx/scala`), each with the right JDBC driver dependency. Also add the driver to the + `typr-codegen` project's dependencies so the CLI can connect. +- `typr.yaml` — add a boundary entry (with `schema_sql`, `sql_scripts`, `path` or host/port) and + three outputs (`xxx-java`, `xxx-kotlin`, `xxx-scala`). + +## 9. Test data + scripts + +- `sql-init/xxx/00-schema.sql` — exercise every column type your `db.XxxType` ADT models, plus + composite PK, composite FK, UNIQUE, views, and `precision_types[_null]` for precise-type + generation. +- `sql-scripts/xxx/*.sql` — half a dozen parameterised queries covering SELECT, INSERT-with- + RETURNING, UPDATE, DELETE, JOIN. + +## 10. Testers + +Under `testers/xxx/{java,kotlin,scala}` add a `src/{lang}/testdb/XxxTestHelper` and a +`BasicCrudTest` that exercises the generated repos. Mirror `testers/duckdb/{java,kotlin,scala}` — +if your driver supports multi-statement `execute()`, you can use `connectionInitSql(schema)` +directly; otherwise split the schema yourself (SQLite shows this pattern). + +## 11. Generate, fmt, test + +```bash +bleep run typr -- generate --source xxx --accept +bleep fmt +bleep test testers/xxx +``` + +## Things that bit me on SQLite specifically + +- **Single connection, in-memory.** `:memory:` databases live inside one JDBC connection; opening + a second connection gives you an empty DB. Foundations' `singleConnectionMode()` handles the + reuse but `connectionInitSql` runs once via a *single* `stmt.execute(...)` — for drivers that + don't accept multi-statement strings (xerial SQLite is one) the schema only partially loads. + The fix is to bypass `connectionInitSql` and run statements one at a time during a one-shot + init, then switch the transactor to `rollbackOnly()` for tests. +- **No schemas.** Force `SchemaMode.SingleSchema("main")` in your `convertXxxBoundary`, and emit + `RelationName(None, name)` in metadata. SQLite's `main` namespace isn't really a schema. +- **Type affinity, not declared type.** SQLite stores values in five storage classes regardless + of column declaration — your `XxxTypeMapperDb` needs to match common synonyms (BIGINT, INT8, + INT2, VARCHAR(n), CLOB, …) to a specific `db.XxxType` so the codecs round-trip. The full + affinity-substring fallback at the bottom of `SqliteTypeMapperDb` handles "anything goes" cases + (`VARYING CHARACTER`, `DOUBLE PRECISION`, etc.). +- **Foreign keys off by default.** SQLite needs `PRAGMA foreign_keys = ON` per connection. The + foundations `SqliteConfig.Builder.foreignKeys(true)` sets it via a driver property, but if + you're opening raw JDBC for tests, set it yourself. diff --git a/CLAUDE.md b/CLAUDE.md index bc3d774f42..0a849e74d5 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -15,10 +15,14 @@ Typr is a database code generator that creates type-safe JVM code from database - **DuckDB** - embedded analytical database - **SQL Server** - T-SQL specific features - **Oracle** - including OBJECT and MULTISET types +- **DB2** - including distinct types +- **SQLite** - embedded, type-affinity model with foundations SqliteTypes aliases + +When adding a new dialect, follow [`.claude/add-a-dialect.md`](.claude/add-a-dialect.md) — a touch-point checklist distilled from the SQLite work. ## Foundations JDBC -`foundations-jdbc` is a standalone JDBC wrapper library with perfect type modeling for all supported databases. See `site/docs-jdbc/` for full documentation. +`foundations-jdbc` is a standalone JDBC wrapper library with perfect type modeling for all supported databases. It lives in its own repository (`dev.typr.foundations:foundations-jdbc`, currently RC6) — typr depends on it as a Maven artifact, not as a submodule. Its docs ship from that repo, not from this one. ## Build System @@ -143,6 +147,7 @@ All databases use `sql-init/{database}/` for schema initialization, mounted to ` - **SQL Server**: `sql-init/sqlserver/` - Custom entrypoint `00-entrypoint.sh` starts server and runs SQL - **DB2**: `sql-init/db2/` - Shell script `00-run-sql.sh` runs SQL files - **DuckDB**: `sql-init/duckdb/` - Loaded by generation script (embedded database, no docker) +- **SQLite**: `sql-init/sqlite/` - Loaded by generation script (embedded database, no docker) ### Ensuring Databases Are Up to Date @@ -296,6 +301,8 @@ typr/ # Main code generator │ ├── mariadb/ # MariaDB adapter │ ├── oracle/ # Oracle adapter │ ├── duckdb/ # DuckDB adapter +│ ├── db2/ # DB2 adapter +│ ├── sqlite/ # SQLite adapter │ └── sqlserver/ # SQL Server adapter │ └── openapi/ # OpenAPI code generation @@ -308,6 +315,8 @@ testers/ # Integration test projects ├── duckdb/ # DuckDB testers (java, kotlin, scala) ├── oracle/ # Oracle testers (java, kotlin, scala) ├── sqlserver/ # SQL Server testers (java, kotlin, scala) +├── db2/ # DB2 testers (java, kotlin, scala) +├── sqlite/ # SQLite testers (java, kotlin, scala) └── openapi/ # OpenAPI framework testers ├── java/ # JAX-RS, Spring, Quarkus ├── kotlin/ # JAX-RS, Spring, Quarkus @@ -332,14 +341,18 @@ sql-init/ # Schema files (mounted to Docker) ├── mariadb/ # MariaDB schemas ├── oracle/ # Oracle schemas ├── sqlserver/ # SQL Server schemas -└── duckdb/ # DuckDB schemas (loaded by script) +├── duckdb/ # DuckDB schemas (loaded by script) +├── db2/ # DB2 schemas +└── sqlite/ # SQLite schemas (loaded by script) sql-scripts/ # SQL query files for code generation ├── postgres/ # PostgreSQL SQL queries ├── mariadb/ # MariaDB SQL queries ├── sqlserver/ # SQL Server SQL queries ├── oracle/ # Oracle SQL queries -└── duckdb/ # DuckDB SQL queries +├── duckdb/ # DuckDB SQL queries +├── db2/ # DB2 SQL queries +└── sqlite/ # SQLite SQL queries typr-internal-sql/ # Internal SQL for Typr codegen ``` diff --git a/bleep.yaml b/bleep.yaml index 950a748e95..faf103fdf1 100644 --- a/bleep.yaml +++ b/bleep.yaml @@ -149,6 +149,42 @@ projects: sources: - ./generated-and-checked-in - ./src/scala + testers/sqlite/java: + dependencies: + - com.fasterxml.jackson.core:jackson-annotations:2.17.2 + - com.fasterxml.jackson.core:jackson-databind:2.17.2 + - com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.17.2 + - com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.17.2 + - com.github.sbt:junit-interface:0.13.3 + - junit:junit:4.13.2 + - org.xerial:sqlite-jdbc:3.46.1.3 + dependsOn: typr-dsl + isTestProject: true + java: + options: -proc:none + platform: + name: jvm + sources: + - ./generated-and-checked-in + - ./src/java + testers/sqlite/kotlin: + dependencies: org.xerial:sqlite-jdbc:3.46.1.3 + extends: template-kotlin-db-tester + testers/sqlite/scala: + dependencies: + - com.fasterxml.jackson.core:jackson-annotations:2.17.2 + - com.fasterxml.jackson.core:jackson-databind:2.17.2 + - com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.17.2 + - com.fasterxml.jackson.datatype:jackson-datatype-jsr310:2.17.2 + - com.github.sbt:junit-interface:0.13.3 + - junit:junit:4.13.2 + - org.xerial:sqlite-jdbc:3.46.1.3 + dependsOn: typr-dsl-scala + extends: template-scala-3 + isTestProject: true + sources: + - ./generated-and-checked-in + - ./src/scala testers/duckdb/java: dependencies: - com.fasterxml.jackson.core:jackson-annotations:2.17.2 @@ -937,6 +973,7 @@ projects: - org.playframework.anorm::anorm:2.7.0 - org.postgresql:postgresql:42.7.3 - org.slf4j:slf4j-nop:2.0.13 + - org.xerial:sqlite-jdbc:3.46.1.3 dependsOn: typr-dsl-scala extends: - template-scala-3 diff --git a/site/docs-typr/boundaries/databases/readme.md b/site/docs-typr/boundaries/databases/readme.md index 69c0cd2b11..e5ffe9f26c 100644 --- a/site/docs-typr/boundaries/databases/readme.md +++ b/site/docs-typr/boundaries/databases/readme.md @@ -22,7 +22,7 @@ The compiler checks your application code. But at the database boundary, you're Typr DB treats your database schema as the source of truth: -1. **Read your schema** from PostgreSQL, MariaDB, Oracle, SQL Server, DuckDB, or DB2 +1. **Read your schema** from PostgreSQL, MariaDB, Oracle, SQL Server, DuckDB, DB2, or SQLite 2. **Generate typed code** for every table, view, and relationship 3. **Enforce at compile time** that all database access uses the correct types @@ -57,6 +57,7 @@ When you change a column, rename a table, or modify a relationship—the compile | SQL Server | Full support | | DuckDB | Full support | | IBM DB2 | Full support | +| SQLite | Full support | ## Supported Languages diff --git a/site/docs-typr/boundaries/databases/setup.md b/site/docs-typr/boundaries/databases/setup.md index 7444fe63de..f679d4bbeb 100644 --- a/site/docs-typr/boundaries/databases/setup.md +++ b/site/docs-typr/boundaries/databases/setup.md @@ -19,6 +19,11 @@ For complete installation and configuration instructions, see the [Getting Start | Oracle | Full support including OBJECT and MULTISET types | | DuckDB | Full support for embedded analytical workloads | | IBM DB2 | Full support including distinct types | +| SQLite | Full support for embedded workloads — every type affinity, RETURNING, ON CONFLICT upserts | + +:::tip SQLite foreign keys +SQLite parses `REFERENCES` clauses but doesn't enforce them unless `PRAGMA foreign_keys = ON` is set on each connection. The `SqliteConfig.Builder.foreignKeys(true)` helper writes this as a driver property so every pooled connection inherits it — turn it on explicitly if you're building a `SqliteConfig` by hand. +::: ### Configuration Example @@ -54,6 +59,7 @@ Each database has unique features that Typr models with full fidelity: - **Oracle**: OBJECT types, nested tables, MULTISET - **SQL Server**: Alias types, table-valued parameters - **DuckDB**: Nested types, structs, lists +- **SQLite**: Type-affinity model with aliases (BIGINT/INT8/VARCHAR/CLOB...), ISO-8601 date/time as TEXT, no schemas See [Type Safety](/typr/boundaries/databases/type-safety/id-types) for details on how these are represented in generated code. diff --git a/site/docs-typr/boundaries/databases/type-safety/arrays.md b/site/docs-typr/boundaries/databases/type-safety/arrays.md index 5d32c6fa33..2387812781 100644 --- a/site/docs-typr/boundaries/databases/type-safety/arrays.md +++ b/site/docs-typr/boundaries/databases/type-safety/arrays.md @@ -18,6 +18,7 @@ Typr provides full support for array and list types across databases that suppor | Oracle | VARRAY, Nested Table | Via collection types | | SQL Server | - | No array support | | DB2 | - | No array support | +| SQLite | - | No array support | ## PostgreSQL Arrays diff --git a/site/docs-typr/boundaries/databases/type-safety/collection-types.md b/site/docs-typr/boundaries/databases/type-safety/collection-types.md index 12582c5946..d4b83eda6f 100644 --- a/site/docs-typr/boundaries/databases/type-safety/collection-types.md +++ b/site/docs-typr/boundaries/databases/type-safety/collection-types.md @@ -18,6 +18,7 @@ Some databases support collection types for storing multiple values in a single | SQL Server | Table-valued parameters | Procedure parameters only | | MariaDB/MySQL | JSON arrays | No native arrays | | DB2 | - | No native collections | +| SQLite | - | No native collections | ## PostgreSQL Arrays @@ -97,7 +98,7 @@ Currently mapped to String for flexibility. Native Map support is planned. ## Databases Without Collection Support -MariaDB/MySQL, SQL Server (outside of table types), and DB2 don't have native array types. Alternatives: +MariaDB/MySQL, SQL Server (outside of table types), DB2, and SQLite don't have native array types. Alternatives: - **JSON arrays** - Flexible but less type-safe - **Junction tables** - For many-to-many relationships - **Table-valued parameters** (SQL Server) - For procedure parameters diff --git a/site/docs-typr/boundaries/databases/type-safety/date-time.md b/site/docs-typr/boundaries/databases/type-safety/date-time.md index 9d8fbf07f0..b2fe50950a 100644 --- a/site/docs-typr/boundaries/databases/type-safety/date-time.md +++ b/site/docs-typr/boundaries/databases/type-safety/date-time.md @@ -66,6 +66,17 @@ DuckDB has modern date/time handling: - Microsecond precision - No timezone conversion issues +### SQLite + +SQLite has no native date/time storage class — values are stored as ISO-8601 TEXT (the xerial driver default). Typr generates `LocalDate` / `LocalTime` / `LocalDateTime` / `Instant` codecs that parse and produce the ISO-8601 format, matching the SqliteTypes catalogue. + +- `DATE` → `LocalDate` (ISO-8601 date) +- `TIME` → `LocalTime` +- `DATETIME` / `TIMESTAMP` → `LocalDateTime` +- `TIMESTAMP` (with `Z` suffix) → `Instant` + +Other SQLite date storage modes (INTEGER unix epoch, REAL Julian day) are configurable via `SqliteConfig.dateClass(...)` but require custom codecs — they don't round-trip through the default Typr codegen. + ### Oracle Oracle uses different type names: diff --git a/site/docs-typr/boundaries/databases/type-safety/domains.md b/site/docs-typr/boundaries/databases/type-safety/domains.md index eb9a109831..f57631e9ad 100644 --- a/site/docs-typr/boundaries/databases/type-safety/domains.md +++ b/site/docs-typr/boundaries/databases/type-safety/domains.md @@ -37,6 +37,7 @@ transferFunds(toAccountId, fromAccountId, amount); | DuckDB | - | No domain support, use bimap | | MariaDB | - | No domain support, use bimap | | DB2 | - | No domain support, use bimap | +| SQLite | - | No domain support, use bimap | ## PostgreSQL Domains @@ -80,7 +81,7 @@ Typr generates the same wrapper types as for PostgreSQL domains. ## Databases Without Domain Support -For Oracle, DuckDB, MariaDB, and DB2, use `bimap` to create wrapper types manually: +For Oracle, DuckDB, MariaDB, DB2, and SQLite, use `bimap` to create wrapper types manually: ```java public record AccountId(Long value) {} @@ -100,6 +101,10 @@ OracleType accountIdType = // DuckDB DuckDbType accountIdType = DuckDbTypes.bigint.bimap(AccountId::new, AccountId::value); + +// SQLite +SqliteType accountIdType = + SqliteTypes.integer.bimap(AccountId::new, AccountId::value); ``` ## Benefits diff --git a/site/docs-typr/boundaries/databases/type-safety/enums.md b/site/docs-typr/boundaries/databases/type-safety/enums.md index c9c085451d..e5c5011b3e 100644 --- a/site/docs-typr/boundaries/databases/type-safety/enums.md +++ b/site/docs-typr/boundaries/databases/type-safety/enums.md @@ -17,6 +17,8 @@ Typr generates type-safe enum types from your database schema. Support varies by | MariaDB/MySQL | - | `ENUM('a','b')` column type | Table-based | | Oracle | - | - | Table-based | | SQL Server | - | - | Table-based | +| DB2 | - | - | Table-based | +| SQLite | - | - | Table-based (use `CHECK (col IN ('a','b'))`) | ## Native Enums (PostgreSQL, DuckDB) @@ -51,9 +53,9 @@ CREATE TABLE customer_order ( Since inline enums don't have a schema-level name, Typr maps them to `String`. The allowed values are still enforced by the database, but there's no compile-time type checking. -## No Native Enums (Oracle, SQL Server, DB2) +## No Native Enums (Oracle, SQL Server, DB2, SQLite) -Oracle, SQL Server, and DB2 do not have native enum types. Common alternatives: +Oracle, SQL Server, DB2, and SQLite do not have native enum types. Common alternatives: - **CHECK constraints** on string columns (validated by database, mapped to String) - **Lookup tables** with foreign key constraints (see [Open Enums](/typr/boundaries/databases/type-safety/open-enums)) diff --git a/site/docs-typr/boundaries/databases/type-safety/maps.md b/site/docs-typr/boundaries/databases/type-safety/maps.md index ef5db2dea8..a28c6816ad 100644 --- a/site/docs-typr/boundaries/databases/type-safety/maps.md +++ b/site/docs-typr/boundaries/databases/type-safety/maps.md @@ -16,6 +16,7 @@ Map types store key-value pairs within a single column. Support varies by databa | Oracle | - | No map support | | SQL Server | - | No map support | | DB2 | - | No map support | +| SQLite | - | No map support | ## PostgreSQL hstore diff --git a/site/docs-typr/boundaries/databases/type-safety/precise-types.md b/site/docs-typr/boundaries/databases/type-safety/precise-types.md index b6eed88b5b..95eeeb3f7e 100644 --- a/site/docs-typr/boundaries/databases/type-safety/precise-types.md +++ b/site/docs-typr/boundaries/databases/type-safety/precise-types.md @@ -169,6 +169,8 @@ Precise Types work across all supported databases: | SQL Server | `StringN` | `PaddedStringN` | `DecimalN` | `LocalTimeN` | `LocalDateTimeN` / `OffsetDateTimeN` | | Oracle | `StringN` | `PaddedStringN` | `DecimalN` | - | `InstantN` | | DuckDB | `StringN` | - | `DecimalN` | `LocalTimeN` | `InstantN` | +| DB2 | `StringN` | `PaddedStringN` | `DecimalN` | - | `LocalDateTimeN` | +| SQLite | `StringN` | `PaddedStringN` | `DecimalN` | - | - | ## Language Support diff --git a/site/docs-typr/boundaries/databases/type-safety/struct-types.md b/site/docs-typr/boundaries/databases/type-safety/struct-types.md index 5df884607a..d658d62f69 100644 --- a/site/docs-typr/boundaries/databases/type-safety/struct-types.md +++ b/site/docs-typr/boundaries/databases/type-safety/struct-types.md @@ -18,6 +18,7 @@ A **struct type** (or composite type) combines multiple fields into a single str | SQL Server | **Table Types** | For table-valued parameters only | | MariaDB/MySQL | None | No composite type support | | DB2 | None | No composite type support | +| SQLite | None | No composite type support | ## PostgreSQL Composite Types @@ -76,7 +77,7 @@ Typr generates a record type for each distinct struct: ## Databases Without Struct Support -MariaDB/MySQL, SQL Server (outside of table types), and DB2 don't support composite types. Alternatives: +MariaDB/MySQL, SQL Server (outside of table types), DB2, and SQLite don't support composite types. Alternatives: - Use separate columns - Store as JSON - Use multiple related tables diff --git a/site/docs-typr/comparison.md b/site/docs-typr/comparison.md index 78361eb911..7391555907 100644 --- a/site/docs-typr/comparison.md +++ b/site/docs-typr/comparison.md @@ -13,7 +13,7 @@ Typr isn't the first tool to generate code from database schemas. Here's an hone |---------|------|------|---------|-----------| | **Approach** | Schema-first codegen | Schema-first codegen | Code-first DSL | Code-first ORM | | **Languages** | Java, Kotlin, Scala | Java (Kotlin via Java) | Kotlin | Java, Kotlin | -| **Databases** | 6 (Pg, Maria, Oracle, SQL Server, DuckDB, DB2) | 30+ | 6 | Most | +| **Databases** | 7 (Pg, Maria, Oracle, SQL Server, DuckDB, DB2, SQLite) | 30+ | 6 | Most | | **ID types** | Generated distinct types | No | No | No | | **SQL files** | First-class, typed | Via plain SQL | No | Via native queries | | **API generation** | Yes (OpenAPI) | No | No | No | @@ -107,7 +107,7 @@ Typr isn't the first tool to generate code from database schemas. Here's an hone | Aspect | sqlc | Typr | |--------|------|------| | **Language** | Go | Java, Kotlin, Scala | -| **Databases** | PostgreSQL, MySQL, SQLite | 6 including Oracle, SQL Server, DB2 | +| **Databases** | PostgreSQL, MySQL, SQLite | 7 including Oracle, SQL Server, DB2, SQLite | | **Repository generation** | No | Yes (CRUD for every table) | | **ID types** | No | Yes | | **DSL** | No | Yes | @@ -131,7 +131,7 @@ Typr isn't the first tool to generate code from database schemas. Here's an hone | Aspect | pgtyped | Typr | |--------|---------|------| | **Language** | TypeScript | Java, Kotlin, Scala | -| **Databases** | PostgreSQL only | 6 databases | +| **Databases** | PostgreSQL only | 7 databases | | **Repository generation** | No | Yes | | **ID types** | No | Yes | diff --git a/site/docs-typr/configuration.md b/site/docs-typr/configuration.md index fbd674b90e..6852bad8c6 100644 --- a/site/docs-typr/configuration.md +++ b/site/docs-typr/configuration.md @@ -128,6 +128,23 @@ sources: schemas: [DB2ADMIN] ``` +### SQLite + +```yaml +sources: + sqlite: + type: sqlite + path: ./data/app.db # File-backed + + # For in-memory database + # path: :memory: + + # Optional: load schema from a SQL file on connect (useful for :memory:) + schema_sql: sql-init/sqlite/00-schema.sql +``` + +SQLite has no schemas in the SQL-standard sense — typr generates everything under a single namespace. The xerial sqlite-jdbc driver is bundled in the typr CLI. + ### OpenAPI ```yaml diff --git a/site/docs-typr/index.md b/site/docs-typr/index.md index 1bcfdc3f8b..5a38e5555e 100644 --- a/site/docs-typr/index.md +++ b/site/docs-typr/index.md @@ -12,7 +12,7 @@ Typr generates type-safe code from your database schemas and OpenAPI specificati | Boundary | What it does | |----------|--------------| -| [Databases](/typr/boundaries/databases/) | Generate type-safe database access from PostgreSQL, MariaDB, Oracle, SQL Server, DuckDB, DB2 | +| [Databases](/typr/boundaries/databases/) | Generate type-safe database access from PostgreSQL, MariaDB, Oracle, SQL Server, DuckDB, DB2, SQLite | | [REST APIs](/typr/boundaries/apis/) | Generate type-safe servers and clients from OpenAPI specs | | [Unified Types](/typr/unified-types/) | Share types across all your boundaries | @@ -21,7 +21,7 @@ Typr generates type-safe code from your database schemas and OpenAPI specificati | Category | Supported | |----------|-----------| | **Languages** | Java 17+, Kotlin, Scala 2.13/3.x | -| **Databases** | PostgreSQL, MariaDB/MySQL, Oracle, SQL Server, DuckDB, DB2 | +| **Databases** | PostgreSQL, MariaDB/MySQL, Oracle, SQL Server, DuckDB, DB2, SQLite | | **API Frameworks** | Spring Boot, JAX-RS, Quarkus, Http4s | | **JSON Libraries** | Jackson, Circe, Play JSON, ZIO JSON | diff --git a/site/docs-typr/unified-types/configuration.md b/site/docs-typr/unified-types/configuration.md index fa22d5f5d8..36acc78493 100644 --- a/site/docs-typr/unified-types/configuration.md +++ b/site/docs-typr/unified-types/configuration.md @@ -102,6 +102,15 @@ sources: path: ./data/analytics.duckdb ``` +#### SQLite + +```yaml +sources: + sqlite: + type: sqlite + path: ./data/app.db # or :memory: +``` + #### OpenAPI ```yaml diff --git a/site/src/components/CodeSample/index.js b/site/src/components/CodeSample/index.js deleted file mode 100644 index cc5cb7970f..0000000000 --- a/site/src/components/CodeSample/index.js +++ /dev/null @@ -1,202 +0,0 @@ -/** - * CodeSample - Displays code from showcase-generated based on current stack selection - * - * This component: - * - Reads the current database/language from StackContext - * - Looks up the requested file in the code samples - * - Renders the code with syntax highlighting - * - Shows a helpful message if the sample doesn't exist for current selection - * - Can show tabs for available alternatives - */ - -import React from 'react'; -import CodeBlock from '@theme/CodeBlock'; -import { useStack } from '../../context/StackContext'; -import { getCodeSample, getAllSamplesForFile, DATABASES, LANGUAGES, DATABASE_LABELS, LANGUAGE_LABELS } from '../../data/codeSamples'; -import styles from './styles.module.css'; - -// Map language to Prism language for syntax highlighting -const PRISM_LANGUAGES = { - java: 'java', - kotlin: 'kotlin', - scala: 'scala', -}; - -/** - * Main CodeSample component - * - * @param {Object} props - * @param {string} props.file - The file name to display (e.g., "EmployeeRow") - * @param {string} [props.title] - Optional title to show above the code - * @param {boolean} [props.showTabs] - Whether to show language/db tabs when current selection doesn't exist - * @param {string} [props.className] - Additional CSS class - */ -export default function CodeSample({ file, title, showTabs = false, className }) { - const { database, language, setDatabase, setLanguage, databaseLabel, languageLabel } = useStack(); - - const code = getCodeSample(database, language, file); - const allSamples = getAllSamplesForFile(file); - - // If we have the code for current selection, show it - if (code) { - return ( -
- {title &&
{title}
} - - {code} - -
- ); - } - - // Find what's available - const availableCombinations = []; - for (const db of DATABASES) { - for (const lang of LANGUAGES) { - if (allSamples[db]?.[lang]) { - availableCombinations.push({ db, lang }); - } - } - } - - // If nothing is available at all, show error - if (availableCombinations.length === 0) { - return ( -
-
- Code sample {file} not found -
-
- ); - } - - // If showTabs, offer to switch to an available combination - if (showTabs) { - return ( -
- {title &&
{title}
} -
-

- {file} is not available for {databaseLabel}/{languageLabel}. -

-

Available for:

-
- {availableCombinations.slice(0, 6).map(({ db, lang }) => ( - - ))} -
-
-
- ); - } - - // Default: show first available with a note - const firstAvailable = availableCombinations[0]; - const fallbackCode = allSamples[firstAvailable.db][firstAvailable.lang]; - - return ( -
- {title &&
{title}
} -
- Not available for {databaseLabel}/{languageLabel}. Showing {DATABASE_LABELS[firstAvailable.db]}/{LANGUAGE_LABELS[firstAvailable.lang]}: -
- - {fallbackCode} - -
- ); -} - -/** - * Multi-language code sample that shows tabs for all available languages - * for the current database selection. - */ -export function CodeSampleTabs({ file, title, className }) { - const { database, language, setLanguage, databaseLabel } = useStack(); - const allSamples = getAllSamplesForFile(file); - - // Get languages available for current database - const availableLanguages = LANGUAGES.filter((lang) => allSamples[database]?.[lang]); - - if (availableLanguages.length === 0) { - return ( -
-
- Code sample {file} not available for {databaseLabel} -
-
- ); - } - - // Use selected language if available, otherwise first available - const activeLanguage = availableLanguages.includes(language) ? language : availableLanguages[0]; - const code = allSamples[database][activeLanguage]; - - return ( -
- {title &&
{title}
} -
- {availableLanguages.map((lang) => ( - - ))} -
- - {code} - -
- ); -} - -/** - * Shows a side-by-side comparison of the same file across multiple languages - */ -export function CodeSampleComparison({ file, title, languages = LANGUAGES, className }) { - const { database, databaseLabel } = useStack(); - const allSamples = getAllSamplesForFile(file); - - const availableLangs = languages.filter((lang) => allSamples[database]?.[lang]); - - if (availableLangs.length === 0) { - return ( -
-
- Code sample {file} not available for {databaseLabel} -
-
- ); - } - - return ( -
- {title &&
{title}
} -
- {availableLangs.map((lang) => ( -
-
{LANGUAGE_LABELS[lang]}
- - {allSamples[database][lang]} - -
- ))} -
-
- ); -} diff --git a/site/src/components/CodeSample/styles.module.css b/site/src/components/CodeSample/styles.module.css deleted file mode 100644 index 4a9b4285cf..0000000000 --- a/site/src/components/CodeSample/styles.module.css +++ /dev/null @@ -1,148 +0,0 @@ -.codeSample { - margin: 1rem 0; -} - -.title { - font-weight: 600; - font-size: 0.9rem; - color: var(--ifm-color-emphasis-700); - margin-bottom: 0.5rem; -} - -.notFound { - padding: 1rem; - background: var(--ifm-color-warning-contrast-background); - border: 1px solid var(--ifm-color-warning-dark); - border-radius: var(--ifm-code-border-radius); -} - -.notFoundMessage { - color: var(--ifm-color-warning-darkest); -} - -.notAvailable { - padding: 1rem; - background: var(--ifm-color-emphasis-100); - border: 1px solid var(--ifm-color-emphasis-300); - border-radius: var(--ifm-code-border-radius); -} - -.notAvailable p { - margin: 0 0 0.5rem; -} - -.notAvailable code { - font-weight: 600; -} - -.alternativeButtons { - display: flex; - flex-wrap: wrap; - gap: 0.5rem; - margin-top: 0.75rem; -} - -.alternativeButton { - padding: 0.375rem 0.75rem; - font-size: 0.875rem; - background: var(--ifm-color-primary); - color: white; - border: none; - border-radius: 0.25rem; - cursor: pointer; - transition: background 0.15s ease; -} - -.alternativeButton:hover { - background: var(--ifm-color-primary-dark); -} - -.fallbackNote { - font-size: 0.8rem; - color: var(--ifm-color-emphasis-600); - padding: 0.5rem 0.75rem; - background: var(--ifm-color-emphasis-100); - border-radius: var(--ifm-code-border-radius) var(--ifm-code-border-radius) 0 0; - border: 1px solid var(--ifm-color-emphasis-300); - border-bottom: none; - margin-bottom: -1px; -} - -/* Tabs variant */ -.withTabs { - border: 1px solid var(--ifm-color-emphasis-300); - border-radius: var(--ifm-code-border-radius); - overflow: hidden; -} - -.languageTabs { - display: flex; - background: var(--ifm-color-emphasis-100); - border-bottom: 1px solid var(--ifm-color-emphasis-300); -} - -.languageTab { - padding: 0.5rem 1rem; - font-size: 0.875rem; - font-weight: 500; - background: transparent; - border: none; - border-bottom: 2px solid transparent; - cursor: pointer; - color: var(--ifm-color-emphasis-600); - transition: all 0.15s ease; -} - -.languageTab:hover { - color: var(--ifm-color-emphasis-900); - background: var(--ifm-color-emphasis-200); -} - -.languageTab.activeTab { - color: var(--ifm-color-primary); - border-bottom-color: var(--ifm-color-primary); - background: var(--ifm-background-color); -} - -.withTabs :global(.prism-code) { - border-radius: 0; - border: none; -} - -/* Comparison view */ -.codeComparison { - margin: 1rem 0; -} - -.comparisonGrid { - display: grid; - gap: 1rem; -} - -.comparisonColumn { - min-width: 0; /* Allow shrinking in grid */ -} - -.comparisonHeader { - font-weight: 600; - font-size: 0.875rem; - padding: 0.5rem; - background: var(--ifm-color-emphasis-100); - border: 1px solid var(--ifm-color-emphasis-300); - border-bottom: none; - border-radius: var(--ifm-code-border-radius) var(--ifm-code-border-radius) 0 0; - text-align: center; -} - -.comparisonColumn :global(.prism-code) { - border-radius: 0 0 var(--ifm-code-border-radius) var(--ifm-code-border-radius); - max-height: 400px; - overflow: auto; -} - -/* Responsive */ -@media (max-width: 996px) { - .comparisonGrid { - grid-template-columns: 1fr !important; - } -} diff --git a/site/src/context/StackContext.js b/site/src/context/StackContext.js index c82e75f203..4ad95e5b3b 100644 --- a/site/src/context/StackContext.js +++ b/site/src/context/StackContext.js @@ -2,7 +2,7 @@ * StackContext - Global state for database and language selection * * This context provides: - * - Selected database (postgres, mariadb, duckdb, oracle, sqlserver) + * - Selected database (postgres, mariadb, duckdb, oracle, sqlserver, db2, sqlite) * - Selected language (java, kotlin, scala) * - Persistence to localStorage * - Helper functions for checking availability diff --git a/site/src/data/codeSamples.js b/site/src/data/codeSamples.js deleted file mode 100644 index dd3bbeaa00..0000000000 --- a/site/src/data/codeSamples.js +++ /dev/null @@ -1,636 +0,0 @@ -// AUTO-GENERATED FILE - DO NOT EDIT -// Generated by: node scripts/generate-code-samples.js -// Re-run after updating showcase-generated - -export const DATABASES = ["postgres","mariadb","duckdb","oracle","sqlserver"]; -export const LANGUAGES = ["java","kotlin","scala"]; - -export const DATABASE_LABELS = { - postgres: 'PostgreSQL', - mariadb: 'MariaDB', - duckdb: 'DuckDB', - oracle: 'Oracle', - sqlserver: 'SQL Server' -}; - -export const LANGUAGE_LABELS = { - java: 'Java', - kotlin: 'Kotlin', - scala: 'Scala' -}; - -export const codeSamples = { - "postgres": { - "java": { - "CompanyRow": "package showcase.showcase.company;\n\nimport dev.typr.foundations.PgText;\nimport dev.typr.foundations.PgTypes;\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport java.time.LocalDateTime;\nimport java.util.Optional;\nimport showcase.customtypes.Defaulted;\n\n/** Table: showcase.company\n * Primary key: id\n */\npublic record CompanyRow(\n CompanyId id,\n String name,\n Optional foundedYear,\n /** Default: true */\n Optional active,\n /** Default: CURRENT_TIMESTAMP */\n Optional createdAt\n) {\n public CompanyRow withId(CompanyId id) {\n return new CompanyRow(id, name, foundedYear, active, createdAt);\n };\n\n public CompanyRow withName(String name) {\n return new CompanyRow(id, name, foundedYear, active, createdAt);\n };\n\n public CompanyRow withFoundedYear(Optional foundedYear) {\n return new CompanyRow(id, name, foundedYear, active, createdAt);\n };\n\n /** Default: true */\n public CompanyRow withActive(Optional active) {\n return new CompanyRow(id, name, foundedYear, active, createdAt);\n };\n\n /** Default: CURRENT_TIMESTAMP */\n public CompanyRow withCreatedAt(Optional createdAt) {\n return new CompanyRow(id, name, foundedYear, active, createdAt);\n };\n\n public static RowParser _rowParser = RowParsers.of(CompanyId.pgType, PgTypes.text, PgTypes.int4.opt(), PgTypes.bool.opt(), PgTypes.timestamp.opt(), CompanyRow::new, row -> new Object[]{row.id(), row.name(), row.foundedYear(), row.active(), row.createdAt()});;\n\n static public PgText pgText =\n PgText.from(_rowParser);\n\n public CompanyRowUnsaved toUnsavedRow(\n Defaulted> active,\n Defaulted> createdAt\n ) {\n return new CompanyRowUnsaved(id, name, foundedYear, active, createdAt);\n };\n}", - "CompanyRowUnsaved": "package showcase.showcase.company;\n\nimport dev.typr.foundations.PgText;\nimport dev.typr.foundations.PgTypes;\nimport java.time.LocalDateTime;\nimport java.util.Optional;\nimport showcase.customtypes.Defaulted;\nimport showcase.customtypes.Defaulted.UseDefault;\n\n/** This class corresponds to a row in table `showcase.company` which has not been persisted yet */\npublic record CompanyRowUnsaved(\n CompanyId id,\n String name,\n Optional foundedYear,\n /** Default: true */\n Defaulted> active,\n /** Default: CURRENT_TIMESTAMP */\n Defaulted> createdAt\n) {\n public CompanyRowUnsaved(\n CompanyId id,\n String name\n ) {\n this(id, name, Optional.empty(), new UseDefault<>(), new UseDefault<>());\n };\n\n public CompanyRowUnsaved withId(CompanyId id) {\n return new CompanyRowUnsaved(id, name, foundedYear, active, createdAt);\n };\n\n public CompanyRowUnsaved withName(String name) {\n return new CompanyRowUnsaved(id, name, foundedYear, active, createdAt);\n };\n\n public CompanyRowUnsaved withFoundedYear(Optional foundedYear) {\n return new CompanyRowUnsaved(id, name, foundedYear, active, createdAt);\n };\n\n /** Default: true */\n public CompanyRowUnsaved withActive(Defaulted> active) {\n return new CompanyRowUnsaved(id, name, foundedYear, active, createdAt);\n };\n\n /** Default: CURRENT_TIMESTAMP */\n public CompanyRowUnsaved withCreatedAt(Defaulted> createdAt) {\n return new CompanyRowUnsaved(id, name, foundedYear, active, createdAt);\n };\n\n static public PgText pgText =\n PgText.instance((row, sb) -> {\n CompanyId.pgType.text().unsafeEncode(row.id, sb);\n sb.append(PgText.DELIMETER);\n PgTypes.text.text().unsafeEncode(row.name, sb);\n sb.append(PgText.DELIMETER);\n PgTypes.int4.opt().text().unsafeEncode(row.foundedYear, sb);\n sb.append(PgText.DELIMETER);\n Defaulted.pgText(PgTypes.bool.opt().text()).unsafeEncode(row.active, sb);\n sb.append(PgText.DELIMETER);\n Defaulted.pgText(PgTypes.timestamp.opt().text()).unsafeEncode(row.createdAt, sb);\n });\n\n public CompanyRow toRow(\n java.util.function.Supplier> activeDefault,\n java.util.function.Supplier> createdAtDefault\n ) {\n return new CompanyRow(id, name, foundedYear, active.getOrElse(activeDefault), createdAt.getOrElse(createdAtDefault));\n };\n}", - "CompanyId": "package showcase.showcase.company;\n\nimport dev.typr.foundations.PgType;\nimport dev.typr.foundations.PgTypes;\nimport dev.typr.foundations.dsl.Bijection;\nimport dev.typr.foundations.internal.arrayMap;\n\n/** Type for the primary key of table `showcase.company` */\npublic record CompanyId(String value) {\n public CompanyId withValue(String value) {\n return new CompanyId(value);\n };\n\n @Override\n public java.lang.String toString() {\n return value.toString();\n };\n\n static public Bijection bijection =\n Bijection.of(CompanyId::value, CompanyId::new);\n\n static public PgType pgType =\n PgTypes.text.bimap(CompanyId::new, CompanyId::value);\n\n static public PgType pgTypeArray =\n PgTypes.textArray.bimap(xs -> arrayMap.map(xs, CompanyId::new, CompanyId.class), xs -> arrayMap.map(xs, CompanyId::value, String.class));\n}", - "CompanyRepo": "package showcase.showcase.company;\n\nimport dev.typr.foundations.dsl.DeleteBuilder;\nimport dev.typr.foundations.dsl.SelectBuilder;\nimport dev.typr.foundations.dsl.UpdateBuilder;\nimport java.sql.Connection;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\n\npublic interface CompanyRepo {\n DeleteBuilder delete();\n\n Boolean deleteById(\n CompanyId id,\n Connection c\n );\n\n Integer deleteByIds(\n CompanyId[] ids,\n Connection c\n );\n\n CompanyRow insert(\n CompanyRow unsaved,\n Connection c\n );\n\n CompanyRow insert(\n CompanyRowUnsaved unsaved,\n Connection c\n );\n\n Long insertStreaming(\n Iterator unsaved,\n Integer batchSize,\n Connection c\n );\n\n /** NOTE: this functionality requires PostgreSQL 16 or later! */\n Long insertUnsavedStreaming(\n Iterator unsaved,\n Integer batchSize,\n Connection c\n );\n\n SelectBuilder select();\n\n List selectAll(Connection c);\n\n Optional selectById(\n CompanyId id,\n Connection c\n );\n\n List selectByIds(\n CompanyId[] ids,\n Connection c\n );\n\n Map selectByIdsTracked(\n CompanyId[] ids,\n Connection c\n );\n\n UpdateBuilder update();\n\n Boolean update(\n CompanyRow row,\n Connection c\n );\n\n CompanyRow upsert(\n CompanyRow unsaved,\n Connection c\n );\n\n List upsertBatch(\n Iterator unsaved,\n Connection c\n );\n\n /** NOTE: this functionality is not safe if you use auto-commit mode! it runs 3 SQL statements */\n Integer upsertStreaming(\n Iterator unsaved,\n Integer batchSize,\n Connection c\n );\n}", - "CompanyRepoMock": "package showcase.showcase.company;\n\nimport dev.typr.foundations.dsl.DeleteBuilder;\nimport dev.typr.foundations.dsl.DeleteBuilderMock;\nimport dev.typr.foundations.dsl.DeleteParams;\nimport dev.typr.foundations.dsl.SelectBuilder;\nimport dev.typr.foundations.dsl.SelectBuilderMock;\nimport dev.typr.foundations.dsl.SelectParams;\nimport dev.typr.foundations.dsl.UpdateBuilder;\nimport dev.typr.foundations.dsl.UpdateBuilderMock;\nimport dev.typr.foundations.dsl.UpdateParams;\nimport java.lang.RuntimeException;\nimport java.sql.Connection;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\nimport java.util.function.Function;\nimport java.util.stream.Collectors;\n\npublic record CompanyRepoMock(\n java.util.function.Function toRow,\n HashMap map\n) implements CompanyRepo {\n public CompanyRepoMock(java.util.function.Function toRow) {\n this(toRow, new HashMap());\n };\n\n public CompanyRepoMock withToRow(java.util.function.Function toRow) {\n return new CompanyRepoMock(toRow, map);\n };\n\n public CompanyRepoMock withMap(HashMap map) {\n return new CompanyRepoMock(toRow, map);\n };\n\n @Override\n public DeleteBuilder delete() {\n return new DeleteBuilderMock<>(CompanyFields.structure(), () -> new ArrayList<>(map.values()), DeleteParams.empty(), row -> row.id(), id -> map.remove(id));\n };\n\n @Override\n public Boolean deleteById(\n CompanyId id,\n Connection c\n ) {\n return Optional.ofNullable(map.remove(id)).isPresent();\n };\n\n @Override\n public Integer deleteByIds(\n CompanyId[] ids,\n Connection c\n ) {\n var count = 0;\n for (var id : ids) {\n if (Optional.ofNullable(map.remove(id)).isPresent()) {\n count = count + 1;;\n };\n };\n return count;\n };\n\n @Override\n public CompanyRow insert(\n CompanyRow unsaved,\n Connection c\n ) {\n if (map.containsKey(unsaved.id())) {\n throw new RuntimeException(\"id \" + unsaved.id() + \" already exists\");\n };\n map.put(unsaved.id(), unsaved);\n return unsaved;\n };\n\n @Override\n public CompanyRow insert(\n CompanyRowUnsaved unsaved,\n Connection c\n ) {\n return insert(toRow.apply(unsaved), c);\n };\n\n @Override\n public Long insertStreaming(\n Iterator unsaved,\n Integer batchSize,\n Connection c\n ) {\n var count = 0L;\n while (unsaved.hasNext()) {\n var row = unsaved.next();\n map.put(row.id(), row);\n count = count + 1L;\n };\n return count;\n };\n\n /** NOTE: this functionality requires PostgreSQL 16 or later! */\n @Override\n public Long insertUnsavedStreaming(\n Iterator unsaved,\n Integer batchSize,\n Connection c\n ) {\n var count = 0L;\n while (unsaved.hasNext()) {\n var unsavedRow = unsaved.next();\n var row = toRow.apply(unsavedRow);\n map.put(row.id(), row);\n count = count + 1L;\n };\n return count;\n };\n\n @Override\n public SelectBuilder select() {\n return new SelectBuilderMock<>(CompanyFields.structure(), () -> new ArrayList<>(map.values()), SelectParams.empty());\n };\n\n @Override\n public List selectAll(Connection c) {\n return new ArrayList<>(map.values());\n };\n\n @Override\n public Optional selectById(\n CompanyId id,\n Connection c\n ) {\n return Optional.ofNullable(map.get(id));\n };\n\n @Override\n public List selectByIds(\n CompanyId[] ids,\n Connection c\n ) {\n var result = new ArrayList();\n for (var id : ids) {\n var opt = Optional.ofNullable(map.get(id));\n if (opt.isPresent()) {\n result.add(opt.get());\n };\n };\n return result;\n };\n\n @Override\n public Map selectByIdsTracked(\n CompanyId[] ids,\n Connection c\n ) {\n return selectByIds(ids, c).stream().collect(Collectors.toMap((CompanyRow row) -> row.id(), Function.identity()));\n };\n\n @Override\n public UpdateBuilder update() {\n return new UpdateBuilderMock<>(CompanyFields.structure(), () -> new ArrayList<>(map.values()), UpdateParams.empty(), row -> row);\n };\n\n @Override\n public Boolean update(\n CompanyRow row,\n Connection c\n ) {\n var shouldUpdate = Optional.ofNullable(map.get(row.id())).filter(oldRow -> !oldRow.equals(row)).isPresent();\n if (shouldUpdate) {\n map.put(row.id(), row);;\n };\n return shouldUpdate;\n };\n\n @Override\n public CompanyRow upsert(\n CompanyRow unsaved,\n Connection c\n ) {\n map.put(unsaved.id(), unsaved);\n return unsaved;\n };\n\n @Override\n public List upsertBatch(\n Iterator unsaved,\n Connection c\n ) {\n var result = new ArrayList();\n while (unsaved.hasNext()) {\n var row = unsaved.next();\n map.put(row.id(), row);\n result.add(row);\n };\n return result;\n };\n\n /** NOTE: this functionality is not safe if you use auto-commit mode! it runs 3 SQL statements */\n @Override\n public Integer upsertStreaming(\n Iterator unsaved,\n Integer batchSize,\n Connection c\n ) {\n var count = 0;\n while (unsaved.hasNext()) {\n var row = unsaved.next();\n map.put(row.id(), row);\n count = count + 1;\n };\n return count;\n };\n}", - "EmployeeRow": "package showcase.showcase.employee;\n\nimport dev.typr.foundations.PgText;\nimport dev.typr.foundations.PgTypes;\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport dev.typr.foundations.data.Cidr;\nimport dev.typr.foundations.data.Inet;\nimport dev.typr.foundations.data.Jsonb;\nimport dev.typr.foundations.data.MacAddr;\nimport java.math.BigDecimal;\nimport java.time.LocalDate;\nimport java.time.LocalDateTime;\nimport java.util.Map;\nimport java.util.Optional;\nimport org.postgresql.util.PGInterval;\nimport showcase.customtypes.Defaulted;\nimport showcase.showcase.department.DepartmentId;\n\n/** Table: showcase.employee\n * Primary key: id\n */\npublic record EmployeeRow(\n EmployeeId id,\n /** Points to {@link showcase.showcase.department.DepartmentRow#id()} */\n DepartmentId departmentId,\n /** Points to {@link showcase.showcase.employee.EmployeeRow#id()} */\n Optional managerId,\n String email,\n String firstName,\n String lastName,\n Optional salary,\n Optional hiredAt,\n /** Default: true */\n Optional active,\n /** Default: CURRENT_TIMESTAMP */\n Optional createdAt,\n Optional skills,\n Optional certifications,\n Optional metadata,\n Optional> settings,\n Optional workSchedule,\n Optional ipAddress,\n Optional networkCidr,\n Optional macAddress,\n Optional probationPeriod,\n Optional photo\n) {\n public EmployeeRow withId(EmployeeId id) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, skills, certifications, metadata, settings, workSchedule, ipAddress, networkCidr, macAddress, probationPeriod, photo);\n };\n\n /** Points to {@link showcase.showcase.department.DepartmentRow#id()} */\n public EmployeeRow withDepartmentId(DepartmentId departmentId) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, skills, certifications, metadata, settings, workSchedule, ipAddress, networkCidr, macAddress, probationPeriod, photo);\n };\n\n /** Points to {@link showcase.showcase.employee.EmployeeRow#id()} */\n public EmployeeRow withManagerId(Optional managerId) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, skills, certifications, metadata, settings, workSchedule, ipAddress, networkCidr, macAddress, probationPeriod, photo);\n };\n\n public EmployeeRow withEmail(String email) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, skills, certifications, metadata, settings, workSchedule, ipAddress, networkCidr, macAddress, probationPeriod, photo);\n };\n\n public EmployeeRow withFirstName(String firstName) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, skills, certifications, metadata, settings, workSchedule, ipAddress, networkCidr, macAddress, probationPeriod, photo);\n };\n\n public EmployeeRow withLastName(String lastName) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, skills, certifications, metadata, settings, workSchedule, ipAddress, networkCidr, macAddress, probationPeriod, photo);\n };\n\n public EmployeeRow withSalary(Optional salary) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, skills, certifications, metadata, settings, workSchedule, ipAddress, networkCidr, macAddress, probationPeriod, photo);\n };\n\n public EmployeeRow withHiredAt(Optional hiredAt) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, skills, certifications, metadata, settings, workSchedule, ipAddress, networkCidr, macAddress, probationPeriod, photo);\n };\n\n /** Default: true */\n public EmployeeRow withActive(Optional active) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, skills, certifications, metadata, settings, workSchedule, ipAddress, networkCidr, macAddress, probationPeriod, photo);\n };\n\n /** Default: CURRENT_TIMESTAMP */\n public EmployeeRow withCreatedAt(Optional createdAt) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, skills, certifications, metadata, settings, workSchedule, ipAddress, networkCidr, macAddress, probationPeriod, photo);\n };\n\n public EmployeeRow withSkills(Optional skills) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, skills, certifications, metadata, settings, workSchedule, ipAddress, networkCidr, macAddress, probationPeriod, photo);\n };\n\n public EmployeeRow withCertifications(Optional certifications) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, skills, certifications, metadata, settings, workSchedule, ipAddress, networkCidr, macAddress, probationPeriod, photo);\n };\n\n public EmployeeRow withMetadata(Optional metadata) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, skills, certifications, metadata, settings, workSchedule, ipAddress, networkCidr, macAddress, probationPeriod, photo);\n };\n\n public EmployeeRow withSettings(Optional> settings) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, skills, certifications, metadata, settings, workSchedule, ipAddress, networkCidr, macAddress, probationPeriod, photo);\n };\n\n public EmployeeRow withWorkSchedule(Optional workSchedule) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, skills, certifications, metadata, settings, workSchedule, ipAddress, networkCidr, macAddress, probationPeriod, photo);\n };\n\n public EmployeeRow withIpAddress(Optional ipAddress) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, skills, certifications, metadata, settings, workSchedule, ipAddress, networkCidr, macAddress, probationPeriod, photo);\n };\n\n public EmployeeRow withNetworkCidr(Optional networkCidr) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, skills, certifications, metadata, settings, workSchedule, ipAddress, networkCidr, macAddress, probationPeriod, photo);\n };\n\n public EmployeeRow withMacAddress(Optional macAddress) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, skills, certifications, metadata, settings, workSchedule, ipAddress, networkCidr, macAddress, probationPeriod, photo);\n };\n\n public EmployeeRow withProbationPeriod(Optional probationPeriod) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, skills, certifications, metadata, settings, workSchedule, ipAddress, networkCidr, macAddress, probationPeriod, photo);\n };\n\n public EmployeeRow withPhoto(Optional photo) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, skills, certifications, metadata, settings, workSchedule, ipAddress, networkCidr, macAddress, probationPeriod, photo);\n };\n\n public static RowParser _rowParser = RowParsers.of(EmployeeId.pgType, DepartmentId.pgType, EmployeeId.pgType.opt(), PgTypes.text, PgTypes.text, PgTypes.text, PgTypes.numeric.opt(), PgTypes.date.opt(), PgTypes.bool.opt(), PgTypes.timestamp.opt(), PgTypes.textArray.opt(), PgTypes.textArray.opt(), PgTypes.jsonb.opt(), PgTypes.hstore.opt(), PgTypes.boolArray.opt(), PgTypes.inet.opt(), PgTypes.cidr.opt(), PgTypes.macaddr.opt(), PgTypes.interval.opt(), PgTypes.bytea.opt(), EmployeeRow::new, row -> new Object[]{row.id(), row.departmentId(), row.managerId(), row.email(), row.firstName(), row.lastName(), row.salary(), row.hiredAt(), row.active(), row.createdAt(), row.skills(), row.certifications(), row.metadata(), row.settings(), row.workSchedule(), row.ipAddress(), row.networkCidr(), row.macAddress(), row.probationPeriod(), row.photo()});;\n\n static public PgText pgText =\n PgText.from(_rowParser);\n\n public EmployeeRowUnsaved toUnsavedRow(\n Defaulted> active,\n Defaulted> createdAt\n ) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, skills, certifications, metadata, settings, workSchedule, ipAddress, networkCidr, macAddress, probationPeriod, photo, active, createdAt);\n };\n}", - "EmployeeRowUnsaved": "package showcase.showcase.employee;\n\nimport dev.typr.foundations.PgText;\nimport dev.typr.foundations.PgTypes;\nimport dev.typr.foundations.data.Cidr;\nimport dev.typr.foundations.data.Inet;\nimport dev.typr.foundations.data.Jsonb;\nimport dev.typr.foundations.data.MacAddr;\nimport java.math.BigDecimal;\nimport java.time.LocalDate;\nimport java.time.LocalDateTime;\nimport java.util.Map;\nimport java.util.Optional;\nimport org.postgresql.util.PGInterval;\nimport showcase.customtypes.Defaulted;\nimport showcase.customtypes.Defaulted.UseDefault;\nimport showcase.showcase.department.DepartmentId;\n\n/** This class corresponds to a row in table `showcase.employee` which has not been persisted yet */\npublic record EmployeeRowUnsaved(\n EmployeeId id,\n /** Points to {@link showcase.showcase.department.DepartmentRow#id()} */\n DepartmentId departmentId,\n /** Points to {@link showcase.showcase.employee.EmployeeRow#id()} */\n Optional managerId,\n String email,\n String firstName,\n String lastName,\n Optional salary,\n Optional hiredAt,\n Optional skills,\n Optional certifications,\n Optional metadata,\n Optional> settings,\n Optional workSchedule,\n Optional ipAddress,\n Optional networkCidr,\n Optional macAddress,\n Optional probationPeriod,\n Optional photo,\n /** Default: true */\n Defaulted> active,\n /** Default: CURRENT_TIMESTAMP */\n Defaulted> createdAt\n) {\n public EmployeeRowUnsaved(\n EmployeeId id,\n /** Points to {@link showcase.showcase.department.DepartmentRow#id()} */\n DepartmentId departmentId,\n String email,\n String firstName,\n String lastName\n ) {\n this(id, departmentId, Optional.empty(), email, firstName, lastName, Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), new UseDefault<>(), new UseDefault<>());\n };\n\n public EmployeeRowUnsaved withId(EmployeeId id) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, skills, certifications, metadata, settings, workSchedule, ipAddress, networkCidr, macAddress, probationPeriod, photo, active, createdAt);\n };\n\n /** Points to {@link showcase.showcase.department.DepartmentRow#id()} */\n public EmployeeRowUnsaved withDepartmentId(DepartmentId departmentId) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, skills, certifications, metadata, settings, workSchedule, ipAddress, networkCidr, macAddress, probationPeriod, photo, active, createdAt);\n };\n\n /** Points to {@link showcase.showcase.employee.EmployeeRow#id()} */\n public EmployeeRowUnsaved withManagerId(Optional managerId) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, skills, certifications, metadata, settings, workSchedule, ipAddress, networkCidr, macAddress, probationPeriod, photo, active, createdAt);\n };\n\n public EmployeeRowUnsaved withEmail(String email) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, skills, certifications, metadata, settings, workSchedule, ipAddress, networkCidr, macAddress, probationPeriod, photo, active, createdAt);\n };\n\n public EmployeeRowUnsaved withFirstName(String firstName) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, skills, certifications, metadata, settings, workSchedule, ipAddress, networkCidr, macAddress, probationPeriod, photo, active, createdAt);\n };\n\n public EmployeeRowUnsaved withLastName(String lastName) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, skills, certifications, metadata, settings, workSchedule, ipAddress, networkCidr, macAddress, probationPeriod, photo, active, createdAt);\n };\n\n public EmployeeRowUnsaved withSalary(Optional salary) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, skills, certifications, metadata, settings, workSchedule, ipAddress, networkCidr, macAddress, probationPeriod, photo, active, createdAt);\n };\n\n public EmployeeRowUnsaved withHiredAt(Optional hiredAt) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, skills, certifications, metadata, settings, workSchedule, ipAddress, networkCidr, macAddress, probationPeriod, photo, active, createdAt);\n };\n\n public EmployeeRowUnsaved withSkills(Optional skills) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, skills, certifications, metadata, settings, workSchedule, ipAddress, networkCidr, macAddress, probationPeriod, photo, active, createdAt);\n };\n\n public EmployeeRowUnsaved withCertifications(Optional certifications) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, skills, certifications, metadata, settings, workSchedule, ipAddress, networkCidr, macAddress, probationPeriod, photo, active, createdAt);\n };\n\n public EmployeeRowUnsaved withMetadata(Optional metadata) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, skills, certifications, metadata, settings, workSchedule, ipAddress, networkCidr, macAddress, probationPeriod, photo, active, createdAt);\n };\n\n public EmployeeRowUnsaved withSettings(Optional> settings) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, skills, certifications, metadata, settings, workSchedule, ipAddress, networkCidr, macAddress, probationPeriod, photo, active, createdAt);\n };\n\n public EmployeeRowUnsaved withWorkSchedule(Optional workSchedule) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, skills, certifications, metadata, settings, workSchedule, ipAddress, networkCidr, macAddress, probationPeriod, photo, active, createdAt);\n };\n\n public EmployeeRowUnsaved withIpAddress(Optional ipAddress) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, skills, certifications, metadata, settings, workSchedule, ipAddress, networkCidr, macAddress, probationPeriod, photo, active, createdAt);\n };\n\n public EmployeeRowUnsaved withNetworkCidr(Optional networkCidr) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, skills, certifications, metadata, settings, workSchedule, ipAddress, networkCidr, macAddress, probationPeriod, photo, active, createdAt);\n };\n\n public EmployeeRowUnsaved withMacAddress(Optional macAddress) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, skills, certifications, metadata, settings, workSchedule, ipAddress, networkCidr, macAddress, probationPeriod, photo, active, createdAt);\n };\n\n public EmployeeRowUnsaved withProbationPeriod(Optional probationPeriod) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, skills, certifications, metadata, settings, workSchedule, ipAddress, networkCidr, macAddress, probationPeriod, photo, active, createdAt);\n };\n\n public EmployeeRowUnsaved withPhoto(Optional photo) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, skills, certifications, metadata, settings, workSchedule, ipAddress, networkCidr, macAddress, probationPeriod, photo, active, createdAt);\n };\n\n /** Default: true */\n public EmployeeRowUnsaved withActive(Defaulted> active) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, skills, certifications, metadata, settings, workSchedule, ipAddress, networkCidr, macAddress, probationPeriod, photo, active, createdAt);\n };\n\n /** Default: CURRENT_TIMESTAMP */\n public EmployeeRowUnsaved withCreatedAt(Defaulted> createdAt) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, skills, certifications, metadata, settings, workSchedule, ipAddress, networkCidr, macAddress, probationPeriod, photo, active, createdAt);\n };\n\n static public PgText pgText =\n PgText.instance((row, sb) -> {\n EmployeeId.pgType.text().unsafeEncode(row.id, sb);\n sb.append(PgText.DELIMETER);\n DepartmentId.pgType.text().unsafeEncode(row.departmentId, sb);\n sb.append(PgText.DELIMETER);\n EmployeeId.pgType.opt().text().unsafeEncode(row.managerId, sb);\n sb.append(PgText.DELIMETER);\n PgTypes.text.text().unsafeEncode(row.email, sb);\n sb.append(PgText.DELIMETER);\n PgTypes.text.text().unsafeEncode(row.firstName, sb);\n sb.append(PgText.DELIMETER);\n PgTypes.text.text().unsafeEncode(row.lastName, sb);\n sb.append(PgText.DELIMETER);\n PgTypes.numeric.opt().text().unsafeEncode(row.salary, sb);\n sb.append(PgText.DELIMETER);\n PgTypes.date.opt().text().unsafeEncode(row.hiredAt, sb);\n sb.append(PgText.DELIMETER);\n PgTypes.textArray.opt().text().unsafeEncode(row.skills, sb);\n sb.append(PgText.DELIMETER);\n PgTypes.textArray.opt().text().unsafeEncode(row.certifications, sb);\n sb.append(PgText.DELIMETER);\n PgTypes.jsonb.opt().text().unsafeEncode(row.metadata, sb);\n sb.append(PgText.DELIMETER);\n PgTypes.hstore.opt().text().unsafeEncode(row.settings, sb);\n sb.append(PgText.DELIMETER);\n PgTypes.boolArray.opt().text().unsafeEncode(row.workSchedule, sb);\n sb.append(PgText.DELIMETER);\n PgTypes.inet.opt().text().unsafeEncode(row.ipAddress, sb);\n sb.append(PgText.DELIMETER);\n PgTypes.cidr.opt().text().unsafeEncode(row.networkCidr, sb);\n sb.append(PgText.DELIMETER);\n PgTypes.macaddr.opt().text().unsafeEncode(row.macAddress, sb);\n sb.append(PgText.DELIMETER);\n PgTypes.interval.opt().text().unsafeEncode(row.probationPeriod, sb);\n sb.append(PgText.DELIMETER);\n PgTypes.bytea.opt().text().unsafeEncode(row.photo, sb);\n sb.append(PgText.DELIMETER);\n Defaulted.pgText(PgTypes.bool.opt().text()).unsafeEncode(row.active, sb);\n sb.append(PgText.DELIMETER);\n Defaulted.pgText(PgTypes.timestamp.opt().text()).unsafeEncode(row.createdAt, sb);\n });\n\n public EmployeeRow toRow(\n java.util.function.Supplier> activeDefault,\n java.util.function.Supplier> createdAtDefault\n ) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active.getOrElse(activeDefault), createdAt.getOrElse(createdAtDefault), skills, certifications, metadata, settings, workSchedule, ipAddress, networkCidr, macAddress, probationPeriod, photo);\n };\n}", - "EmployeeId": "package showcase.showcase.employee;\n\nimport dev.typr.foundations.PgType;\nimport dev.typr.foundations.PgTypes;\nimport dev.typr.foundations.dsl.Bijection;\nimport dev.typr.foundations.internal.arrayMap;\n\n/** Type for the primary key of table `showcase.employee` */\npublic record EmployeeId(String value) {\n public EmployeeId withValue(String value) {\n return new EmployeeId(value);\n };\n\n @Override\n public java.lang.String toString() {\n return value.toString();\n };\n\n static public Bijection bijection =\n Bijection.of(EmployeeId::value, EmployeeId::new);\n\n static public PgType pgType =\n PgTypes.text.bimap(EmployeeId::new, EmployeeId::value);\n\n static public PgType pgTypeArray =\n PgTypes.textArray.bimap(xs -> arrayMap.map(xs, EmployeeId::new, EmployeeId.class), xs -> arrayMap.map(xs, EmployeeId::value, String.class));\n}", - "EmployeeRepo": "package showcase.showcase.employee;\n\nimport dev.typr.foundations.dsl.DeleteBuilder;\nimport dev.typr.foundations.dsl.SelectBuilder;\nimport dev.typr.foundations.dsl.UpdateBuilder;\nimport java.sql.Connection;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\n\npublic interface EmployeeRepo {\n DeleteBuilder delete();\n\n Boolean deleteById(\n EmployeeId id,\n Connection c\n );\n\n Integer deleteByIds(\n EmployeeId[] ids,\n Connection c\n );\n\n EmployeeRow insert(\n EmployeeRow unsaved,\n Connection c\n );\n\n EmployeeRow insert(\n EmployeeRowUnsaved unsaved,\n Connection c\n );\n\n Long insertStreaming(\n Iterator unsaved,\n Integer batchSize,\n Connection c\n );\n\n /** NOTE: this functionality requires PostgreSQL 16 or later! */\n Long insertUnsavedStreaming(\n Iterator unsaved,\n Integer batchSize,\n Connection c\n );\n\n SelectBuilder select();\n\n List selectAll(Connection c);\n\n Optional selectById(\n EmployeeId id,\n Connection c\n );\n\n List selectByIds(\n EmployeeId[] ids,\n Connection c\n );\n\n Map selectByIdsTracked(\n EmployeeId[] ids,\n Connection c\n );\n\n Optional selectByUniqueEmail(\n String email,\n Connection c\n );\n\n UpdateBuilder update();\n\n Boolean update(\n EmployeeRow row,\n Connection c\n );\n\n EmployeeRow upsert(\n EmployeeRow unsaved,\n Connection c\n );\n\n List upsertBatch(\n Iterator unsaved,\n Connection c\n );\n\n /** NOTE: this functionality is not safe if you use auto-commit mode! it runs 3 SQL statements */\n Integer upsertStreaming(\n Iterator unsaved,\n Integer batchSize,\n Connection c\n );\n}", - "EmployeeRepoImpl": "package showcase.showcase.employee;\n\nimport dev.typr.foundations.Fragment;\nimport dev.typr.foundations.PgTypes;\nimport dev.typr.foundations.dsl.DeleteBuilder;\nimport dev.typr.foundations.dsl.Dialect;\nimport dev.typr.foundations.dsl.SelectBuilder;\nimport dev.typr.foundations.dsl.UpdateBuilder;\nimport dev.typr.foundations.streamingInsert;\nimport java.sql.Connection;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\nimport showcase.showcase.department.DepartmentId;\nimport static dev.typr.foundations.Fragment.interpolate;\n\npublic class EmployeeRepoImpl implements EmployeeRepo {\n @Override\n public DeleteBuilder delete() {\n return DeleteBuilder.of(\"\\\"showcase\\\".\\\"employee\\\"\", EmployeeFields.structure(), Dialect.POSTGRESQL);\n };\n\n @Override\n public Boolean deleteById(\n EmployeeId id,\n Connection c\n ) {\n return interpolate(Fragment.lit(\"delete from \\\"showcase\\\".\\\"employee\\\" where \\\"id\\\" = \"), Fragment.encode(EmployeeId.pgType, id), Fragment.lit(\"\")).update().runUnchecked(c) > 0;\n };\n\n @Override\n public Integer deleteByIds(\n EmployeeId[] ids,\n Connection c\n ) {\n return interpolate(Fragment.lit(\"delete\\nfrom \\\"showcase\\\".\\\"employee\\\"\\nwhere \\\"id\\\" = ANY(\"), Fragment.encode(EmployeeId.pgTypeArray, ids), Fragment.lit(\")\"))\n .update()\n .runUnchecked(c);\n };\n\n @Override\n public EmployeeRow insert(\n EmployeeRow unsaved,\n Connection c\n ) {\n return interpolate(Fragment.lit(\"insert into \\\"showcase\\\".\\\"employee\\\"(\\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"skills\\\", \\\"certifications\\\", \\\"metadata\\\", \\\"settings\\\", \\\"work_schedule\\\", \\\"ip_address\\\", \\\"network_cidr\\\", \\\"mac_address\\\", \\\"probation_period\\\", \\\"photo\\\")\\nvalues (\"), Fragment.encode(EmployeeId.pgType, unsaved.id()), Fragment.lit(\", \"), Fragment.encode(DepartmentId.pgType, unsaved.departmentId()), Fragment.lit(\", \"), Fragment.encode(EmployeeId.pgType.opt(), unsaved.managerId()), Fragment.lit(\", \"), Fragment.encode(PgTypes.text, unsaved.email()), Fragment.lit(\", \"), Fragment.encode(PgTypes.text, unsaved.firstName()), Fragment.lit(\", \"), Fragment.encode(PgTypes.text, unsaved.lastName()), Fragment.lit(\", \"), Fragment.encode(PgTypes.numeric.opt(), unsaved.salary()), Fragment.lit(\", \"), Fragment.encode(PgTypes.date.opt(), unsaved.hiredAt()), Fragment.lit(\", \"), Fragment.encode(PgTypes.bool.opt(), unsaved.active()), Fragment.lit(\", \"), Fragment.encode(PgTypes.timestamp.opt(), unsaved.createdAt()), Fragment.lit(\", \"), Fragment.encode(PgTypes.textArray.opt(), unsaved.skills()), Fragment.lit(\", \"), Fragment.encode(PgTypes.textArray.opt(), unsaved.certifications()), Fragment.lit(\", \"), Fragment.encode(PgTypes.jsonb.opt(), unsaved.metadata()), Fragment.lit(\", \"), Fragment.encode(PgTypes.hstore.opt(), unsaved.settings()), Fragment.lit(\", \"), Fragment.encode(PgTypes.boolArray.opt(), unsaved.workSchedule()), Fragment.lit(\", \"), Fragment.encode(PgTypes.inet.opt(), unsaved.ipAddress()), Fragment.lit(\", \"), Fragment.encode(PgTypes.cidr.opt(), unsaved.networkCidr()), Fragment.lit(\", \"), Fragment.encode(PgTypes.macaddr.opt(), unsaved.macAddress()), Fragment.lit(\", \"), Fragment.encode(PgTypes.interval.opt(), unsaved.probationPeriod()), Fragment.lit(\", \"), Fragment.encode(PgTypes.bytea.opt(), unsaved.photo()), Fragment.lit(\")\\nRETURNING \\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"skills\\\", \\\"certifications\\\", \\\"metadata\\\", \\\"settings\\\", \\\"work_schedule\\\", \\\"ip_address\\\", \\\"network_cidr\\\", \\\"mac_address\\\", \\\"probation_period\\\", \\\"photo\\\"\\n\"))\n .updateReturning(EmployeeRow._rowParser.exactlyOne()).runUnchecked(c);\n };\n\n @Override\n public EmployeeRow insert(\n EmployeeRowUnsaved unsaved,\n Connection c\n ) {\n ArrayList columns = new ArrayList<>();;\n ArrayList values = new ArrayList<>();;\n columns.add(Fragment.lit(\"\\\"id\\\"\"));\n values.add(interpolate(Fragment.encode(EmployeeId.pgType, unsaved.id()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"\\\"department_id\\\"\"));\n values.add(interpolate(Fragment.encode(DepartmentId.pgType, unsaved.departmentId()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"\\\"manager_id\\\"\"));\n values.add(interpolate(Fragment.encode(EmployeeId.pgType.opt(), unsaved.managerId()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"\\\"email\\\"\"));\n values.add(interpolate(Fragment.encode(PgTypes.text, unsaved.email()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"\\\"first_name\\\"\"));\n values.add(interpolate(Fragment.encode(PgTypes.text, unsaved.firstName()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"\\\"last_name\\\"\"));\n values.add(interpolate(Fragment.encode(PgTypes.text, unsaved.lastName()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"\\\"salary\\\"\"));\n values.add(interpolate(Fragment.encode(PgTypes.numeric.opt(), unsaved.salary()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"\\\"hired_at\\\"\"));\n values.add(interpolate(Fragment.encode(PgTypes.date.opt(), unsaved.hiredAt()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"\\\"skills\\\"\"));\n values.add(interpolate(Fragment.encode(PgTypes.textArray.opt(), unsaved.skills()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"\\\"certifications\\\"\"));\n values.add(interpolate(Fragment.encode(PgTypes.textArray.opt(), unsaved.certifications()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"\\\"metadata\\\"\"));\n values.add(interpolate(Fragment.encode(PgTypes.jsonb.opt(), unsaved.metadata()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"\\\"settings\\\"\"));\n values.add(interpolate(Fragment.encode(PgTypes.hstore.opt(), unsaved.settings()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"\\\"work_schedule\\\"\"));\n values.add(interpolate(Fragment.encode(PgTypes.boolArray.opt(), unsaved.workSchedule()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"\\\"ip_address\\\"\"));\n values.add(interpolate(Fragment.encode(PgTypes.inet.opt(), unsaved.ipAddress()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"\\\"network_cidr\\\"\"));\n values.add(interpolate(Fragment.encode(PgTypes.cidr.opt(), unsaved.networkCidr()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"\\\"mac_address\\\"\"));\n values.add(interpolate(Fragment.encode(PgTypes.macaddr.opt(), unsaved.macAddress()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"\\\"probation_period\\\"\"));\n values.add(interpolate(Fragment.encode(PgTypes.interval.opt(), unsaved.probationPeriod()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"\\\"photo\\\"\"));\n values.add(interpolate(Fragment.encode(PgTypes.bytea.opt(), unsaved.photo()), Fragment.lit(\"\")));\n unsaved.active().visit(\n () -> {\n \n },\n value -> {\n columns.add(Fragment.lit(\"\\\"active\\\"\"));\n values.add(interpolate(Fragment.encode(PgTypes.bool.opt(), value), Fragment.lit(\"\")));\n }\n );;\n unsaved.createdAt().visit(\n () -> {\n \n },\n value -> {\n columns.add(Fragment.lit(\"\\\"created_at\\\"\"));\n values.add(interpolate(Fragment.encode(PgTypes.timestamp.opt(), value), Fragment.lit(\"\")));\n }\n );;\n Fragment q = interpolate(Fragment.lit(\"insert into \\\"showcase\\\".\\\"employee\\\"(\"), Fragment.comma(columns), Fragment.lit(\")\\nvalues (\"), Fragment.comma(values), Fragment.lit(\")\\nRETURNING \\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"skills\\\", \\\"certifications\\\", \\\"metadata\\\", \\\"settings\\\", \\\"work_schedule\\\", \\\"ip_address\\\", \\\"network_cidr\\\", \\\"mac_address\\\", \\\"probation_period\\\", \\\"photo\\\"\\n\"));;\n return q.updateReturning(EmployeeRow._rowParser.exactlyOne()).runUnchecked(c);\n };\n\n @Override\n public Long insertStreaming(\n Iterator unsaved,\n Integer batchSize,\n Connection c\n ) {\n return streamingInsert.insertUnchecked(\"COPY \\\"showcase\\\".\\\"employee\\\"(\\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"skills\\\", \\\"certifications\\\", \\\"metadata\\\", \\\"settings\\\", \\\"work_schedule\\\", \\\"ip_address\\\", \\\"network_cidr\\\", \\\"mac_address\\\", \\\"probation_period\\\", \\\"photo\\\") FROM STDIN\", batchSize, unsaved, c, EmployeeRow.pgText);\n };\n\n /** NOTE: this functionality requires PostgreSQL 16 or later! */\n @Override\n public Long insertUnsavedStreaming(\n Iterator unsaved,\n Integer batchSize,\n Connection c\n ) {\n return streamingInsert.insertUnchecked(\"COPY \\\"showcase\\\".\\\"employee\\\"(\\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"skills\\\", \\\"certifications\\\", \\\"metadata\\\", \\\"settings\\\", \\\"work_schedule\\\", \\\"ip_address\\\", \\\"network_cidr\\\", \\\"mac_address\\\", \\\"probation_period\\\", \\\"photo\\\", \\\"active\\\", \\\"created_at\\\") FROM STDIN (DEFAULT '__DEFAULT_VALUE__')\", batchSize, unsaved, c, EmployeeRowUnsaved.pgText);\n };\n\n @Override\n public SelectBuilder select() {\n return SelectBuilder.of(\"\\\"showcase\\\".\\\"employee\\\"\", EmployeeFields.structure(), EmployeeRow._rowParser, Dialect.POSTGRESQL);\n };\n\n @Override\n public List selectAll(Connection c) {\n return interpolate(Fragment.lit(\"select \\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"skills\\\", \\\"certifications\\\", \\\"metadata\\\", \\\"settings\\\", \\\"work_schedule\\\", \\\"ip_address\\\", \\\"network_cidr\\\", \\\"mac_address\\\", \\\"probation_period\\\", \\\"photo\\\"\\nfrom \\\"showcase\\\".\\\"employee\\\"\\n\")).query(EmployeeRow._rowParser.all()).runUnchecked(c);\n };\n\n @Override\n public Optional selectById(\n EmployeeId id,\n Connection c\n ) {\n return interpolate(Fragment.lit(\"select \\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"skills\\\", \\\"certifications\\\", \\\"metadata\\\", \\\"settings\\\", \\\"work_schedule\\\", \\\"ip_address\\\", \\\"network_cidr\\\", \\\"mac_address\\\", \\\"probation_period\\\", \\\"photo\\\"\\nfrom \\\"showcase\\\".\\\"employee\\\"\\nwhere \\\"id\\\" = \"), Fragment.encode(EmployeeId.pgType, id), Fragment.lit(\"\")).query(EmployeeRow._rowParser.first()).runUnchecked(c);\n };\n\n @Override\n public List selectByIds(\n EmployeeId[] ids,\n Connection c\n ) {\n return interpolate(Fragment.lit(\"select \\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"skills\\\", \\\"certifications\\\", \\\"metadata\\\", \\\"settings\\\", \\\"work_schedule\\\", \\\"ip_address\\\", \\\"network_cidr\\\", \\\"mac_address\\\", \\\"probation_period\\\", \\\"photo\\\"\\nfrom \\\"showcase\\\".\\\"employee\\\"\\nwhere \\\"id\\\" = ANY(\"), Fragment.encode(EmployeeId.pgTypeArray, ids), Fragment.lit(\")\")).query(EmployeeRow._rowParser.all()).runUnchecked(c);\n };\n\n @Override\n public Map selectByIdsTracked(\n EmployeeId[] ids,\n Connection c\n ) {\n HashMap ret = new HashMap();\n selectByIds(ids, c).forEach(row -> ret.put(row.id(), row));\n return ret;\n };\n\n @Override\n public Optional selectByUniqueEmail(\n String email,\n Connection c\n ) {\n return interpolate(Fragment.lit(\"select \\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"skills\\\", \\\"certifications\\\", \\\"metadata\\\", \\\"settings\\\", \\\"work_schedule\\\", \\\"ip_address\\\", \\\"network_cidr\\\", \\\"mac_address\\\", \\\"probation_period\\\", \\\"photo\\\"\\nfrom \\\"showcase\\\".\\\"employee\\\"\\nwhere \\\"email\\\" = \"), Fragment.encode(PgTypes.text, email), Fragment.lit(\"\\n\")).query(EmployeeRow._rowParser.first()).runUnchecked(c);\n };\n\n @Override\n public UpdateBuilder update() {\n return UpdateBuilder.of(\"\\\"showcase\\\".\\\"employee\\\"\", EmployeeFields.structure(), EmployeeRow._rowParser, Dialect.POSTGRESQL);\n };\n\n @Override\n public Boolean update(\n EmployeeRow row,\n Connection c\n ) {\n EmployeeId id = row.id();;\n return interpolate(Fragment.lit(\"update \\\"showcase\\\".\\\"employee\\\"\\nset \\\"department_id\\\" = \"), Fragment.encode(DepartmentId.pgType, row.departmentId()), Fragment.lit(\",\\n\\\"manager_id\\\" = \"), Fragment.encode(EmployeeId.pgType.opt(), row.managerId()), Fragment.lit(\",\\n\\\"email\\\" = \"), Fragment.encode(PgTypes.text, row.email()), Fragment.lit(\",\\n\\\"first_name\\\" = \"), Fragment.encode(PgTypes.text, row.firstName()), Fragment.lit(\",\\n\\\"last_name\\\" = \"), Fragment.encode(PgTypes.text, row.lastName()), Fragment.lit(\",\\n\\\"salary\\\" = \"), Fragment.encode(PgTypes.numeric.opt(), row.salary()), Fragment.lit(\",\\n\\\"hired_at\\\" = \"), Fragment.encode(PgTypes.date.opt(), row.hiredAt()), Fragment.lit(\",\\n\\\"active\\\" = \"), Fragment.encode(PgTypes.bool.opt(), row.active()), Fragment.lit(\",\\n\\\"created_at\\\" = \"), Fragment.encode(PgTypes.timestamp.opt(), row.createdAt()), Fragment.lit(\",\\n\\\"skills\\\" = \"), Fragment.encode(PgTypes.textArray.opt(), row.skills()), Fragment.lit(\",\\n\\\"certifications\\\" = \"), Fragment.encode(PgTypes.textArray.opt(), row.certifications()), Fragment.lit(\",\\n\\\"metadata\\\" = \"), Fragment.encode(PgTypes.jsonb.opt(), row.metadata()), Fragment.lit(\",\\n\\\"settings\\\" = \"), Fragment.encode(PgTypes.hstore.opt(), row.settings()), Fragment.lit(\",\\n\\\"work_schedule\\\" = \"), Fragment.encode(PgTypes.boolArray.opt(), row.workSchedule()), Fragment.lit(\",\\n\\\"ip_address\\\" = \"), Fragment.encode(PgTypes.inet.opt(), row.ipAddress()), Fragment.lit(\",\\n\\\"network_cidr\\\" = \"), Fragment.encode(PgTypes.cidr.opt(), row.networkCidr()), Fragment.lit(\",\\n\\\"mac_address\\\" = \"), Fragment.encode(PgTypes.macaddr.opt(), row.macAddress()), Fragment.lit(\",\\n\\\"probation_period\\\" = \"), Fragment.encode(PgTypes.interval.opt(), row.probationPeriod()), Fragment.lit(\",\\n\\\"photo\\\" = \"), Fragment.encode(PgTypes.bytea.opt(), row.photo()), Fragment.lit(\"\\nwhere \\\"id\\\" = \"), Fragment.encode(EmployeeId.pgType, id), Fragment.lit(\"\")).update().runUnchecked(c) > 0;\n };\n\n @Override\n public EmployeeRow upsert(\n EmployeeRow unsaved,\n Connection c\n ) {\n return interpolate(Fragment.lit(\"insert into \\\"showcase\\\".\\\"employee\\\"(\\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"skills\\\", \\\"certifications\\\", \\\"metadata\\\", \\\"settings\\\", \\\"work_schedule\\\", \\\"ip_address\\\", \\\"network_cidr\\\", \\\"mac_address\\\", \\\"probation_period\\\", \\\"photo\\\")\\nvalues (\"), Fragment.encode(EmployeeId.pgType, unsaved.id()), Fragment.lit(\", \"), Fragment.encode(DepartmentId.pgType, unsaved.departmentId()), Fragment.lit(\", \"), Fragment.encode(EmployeeId.pgType.opt(), unsaved.managerId()), Fragment.lit(\", \"), Fragment.encode(PgTypes.text, unsaved.email()), Fragment.lit(\", \"), Fragment.encode(PgTypes.text, unsaved.firstName()), Fragment.lit(\", \"), Fragment.encode(PgTypes.text, unsaved.lastName()), Fragment.lit(\", \"), Fragment.encode(PgTypes.numeric.opt(), unsaved.salary()), Fragment.lit(\", \"), Fragment.encode(PgTypes.date.opt(), unsaved.hiredAt()), Fragment.lit(\", \"), Fragment.encode(PgTypes.bool.opt(), unsaved.active()), Fragment.lit(\", \"), Fragment.encode(PgTypes.timestamp.opt(), unsaved.createdAt()), Fragment.lit(\", \"), Fragment.encode(PgTypes.textArray.opt(), unsaved.skills()), Fragment.lit(\", \"), Fragment.encode(PgTypes.textArray.opt(), unsaved.certifications()), Fragment.lit(\", \"), Fragment.encode(PgTypes.jsonb.opt(), unsaved.metadata()), Fragment.lit(\", \"), Fragment.encode(PgTypes.hstore.opt(), unsaved.settings()), Fragment.lit(\", \"), Fragment.encode(PgTypes.boolArray.opt(), unsaved.workSchedule()), Fragment.lit(\", \"), Fragment.encode(PgTypes.inet.opt(), unsaved.ipAddress()), Fragment.lit(\", \"), Fragment.encode(PgTypes.cidr.opt(), unsaved.networkCidr()), Fragment.lit(\", \"), Fragment.encode(PgTypes.macaddr.opt(), unsaved.macAddress()), Fragment.lit(\", \"), Fragment.encode(PgTypes.interval.opt(), unsaved.probationPeriod()), Fragment.lit(\", \"), Fragment.encode(PgTypes.bytea.opt(), unsaved.photo()), Fragment.lit(\")\\non conflict (\\\"id\\\")\\ndo update set\\n \\\"department_id\\\" = EXCLUDED.\\\"department_id\\\",\\n\\\"manager_id\\\" = EXCLUDED.\\\"manager_id\\\",\\n\\\"email\\\" = EXCLUDED.\\\"email\\\",\\n\\\"first_name\\\" = EXCLUDED.\\\"first_name\\\",\\n\\\"last_name\\\" = EXCLUDED.\\\"last_name\\\",\\n\\\"salary\\\" = EXCLUDED.\\\"salary\\\",\\n\\\"hired_at\\\" = EXCLUDED.\\\"hired_at\\\",\\n\\\"active\\\" = EXCLUDED.\\\"active\\\",\\n\\\"created_at\\\" = EXCLUDED.\\\"created_at\\\",\\n\\\"skills\\\" = EXCLUDED.\\\"skills\\\",\\n\\\"certifications\\\" = EXCLUDED.\\\"certifications\\\",\\n\\\"metadata\\\" = EXCLUDED.\\\"metadata\\\",\\n\\\"settings\\\" = EXCLUDED.\\\"settings\\\",\\n\\\"work_schedule\\\" = EXCLUDED.\\\"work_schedule\\\",\\n\\\"ip_address\\\" = EXCLUDED.\\\"ip_address\\\",\\n\\\"network_cidr\\\" = EXCLUDED.\\\"network_cidr\\\",\\n\\\"mac_address\\\" = EXCLUDED.\\\"mac_address\\\",\\n\\\"probation_period\\\" = EXCLUDED.\\\"probation_period\\\",\\n\\\"photo\\\" = EXCLUDED.\\\"photo\\\"\\nreturning \\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"skills\\\", \\\"certifications\\\", \\\"metadata\\\", \\\"settings\\\", \\\"work_schedule\\\", \\\"ip_address\\\", \\\"network_cidr\\\", \\\"mac_address\\\", \\\"probation_period\\\", \\\"photo\\\"\"))\n .updateReturning(EmployeeRow._rowParser.exactlyOne())\n .runUnchecked(c);\n };\n\n @Override\n public List upsertBatch(\n Iterator unsaved,\n Connection c\n ) {\n return interpolate(Fragment.lit(\"insert into \\\"showcase\\\".\\\"employee\\\"(\\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"skills\\\", \\\"certifications\\\", \\\"metadata\\\", \\\"settings\\\", \\\"work_schedule\\\", \\\"ip_address\\\", \\\"network_cidr\\\", \\\"mac_address\\\", \\\"probation_period\\\", \\\"photo\\\")\\nvalues (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\\non conflict (\\\"id\\\")\\ndo update set\\n \\\"department_id\\\" = EXCLUDED.\\\"department_id\\\",\\n\\\"manager_id\\\" = EXCLUDED.\\\"manager_id\\\",\\n\\\"email\\\" = EXCLUDED.\\\"email\\\",\\n\\\"first_name\\\" = EXCLUDED.\\\"first_name\\\",\\n\\\"last_name\\\" = EXCLUDED.\\\"last_name\\\",\\n\\\"salary\\\" = EXCLUDED.\\\"salary\\\",\\n\\\"hired_at\\\" = EXCLUDED.\\\"hired_at\\\",\\n\\\"active\\\" = EXCLUDED.\\\"active\\\",\\n\\\"created_at\\\" = EXCLUDED.\\\"created_at\\\",\\n\\\"skills\\\" = EXCLUDED.\\\"skills\\\",\\n\\\"certifications\\\" = EXCLUDED.\\\"certifications\\\",\\n\\\"metadata\\\" = EXCLUDED.\\\"metadata\\\",\\n\\\"settings\\\" = EXCLUDED.\\\"settings\\\",\\n\\\"work_schedule\\\" = EXCLUDED.\\\"work_schedule\\\",\\n\\\"ip_address\\\" = EXCLUDED.\\\"ip_address\\\",\\n\\\"network_cidr\\\" = EXCLUDED.\\\"network_cidr\\\",\\n\\\"mac_address\\\" = EXCLUDED.\\\"mac_address\\\",\\n\\\"probation_period\\\" = EXCLUDED.\\\"probation_period\\\",\\n\\\"photo\\\" = EXCLUDED.\\\"photo\\\"\\nreturning \\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"skills\\\", \\\"certifications\\\", \\\"metadata\\\", \\\"settings\\\", \\\"work_schedule\\\", \\\"ip_address\\\", \\\"network_cidr\\\", \\\"mac_address\\\", \\\"probation_period\\\", \\\"photo\\\"\"))\n .updateManyReturning(EmployeeRow._rowParser, unsaved)\n .runUnchecked(c);\n };\n\n /** NOTE: this functionality is not safe if you use auto-commit mode! it runs 3 SQL statements */\n @Override\n public Integer upsertStreaming(\n Iterator unsaved,\n Integer batchSize,\n Connection c\n ) {\n interpolate(Fragment.lit(\"create temporary table employee_TEMP (like \\\"showcase\\\".\\\"employee\\\") on commit drop\")).update().runUnchecked(c);\n streamingInsert.insertUnchecked(\"copy employee_TEMP(\\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"skills\\\", \\\"certifications\\\", \\\"metadata\\\", \\\"settings\\\", \\\"work_schedule\\\", \\\"ip_address\\\", \\\"network_cidr\\\", \\\"mac_address\\\", \\\"probation_period\\\", \\\"photo\\\") from stdin\", batchSize, unsaved, c, EmployeeRow.pgText);\n return interpolate(Fragment.lit(\"insert into \\\"showcase\\\".\\\"employee\\\"(\\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"skills\\\", \\\"certifications\\\", \\\"metadata\\\", \\\"settings\\\", \\\"work_schedule\\\", \\\"ip_address\\\", \\\"network_cidr\\\", \\\"mac_address\\\", \\\"probation_period\\\", \\\"photo\\\")\\nselect * from employee_TEMP\\non conflict (\\\"id\\\")\\ndo update set\\n \\\"department_id\\\" = EXCLUDED.\\\"department_id\\\",\\n\\\"manager_id\\\" = EXCLUDED.\\\"manager_id\\\",\\n\\\"email\\\" = EXCLUDED.\\\"email\\\",\\n\\\"first_name\\\" = EXCLUDED.\\\"first_name\\\",\\n\\\"last_name\\\" = EXCLUDED.\\\"last_name\\\",\\n\\\"salary\\\" = EXCLUDED.\\\"salary\\\",\\n\\\"hired_at\\\" = EXCLUDED.\\\"hired_at\\\",\\n\\\"active\\\" = EXCLUDED.\\\"active\\\",\\n\\\"created_at\\\" = EXCLUDED.\\\"created_at\\\",\\n\\\"skills\\\" = EXCLUDED.\\\"skills\\\",\\n\\\"certifications\\\" = EXCLUDED.\\\"certifications\\\",\\n\\\"metadata\\\" = EXCLUDED.\\\"metadata\\\",\\n\\\"settings\\\" = EXCLUDED.\\\"settings\\\",\\n\\\"work_schedule\\\" = EXCLUDED.\\\"work_schedule\\\",\\n\\\"ip_address\\\" = EXCLUDED.\\\"ip_address\\\",\\n\\\"network_cidr\\\" = EXCLUDED.\\\"network_cidr\\\",\\n\\\"mac_address\\\" = EXCLUDED.\\\"mac_address\\\",\\n\\\"probation_period\\\" = EXCLUDED.\\\"probation_period\\\",\\n\\\"photo\\\" = EXCLUDED.\\\"photo\\\"\\n;\\ndrop table employee_TEMP;\")).update().runUnchecked(c);\n };\n}", - "EmployeeRepoMock": "package showcase.showcase.employee;\n\nimport dev.typr.foundations.dsl.DeleteBuilder;\nimport dev.typr.foundations.dsl.DeleteBuilderMock;\nimport dev.typr.foundations.dsl.DeleteParams;\nimport dev.typr.foundations.dsl.SelectBuilder;\nimport dev.typr.foundations.dsl.SelectBuilderMock;\nimport dev.typr.foundations.dsl.SelectParams;\nimport dev.typr.foundations.dsl.UpdateBuilder;\nimport dev.typr.foundations.dsl.UpdateBuilderMock;\nimport dev.typr.foundations.dsl.UpdateParams;\nimport java.lang.RuntimeException;\nimport java.sql.Connection;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\nimport java.util.function.Function;\nimport java.util.stream.Collectors;\n\npublic record EmployeeRepoMock(\n java.util.function.Function toRow,\n HashMap map\n) implements EmployeeRepo {\n public EmployeeRepoMock(java.util.function.Function toRow) {\n this(toRow, new HashMap());\n };\n\n public EmployeeRepoMock withToRow(java.util.function.Function toRow) {\n return new EmployeeRepoMock(toRow, map);\n };\n\n public EmployeeRepoMock withMap(HashMap map) {\n return new EmployeeRepoMock(toRow, map);\n };\n\n @Override\n public DeleteBuilder delete() {\n return new DeleteBuilderMock<>(EmployeeFields.structure(), () -> new ArrayList<>(map.values()), DeleteParams.empty(), row -> row.id(), id -> map.remove(id));\n };\n\n @Override\n public Boolean deleteById(\n EmployeeId id,\n Connection c\n ) {\n return Optional.ofNullable(map.remove(id)).isPresent();\n };\n\n @Override\n public Integer deleteByIds(\n EmployeeId[] ids,\n Connection c\n ) {\n var count = 0;\n for (var id : ids) {\n if (Optional.ofNullable(map.remove(id)).isPresent()) {\n count = count + 1;;\n };\n };\n return count;\n };\n\n @Override\n public EmployeeRow insert(\n EmployeeRow unsaved,\n Connection c\n ) {\n if (map.containsKey(unsaved.id())) {\n throw new RuntimeException(\"id \" + unsaved.id() + \" already exists\");\n };\n map.put(unsaved.id(), unsaved);\n return unsaved;\n };\n\n @Override\n public EmployeeRow insert(\n EmployeeRowUnsaved unsaved,\n Connection c\n ) {\n return insert(toRow.apply(unsaved), c);\n };\n\n @Override\n public Long insertStreaming(\n Iterator unsaved,\n Integer batchSize,\n Connection c\n ) {\n var count = 0L;\n while (unsaved.hasNext()) {\n var row = unsaved.next();\n map.put(row.id(), row);\n count = count + 1L;\n };\n return count;\n };\n\n /** NOTE: this functionality requires PostgreSQL 16 or later! */\n @Override\n public Long insertUnsavedStreaming(\n Iterator unsaved,\n Integer batchSize,\n Connection c\n ) {\n var count = 0L;\n while (unsaved.hasNext()) {\n var unsavedRow = unsaved.next();\n var row = toRow.apply(unsavedRow);\n map.put(row.id(), row);\n count = count + 1L;\n };\n return count;\n };\n\n @Override\n public SelectBuilder select() {\n return new SelectBuilderMock<>(EmployeeFields.structure(), () -> new ArrayList<>(map.values()), SelectParams.empty());\n };\n\n @Override\n public List selectAll(Connection c) {\n return new ArrayList<>(map.values());\n };\n\n @Override\n public Optional selectById(\n EmployeeId id,\n Connection c\n ) {\n return Optional.ofNullable(map.get(id));\n };\n\n @Override\n public List selectByIds(\n EmployeeId[] ids,\n Connection c\n ) {\n var result = new ArrayList();\n for (var id : ids) {\n var opt = Optional.ofNullable(map.get(id));\n if (opt.isPresent()) {\n result.add(opt.get());\n };\n };\n return result;\n };\n\n @Override\n public Map selectByIdsTracked(\n EmployeeId[] ids,\n Connection c\n ) {\n return selectByIds(ids, c).stream().collect(Collectors.toMap((EmployeeRow row) -> row.id(), Function.identity()));\n };\n\n @Override\n public Optional selectByUniqueEmail(\n String email,\n Connection c\n ) {\n return new ArrayList<>(map.values()).stream().filter(v -> email.equals(v.email())).findFirst();\n };\n\n @Override\n public UpdateBuilder update() {\n return new UpdateBuilderMock<>(EmployeeFields.structure(), () -> new ArrayList<>(map.values()), UpdateParams.empty(), row -> row);\n };\n\n @Override\n public Boolean update(\n EmployeeRow row,\n Connection c\n ) {\n var shouldUpdate = Optional.ofNullable(map.get(row.id())).filter(oldRow -> !oldRow.equals(row)).isPresent();\n if (shouldUpdate) {\n map.put(row.id(), row);;\n };\n return shouldUpdate;\n };\n\n @Override\n public EmployeeRow upsert(\n EmployeeRow unsaved,\n Connection c\n ) {\n map.put(unsaved.id(), unsaved);\n return unsaved;\n };\n\n @Override\n public List upsertBatch(\n Iterator unsaved,\n Connection c\n ) {\n var result = new ArrayList();\n while (unsaved.hasNext()) {\n var row = unsaved.next();\n map.put(row.id(), row);\n result.add(row);\n };\n return result;\n };\n\n /** NOTE: this functionality is not safe if you use auto-commit mode! it runs 3 SQL statements */\n @Override\n public Integer upsertStreaming(\n Iterator unsaved,\n Integer batchSize,\n Connection c\n ) {\n var count = 0;\n while (unsaved.hasNext()) {\n var row = unsaved.next();\n map.put(row.id(), row);\n count = count + 1;\n };\n return count;\n };\n}", - "EmployeeFields": "package showcase.showcase.employee;\n\nimport dev.typr.foundations.PgTypes;\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.data.Cidr;\nimport dev.typr.foundations.data.Inet;\nimport dev.typr.foundations.data.Jsonb;\nimport dev.typr.foundations.data.MacAddr;\nimport dev.typr.foundations.dsl.FieldsExpr;\nimport dev.typr.foundations.dsl.ForeignKey;\nimport dev.typr.foundations.dsl.Path;\nimport dev.typr.foundations.dsl.RelationStructure;\nimport dev.typr.foundations.dsl.SqlExpr.Field;\nimport dev.typr.foundations.dsl.SqlExpr.FieldLike;\nimport dev.typr.foundations.dsl.SqlExpr.IdField;\nimport dev.typr.foundations.dsl.SqlExpr.OptField;\nimport java.math.BigDecimal;\nimport java.time.LocalDate;\nimport java.time.LocalDateTime;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\nimport org.postgresql.util.PGInterval;\nimport showcase.showcase.department.DepartmentFields;\nimport showcase.showcase.department.DepartmentId;\nimport showcase.showcase.department.DepartmentRow;\n\npublic interface EmployeeFields extends FieldsExpr {\n record Impl(List _path) implements EmployeeFields, RelationStructure {\n @Override\n public IdField id() {\n return new IdField(_path, \"id\", EmployeeRow::id, Optional.empty(), Optional.empty(), (row, value) -> row.withId(value), EmployeeId.pgType);\n };\n\n @Override\n public Field departmentId() {\n return new Field(_path, \"department_id\", EmployeeRow::departmentId, Optional.empty(), Optional.empty(), (row, value) -> row.withDepartmentId(value), DepartmentId.pgType);\n };\n\n @Override\n public OptField managerId() {\n return new OptField(_path, \"manager_id\", EmployeeRow::managerId, Optional.empty(), Optional.empty(), (row, value) -> row.withManagerId(value), EmployeeId.pgType);\n };\n\n @Override\n public Field email() {\n return new Field(_path, \"email\", EmployeeRow::email, Optional.empty(), Optional.empty(), (row, value) -> row.withEmail(value), PgTypes.text);\n };\n\n @Override\n public Field firstName() {\n return new Field(_path, \"first_name\", EmployeeRow::firstName, Optional.empty(), Optional.empty(), (row, value) -> row.withFirstName(value), PgTypes.text);\n };\n\n @Override\n public Field lastName() {\n return new Field(_path, \"last_name\", EmployeeRow::lastName, Optional.empty(), Optional.empty(), (row, value) -> row.withLastName(value), PgTypes.text);\n };\n\n @Override\n public OptField salary() {\n return new OptField(_path, \"salary\", EmployeeRow::salary, Optional.empty(), Optional.empty(), (row, value) -> row.withSalary(value), PgTypes.numeric);\n };\n\n @Override\n public OptField hiredAt() {\n return new OptField(_path, \"hired_at\", EmployeeRow::hiredAt, Optional.empty(), Optional.empty(), (row, value) -> row.withHiredAt(value), PgTypes.date);\n };\n\n @Override\n public OptField active() {\n return new OptField(_path, \"active\", EmployeeRow::active, Optional.empty(), Optional.empty(), (row, value) -> row.withActive(value), PgTypes.bool);\n };\n\n @Override\n public OptField createdAt() {\n return new OptField(_path, \"created_at\", EmployeeRow::createdAt, Optional.empty(), Optional.empty(), (row, value) -> row.withCreatedAt(value), PgTypes.timestamp);\n };\n\n @Override\n public OptField skills() {\n return new OptField(_path, \"skills\", EmployeeRow::skills, Optional.empty(), Optional.empty(), (row, value) -> row.withSkills(value), PgTypes.textArray);\n };\n\n @Override\n public OptField certifications() {\n return new OptField(_path, \"certifications\", EmployeeRow::certifications, Optional.empty(), Optional.empty(), (row, value) -> row.withCertifications(value), PgTypes.textArray);\n };\n\n @Override\n public OptField metadata() {\n return new OptField(_path, \"metadata\", EmployeeRow::metadata, Optional.empty(), Optional.empty(), (row, value) -> row.withMetadata(value), PgTypes.jsonb);\n };\n\n @Override\n public OptField, EmployeeRow> settings() {\n return new OptField, EmployeeRow>(_path, \"settings\", EmployeeRow::settings, Optional.empty(), Optional.empty(), (row, value) -> row.withSettings(value), PgTypes.hstore);\n };\n\n @Override\n public OptField workSchedule() {\n return new OptField(_path, \"work_schedule\", EmployeeRow::workSchedule, Optional.empty(), Optional.empty(), (row, value) -> row.withWorkSchedule(value), PgTypes.boolArray);\n };\n\n @Override\n public OptField ipAddress() {\n return new OptField(_path, \"ip_address\", EmployeeRow::ipAddress, Optional.empty(), Optional.empty(), (row, value) -> row.withIpAddress(value), PgTypes.inet);\n };\n\n @Override\n public OptField networkCidr() {\n return new OptField(_path, \"network_cidr\", EmployeeRow::networkCidr, Optional.empty(), Optional.empty(), (row, value) -> row.withNetworkCidr(value), PgTypes.cidr);\n };\n\n @Override\n public OptField macAddress() {\n return new OptField(_path, \"mac_address\", EmployeeRow::macAddress, Optional.empty(), Optional.empty(), (row, value) -> row.withMacAddress(value), PgTypes.macaddr);\n };\n\n @Override\n public OptField probationPeriod() {\n return new OptField(_path, \"probation_period\", EmployeeRow::probationPeriod, Optional.empty(), Optional.empty(), (row, value) -> row.withProbationPeriod(value), PgTypes.interval);\n };\n\n @Override\n public OptField photo() {\n return new OptField(_path, \"photo\", EmployeeRow::photo, Optional.empty(), Optional.empty(), (row, value) -> row.withPhoto(value), PgTypes.bytea);\n };\n\n @Override\n public List> columns() {\n return java.util.List.of(this.id(), this.departmentId(), this.managerId(), this.email(), this.firstName(), this.lastName(), this.salary(), this.hiredAt(), this.active(), this.createdAt(), this.skills(), this.certifications(), this.metadata(), this.settings(), this.workSchedule(), this.ipAddress(), this.networkCidr(), this.macAddress(), this.probationPeriod(), this.photo());\n };\n\n @Override\n public RelationStructure withPaths(List _path) {\n return new Impl(_path);\n };\n };\n\n static Impl structure() {\n return new Impl(java.util.Collections.emptyList());\n };\n\n IdField id();\n\n Field departmentId();\n\n OptField managerId();\n\n Field email();\n\n Field firstName();\n\n Field lastName();\n\n OptField salary();\n\n OptField hiredAt();\n\n OptField active();\n\n OptField createdAt();\n\n OptField skills();\n\n OptField certifications();\n\n OptField metadata();\n\n OptField, EmployeeRow> settings();\n\n OptField workSchedule();\n\n OptField ipAddress();\n\n OptField networkCidr();\n\n OptField macAddress();\n\n OptField probationPeriod();\n\n OptField photo();\n\n default ForeignKey fkDepartment() {\n return ForeignKey.of(\"employee_department_fk\").withColumnPair(departmentId(), DepartmentFields::id);\n };\n\n default ForeignKey fkEmployee() {\n return ForeignKey.of(\"employee_manager_fk\").withColumnPair(managerId(), EmployeeFields::id);\n };\n\n @Override\n List> columns();\n\n @Override\n default RowParser rowParser() {\n return EmployeeRow._rowParser;\n };\n}", - "DepartmentRow": "package showcase.showcase.department;\n\nimport dev.typr.foundations.PgText;\nimport dev.typr.foundations.PgTypes;\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport java.math.BigDecimal;\nimport java.util.Optional;\nimport showcase.showcase.company.CompanyId;\n\n/** Table: showcase.department\n * Primary key: id\n */\npublic record DepartmentRow(\n DepartmentId id,\n /** Points to {@link showcase.showcase.company.CompanyRow#id()} */\n CompanyId companyId,\n String name,\n Optional budget\n) {\n public DepartmentRow withId(DepartmentId id) {\n return new DepartmentRow(id, companyId, name, budget);\n };\n\n /** Points to {@link showcase.showcase.company.CompanyRow#id()} */\n public DepartmentRow withCompanyId(CompanyId companyId) {\n return new DepartmentRow(id, companyId, name, budget);\n };\n\n public DepartmentRow withName(String name) {\n return new DepartmentRow(id, companyId, name, budget);\n };\n\n public DepartmentRow withBudget(Optional budget) {\n return new DepartmentRow(id, companyId, name, budget);\n };\n\n public static RowParser _rowParser = RowParsers.of(DepartmentId.pgType, CompanyId.pgType, PgTypes.text, PgTypes.numeric.opt(), DepartmentRow::new, row -> new Object[]{row.id(), row.companyId(), row.name(), row.budget()});;\n\n static public PgText pgText =\n PgText.from(_rowParser);\n}", - "DepartmentId": "package showcase.showcase.department;\n\nimport dev.typr.foundations.PgType;\nimport dev.typr.foundations.PgTypes;\nimport dev.typr.foundations.dsl.Bijection;\nimport dev.typr.foundations.internal.arrayMap;\n\n/** Type for the primary key of table `showcase.department` */\npublic record DepartmentId(String value) {\n public DepartmentId withValue(String value) {\n return new DepartmentId(value);\n };\n\n @Override\n public java.lang.String toString() {\n return value.toString();\n };\n\n static public Bijection bijection =\n Bijection.of(DepartmentId::value, DepartmentId::new);\n\n static public PgType pgType =\n PgTypes.text.bimap(DepartmentId::new, DepartmentId::value);\n\n static public PgType pgTypeArray =\n PgTypes.textArray.bimap(xs -> arrayMap.map(xs, DepartmentId::new, DepartmentId.class), xs -> arrayMap.map(xs, DepartmentId::value, String.class));\n}", - "DepartmentRepo": "package showcase.showcase.department;\n\nimport dev.typr.foundations.dsl.DeleteBuilder;\nimport dev.typr.foundations.dsl.SelectBuilder;\nimport dev.typr.foundations.dsl.UpdateBuilder;\nimport java.sql.Connection;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\n\npublic interface DepartmentRepo {\n DeleteBuilder delete();\n\n Boolean deleteById(\n DepartmentId id,\n Connection c\n );\n\n Integer deleteByIds(\n DepartmentId[] ids,\n Connection c\n );\n\n DepartmentRow insert(\n DepartmentRow unsaved,\n Connection c\n );\n\n Long insertStreaming(\n Iterator unsaved,\n Integer batchSize,\n Connection c\n );\n\n SelectBuilder select();\n\n List selectAll(Connection c);\n\n Optional selectById(\n DepartmentId id,\n Connection c\n );\n\n List selectByIds(\n DepartmentId[] ids,\n Connection c\n );\n\n Map selectByIdsTracked(\n DepartmentId[] ids,\n Connection c\n );\n\n UpdateBuilder update();\n\n Boolean update(\n DepartmentRow row,\n Connection c\n );\n\n DepartmentRow upsert(\n DepartmentRow unsaved,\n Connection c\n );\n\n List upsertBatch(\n Iterator unsaved,\n Connection c\n );\n\n /** NOTE: this functionality is not safe if you use auto-commit mode! it runs 3 SQL statements */\n Integer upsertStreaming(\n Iterator unsaved,\n Integer batchSize,\n Connection c\n );\n}", - "DepartmentRepoMock": "package showcase.showcase.department;\n\nimport dev.typr.foundations.dsl.DeleteBuilder;\nimport dev.typr.foundations.dsl.DeleteBuilderMock;\nimport dev.typr.foundations.dsl.DeleteParams;\nimport dev.typr.foundations.dsl.SelectBuilder;\nimport dev.typr.foundations.dsl.SelectBuilderMock;\nimport dev.typr.foundations.dsl.SelectParams;\nimport dev.typr.foundations.dsl.UpdateBuilder;\nimport dev.typr.foundations.dsl.UpdateBuilderMock;\nimport dev.typr.foundations.dsl.UpdateParams;\nimport java.lang.RuntimeException;\nimport java.sql.Connection;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\nimport java.util.function.Function;\nimport java.util.stream.Collectors;\n\npublic record DepartmentRepoMock(HashMap map) implements DepartmentRepo {\n public DepartmentRepoMock() {\n this(new HashMap());\n };\n\n public DepartmentRepoMock withMap(HashMap map) {\n return new DepartmentRepoMock(map);\n };\n\n @Override\n public DeleteBuilder delete() {\n return new DeleteBuilderMock<>(DepartmentFields.structure(), () -> new ArrayList<>(map.values()), DeleteParams.empty(), row -> row.id(), id -> map.remove(id));\n };\n\n @Override\n public Boolean deleteById(\n DepartmentId id,\n Connection c\n ) {\n return Optional.ofNullable(map.remove(id)).isPresent();\n };\n\n @Override\n public Integer deleteByIds(\n DepartmentId[] ids,\n Connection c\n ) {\n var count = 0;\n for (var id : ids) {\n if (Optional.ofNullable(map.remove(id)).isPresent()) {\n count = count + 1;;\n };\n };\n return count;\n };\n\n @Override\n public DepartmentRow insert(\n DepartmentRow unsaved,\n Connection c\n ) {\n if (map.containsKey(unsaved.id())) {\n throw new RuntimeException(\"id \" + unsaved.id() + \" already exists\");\n };\n map.put(unsaved.id(), unsaved);\n return unsaved;\n };\n\n @Override\n public Long insertStreaming(\n Iterator unsaved,\n Integer batchSize,\n Connection c\n ) {\n var count = 0L;\n while (unsaved.hasNext()) {\n var row = unsaved.next();\n map.put(row.id(), row);\n count = count + 1L;\n };\n return count;\n };\n\n @Override\n public SelectBuilder select() {\n return new SelectBuilderMock<>(DepartmentFields.structure(), () -> new ArrayList<>(map.values()), SelectParams.empty());\n };\n\n @Override\n public List selectAll(Connection c) {\n return new ArrayList<>(map.values());\n };\n\n @Override\n public Optional selectById(\n DepartmentId id,\n Connection c\n ) {\n return Optional.ofNullable(map.get(id));\n };\n\n @Override\n public List selectByIds(\n DepartmentId[] ids,\n Connection c\n ) {\n var result = new ArrayList();\n for (var id : ids) {\n var opt = Optional.ofNullable(map.get(id));\n if (opt.isPresent()) {\n result.add(opt.get());\n };\n };\n return result;\n };\n\n @Override\n public Map selectByIdsTracked(\n DepartmentId[] ids,\n Connection c\n ) {\n return selectByIds(ids, c).stream().collect(Collectors.toMap((DepartmentRow row) -> row.id(), Function.identity()));\n };\n\n @Override\n public UpdateBuilder update() {\n return new UpdateBuilderMock<>(DepartmentFields.structure(), () -> new ArrayList<>(map.values()), UpdateParams.empty(), row -> row);\n };\n\n @Override\n public Boolean update(\n DepartmentRow row,\n Connection c\n ) {\n var shouldUpdate = Optional.ofNullable(map.get(row.id())).filter(oldRow -> !oldRow.equals(row)).isPresent();\n if (shouldUpdate) {\n map.put(row.id(), row);;\n };\n return shouldUpdate;\n };\n\n @Override\n public DepartmentRow upsert(\n DepartmentRow unsaved,\n Connection c\n ) {\n map.put(unsaved.id(), unsaved);\n return unsaved;\n };\n\n @Override\n public List upsertBatch(\n Iterator unsaved,\n Connection c\n ) {\n var result = new ArrayList();\n while (unsaved.hasNext()) {\n var row = unsaved.next();\n map.put(row.id(), row);\n result.add(row);\n };\n return result;\n };\n\n /** NOTE: this functionality is not safe if you use auto-commit mode! it runs 3 SQL statements */\n @Override\n public Integer upsertStreaming(\n Iterator unsaved,\n Integer batchSize,\n Connection c\n ) {\n var count = 0;\n while (unsaved.hasNext()) {\n var row = unsaved.next();\n map.put(row.id(), row);\n count = count + 1;\n };\n return count;\n };\n}", - "ProjectAssignmentRow": "package showcase.showcase.project_assignment;\n\nimport dev.typr.foundations.PgText;\nimport dev.typr.foundations.PgTypes;\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport java.time.LocalDate;\nimport java.util.Optional;\nimport showcase.customtypes.Defaulted;\nimport showcase.showcase.employee.EmployeeId;\nimport showcase.showcase.project.ProjectId;\n\n/** Table: showcase.project_assignment\n * Composite primary key: employee_id, project_id\n */\npublic record ProjectAssignmentRow(\n /** Points to {@link showcase.showcase.employee.EmployeeRow#id()} */\n EmployeeId employeeId,\n /** Points to {@link showcase.showcase.project.ProjectRow#id()} */\n ProjectId projectId,\n String role,\n /** Default: 0 */\n Optional hoursAllocated,\n Optional startDate,\n Optional endDate\n) {\n /** Points to {@link showcase.showcase.employee.EmployeeRow#id()} */\n public ProjectAssignmentRow withEmployeeId(EmployeeId employeeId) {\n return new ProjectAssignmentRow(employeeId, projectId, role, hoursAllocated, startDate, endDate);\n };\n\n /** Points to {@link showcase.showcase.project.ProjectRow#id()} */\n public ProjectAssignmentRow withProjectId(ProjectId projectId) {\n return new ProjectAssignmentRow(employeeId, projectId, role, hoursAllocated, startDate, endDate);\n };\n\n public ProjectAssignmentRow withRole(String role) {\n return new ProjectAssignmentRow(employeeId, projectId, role, hoursAllocated, startDate, endDate);\n };\n\n /** Default: 0 */\n public ProjectAssignmentRow withHoursAllocated(Optional hoursAllocated) {\n return new ProjectAssignmentRow(employeeId, projectId, role, hoursAllocated, startDate, endDate);\n };\n\n public ProjectAssignmentRow withStartDate(Optional startDate) {\n return new ProjectAssignmentRow(employeeId, projectId, role, hoursAllocated, startDate, endDate);\n };\n\n public ProjectAssignmentRow withEndDate(Optional endDate) {\n return new ProjectAssignmentRow(employeeId, projectId, role, hoursAllocated, startDate, endDate);\n };\n\n public static RowParser _rowParser = RowParsers.of(EmployeeId.pgType, ProjectId.pgType, PgTypes.text, PgTypes.int4.opt(), PgTypes.date.opt(), PgTypes.date.opt(), ProjectAssignmentRow::new, row -> new Object[]{row.employeeId(), row.projectId(), row.role(), row.hoursAllocated(), row.startDate(), row.endDate()});;\n\n static public ProjectAssignmentRow apply(\n ProjectAssignmentId compositeId,\n String role,\n Optional hoursAllocated,\n Optional startDate,\n Optional endDate\n ) {\n return new ProjectAssignmentRow(compositeId.employeeId(), compositeId.projectId(), role, hoursAllocated, startDate, endDate);\n };\n\n static public PgText pgText =\n PgText.from(_rowParser);\n\n public ProjectAssignmentId compositeId() {\n return new ProjectAssignmentId(employeeId, projectId);\n };\n\n public ProjectAssignmentId id() {\n return this.compositeId();\n };\n\n public ProjectAssignmentRowUnsaved toUnsavedRow(Defaulted> hoursAllocated) {\n return new ProjectAssignmentRowUnsaved(employeeId, projectId, role, startDate, endDate, hoursAllocated);\n };\n}", - "ProjectAssignmentRowUnsaved": "package showcase.showcase.project_assignment;\n\nimport dev.typr.foundations.PgText;\nimport dev.typr.foundations.PgTypes;\nimport java.time.LocalDate;\nimport java.util.Optional;\nimport showcase.customtypes.Defaulted;\nimport showcase.customtypes.Defaulted.UseDefault;\nimport showcase.showcase.employee.EmployeeId;\nimport showcase.showcase.project.ProjectId;\n\n/** This class corresponds to a row in table `showcase.project_assignment` which has not been persisted yet */\npublic record ProjectAssignmentRowUnsaved(\n /** Points to {@link showcase.showcase.employee.EmployeeRow#id()} */\n EmployeeId employeeId,\n /** Points to {@link showcase.showcase.project.ProjectRow#id()} */\n ProjectId projectId,\n String role,\n Optional startDate,\n Optional endDate,\n /** Default: 0 */\n Defaulted> hoursAllocated\n) {\n public ProjectAssignmentRowUnsaved(\n /** Points to {@link showcase.showcase.employee.EmployeeRow#id()} */\n EmployeeId employeeId,\n /** Points to {@link showcase.showcase.project.ProjectRow#id()} */\n ProjectId projectId,\n String role\n ) {\n this(employeeId, projectId, role, Optional.empty(), Optional.empty(), new UseDefault<>());\n };\n\n /** Points to {@link showcase.showcase.employee.EmployeeRow#id()} */\n public ProjectAssignmentRowUnsaved withEmployeeId(EmployeeId employeeId) {\n return new ProjectAssignmentRowUnsaved(employeeId, projectId, role, startDate, endDate, hoursAllocated);\n };\n\n /** Points to {@link showcase.showcase.project.ProjectRow#id()} */\n public ProjectAssignmentRowUnsaved withProjectId(ProjectId projectId) {\n return new ProjectAssignmentRowUnsaved(employeeId, projectId, role, startDate, endDate, hoursAllocated);\n };\n\n public ProjectAssignmentRowUnsaved withRole(String role) {\n return new ProjectAssignmentRowUnsaved(employeeId, projectId, role, startDate, endDate, hoursAllocated);\n };\n\n public ProjectAssignmentRowUnsaved withStartDate(Optional startDate) {\n return new ProjectAssignmentRowUnsaved(employeeId, projectId, role, startDate, endDate, hoursAllocated);\n };\n\n public ProjectAssignmentRowUnsaved withEndDate(Optional endDate) {\n return new ProjectAssignmentRowUnsaved(employeeId, projectId, role, startDate, endDate, hoursAllocated);\n };\n\n /** Default: 0 */\n public ProjectAssignmentRowUnsaved withHoursAllocated(Defaulted> hoursAllocated) {\n return new ProjectAssignmentRowUnsaved(employeeId, projectId, role, startDate, endDate, hoursAllocated);\n };\n\n static public PgText pgText =\n PgText.instance((row, sb) -> {\n EmployeeId.pgType.text().unsafeEncode(row.employeeId, sb);\n sb.append(PgText.DELIMETER);\n ProjectId.pgType.text().unsafeEncode(row.projectId, sb);\n sb.append(PgText.DELIMETER);\n PgTypes.text.text().unsafeEncode(row.role, sb);\n sb.append(PgText.DELIMETER);\n PgTypes.date.opt().text().unsafeEncode(row.startDate, sb);\n sb.append(PgText.DELIMETER);\n PgTypes.date.opt().text().unsafeEncode(row.endDate, sb);\n sb.append(PgText.DELIMETER);\n Defaulted.pgText(PgTypes.int4.opt().text()).unsafeEncode(row.hoursAllocated, sb);\n });\n\n public ProjectAssignmentRow toRow(java.util.function.Supplier> hoursAllocatedDefault) {\n return new ProjectAssignmentRow(employeeId, projectId, role, hoursAllocated.getOrElse(hoursAllocatedDefault), startDate, endDate);\n };\n}", - "ProjectAssignmentId": "package showcase.showcase.project_assignment;\n\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport showcase.showcase.employee.EmployeeId;\nimport showcase.showcase.project.ProjectId;\n\n/** Type for the composite primary key of table `showcase.project_assignment` */\npublic record ProjectAssignmentId(\n EmployeeId employeeId,\n ProjectId projectId\n) {\n public ProjectAssignmentId withEmployeeId(EmployeeId employeeId) {\n return new ProjectAssignmentId(employeeId, projectId);\n };\n\n public ProjectAssignmentId withProjectId(ProjectId projectId) {\n return new ProjectAssignmentId(employeeId, projectId);\n };\n\n public static RowParser _rowParser = RowParsers.of(EmployeeId.pgType, ProjectId.pgType, ProjectAssignmentId::new, row -> new Object[]{row.employeeId(), row.projectId()});;\n}", - "ProjectAssignmentRepo": "package showcase.showcase.project_assignment;\n\nimport dev.typr.foundations.dsl.DeleteBuilder;\nimport dev.typr.foundations.dsl.SelectBuilder;\nimport dev.typr.foundations.dsl.UpdateBuilder;\nimport java.sql.Connection;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\n\npublic interface ProjectAssignmentRepo {\n DeleteBuilder delete();\n\n Boolean deleteById(\n ProjectAssignmentId compositeId,\n Connection c\n );\n\n Integer deleteByIds(\n ProjectAssignmentId[] compositeIds,\n Connection c\n );\n\n ProjectAssignmentRow insert(\n ProjectAssignmentRow unsaved,\n Connection c\n );\n\n ProjectAssignmentRow insert(\n ProjectAssignmentRowUnsaved unsaved,\n Connection c\n );\n\n Long insertStreaming(\n Iterator unsaved,\n Integer batchSize,\n Connection c\n );\n\n /** NOTE: this functionality requires PostgreSQL 16 or later! */\n Long insertUnsavedStreaming(\n Iterator unsaved,\n Integer batchSize,\n Connection c\n );\n\n SelectBuilder select();\n\n List selectAll(Connection c);\n\n Optional selectById(\n ProjectAssignmentId compositeId,\n Connection c\n );\n\n List selectByIds(\n ProjectAssignmentId[] compositeIds,\n Connection c\n );\n\n Map selectByIdsTracked(\n ProjectAssignmentId[] compositeIds,\n Connection c\n );\n\n UpdateBuilder update();\n\n Boolean update(\n ProjectAssignmentRow row,\n Connection c\n );\n\n ProjectAssignmentRow upsert(\n ProjectAssignmentRow unsaved,\n Connection c\n );\n\n List upsertBatch(\n Iterator unsaved,\n Connection c\n );\n\n /** NOTE: this functionality is not safe if you use auto-commit mode! it runs 3 SQL statements */\n Integer upsertStreaming(\n Iterator unsaved,\n Integer batchSize,\n Connection c\n );\n}", - "ProjectRow": "package showcase.showcase.project;\n\nimport dev.typr.foundations.PgText;\nimport dev.typr.foundations.PgTypes;\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport dev.typr.foundations.data.Jsonb;\nimport java.math.BigDecimal;\nimport java.time.LocalDate;\nimport java.time.LocalDateTime;\nimport java.util.Map;\nimport java.util.Optional;\nimport java.util.UUID;\nimport org.postgresql.util.PGInterval;\nimport showcase.customtypes.Defaulted;\n\n/** Table: showcase.project\n * Primary key: id\n */\npublic record ProjectRow(\n ProjectId id,\n String name,\n Optional description,\n Optional startDate,\n Optional endDate,\n Optional budget,\n /** Default: 'planning' */\n Optional status,\n /** Default: CURRENT_TIMESTAMP */\n Optional createdAt,\n Optional projectUid,\n Optional milestones,\n Optional budgetSnapshots,\n Optional teamMembers,\n Optional metadata,\n Optional> config,\n Optional estimatedDuration,\n Optional actualDuration\n) {\n public ProjectRow withId(ProjectId id) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, projectUid, milestones, budgetSnapshots, teamMembers, metadata, config, estimatedDuration, actualDuration);\n };\n\n public ProjectRow withName(String name) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, projectUid, milestones, budgetSnapshots, teamMembers, metadata, config, estimatedDuration, actualDuration);\n };\n\n public ProjectRow withDescription(Optional description) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, projectUid, milestones, budgetSnapshots, teamMembers, metadata, config, estimatedDuration, actualDuration);\n };\n\n public ProjectRow withStartDate(Optional startDate) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, projectUid, milestones, budgetSnapshots, teamMembers, metadata, config, estimatedDuration, actualDuration);\n };\n\n public ProjectRow withEndDate(Optional endDate) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, projectUid, milestones, budgetSnapshots, teamMembers, metadata, config, estimatedDuration, actualDuration);\n };\n\n public ProjectRow withBudget(Optional budget) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, projectUid, milestones, budgetSnapshots, teamMembers, metadata, config, estimatedDuration, actualDuration);\n };\n\n /** Default: 'planning' */\n public ProjectRow withStatus(Optional status) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, projectUid, milestones, budgetSnapshots, teamMembers, metadata, config, estimatedDuration, actualDuration);\n };\n\n /** Default: CURRENT_TIMESTAMP */\n public ProjectRow withCreatedAt(Optional createdAt) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, projectUid, milestones, budgetSnapshots, teamMembers, metadata, config, estimatedDuration, actualDuration);\n };\n\n public ProjectRow withProjectUid(Optional projectUid) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, projectUid, milestones, budgetSnapshots, teamMembers, metadata, config, estimatedDuration, actualDuration);\n };\n\n public ProjectRow withMilestones(Optional milestones) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, projectUid, milestones, budgetSnapshots, teamMembers, metadata, config, estimatedDuration, actualDuration);\n };\n\n public ProjectRow withBudgetSnapshots(Optional budgetSnapshots) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, projectUid, milestones, budgetSnapshots, teamMembers, metadata, config, estimatedDuration, actualDuration);\n };\n\n public ProjectRow withTeamMembers(Optional teamMembers) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, projectUid, milestones, budgetSnapshots, teamMembers, metadata, config, estimatedDuration, actualDuration);\n };\n\n public ProjectRow withMetadata(Optional metadata) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, projectUid, milestones, budgetSnapshots, teamMembers, metadata, config, estimatedDuration, actualDuration);\n };\n\n public ProjectRow withConfig(Optional> config) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, projectUid, milestones, budgetSnapshots, teamMembers, metadata, config, estimatedDuration, actualDuration);\n };\n\n public ProjectRow withEstimatedDuration(Optional estimatedDuration) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, projectUid, milestones, budgetSnapshots, teamMembers, metadata, config, estimatedDuration, actualDuration);\n };\n\n public ProjectRow withActualDuration(Optional actualDuration) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, projectUid, milestones, budgetSnapshots, teamMembers, metadata, config, estimatedDuration, actualDuration);\n };\n\n public static RowParser _rowParser = RowParsers.of(ProjectId.pgType, PgTypes.text, PgTypes.text.opt(), PgTypes.date.opt(), PgTypes.date.opt(), PgTypes.numeric.opt(), PgTypes.text.opt(), PgTypes.timestamp.opt(), PgTypes.uuid.opt(), PgTypes.textArray.opt(), PgTypes.numericArray.opt(), PgTypes.textArray.opt(), PgTypes.jsonb.opt(), PgTypes.hstore.opt(), PgTypes.interval.opt(), PgTypes.interval.opt(), ProjectRow::new, row -> new Object[]{row.id(), row.name(), row.description(), row.startDate(), row.endDate(), row.budget(), row.status(), row.createdAt(), row.projectUid(), row.milestones(), row.budgetSnapshots(), row.teamMembers(), row.metadata(), row.config(), row.estimatedDuration(), row.actualDuration()});;\n\n static public PgText pgText =\n PgText.from(_rowParser);\n\n public ProjectRowUnsaved toUnsavedRow(\n Defaulted> status,\n Defaulted> createdAt\n ) {\n return new ProjectRowUnsaved(id, name, description, startDate, endDate, budget, projectUid, milestones, budgetSnapshots, teamMembers, metadata, config, estimatedDuration, actualDuration, status, createdAt);\n };\n}", - "ProjectId": "package showcase.showcase.project;\n\nimport dev.typr.foundations.PgType;\nimport dev.typr.foundations.PgTypes;\nimport dev.typr.foundations.dsl.Bijection;\nimport dev.typr.foundations.internal.arrayMap;\n\n/** Type for the primary key of table `showcase.project` */\npublic record ProjectId(String value) {\n public ProjectId withValue(String value) {\n return new ProjectId(value);\n };\n\n @Override\n public java.lang.String toString() {\n return value.toString();\n };\n\n static public Bijection bijection =\n Bijection.of(ProjectId::value, ProjectId::new);\n\n static public PgType pgType =\n PgTypes.text.bimap(ProjectId::new, ProjectId::value);\n\n static public PgType pgTypeArray =\n PgTypes.textArray.bimap(xs -> arrayMap.map(xs, ProjectId::new, ProjectId.class), xs -> arrayMap.map(xs, ProjectId::value, String.class));\n}", - "EmployeeSummaryViewRow": "package showcase.showcase.employee_summary;\n\nimport dev.typr.foundations.PgTypes;\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport java.math.BigDecimal;\nimport java.time.LocalDate;\nimport java.util.Optional;\nimport showcase.showcase.company.CompanyId;\nimport showcase.showcase.department.DepartmentId;\nimport showcase.showcase.employee.EmployeeId;\n\n/** View: showcase.employee_summary\n * Summary view of employees with their department and company information\n */\npublic record EmployeeSummaryViewRow(\n /** Points to {@link showcase.showcase.employee.EmployeeRow#id()} */\n EmployeeId employeeId,\n String email,\n String firstName,\n String lastName,\n Optional salary,\n Optional hiredAt,\n Optional active,\n /** Points to {@link showcase.showcase.department.DepartmentRow#id()} */\n DepartmentId departmentId,\n String departmentName,\n Optional departmentBudget,\n /** Points to {@link showcase.showcase.company.CompanyRow#id()} */\n CompanyId companyId,\n String companyName,\n Optional managerId,\n Optional managerFirstName,\n Optional managerLastName\n) {\n /** Points to {@link showcase.showcase.employee.EmployeeRow#id()} */\n public EmployeeSummaryViewRow withEmployeeId(EmployeeId employeeId) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withEmail(String email) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withFirstName(String firstName) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withLastName(String lastName) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withSalary(Optional salary) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withHiredAt(Optional hiredAt) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withActive(Optional active) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n /** Points to {@link showcase.showcase.department.DepartmentRow#id()} */\n public EmployeeSummaryViewRow withDepartmentId(DepartmentId departmentId) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withDepartmentName(String departmentName) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withDepartmentBudget(Optional departmentBudget) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n /** Points to {@link showcase.showcase.company.CompanyRow#id()} */\n public EmployeeSummaryViewRow withCompanyId(CompanyId companyId) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withCompanyName(String companyName) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withManagerId(Optional managerId) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withManagerFirstName(Optional managerFirstName) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withManagerLastName(Optional managerLastName) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public static RowParser _rowParser = RowParsers.of(EmployeeId.pgType, PgTypes.text, PgTypes.text, PgTypes.text, PgTypes.numeric.opt(), PgTypes.date.opt(), PgTypes.bool.opt(), DepartmentId.pgType, PgTypes.text, PgTypes.numeric.opt(), CompanyId.pgType, PgTypes.text, PgTypes.text.opt(), PgTypes.text.opt(), PgTypes.text.opt(), EmployeeSummaryViewRow::new, row -> new Object[]{row.employeeId(), row.email(), row.firstName(), row.lastName(), row.salary(), row.hiredAt(), row.active(), row.departmentId(), row.departmentName(), row.departmentBudget(), row.companyId(), row.companyName(), row.managerId(), row.managerFirstName(), row.managerLastName()});;\n}", - "EmployeeSummaryViewRepo": "package showcase.showcase.employee_summary;\n\nimport dev.typr.foundations.dsl.SelectBuilder;\nimport java.sql.Connection;\nimport java.util.List;\n\npublic interface EmployeeSummaryViewRepo {\n SelectBuilder select();\n\n List selectAll(Connection c);\n}", - "CustomerOrderRow": "package showcase.showcase.customer_order;\n\nimport dev.typr.foundations.PgText;\nimport dev.typr.foundations.PgTypes;\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport dev.typr.foundations.data.Inet;\nimport dev.typr.foundations.data.Jsonb;\nimport java.math.BigDecimal;\nimport java.time.LocalDateTime;\nimport java.util.Optional;\nimport java.util.UUID;\nimport org.postgresql.util.PGInterval;\nimport showcase.customtypes.Defaulted;\nimport showcase.showcase.address.AddressId;\nimport showcase.showcase.customer.CustomerId;\n\n/** Table: showcase.customer_order\n * Primary key: id\n */\npublic record CustomerOrderRow(\n CustomerOrderId id,\n /** Points to {@link showcase.showcase.customer.CustomerRow#id()} */\n CustomerId customerId,\n /** Points to {@link showcase.showcase.address.AddressRow#id()} */\n Optional shippingAddressId,\n /** Points to {@link showcase.showcase.address.AddressRow#id()} */\n Optional billingAddressId,\n /** Default: 'pending' */\n Optional status,\n BigDecimal subtotal,\n /** Default: 0 */\n Optional tax,\n /** Default: 0 */\n Optional shipping,\n BigDecimal total,\n Optional notes,\n /** Default: CURRENT_TIMESTAMP */\n Optional createdAt,\n Optional shippedAt,\n Optional deliveredAt,\n Optional orderUid,\n Optional metadata,\n Optional tags,\n Optional fulfillmentTimes,\n Optional ipAddress,\n Optional processingTime\n) {\n public CustomerOrderRow withId(CustomerOrderId id) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderUid, metadata, tags, fulfillmentTimes, ipAddress, processingTime);\n };\n\n /** Points to {@link showcase.showcase.customer.CustomerRow#id()} */\n public CustomerOrderRow withCustomerId(CustomerId customerId) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderUid, metadata, tags, fulfillmentTimes, ipAddress, processingTime);\n };\n\n /** Points to {@link showcase.showcase.address.AddressRow#id()} */\n public CustomerOrderRow withShippingAddressId(Optional shippingAddressId) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderUid, metadata, tags, fulfillmentTimes, ipAddress, processingTime);\n };\n\n /** Points to {@link showcase.showcase.address.AddressRow#id()} */\n public CustomerOrderRow withBillingAddressId(Optional billingAddressId) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderUid, metadata, tags, fulfillmentTimes, ipAddress, processingTime);\n };\n\n /** Default: 'pending' */\n public CustomerOrderRow withStatus(Optional status) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderUid, metadata, tags, fulfillmentTimes, ipAddress, processingTime);\n };\n\n public CustomerOrderRow withSubtotal(BigDecimal subtotal) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderUid, metadata, tags, fulfillmentTimes, ipAddress, processingTime);\n };\n\n /** Default: 0 */\n public CustomerOrderRow withTax(Optional tax) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderUid, metadata, tags, fulfillmentTimes, ipAddress, processingTime);\n };\n\n /** Default: 0 */\n public CustomerOrderRow withShipping(Optional shipping) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderUid, metadata, tags, fulfillmentTimes, ipAddress, processingTime);\n };\n\n public CustomerOrderRow withTotal(BigDecimal total) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderUid, metadata, tags, fulfillmentTimes, ipAddress, processingTime);\n };\n\n public CustomerOrderRow withNotes(Optional notes) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderUid, metadata, tags, fulfillmentTimes, ipAddress, processingTime);\n };\n\n /** Default: CURRENT_TIMESTAMP */\n public CustomerOrderRow withCreatedAt(Optional createdAt) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderUid, metadata, tags, fulfillmentTimes, ipAddress, processingTime);\n };\n\n public CustomerOrderRow withShippedAt(Optional shippedAt) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderUid, metadata, tags, fulfillmentTimes, ipAddress, processingTime);\n };\n\n public CustomerOrderRow withDeliveredAt(Optional deliveredAt) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderUid, metadata, tags, fulfillmentTimes, ipAddress, processingTime);\n };\n\n public CustomerOrderRow withOrderUid(Optional orderUid) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderUid, metadata, tags, fulfillmentTimes, ipAddress, processingTime);\n };\n\n public CustomerOrderRow withMetadata(Optional metadata) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderUid, metadata, tags, fulfillmentTimes, ipAddress, processingTime);\n };\n\n public CustomerOrderRow withTags(Optional tags) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderUid, metadata, tags, fulfillmentTimes, ipAddress, processingTime);\n };\n\n public CustomerOrderRow withFulfillmentTimes(Optional fulfillmentTimes) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderUid, metadata, tags, fulfillmentTimes, ipAddress, processingTime);\n };\n\n public CustomerOrderRow withIpAddress(Optional ipAddress) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderUid, metadata, tags, fulfillmentTimes, ipAddress, processingTime);\n };\n\n public CustomerOrderRow withProcessingTime(Optional processingTime) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderUid, metadata, tags, fulfillmentTimes, ipAddress, processingTime);\n };\n\n public static RowParser _rowParser = RowParsers.of(CustomerOrderId.pgType, CustomerId.pgType, AddressId.pgType.opt(), AddressId.pgType.opt(), PgTypes.text.opt(), PgTypes.numeric, PgTypes.numeric.opt(), PgTypes.numeric.opt(), PgTypes.numeric, PgTypes.text.opt(), PgTypes.timestamp.opt(), PgTypes.timestamp.opt(), PgTypes.timestamp.opt(), PgTypes.uuid.opt(), PgTypes.jsonb.opt(), PgTypes.textArray.opt(), PgTypes.timestampArray.opt(), PgTypes.inet.opt(), PgTypes.interval.opt(), CustomerOrderRow::new, row -> new Object[]{row.id(), row.customerId(), row.shippingAddressId(), row.billingAddressId(), row.status(), row.subtotal(), row.tax(), row.shipping(), row.total(), row.notes(), row.createdAt(), row.shippedAt(), row.deliveredAt(), row.orderUid(), row.metadata(), row.tags(), row.fulfillmentTimes(), row.ipAddress(), row.processingTime()});;\n\n static public PgText pgText =\n PgText.from(_rowParser);\n\n public CustomerOrderRowUnsaved toUnsavedRow(\n Defaulted> status,\n Defaulted> tax,\n Defaulted> shipping,\n Defaulted> createdAt\n ) {\n return new CustomerOrderRowUnsaved(id, customerId, shippingAddressId, billingAddressId, subtotal, total, notes, shippedAt, deliveredAt, orderUid, metadata, tags, fulfillmentTimes, ipAddress, processingTime, status, tax, shipping, createdAt);\n };\n}", - "CustomerOrderRepo": "package showcase.showcase.customer_order;\n\nimport dev.typr.foundations.dsl.DeleteBuilder;\nimport dev.typr.foundations.dsl.SelectBuilder;\nimport dev.typr.foundations.dsl.UpdateBuilder;\nimport java.sql.Connection;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\n\npublic interface CustomerOrderRepo {\n DeleteBuilder delete();\n\n Boolean deleteById(\n CustomerOrderId id,\n Connection c\n );\n\n Integer deleteByIds(\n CustomerOrderId[] ids,\n Connection c\n );\n\n CustomerOrderRow insert(\n CustomerOrderRow unsaved,\n Connection c\n );\n\n CustomerOrderRow insert(\n CustomerOrderRowUnsaved unsaved,\n Connection c\n );\n\n Long insertStreaming(\n Iterator unsaved,\n Integer batchSize,\n Connection c\n );\n\n /** NOTE: this functionality requires PostgreSQL 16 or later! */\n Long insertUnsavedStreaming(\n Iterator unsaved,\n Integer batchSize,\n Connection c\n );\n\n SelectBuilder select();\n\n List selectAll(Connection c);\n\n Optional selectById(\n CustomerOrderId id,\n Connection c\n );\n\n List selectByIds(\n CustomerOrderId[] ids,\n Connection c\n );\n\n Map selectByIdsTracked(\n CustomerOrderId[] ids,\n Connection c\n );\n\n UpdateBuilder update();\n\n Boolean update(\n CustomerOrderRow row,\n Connection c\n );\n\n CustomerOrderRow upsert(\n CustomerOrderRow unsaved,\n Connection c\n );\n\n List upsertBatch(\n Iterator unsaved,\n Connection c\n );\n\n /** NOTE: this functionality is not safe if you use auto-commit mode! it runs 3 SQL statements */\n Integer upsertStreaming(\n Iterator unsaved,\n Integer batchSize,\n Connection c\n );\n}", - "OrderItemRow": "package showcase.showcase.order_item;\n\nimport dev.typr.foundations.PgText;\nimport dev.typr.foundations.PgTypes;\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport java.math.BigDecimal;\nimport java.util.Optional;\nimport showcase.customtypes.Defaulted;\nimport showcase.showcase.customer_order.CustomerOrderId;\nimport showcase.showcase.product.ProductId;\n\n/** Table: showcase.order_item\n * Composite primary key: order_id, product_id\n */\npublic record OrderItemRow(\n /** Points to {@link showcase.showcase.customer_order.CustomerOrderRow#id()} */\n CustomerOrderId orderId,\n /** Points to {@link showcase.showcase.product.ProductRow#id()} */\n ProductId productId,\n Integer quantity,\n BigDecimal unitPrice,\n /** Default: 0 */\n Optional discount\n) {\n /** Points to {@link showcase.showcase.customer_order.CustomerOrderRow#id()} */\n public OrderItemRow withOrderId(CustomerOrderId orderId) {\n return new OrderItemRow(orderId, productId, quantity, unitPrice, discount);\n };\n\n /** Points to {@link showcase.showcase.product.ProductRow#id()} */\n public OrderItemRow withProductId(ProductId productId) {\n return new OrderItemRow(orderId, productId, quantity, unitPrice, discount);\n };\n\n public OrderItemRow withQuantity(Integer quantity) {\n return new OrderItemRow(orderId, productId, quantity, unitPrice, discount);\n };\n\n public OrderItemRow withUnitPrice(BigDecimal unitPrice) {\n return new OrderItemRow(orderId, productId, quantity, unitPrice, discount);\n };\n\n /** Default: 0 */\n public OrderItemRow withDiscount(Optional discount) {\n return new OrderItemRow(orderId, productId, quantity, unitPrice, discount);\n };\n\n public static RowParser _rowParser = RowParsers.of(CustomerOrderId.pgType, ProductId.pgType, PgTypes.int4, PgTypes.numeric, PgTypes.numeric.opt(), OrderItemRow::new, row -> new Object[]{row.orderId(), row.productId(), row.quantity(), row.unitPrice(), row.discount()});;\n\n static public OrderItemRow apply(\n OrderItemId compositeId,\n Integer quantity,\n BigDecimal unitPrice,\n Optional discount\n ) {\n return new OrderItemRow(compositeId.orderId(), compositeId.productId(), quantity, unitPrice, discount);\n };\n\n static public PgText pgText =\n PgText.from(_rowParser);\n\n public OrderItemId compositeId() {\n return new OrderItemId(orderId, productId);\n };\n\n public OrderItemId id() {\n return this.compositeId();\n };\n\n public OrderItemRowUnsaved toUnsavedRow(Defaulted> discount) {\n return new OrderItemRowUnsaved(orderId, productId, quantity, unitPrice, discount);\n };\n}", - "OrderItemId": "package showcase.showcase.order_item;\n\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport showcase.showcase.customer_order.CustomerOrderId;\nimport showcase.showcase.product.ProductId;\n\n/** Type for the composite primary key of table `showcase.order_item` */\npublic record OrderItemId(\n CustomerOrderId orderId,\n ProductId productId\n) {\n public OrderItemId withOrderId(CustomerOrderId orderId) {\n return new OrderItemId(orderId, productId);\n };\n\n public OrderItemId withProductId(ProductId productId) {\n return new OrderItemId(orderId, productId);\n };\n\n public static RowParser _rowParser = RowParsers.of(CustomerOrderId.pgType, ProductId.pgType, OrderItemId::new, row -> new Object[]{row.orderId(), row.productId()});;\n}", - "ProductRow": "package showcase.showcase.product;\n\nimport dev.typr.foundations.PgText;\nimport dev.typr.foundations.PgTypes;\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport dev.typr.foundations.data.Jsonb;\nimport java.math.BigDecimal;\nimport java.time.LocalDateTime;\nimport java.util.Optional;\nimport java.util.UUID;\nimport showcase.customtypes.Defaulted;\nimport showcase.showcase.category.CategoryId;\n\n/** Table: showcase.product\n * Primary key: id\n */\npublic record ProductRow(\n ProductId id,\n /** Points to {@link showcase.showcase.category.CategoryRow#id()} */\n Optional categoryId,\n String name,\n String sku,\n BigDecimal price,\n Optional cost,\n /** Default: true */\n Optional inStock,\n /** Default: 0 */\n Optional quantity,\n Optional weight,\n /** Default: CURRENT_TIMESTAMP */\n Optional createdAt,\n Optional tags,\n Optional images,\n Optional relatedSkus,\n Optional priceHistory,\n Optional attributes,\n Optional specifications,\n Optional seoMetadata,\n Optional searchVector,\n Optional productUid\n) {\n public ProductRow withId(ProductId id) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, tags, images, relatedSkus, priceHistory, attributes, specifications, seoMetadata, searchVector, productUid);\n };\n\n /** Points to {@link showcase.showcase.category.CategoryRow#id()} */\n public ProductRow withCategoryId(Optional categoryId) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, tags, images, relatedSkus, priceHistory, attributes, specifications, seoMetadata, searchVector, productUid);\n };\n\n public ProductRow withName(String name) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, tags, images, relatedSkus, priceHistory, attributes, specifications, seoMetadata, searchVector, productUid);\n };\n\n public ProductRow withSku(String sku) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, tags, images, relatedSkus, priceHistory, attributes, specifications, seoMetadata, searchVector, productUid);\n };\n\n public ProductRow withPrice(BigDecimal price) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, tags, images, relatedSkus, priceHistory, attributes, specifications, seoMetadata, searchVector, productUid);\n };\n\n public ProductRow withCost(Optional cost) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, tags, images, relatedSkus, priceHistory, attributes, specifications, seoMetadata, searchVector, productUid);\n };\n\n /** Default: true */\n public ProductRow withInStock(Optional inStock) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, tags, images, relatedSkus, priceHistory, attributes, specifications, seoMetadata, searchVector, productUid);\n };\n\n /** Default: 0 */\n public ProductRow withQuantity(Optional quantity) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, tags, images, relatedSkus, priceHistory, attributes, specifications, seoMetadata, searchVector, productUid);\n };\n\n public ProductRow withWeight(Optional weight) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, tags, images, relatedSkus, priceHistory, attributes, specifications, seoMetadata, searchVector, productUid);\n };\n\n /** Default: CURRENT_TIMESTAMP */\n public ProductRow withCreatedAt(Optional createdAt) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, tags, images, relatedSkus, priceHistory, attributes, specifications, seoMetadata, searchVector, productUid);\n };\n\n public ProductRow withTags(Optional tags) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, tags, images, relatedSkus, priceHistory, attributes, specifications, seoMetadata, searchVector, productUid);\n };\n\n public ProductRow withImages(Optional images) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, tags, images, relatedSkus, priceHistory, attributes, specifications, seoMetadata, searchVector, productUid);\n };\n\n public ProductRow withRelatedSkus(Optional relatedSkus) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, tags, images, relatedSkus, priceHistory, attributes, specifications, seoMetadata, searchVector, productUid);\n };\n\n public ProductRow withPriceHistory(Optional priceHistory) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, tags, images, relatedSkus, priceHistory, attributes, specifications, seoMetadata, searchVector, productUid);\n };\n\n public ProductRow withAttributes(Optional attributes) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, tags, images, relatedSkus, priceHistory, attributes, specifications, seoMetadata, searchVector, productUid);\n };\n\n public ProductRow withSpecifications(Optional specifications) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, tags, images, relatedSkus, priceHistory, attributes, specifications, seoMetadata, searchVector, productUid);\n };\n\n public ProductRow withSeoMetadata(Optional seoMetadata) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, tags, images, relatedSkus, priceHistory, attributes, specifications, seoMetadata, searchVector, productUid);\n };\n\n public ProductRow withSearchVector(Optional searchVector) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, tags, images, relatedSkus, priceHistory, attributes, specifications, seoMetadata, searchVector, productUid);\n };\n\n public ProductRow withProductUid(Optional productUid) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, tags, images, relatedSkus, priceHistory, attributes, specifications, seoMetadata, searchVector, productUid);\n };\n\n public static RowParser _rowParser = RowParsers.of(ProductId.pgType, CategoryId.pgType.opt(), PgTypes.text, PgTypes.text, PgTypes.numeric, PgTypes.numeric.opt(), PgTypes.bool.opt(), PgTypes.int4.opt(), PgTypes.numeric.opt(), PgTypes.timestamp.opt(), PgTypes.textArray.opt(), PgTypes.textArray.opt(), PgTypes.textArray.opt(), PgTypes.numericArray.opt(), PgTypes.jsonb.opt(), PgTypes.jsonb.opt(), PgTypes.jsonb.opt(), PgTypes.text.opt(), PgTypes.uuid.opt(), ProductRow::new, row -> new Object[]{row.id(), row.categoryId(), row.name(), row.sku(), row.price(), row.cost(), row.inStock(), row.quantity(), row.weight(), row.createdAt(), row.tags(), row.images(), row.relatedSkus(), row.priceHistory(), row.attributes(), row.specifications(), row.seoMetadata(), row.searchVector(), row.productUid()});;\n\n static public PgText pgText =\n PgText.from(_rowParser);\n\n public ProductRowUnsaved toUnsavedRow(\n Defaulted> inStock,\n Defaulted> quantity,\n Defaulted> createdAt\n ) {\n return new ProductRowUnsaved(id, categoryId, name, sku, price, cost, weight, tags, images, relatedSkus, priceHistory, attributes, specifications, seoMetadata, searchVector, productUid, inStock, quantity, createdAt);\n };\n}", - "ProductId": "package showcase.showcase.product;\n\nimport dev.typr.foundations.PgType;\nimport dev.typr.foundations.PgTypes;\nimport dev.typr.foundations.dsl.Bijection;\nimport dev.typr.foundations.internal.arrayMap;\n\n/** Type for the primary key of table `showcase.product` */\npublic record ProductId(String value) {\n public ProductId withValue(String value) {\n return new ProductId(value);\n };\n\n @Override\n public java.lang.String toString() {\n return value.toString();\n };\n\n static public Bijection bijection =\n Bijection.of(ProductId::value, ProductId::new);\n\n static public PgType pgType =\n PgTypes.text.bimap(ProductId::new, ProductId::value);\n\n static public PgType pgTypeArray =\n PgTypes.textArray.bimap(xs -> arrayMap.map(xs, ProductId::new, ProductId.class), xs -> arrayMap.map(xs, ProductId::value, String.class));\n}", - "CategoryRow": "package showcase.showcase.category;\n\nimport dev.typr.foundations.PgText;\nimport dev.typr.foundations.PgTypes;\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport java.util.Optional;\n\n/** Table: showcase.category\n * Primary key: id\n */\npublic record CategoryRow(\n CategoryId id,\n /** Points to {@link showcase.showcase.category.CategoryRow#id()} */\n Optional parentId,\n String name,\n Optional description\n) {\n public CategoryRow withId(CategoryId id) {\n return new CategoryRow(id, parentId, name, description);\n };\n\n /** Points to {@link showcase.showcase.category.CategoryRow#id()} */\n public CategoryRow withParentId(Optional parentId) {\n return new CategoryRow(id, parentId, name, description);\n };\n\n public CategoryRow withName(String name) {\n return new CategoryRow(id, parentId, name, description);\n };\n\n public CategoryRow withDescription(Optional description) {\n return new CategoryRow(id, parentId, name, description);\n };\n\n public static RowParser _rowParser = RowParsers.of(CategoryId.pgType, CategoryId.pgType.opt(), PgTypes.text, PgTypes.text.opt(), CategoryRow::new, row -> new Object[]{row.id(), row.parentId(), row.name(), row.description()});;\n\n static public PgText pgText =\n PgText.from(_rowParser);\n}", - "CategoryId": "package showcase.showcase.category;\n\nimport dev.typr.foundations.PgType;\nimport dev.typr.foundations.PgTypes;\nimport dev.typr.foundations.dsl.Bijection;\nimport dev.typr.foundations.internal.arrayMap;\n\n/** Type for the primary key of table `showcase.category` */\npublic record CategoryId(String value) {\n public CategoryId withValue(String value) {\n return new CategoryId(value);\n };\n\n @Override\n public java.lang.String toString() {\n return value.toString();\n };\n\n static public Bijection bijection =\n Bijection.of(CategoryId::value, CategoryId::new);\n\n static public PgType pgType =\n PgTypes.text.bimap(CategoryId::new, CategoryId::value);\n\n static public PgType pgTypeArray =\n PgTypes.textArray.bimap(xs -> arrayMap.map(xs, CategoryId::new, CategoryId.class), xs -> arrayMap.map(xs, CategoryId::value, String.class));\n}", - "AddressRow": "package showcase.showcase.address;\n\nimport dev.typr.foundations.PgText;\nimport dev.typr.foundations.PgTypes;\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport java.util.Optional;\nimport org.postgresql.geometric.PGbox;\nimport org.postgresql.geometric.PGpoint;\nimport org.postgresql.geometric.PGpolygon;\nimport showcase.customtypes.Defaulted;\nimport showcase.showcase.customer.CustomerId;\n\n/** Table: showcase.address\n * Primary key: id\n */\npublic record AddressRow(\n AddressId id,\n /** Points to {@link showcase.showcase.customer.CustomerRow#id()} */\n CustomerId customerId,\n String addressType,\n String street,\n String city,\n Optional state,\n Optional postalCode,\n String country,\n /** Default: false */\n Optional isDefault,\n Optional location,\n Optional boundary,\n Optional deliveryZone\n) {\n public AddressRow withId(AddressId id) {\n return new AddressRow(id, customerId, addressType, street, city, state, postalCode, country, isDefault, location, boundary, deliveryZone);\n };\n\n /** Points to {@link showcase.showcase.customer.CustomerRow#id()} */\n public AddressRow withCustomerId(CustomerId customerId) {\n return new AddressRow(id, customerId, addressType, street, city, state, postalCode, country, isDefault, location, boundary, deliveryZone);\n };\n\n public AddressRow withAddressType(String addressType) {\n return new AddressRow(id, customerId, addressType, street, city, state, postalCode, country, isDefault, location, boundary, deliveryZone);\n };\n\n public AddressRow withStreet(String street) {\n return new AddressRow(id, customerId, addressType, street, city, state, postalCode, country, isDefault, location, boundary, deliveryZone);\n };\n\n public AddressRow withCity(String city) {\n return new AddressRow(id, customerId, addressType, street, city, state, postalCode, country, isDefault, location, boundary, deliveryZone);\n };\n\n public AddressRow withState(Optional state) {\n return new AddressRow(id, customerId, addressType, street, city, state, postalCode, country, isDefault, location, boundary, deliveryZone);\n };\n\n public AddressRow withPostalCode(Optional postalCode) {\n return new AddressRow(id, customerId, addressType, street, city, state, postalCode, country, isDefault, location, boundary, deliveryZone);\n };\n\n public AddressRow withCountry(String country) {\n return new AddressRow(id, customerId, addressType, street, city, state, postalCode, country, isDefault, location, boundary, deliveryZone);\n };\n\n /** Default: false */\n public AddressRow withIsDefault(Optional isDefault) {\n return new AddressRow(id, customerId, addressType, street, city, state, postalCode, country, isDefault, location, boundary, deliveryZone);\n };\n\n public AddressRow withLocation(Optional location) {\n return new AddressRow(id, customerId, addressType, street, city, state, postalCode, country, isDefault, location, boundary, deliveryZone);\n };\n\n public AddressRow withBoundary(Optional boundary) {\n return new AddressRow(id, customerId, addressType, street, city, state, postalCode, country, isDefault, location, boundary, deliveryZone);\n };\n\n public AddressRow withDeliveryZone(Optional deliveryZone) {\n return new AddressRow(id, customerId, addressType, street, city, state, postalCode, country, isDefault, location, boundary, deliveryZone);\n };\n\n public static RowParser _rowParser = RowParsers.of(AddressId.pgType, CustomerId.pgType, PgTypes.text, PgTypes.text, PgTypes.text, PgTypes.text.opt(), PgTypes.text.opt(), PgTypes.text, PgTypes.bool.opt(), PgTypes.point.opt(), PgTypes.box.opt(), PgTypes.polygon.opt(), AddressRow::new, row -> new Object[]{row.id(), row.customerId(), row.addressType(), row.street(), row.city(), row.state(), row.postalCode(), row.country(), row.isDefault(), row.location(), row.boundary(), row.deliveryZone()});;\n\n static public PgText pgText =\n PgText.from(_rowParser);\n\n public AddressRowUnsaved toUnsavedRow(Defaulted> isDefault) {\n return new AddressRowUnsaved(id, customerId, addressType, street, city, state, postalCode, country, location, boundary, deliveryZone, isDefault);\n };\n}", - "AddressId": "package showcase.showcase.address;\n\nimport dev.typr.foundations.PgType;\nimport dev.typr.foundations.PgTypes;\nimport dev.typr.foundations.dsl.Bijection;\nimport dev.typr.foundations.internal.arrayMap;\n\n/** Type for the primary key of table `showcase.address` */\npublic record AddressId(String value) {\n public AddressId withValue(String value) {\n return new AddressId(value);\n };\n\n @Override\n public java.lang.String toString() {\n return value.toString();\n };\n\n static public Bijection bijection =\n Bijection.of(AddressId::value, AddressId::new);\n\n static public PgType pgType =\n PgTypes.text.bimap(AddressId::new, AddressId::value);\n\n static public PgType pgTypeArray =\n PgTypes.textArray.bimap(xs -> arrayMap.map(xs, AddressId::new, AddressId.class), xs -> arrayMap.map(xs, AddressId::value, String.class));\n}", - "Defaulted": "package showcase.customtypes;\n\nimport dev.typr.foundations.DbText;\nimport dev.typr.foundations.PgText;\n\n/** This signals a value where if you don't provide it, postgres will generate it for you */\npublic sealed interface Defaulted permits Defaulted.Provided, Defaulted.UseDefault {\n record Provided(T value) implements Defaulted {\n public Provided withValue(T value) {\n return new Provided<>(value);\n };\n\n @Override\n public U fold(\n java.util.function.Supplier onDefault,\n java.util.function.Function onProvided\n ) {\n return onProvided.apply(value);\n };\n\n @Override\n public T getOrElse(java.util.function.Supplier onDefault) {\n return value;\n };\n\n @Override\n public void visit(\n java.lang.Runnable onDefault,\n java.util.function.Consumer onProvided\n ) {\n onProvided.accept(value);\n };\n };\n\n record UseDefault() implements Defaulted {\n @Override\n public U fold(\n java.util.function.Supplier onDefault,\n java.util.function.Function onProvided\n ) {\n return onDefault.get();\n };\n\n @Override\n public T getOrElse(java.util.function.Supplier onDefault) {\n return onDefault.get();\n };\n\n @Override\n public void visit(\n java.lang.Runnable onDefault,\n java.util.function.Consumer onProvided\n ) {\n onDefault.run();\n };\n };\n\n static PgText> pgText(DbText t) {\n return PgText.instance((ot, sb) -> ot.visit(() -> {\n sb.append(\"__DEFAULT_VALUE__\");\n }, value -> t.unsafeEncode(value, sb)));\n };\n\n U fold(\n java.util.function.Supplier onDefault,\n java.util.function.Function onProvided\n );\n\n T getOrElse(java.util.function.Supplier onDefault);\n\n void visit(\n java.lang.Runnable onDefault,\n java.util.function.Consumer onProvided\n );\n}", - "TestInsert": "package showcase;\n\nimport dev.typr.foundations.data.Cidr;\nimport dev.typr.foundations.data.Inet;\nimport dev.typr.foundations.data.Jsonb;\nimport dev.typr.foundations.data.MacAddr;\nimport dev.typr.foundations.internal.RandomHelper;\nimport java.math.BigDecimal;\nimport java.sql.Connection;\nimport java.time.LocalDate;\nimport java.time.LocalDateTime;\nimport java.util.Map;\nimport java.util.Optional;\nimport java.util.Random;\nimport java.util.UUID;\nimport java.util.stream.Stream;\nimport org.postgresql.geometric.PGbox;\nimport org.postgresql.geometric.PGpoint;\nimport org.postgresql.geometric.PGpolygon;\nimport org.postgresql.util.PGInterval;\nimport showcase.customtypes.Defaulted;\nimport showcase.showcase.address.AddressId;\nimport showcase.showcase.address.AddressRepoImpl;\nimport showcase.showcase.address.AddressRow;\nimport showcase.showcase.address.AddressRowUnsaved;\nimport showcase.showcase.audit_log.AuditLogId;\nimport showcase.showcase.audit_log.AuditLogRepoImpl;\nimport showcase.showcase.audit_log.AuditLogRow;\nimport showcase.showcase.audit_log.AuditLogRowUnsaved;\nimport showcase.showcase.category.CategoryId;\nimport showcase.showcase.category.CategoryRepoImpl;\nimport showcase.showcase.category.CategoryRow;\nimport showcase.showcase.company.CompanyId;\nimport showcase.showcase.company.CompanyRepoImpl;\nimport showcase.showcase.company.CompanyRow;\nimport showcase.showcase.company.CompanyRowUnsaved;\nimport showcase.showcase.customer.CustomerId;\nimport showcase.showcase.customer.CustomerRepoImpl;\nimport showcase.showcase.customer.CustomerRow;\nimport showcase.showcase.customer.CustomerRowUnsaved;\nimport showcase.showcase.customer_order.CustomerOrderId;\nimport showcase.showcase.customer_order.CustomerOrderRepoImpl;\nimport showcase.showcase.customer_order.CustomerOrderRow;\nimport showcase.showcase.customer_order.CustomerOrderRowUnsaved;\nimport showcase.showcase.department.DepartmentId;\nimport showcase.showcase.department.DepartmentRepoImpl;\nimport showcase.showcase.department.DepartmentRow;\nimport showcase.showcase.employee.EmployeeId;\nimport showcase.showcase.employee.EmployeeRepoImpl;\nimport showcase.showcase.employee.EmployeeRow;\nimport showcase.showcase.employee.EmployeeRowUnsaved;\nimport showcase.showcase.order_item.OrderItemRepoImpl;\nimport showcase.showcase.order_item.OrderItemRow;\nimport showcase.showcase.order_item.OrderItemRowUnsaved;\nimport showcase.showcase.product.ProductId;\nimport showcase.showcase.product.ProductRepoImpl;\nimport showcase.showcase.product.ProductRow;\nimport showcase.showcase.product.ProductRowUnsaved;\nimport showcase.showcase.project.ProjectId;\nimport showcase.showcase.project.ProjectRepoImpl;\nimport showcase.showcase.project.ProjectRow;\nimport showcase.showcase.project.ProjectRowUnsaved;\nimport showcase.showcase.project_assignment.ProjectAssignmentRepoImpl;\nimport showcase.showcase.project_assignment.ProjectAssignmentRow;\nimport showcase.showcase.project_assignment.ProjectAssignmentRowUnsaved;\n\n/** Methods to generate random data for `Ident(TestInsert)` */\npublic record TestInsert(Random random) {\n public TestInsert withRandom(Random random) {\n return new TestInsert(random);\n };\n\n public AddressRow showcaseAddress(\n CustomerId customerId,\n AddressId id,\n String addressType,\n String street,\n String city,\n Optional state,\n Optional postalCode,\n String country,\n Optional location,\n Optional boundary,\n Optional deliveryZone,\n Defaulted> isDefault,\n Connection c\n ) {\n return (new AddressRepoImpl()).insert(new AddressRowUnsaved(id, customerId, addressType, street, city, state, postalCode, country, location, boundary, deliveryZone, isDefault), c);\n };\n\n public AuditLogRow showcaseAuditLog(\n AuditLogId id,\n String tableName,\n String recordId,\n String action,\n Optional oldValues,\n Optional newValues,\n Optional changedBy,\n Defaulted> changedAt,\n Connection c\n ) {\n return (new AuditLogRepoImpl()).insert(new AuditLogRowUnsaved(id, tableName, recordId, action, oldValues, newValues, changedBy, changedAt), c);\n };\n\n public CategoryRow showcaseCategory(\n CategoryId id,\n Optional parentId,\n String name,\n Optional description,\n Connection c\n ) {\n return (new CategoryRepoImpl()).insert(new CategoryRow(id, parentId, name, description), c);\n };\n\n public CompanyRow showcaseCompany(\n CompanyId id,\n String name,\n Optional foundedYear,\n Defaulted> active,\n Defaulted> createdAt,\n Connection c\n ) {\n return (new CompanyRepoImpl()).insert(new CompanyRowUnsaved(id, name, foundedYear, active, createdAt), c);\n };\n\n public CustomerRow showcaseCustomer(\n CustomerId id,\n String email,\n String firstName,\n String lastName,\n Optional phone,\n Optional interests,\n Optional preferences,\n Optional> metadata,\n Optional customerUid,\n Optional avatar,\n Defaulted> verified,\n Defaulted> createdAt,\n Connection c\n ) {\n return (new CustomerRepoImpl()).insert(new CustomerRowUnsaved(id, email, firstName, lastName, phone, interests, preferences, metadata, customerUid, avatar, verified, createdAt), c);\n };\n\n public CustomerOrderRow showcaseCustomerOrder(\n CustomerId customerId,\n CustomerOrderId id,\n Optional shippingAddressId,\n Optional billingAddressId,\n BigDecimal subtotal,\n BigDecimal total,\n Optional notes,\n Optional shippedAt,\n Optional deliveredAt,\n Optional orderUid,\n Optional metadata,\n Optional tags,\n Optional fulfillmentTimes,\n Optional ipAddress,\n Optional processingTime,\n Defaulted> status,\n Defaulted> tax,\n Defaulted> shipping,\n Defaulted> createdAt,\n Connection c\n ) {\n return (new CustomerOrderRepoImpl()).insert(new CustomerOrderRowUnsaved(id, customerId, shippingAddressId, billingAddressId, subtotal, total, notes, shippedAt, deliveredAt, orderUid, metadata, tags, fulfillmentTimes, ipAddress, processingTime, status, tax, shipping, createdAt), c);\n };\n\n public DepartmentRow showcaseDepartment(\n CompanyId companyId,\n DepartmentId id,\n String name,\n Optional budget,\n Connection c\n ) {\n return (new DepartmentRepoImpl()).insert(new DepartmentRow(id, companyId, name, budget), c);\n };\n\n public EmployeeRow showcaseEmployee(\n DepartmentId departmentId,\n EmployeeId id,\n Optional managerId,\n String email,\n String firstName,\n String lastName,\n Optional salary,\n Optional hiredAt,\n Optional skills,\n Optional certifications,\n Optional metadata,\n Optional> settings,\n Optional workSchedule,\n Optional ipAddress,\n Optional networkCidr,\n Optional macAddress,\n Optional probationPeriod,\n Optional photo,\n Defaulted> active,\n Defaulted> createdAt,\n Connection c\n ) {\n return (new EmployeeRepoImpl()).insert(new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, skills, certifications, metadata, settings, workSchedule, ipAddress, networkCidr, macAddress, probationPeriod, photo, active, createdAt), c);\n };\n\n public OrderItemRow showcaseOrderItem(\n CustomerOrderId orderId,\n ProductId productId,\n Integer quantity,\n BigDecimal unitPrice,\n Defaulted> discount,\n Connection c\n ) {\n return (new OrderItemRepoImpl()).insert(new OrderItemRowUnsaved(orderId, productId, quantity, unitPrice, discount), c);\n };\n\n public ProductRow showcaseProduct(\n ProductId id,\n Optional categoryId,\n String name,\n String sku,\n BigDecimal price,\n Optional cost,\n Optional weight,\n Optional tags,\n Optional images,\n Optional relatedSkus,\n Optional priceHistory,\n Optional attributes,\n Optional specifications,\n Optional seoMetadata,\n Optional searchVector,\n Optional productUid,\n Defaulted> inStock,\n Defaulted> quantity,\n Defaulted> createdAt,\n Connection c\n ) {\n return (new ProductRepoImpl()).insert(new ProductRowUnsaved(id, categoryId, name, sku, price, cost, weight, tags, images, relatedSkus, priceHistory, attributes, specifications, seoMetadata, searchVector, productUid, inStock, quantity, createdAt), c);\n };\n\n public ProjectRow showcaseProject(\n ProjectId id,\n String name,\n Optional description,\n Optional startDate,\n Optional endDate,\n Optional budget,\n Optional projectUid,\n Optional milestones,\n Optional budgetSnapshots,\n Optional teamMembers,\n Optional metadata,\n Optional> config,\n Optional estimatedDuration,\n Optional actualDuration,\n Defaulted> status,\n Defaulted> createdAt,\n Connection c\n ) {\n return (new ProjectRepoImpl()).insert(new ProjectRowUnsaved(id, name, description, startDate, endDate, budget, projectUid, milestones, budgetSnapshots, teamMembers, metadata, config, estimatedDuration, actualDuration, status, createdAt), c);\n };\n\n public ProjectAssignmentRow showcaseProjectAssignment(\n EmployeeId employeeId,\n ProjectId projectId,\n String role,\n Optional startDate,\n Optional endDate,\n Defaulted> hoursAllocated,\n Connection c\n ) {\n return (new ProjectAssignmentRepoImpl()).insert(new ProjectAssignmentRowUnsaved(employeeId, projectId, role, startDate, endDate, hoursAllocated), c);\n };\n}" - }, - "kotlin": { - "CompanyRow": "package showcase.showcase.company\n\nimport dev.typr.foundations.PgText\nimport dev.typr.foundations.PgTypes\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport dev.typr.foundations.kotlin.nullable\nimport java.time.LocalDateTime\nimport showcase.customtypes.Defaulted\n\n/** Table: showcase.company\n * Primary key: id\n */\ndata class CompanyRow(\n val id: CompanyId,\n val name: String,\n val foundedYear: Int?,\n /** Default: true */\n val active: Boolean?,\n /** Default: CURRENT_TIMESTAMP */\n val createdAt: LocalDateTime?\n) {\n fun toUnsavedRow(\n active: Defaulted,\n createdAt: Defaulted\n ): CompanyRowUnsaved = CompanyRowUnsaved(id, name, foundedYear, active, createdAt)\n\n companion object {\n val _rowParser: RowParser = RowParsers.of(CompanyId.pgType, PgTypes.text, KotlinDbTypes.PgTypes.int4.nullable(), KotlinDbTypes.PgTypes.bool.nullable(), PgTypes.timestamp.nullable(), { t0, t1, t2, t3, t4 -> CompanyRow(t0, t1, t2, t3, t4) }, { row -> arrayOf(row.id, row.name, row.foundedYear, row.active, row.createdAt) })\n\n val pgText: PgText =\n PgText.from(_rowParser.underlying)\n }\n}", - "CompanyRowUnsaved": "package showcase.showcase.company\n\nimport dev.typr.foundations.PgText\nimport dev.typr.foundations.PgTypes\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.nullable\nimport java.time.LocalDateTime\nimport showcase.customtypes.Defaulted\nimport showcase.customtypes.Defaulted.UseDefault\n\n/** This class corresponds to a row in table `showcase.company` which has not been persisted yet */\ndata class CompanyRowUnsaved(\n val id: CompanyId,\n val name: String,\n val foundedYear: Int? = null,\n /** Default: true */\n val active: Defaulted = UseDefault(),\n /** Default: CURRENT_TIMESTAMP */\n val createdAt: Defaulted = UseDefault()\n) {\n fun toRow(\n activeDefault: () -> Boolean?,\n createdAtDefault: () -> LocalDateTime?\n ): CompanyRow = CompanyRow(id = id, name = name, foundedYear = foundedYear, active = active.getOrElse(activeDefault), createdAt = createdAt.getOrElse(createdAtDefault))\n\n companion object {\n val pgText: PgText =\n PgText.instance({ row, sb -> CompanyId.pgType.text().unsafeEncode(row.id, sb)\n sb.append(PgText.DELIMETER)\n PgTypes.text.text().unsafeEncode(row.name, sb)\n sb.append(PgText.DELIMETER)\n KotlinDbTypes.PgTypes.int4.nullable().text().unsafeEncode(row.foundedYear, sb)\n sb.append(PgText.DELIMETER)\n Defaulted.pgText(KotlinDbTypes.PgTypes.bool.nullable().text()).unsafeEncode(row.active, sb)\n sb.append(PgText.DELIMETER)\n Defaulted.pgText(PgTypes.timestamp.nullable().text()).unsafeEncode(row.createdAt, sb) })\n }\n}", - "CompanyId": "package showcase.showcase.company\n\nimport dev.typr.foundations.PgType\nimport dev.typr.foundations.PgTypes\nimport dev.typr.foundations.internal.arrayMap\nimport dev.typr.foundations.kotlin.Bijection\n\n/** Type for the primary key of table `showcase.company` */\ndata class CompanyId(val value: String) {\n override fun toString(): kotlin.String {\n return value.toString()\n }\n\n companion object {\n val bijection: Bijection =\n Bijection.of(CompanyId::value, ::CompanyId)\n\n val pgType: PgType =\n PgTypes.text.bimap(::CompanyId, CompanyId::value)\n\n val pgTypeArray: PgType> =\n PgTypes.textArray.bimap({ xs -> arrayMap.map(xs, ::CompanyId, CompanyId::class.java) }, { xs -> arrayMap.map(xs, CompanyId::value, String::class.java) })\n }\n}", - "CompanyRepo": "package showcase.showcase.company\n\nimport dev.typr.foundations.kotlin.DeleteBuilder\nimport dev.typr.foundations.kotlin.SelectBuilder\nimport dev.typr.foundations.kotlin.UpdateBuilder\nimport java.sql.Connection\nimport kotlin.collections.Iterator\nimport kotlin.collections.List\nimport kotlin.collections.Map\n\ninterface CompanyRepo {\n abstract fun delete(): DeleteBuilder\n\n abstract fun deleteById(\n id: CompanyId,\n c: Connection\n ): Boolean\n\n abstract fun deleteByIds(\n ids: Array,\n c: Connection\n ): Int\n\n abstract fun insert(\n unsaved: CompanyRow,\n c: Connection\n ): CompanyRow\n\n abstract fun insert(\n unsaved: CompanyRowUnsaved,\n c: Connection\n ): CompanyRow\n\n abstract fun insertStreaming(\n unsaved: Iterator,\n batchSize: Int,\n c: Connection\n ): Long\n\n /** NOTE: this functionality requires PostgreSQL 16 or later! */\n abstract fun insertUnsavedStreaming(\n unsaved: Iterator,\n batchSize: Int,\n c: Connection\n ): Long\n\n abstract fun select(): SelectBuilder\n\n abstract fun selectAll(c: Connection): List\n\n abstract fun selectById(\n id: CompanyId,\n c: Connection\n ): CompanyRow?\n\n abstract fun selectByIds(\n ids: Array,\n c: Connection\n ): List\n\n abstract fun selectByIdsTracked(\n ids: Array,\n c: Connection\n ): Map\n\n abstract fun update(): UpdateBuilder\n\n abstract fun update(\n row: CompanyRow,\n c: Connection\n ): Boolean\n\n abstract fun upsert(\n unsaved: CompanyRow,\n c: Connection\n ): CompanyRow\n\n abstract fun upsertBatch(\n unsaved: Iterator,\n c: Connection\n ): List\n\n /** NOTE: this functionality is not safe if you use auto-commit mode! it runs 3 SQL statements */\n abstract fun upsertStreaming(\n unsaved: Iterator,\n batchSize: Int,\n c: Connection\n ): Int\n}", - "CompanyRepoMock": "package showcase.showcase.company\n\nimport dev.typr.foundations.kotlin.DeleteBuilder\nimport dev.typr.foundations.kotlin.DeleteBuilderMock\nimport dev.typr.foundations.kotlin.DeleteParams\nimport dev.typr.foundations.kotlin.SelectBuilder\nimport dev.typr.foundations.kotlin.SelectBuilderMock\nimport dev.typr.foundations.kotlin.SelectParams\nimport dev.typr.foundations.kotlin.UpdateBuilder\nimport dev.typr.foundations.kotlin.UpdateBuilderMock\nimport dev.typr.foundations.kotlin.UpdateParams\nimport java.lang.RuntimeException\nimport java.sql.Connection\nimport java.util.ArrayList\nimport kotlin.collections.Iterator\nimport kotlin.collections.List\nimport kotlin.collections.Map\nimport kotlin.collections.MutableMap\n\ndata class CompanyRepoMock(\n val toRow: (CompanyRowUnsaved) -> CompanyRow,\n val map: MutableMap = mutableMapOf()\n) : CompanyRepo {\n override fun delete(): DeleteBuilder = DeleteBuilderMock(CompanyFields.structure, { map.values.toList() }, DeleteParams.empty(), { row -> row.id }, { id -> map.remove(id) })\n\n override fun deleteById(\n id: CompanyId,\n c: Connection\n ): Boolean = map.remove(id) != null\n\n override fun deleteByIds(\n ids: Array,\n c: Connection\n ): Int {\n var count = 0\n for (id in ids) {\n if (map.remove(id) != null) {\n count = count + 1\n }\n }\n return count\n }\n\n override fun insert(\n unsaved: CompanyRow,\n c: Connection\n ): CompanyRow {\n if (map.containsKey(unsaved.id)) {\n throw RuntimeException(\"id \" + unsaved.id + \" already exists\")\n }\n map[unsaved.id] = unsaved\n return unsaved\n }\n\n override fun insert(\n unsaved: CompanyRowUnsaved,\n c: Connection\n ): CompanyRow = insert(toRow(unsaved), c)\n\n override fun insertStreaming(\n unsaved: Iterator,\n batchSize: Int,\n c: Connection\n ): Long {\n var count = 0L\n while (unsaved.hasNext()) {\n val row = unsaved.next()\n map[row.id] = row\n count = count + 1L\n }\n return count\n }\n\n /** NOTE: this functionality requires PostgreSQL 16 or later! */\n override fun insertUnsavedStreaming(\n unsaved: Iterator,\n batchSize: Int,\n c: Connection\n ): Long {\n var count = 0L\n while (unsaved.hasNext()) {\n val unsavedRow = unsaved.next()\n val row = toRow(unsavedRow)\n map[row.id] = row\n count = count + 1L\n }\n return count\n }\n\n override fun select(): SelectBuilder = SelectBuilderMock(CompanyFields.structure, { map.values.toList() }, SelectParams.empty())\n\n override fun selectAll(c: Connection): List = map.values.toList()\n\n override fun selectById(\n id: CompanyId,\n c: Connection\n ): CompanyRow? = map[id]\n\n override fun selectByIds(\n ids: Array,\n c: Connection\n ): List {\n val result = ArrayList()\n for (id in ids) {\n val opt = map[id]\n if (opt != null) {\n result.add(opt!!)\n }\n }\n return result\n }\n\n override fun selectByIdsTracked(\n ids: Array,\n c: Connection\n ): Map = selectByIds(ids, c).associateBy({ row: CompanyRow -> row.id })\n\n override fun update(): UpdateBuilder = UpdateBuilderMock(CompanyFields.structure, { map.values.toList() }, UpdateParams.empty(), { row -> row })\n\n override fun update(\n row: CompanyRow,\n c: Connection\n ): Boolean {\n val shouldUpdate = map[row.id]?.takeIf({ oldRow -> (oldRow != row) }) != null\n if (shouldUpdate) {\n map[row.id] = row\n }\n return shouldUpdate\n }\n\n override fun upsert(\n unsaved: CompanyRow,\n c: Connection\n ): CompanyRow {\n map[unsaved.id] = unsaved\n return unsaved\n }\n\n override fun upsertBatch(\n unsaved: Iterator,\n c: Connection\n ): List {\n val result = ArrayList()\n while (unsaved.hasNext()) {\n val row = unsaved.next()\n map[row.id] = row\n result.add(row)\n }\n return result\n }\n\n /** NOTE: this functionality is not safe if you use auto-commit mode! it runs 3 SQL statements */\n override fun upsertStreaming(\n unsaved: Iterator,\n batchSize: Int,\n c: Connection\n ): Int {\n var count = 0\n while (unsaved.hasNext()) {\n val row = unsaved.next()\n map[row.id] = row\n count = count + 1\n }\n return count\n }\n}", - "EmployeeRow": "package showcase.showcase.employee\n\nimport dev.typr.foundations.PgText\nimport dev.typr.foundations.PgTypes\nimport dev.typr.foundations.data.Cidr\nimport dev.typr.foundations.data.Inet\nimport dev.typr.foundations.data.Jsonb\nimport dev.typr.foundations.data.MacAddr\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport dev.typr.foundations.kotlin.nullable\nimport java.math.BigDecimal\nimport java.time.LocalDate\nimport java.time.LocalDateTime\nimport kotlin.collections.Map\nimport org.postgresql.util.PGInterval\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.department.DepartmentId\n\n/** Table: showcase.employee\n * Primary key: id\n */\ndata class EmployeeRow(\n val id: EmployeeId,\n /** Points to [showcase.showcase.department.DepartmentRow.id] */\n val departmentId: DepartmentId,\n /** Points to [showcase.showcase.employee.EmployeeRow.id] */\n val managerId: EmployeeId?,\n val email: String,\n val firstName: String,\n val lastName: String,\n val salary: BigDecimal?,\n val hiredAt: LocalDate?,\n /** Default: true */\n val active: Boolean?,\n /** Default: CURRENT_TIMESTAMP */\n val createdAt: LocalDateTime?,\n val skills: Array?,\n val certifications: Array?,\n val metadata: Jsonb?,\n val settings: Map?,\n val workSchedule: Array?,\n val ipAddress: Inet?,\n val networkCidr: Cidr?,\n val macAddress: MacAddr?,\n val probationPeriod: PGInterval?,\n val photo: ByteArray?\n) {\n fun toUnsavedRow(\n active: Defaulted,\n createdAt: Defaulted\n ): EmployeeRowUnsaved = EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, skills, certifications, metadata, settings, workSchedule, ipAddress, networkCidr, macAddress, probationPeriod, photo, active, createdAt)\n\n companion object {\n val _rowParser: RowParser = RowParsers.of(EmployeeId.pgType, DepartmentId.pgType, EmployeeId.pgType.nullable(), PgTypes.text, PgTypes.text, PgTypes.text, PgTypes.numeric.nullable(), PgTypes.date.nullable(), KotlinDbTypes.PgTypes.bool.nullable(), PgTypes.timestamp.nullable(), PgTypes.textArray.nullable(), PgTypes.textArray.nullable(), PgTypes.jsonb.nullable(), KotlinDbTypes.PgTypes.hstore.nullable(), PgTypes.boolArray.nullable(), PgTypes.inet.nullable(), PgTypes.cidr.nullable(), PgTypes.macaddr.nullable(), PgTypes.interval.nullable(), PgTypes.bytea.nullable(), { t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17, t18, t19 -> EmployeeRow(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17, t18, t19) }, { row -> arrayOf(row.id, row.departmentId, row.managerId, row.email, row.firstName, row.lastName, row.salary, row.hiredAt, row.active, row.createdAt, row.skills, row.certifications, row.metadata, row.settings, row.workSchedule, row.ipAddress, row.networkCidr, row.macAddress, row.probationPeriod, row.photo) })\n\n val pgText: PgText =\n PgText.from(_rowParser.underlying)\n }\n}", - "EmployeeRowUnsaved": "package showcase.showcase.employee\n\nimport dev.typr.foundations.PgText\nimport dev.typr.foundations.PgTypes\nimport dev.typr.foundations.data.Cidr\nimport dev.typr.foundations.data.Inet\nimport dev.typr.foundations.data.Jsonb\nimport dev.typr.foundations.data.MacAddr\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.nullable\nimport java.math.BigDecimal\nimport java.time.LocalDate\nimport java.time.LocalDateTime\nimport kotlin.collections.Map\nimport org.postgresql.util.PGInterval\nimport showcase.customtypes.Defaulted\nimport showcase.customtypes.Defaulted.UseDefault\nimport showcase.showcase.department.DepartmentId\n\n/** This class corresponds to a row in table `showcase.employee` which has not been persisted yet */\ndata class EmployeeRowUnsaved(\n val id: EmployeeId,\n /** Points to [showcase.showcase.department.DepartmentRow.id] */\n val departmentId: DepartmentId,\n /** Points to [showcase.showcase.employee.EmployeeRow.id] */\n val managerId: EmployeeId? = null,\n val email: String,\n val firstName: String,\n val lastName: String,\n val salary: BigDecimal? = null,\n val hiredAt: LocalDate? = null,\n val skills: Array? = null,\n val certifications: Array? = null,\n val metadata: Jsonb? = null,\n val settings: Map? = null,\n val workSchedule: Array? = null,\n val ipAddress: Inet? = null,\n val networkCidr: Cidr? = null,\n val macAddress: MacAddr? = null,\n val probationPeriod: PGInterval? = null,\n val photo: ByteArray? = null,\n /** Default: true */\n val active: Defaulted = UseDefault(),\n /** Default: CURRENT_TIMESTAMP */\n val createdAt: Defaulted = UseDefault()\n) {\n fun toRow(\n activeDefault: () -> Boolean?,\n createdAtDefault: () -> LocalDateTime?\n ): EmployeeRow = EmployeeRow(id = id, departmentId = departmentId, managerId = managerId, email = email, firstName = firstName, lastName = lastName, salary = salary, hiredAt = hiredAt, active = active.getOrElse(activeDefault), createdAt = createdAt.getOrElse(createdAtDefault), skills = skills, certifications = certifications, metadata = metadata, settings = settings, workSchedule = workSchedule, ipAddress = ipAddress, networkCidr = networkCidr, macAddress = macAddress, probationPeriod = probationPeriod, photo = photo)\n\n companion object {\n val pgText: PgText =\n PgText.instance({ row, sb -> EmployeeId.pgType.text().unsafeEncode(row.id, sb)\n sb.append(PgText.DELIMETER)\n DepartmentId.pgType.text().unsafeEncode(row.departmentId, sb)\n sb.append(PgText.DELIMETER)\n EmployeeId.pgType.nullable().text().unsafeEncode(row.managerId, sb)\n sb.append(PgText.DELIMETER)\n PgTypes.text.text().unsafeEncode(row.email, sb)\n sb.append(PgText.DELIMETER)\n PgTypes.text.text().unsafeEncode(row.firstName, sb)\n sb.append(PgText.DELIMETER)\n PgTypes.text.text().unsafeEncode(row.lastName, sb)\n sb.append(PgText.DELIMETER)\n PgTypes.numeric.nullable().text().unsafeEncode(row.salary, sb)\n sb.append(PgText.DELIMETER)\n PgTypes.date.nullable().text().unsafeEncode(row.hiredAt, sb)\n sb.append(PgText.DELIMETER)\n PgTypes.textArray.nullable().text().unsafeEncode(row.skills, sb)\n sb.append(PgText.DELIMETER)\n PgTypes.textArray.nullable().text().unsafeEncode(row.certifications, sb)\n sb.append(PgText.DELIMETER)\n PgTypes.jsonb.nullable().text().unsafeEncode(row.metadata, sb)\n sb.append(PgText.DELIMETER)\n KotlinDbTypes.PgTypes.hstore.nullable().text().unsafeEncode(row.settings, sb)\n sb.append(PgText.DELIMETER)\n PgTypes.boolArray.nullable().text().unsafeEncode(row.workSchedule, sb)\n sb.append(PgText.DELIMETER)\n PgTypes.inet.nullable().text().unsafeEncode(row.ipAddress, sb)\n sb.append(PgText.DELIMETER)\n PgTypes.cidr.nullable().text().unsafeEncode(row.networkCidr, sb)\n sb.append(PgText.DELIMETER)\n PgTypes.macaddr.nullable().text().unsafeEncode(row.macAddress, sb)\n sb.append(PgText.DELIMETER)\n PgTypes.interval.nullable().text().unsafeEncode(row.probationPeriod, sb)\n sb.append(PgText.DELIMETER)\n PgTypes.bytea.nullable().text().unsafeEncode(row.photo, sb)\n sb.append(PgText.DELIMETER)\n Defaulted.pgText(KotlinDbTypes.PgTypes.bool.nullable().text()).unsafeEncode(row.active, sb)\n sb.append(PgText.DELIMETER)\n Defaulted.pgText(PgTypes.timestamp.nullable().text()).unsafeEncode(row.createdAt, sb) })\n }\n}", - "EmployeeId": "package showcase.showcase.employee\n\nimport dev.typr.foundations.PgType\nimport dev.typr.foundations.PgTypes\nimport dev.typr.foundations.internal.arrayMap\nimport dev.typr.foundations.kotlin.Bijection\n\n/** Type for the primary key of table `showcase.employee` */\ndata class EmployeeId(val value: String) {\n override fun toString(): kotlin.String {\n return value.toString()\n }\n\n companion object {\n val bijection: Bijection =\n Bijection.of(EmployeeId::value, ::EmployeeId)\n\n val pgType: PgType =\n PgTypes.text.bimap(::EmployeeId, EmployeeId::value)\n\n val pgTypeArray: PgType> =\n PgTypes.textArray.bimap({ xs -> arrayMap.map(xs, ::EmployeeId, EmployeeId::class.java) }, { xs -> arrayMap.map(xs, EmployeeId::value, String::class.java) })\n }\n}", - "EmployeeRepo": "package showcase.showcase.employee\n\nimport dev.typr.foundations.kotlin.DeleteBuilder\nimport dev.typr.foundations.kotlin.SelectBuilder\nimport dev.typr.foundations.kotlin.UpdateBuilder\nimport java.sql.Connection\nimport kotlin.collections.Iterator\nimport kotlin.collections.List\nimport kotlin.collections.Map\n\ninterface EmployeeRepo {\n abstract fun delete(): DeleteBuilder\n\n abstract fun deleteById(\n id: EmployeeId,\n c: Connection\n ): Boolean\n\n abstract fun deleteByIds(\n ids: Array,\n c: Connection\n ): Int\n\n abstract fun insert(\n unsaved: EmployeeRow,\n c: Connection\n ): EmployeeRow\n\n abstract fun insert(\n unsaved: EmployeeRowUnsaved,\n c: Connection\n ): EmployeeRow\n\n abstract fun insertStreaming(\n unsaved: Iterator,\n batchSize: Int,\n c: Connection\n ): Long\n\n /** NOTE: this functionality requires PostgreSQL 16 or later! */\n abstract fun insertUnsavedStreaming(\n unsaved: Iterator,\n batchSize: Int,\n c: Connection\n ): Long\n\n abstract fun select(): SelectBuilder\n\n abstract fun selectAll(c: Connection): List\n\n abstract fun selectById(\n id: EmployeeId,\n c: Connection\n ): EmployeeRow?\n\n abstract fun selectByIds(\n ids: Array,\n c: Connection\n ): List\n\n abstract fun selectByIdsTracked(\n ids: Array,\n c: Connection\n ): Map\n\n abstract fun selectByUniqueEmail(\n email: String,\n c: Connection\n ): EmployeeRow?\n\n abstract fun update(): UpdateBuilder\n\n abstract fun update(\n row: EmployeeRow,\n c: Connection\n ): Boolean\n\n abstract fun upsert(\n unsaved: EmployeeRow,\n c: Connection\n ): EmployeeRow\n\n abstract fun upsertBatch(\n unsaved: Iterator,\n c: Connection\n ): List\n\n /** NOTE: this functionality is not safe if you use auto-commit mode! it runs 3 SQL statements */\n abstract fun upsertStreaming(\n unsaved: Iterator,\n batchSize: Int,\n c: Connection\n ): Int\n}", - "EmployeeRepoImpl": "package showcase.showcase.employee\n\nimport dev.typr.foundations.PgTypes\nimport dev.typr.foundations.kotlin.DeleteBuilder\nimport dev.typr.foundations.kotlin.Dialect\nimport dev.typr.foundations.kotlin.Fragment\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.SelectBuilder\nimport dev.typr.foundations.kotlin.UpdateBuilder\nimport dev.typr.foundations.kotlin.nullable\nimport dev.typr.foundations.streamingInsert\nimport java.sql.Connection\nimport java.util.ArrayList\nimport kotlin.collections.Iterator\nimport kotlin.collections.List\nimport kotlin.collections.Map\nimport kotlin.collections.MutableMap\nimport showcase.showcase.department.DepartmentId\n\nclass EmployeeRepoImpl() : EmployeeRepo {\n override fun delete(): DeleteBuilder = DeleteBuilder.of(\"\\\"showcase\\\".\\\"employee\\\"\", EmployeeFields.structure, Dialect.POSTGRESQL)\n\n override fun deleteById(\n id: EmployeeId,\n c: Connection\n ): Boolean = Fragment.interpolate(Fragment.lit(\"delete from \\\"showcase\\\".\\\"employee\\\" where \\\"id\\\" = \"), Fragment.encode(EmployeeId.pgType, id), Fragment.lit(\"\")).update().runUnchecked(c) > 0\n\n override fun deleteByIds(\n ids: Array,\n c: Connection\n ): Int = Fragment.interpolate(Fragment.lit(\"delete\\nfrom \\\"showcase\\\".\\\"employee\\\"\\nwhere \\\"id\\\" = ANY(\"), Fragment.encode(EmployeeId.pgTypeArray, ids), Fragment.lit(\")\"))\n .update()\n .runUnchecked(c)\n\n override fun insert(\n unsaved: EmployeeRow,\n c: Connection\n ): EmployeeRow = Fragment.interpolate(Fragment.lit(\"insert into \\\"showcase\\\".\\\"employee\\\"(\\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"skills\\\", \\\"certifications\\\", \\\"metadata\\\", \\\"settings\\\", \\\"work_schedule\\\", \\\"ip_address\\\", \\\"network_cidr\\\", \\\"mac_address\\\", \\\"probation_period\\\", \\\"photo\\\")\\nvalues (\"), Fragment.encode(EmployeeId.pgType, unsaved.id), Fragment.lit(\", \"), Fragment.encode(DepartmentId.pgType, unsaved.departmentId), Fragment.lit(\", \"), Fragment.encode(EmployeeId.pgType.nullable(), unsaved.managerId), Fragment.lit(\", \"), Fragment.encode(PgTypes.text, unsaved.email), Fragment.lit(\", \"), Fragment.encode(PgTypes.text, unsaved.firstName), Fragment.lit(\", \"), Fragment.encode(PgTypes.text, unsaved.lastName), Fragment.lit(\", \"), Fragment.encode(PgTypes.numeric.nullable(), unsaved.salary), Fragment.lit(\", \"), Fragment.encode(PgTypes.date.nullable(), unsaved.hiredAt), Fragment.lit(\", \"), Fragment.encode(KotlinDbTypes.PgTypes.bool.nullable(), unsaved.active), Fragment.lit(\", \"), Fragment.encode(PgTypes.timestamp.nullable(), unsaved.createdAt), Fragment.lit(\", \"), Fragment.encode(PgTypes.textArray.nullable(), unsaved.skills), Fragment.lit(\", \"), Fragment.encode(PgTypes.textArray.nullable(), unsaved.certifications), Fragment.lit(\", \"), Fragment.encode(PgTypes.jsonb.nullable(), unsaved.metadata), Fragment.lit(\", \"), Fragment.encode(KotlinDbTypes.PgTypes.hstore.nullable(), unsaved.settings), Fragment.lit(\", \"), Fragment.encode(PgTypes.boolArray.nullable(), unsaved.workSchedule), Fragment.lit(\", \"), Fragment.encode(PgTypes.inet.nullable(), unsaved.ipAddress), Fragment.lit(\", \"), Fragment.encode(PgTypes.cidr.nullable(), unsaved.networkCidr), Fragment.lit(\", \"), Fragment.encode(PgTypes.macaddr.nullable(), unsaved.macAddress), Fragment.lit(\", \"), Fragment.encode(PgTypes.interval.nullable(), unsaved.probationPeriod), Fragment.lit(\", \"), Fragment.encode(PgTypes.bytea.nullable(), unsaved.photo), Fragment.lit(\")\\nRETURNING \\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"skills\\\", \\\"certifications\\\", \\\"metadata\\\", \\\"settings\\\", \\\"work_schedule\\\", \\\"ip_address\\\", \\\"network_cidr\\\", \\\"mac_address\\\", \\\"probation_period\\\", \\\"photo\\\"\\n\"))\n .updateReturning(EmployeeRow._rowParser.exactlyOne()).runUnchecked(c)\n\n override fun insert(\n unsaved: EmployeeRowUnsaved,\n c: Connection\n ): EmployeeRow {\n val columns: ArrayList = ArrayList()\n val values: ArrayList = ArrayList()\n columns.add(Fragment.lit(\"\\\"id\\\"\"))\n values.add(Fragment.interpolate(Fragment.encode(EmployeeId.pgType, unsaved.id), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"\\\"department_id\\\"\"))\n values.add(Fragment.interpolate(Fragment.encode(DepartmentId.pgType, unsaved.departmentId), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"\\\"manager_id\\\"\"))\n values.add(Fragment.interpolate(Fragment.encode(EmployeeId.pgType.nullable(), unsaved.managerId), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"\\\"email\\\"\"))\n values.add(Fragment.interpolate(Fragment.encode(PgTypes.text, unsaved.email), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"\\\"first_name\\\"\"))\n values.add(Fragment.interpolate(Fragment.encode(PgTypes.text, unsaved.firstName), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"\\\"last_name\\\"\"))\n values.add(Fragment.interpolate(Fragment.encode(PgTypes.text, unsaved.lastName), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"\\\"salary\\\"\"))\n values.add(Fragment.interpolate(Fragment.encode(PgTypes.numeric.nullable(), unsaved.salary), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"\\\"hired_at\\\"\"))\n values.add(Fragment.interpolate(Fragment.encode(PgTypes.date.nullable(), unsaved.hiredAt), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"\\\"skills\\\"\"))\n values.add(Fragment.interpolate(Fragment.encode(PgTypes.textArray.nullable(), unsaved.skills), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"\\\"certifications\\\"\"))\n values.add(Fragment.interpolate(Fragment.encode(PgTypes.textArray.nullable(), unsaved.certifications), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"\\\"metadata\\\"\"))\n values.add(Fragment.interpolate(Fragment.encode(PgTypes.jsonb.nullable(), unsaved.metadata), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"\\\"settings\\\"\"))\n values.add(Fragment.interpolate(Fragment.encode(KotlinDbTypes.PgTypes.hstore.nullable(), unsaved.settings), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"\\\"work_schedule\\\"\"))\n values.add(Fragment.interpolate(Fragment.encode(PgTypes.boolArray.nullable(), unsaved.workSchedule), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"\\\"ip_address\\\"\"))\n values.add(Fragment.interpolate(Fragment.encode(PgTypes.inet.nullable(), unsaved.ipAddress), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"\\\"network_cidr\\\"\"))\n values.add(Fragment.interpolate(Fragment.encode(PgTypes.cidr.nullable(), unsaved.networkCidr), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"\\\"mac_address\\\"\"))\n values.add(Fragment.interpolate(Fragment.encode(PgTypes.macaddr.nullable(), unsaved.macAddress), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"\\\"probation_period\\\"\"))\n values.add(Fragment.interpolate(Fragment.encode(PgTypes.interval.nullable(), unsaved.probationPeriod), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"\\\"photo\\\"\"))\n values.add(Fragment.interpolate(Fragment.encode(PgTypes.bytea.nullable(), unsaved.photo), Fragment.lit(\"\")))\n unsaved.active.visit(\n { },\n { value -> columns.add(Fragment.lit(\"\\\"active\\\"\"))\n values.add(Fragment.interpolate(Fragment.encode(KotlinDbTypes.PgTypes.bool.nullable(), value), Fragment.lit(\"\"))) }\n );\n unsaved.createdAt.visit(\n { },\n { value -> columns.add(Fragment.lit(\"\\\"created_at\\\"\"))\n values.add(Fragment.interpolate(Fragment.encode(PgTypes.timestamp.nullable(), value), Fragment.lit(\"\"))) }\n );\n val q: Fragment = Fragment.interpolate(Fragment.lit(\"insert into \\\"showcase\\\".\\\"employee\\\"(\"), Fragment.comma(columns.toMutableList()), Fragment.lit(\")\\nvalues (\"), Fragment.comma(values.toMutableList()), Fragment.lit(\")\\nRETURNING \\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"skills\\\", \\\"certifications\\\", \\\"metadata\\\", \\\"settings\\\", \\\"work_schedule\\\", \\\"ip_address\\\", \\\"network_cidr\\\", \\\"mac_address\\\", \\\"probation_period\\\", \\\"photo\\\"\\n\"))\n return q.updateReturning(EmployeeRow._rowParser.exactlyOne()).runUnchecked(c)\n }\n\n override fun insertStreaming(\n unsaved: Iterator,\n batchSize: Int,\n c: Connection\n ): Long = streamingInsert.insertUnchecked(\"COPY \\\"showcase\\\".\\\"employee\\\"(\\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"skills\\\", \\\"certifications\\\", \\\"metadata\\\", \\\"settings\\\", \\\"work_schedule\\\", \\\"ip_address\\\", \\\"network_cidr\\\", \\\"mac_address\\\", \\\"probation_period\\\", \\\"photo\\\") FROM STDIN\", batchSize, unsaved, c, EmployeeRow.pgText)\n\n /** NOTE: this functionality requires PostgreSQL 16 or later! */\n override fun insertUnsavedStreaming(\n unsaved: Iterator,\n batchSize: Int,\n c: Connection\n ): Long = streamingInsert.insertUnchecked(\"COPY \\\"showcase\\\".\\\"employee\\\"(\\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"skills\\\", \\\"certifications\\\", \\\"metadata\\\", \\\"settings\\\", \\\"work_schedule\\\", \\\"ip_address\\\", \\\"network_cidr\\\", \\\"mac_address\\\", \\\"probation_period\\\", \\\"photo\\\", \\\"active\\\", \\\"created_at\\\") FROM STDIN (DEFAULT '__DEFAULT_VALUE__')\", batchSize, unsaved, c, EmployeeRowUnsaved.pgText)\n\n override fun select(): SelectBuilder = SelectBuilder.of(\"\\\"showcase\\\".\\\"employee\\\"\", EmployeeFields.structure, EmployeeRow._rowParser, Dialect.POSTGRESQL)\n\n override fun selectAll(c: Connection): List = Fragment.interpolate(Fragment.lit(\"select \\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"skills\\\", \\\"certifications\\\", \\\"metadata\\\", \\\"settings\\\", \\\"work_schedule\\\", \\\"ip_address\\\", \\\"network_cidr\\\", \\\"mac_address\\\", \\\"probation_period\\\", \\\"photo\\\"\\nfrom \\\"showcase\\\".\\\"employee\\\"\\n\")).query(EmployeeRow._rowParser.all()).runUnchecked(c)\n\n override fun selectById(\n id: EmployeeId,\n c: Connection\n ): EmployeeRow? = Fragment.interpolate(Fragment.lit(\"select \\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"skills\\\", \\\"certifications\\\", \\\"metadata\\\", \\\"settings\\\", \\\"work_schedule\\\", \\\"ip_address\\\", \\\"network_cidr\\\", \\\"mac_address\\\", \\\"probation_period\\\", \\\"photo\\\"\\nfrom \\\"showcase\\\".\\\"employee\\\"\\nwhere \\\"id\\\" = \"), Fragment.encode(EmployeeId.pgType, id), Fragment.lit(\"\")).query(EmployeeRow._rowParser.first()).runUnchecked(c)\n\n override fun selectByIds(\n ids: Array,\n c: Connection\n ): List = Fragment.interpolate(Fragment.lit(\"select \\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"skills\\\", \\\"certifications\\\", \\\"metadata\\\", \\\"settings\\\", \\\"work_schedule\\\", \\\"ip_address\\\", \\\"network_cidr\\\", \\\"mac_address\\\", \\\"probation_period\\\", \\\"photo\\\"\\nfrom \\\"showcase\\\".\\\"employee\\\"\\nwhere \\\"id\\\" = ANY(\"), Fragment.encode(EmployeeId.pgTypeArray, ids), Fragment.lit(\")\")).query(EmployeeRow._rowParser.all()).runUnchecked(c)\n\n override fun selectByIdsTracked(\n ids: Array,\n c: Connection\n ): Map {\n val ret: MutableMap = mutableMapOf()\n selectByIds(ids, c).forEach({ row -> ret.put(row.id, row) })\n return ret.toMap()\n }\n\n override fun selectByUniqueEmail(\n email: String,\n c: Connection\n ): EmployeeRow? = Fragment.interpolate(Fragment.lit(\"select \\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"skills\\\", \\\"certifications\\\", \\\"metadata\\\", \\\"settings\\\", \\\"work_schedule\\\", \\\"ip_address\\\", \\\"network_cidr\\\", \\\"mac_address\\\", \\\"probation_period\\\", \\\"photo\\\"\\nfrom \\\"showcase\\\".\\\"employee\\\"\\nwhere \\\"email\\\" = \"), Fragment.encode(PgTypes.text, email), Fragment.lit(\"\\n\")).query(EmployeeRow._rowParser.first()).runUnchecked(c)\n\n override fun update(): UpdateBuilder = UpdateBuilder.of(\"\\\"showcase\\\".\\\"employee\\\"\", EmployeeFields.structure, EmployeeRow._rowParser, Dialect.POSTGRESQL)\n\n override fun update(\n row: EmployeeRow,\n c: Connection\n ): Boolean {\n val id: EmployeeId = row.id\n return Fragment.interpolate(Fragment.lit(\"update \\\"showcase\\\".\\\"employee\\\"\\nset \\\"department_id\\\" = \"), Fragment.encode(DepartmentId.pgType, row.departmentId), Fragment.lit(\",\\n\\\"manager_id\\\" = \"), Fragment.encode(EmployeeId.pgType.nullable(), row.managerId), Fragment.lit(\",\\n\\\"email\\\" = \"), Fragment.encode(PgTypes.text, row.email), Fragment.lit(\",\\n\\\"first_name\\\" = \"), Fragment.encode(PgTypes.text, row.firstName), Fragment.lit(\",\\n\\\"last_name\\\" = \"), Fragment.encode(PgTypes.text, row.lastName), Fragment.lit(\",\\n\\\"salary\\\" = \"), Fragment.encode(PgTypes.numeric.nullable(), row.salary), Fragment.lit(\",\\n\\\"hired_at\\\" = \"), Fragment.encode(PgTypes.date.nullable(), row.hiredAt), Fragment.lit(\",\\n\\\"active\\\" = \"), Fragment.encode(KotlinDbTypes.PgTypes.bool.nullable(), row.active), Fragment.lit(\",\\n\\\"created_at\\\" = \"), Fragment.encode(PgTypes.timestamp.nullable(), row.createdAt), Fragment.lit(\",\\n\\\"skills\\\" = \"), Fragment.encode(PgTypes.textArray.nullable(), row.skills), Fragment.lit(\",\\n\\\"certifications\\\" = \"), Fragment.encode(PgTypes.textArray.nullable(), row.certifications), Fragment.lit(\",\\n\\\"metadata\\\" = \"), Fragment.encode(PgTypes.jsonb.nullable(), row.metadata), Fragment.lit(\",\\n\\\"settings\\\" = \"), Fragment.encode(KotlinDbTypes.PgTypes.hstore.nullable(), row.settings), Fragment.lit(\",\\n\\\"work_schedule\\\" = \"), Fragment.encode(PgTypes.boolArray.nullable(), row.workSchedule), Fragment.lit(\",\\n\\\"ip_address\\\" = \"), Fragment.encode(PgTypes.inet.nullable(), row.ipAddress), Fragment.lit(\",\\n\\\"network_cidr\\\" = \"), Fragment.encode(PgTypes.cidr.nullable(), row.networkCidr), Fragment.lit(\",\\n\\\"mac_address\\\" = \"), Fragment.encode(PgTypes.macaddr.nullable(), row.macAddress), Fragment.lit(\",\\n\\\"probation_period\\\" = \"), Fragment.encode(PgTypes.interval.nullable(), row.probationPeriod), Fragment.lit(\",\\n\\\"photo\\\" = \"), Fragment.encode(PgTypes.bytea.nullable(), row.photo), Fragment.lit(\"\\nwhere \\\"id\\\" = \"), Fragment.encode(EmployeeId.pgType, id), Fragment.lit(\"\")).update().runUnchecked(c) > 0\n }\n\n override fun upsert(\n unsaved: EmployeeRow,\n c: Connection\n ): EmployeeRow = Fragment.interpolate(Fragment.lit(\"insert into \\\"showcase\\\".\\\"employee\\\"(\\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"skills\\\", \\\"certifications\\\", \\\"metadata\\\", \\\"settings\\\", \\\"work_schedule\\\", \\\"ip_address\\\", \\\"network_cidr\\\", \\\"mac_address\\\", \\\"probation_period\\\", \\\"photo\\\")\\nvalues (\"), Fragment.encode(EmployeeId.pgType, unsaved.id), Fragment.lit(\", \"), Fragment.encode(DepartmentId.pgType, unsaved.departmentId), Fragment.lit(\", \"), Fragment.encode(EmployeeId.pgType.nullable(), unsaved.managerId), Fragment.lit(\", \"), Fragment.encode(PgTypes.text, unsaved.email), Fragment.lit(\", \"), Fragment.encode(PgTypes.text, unsaved.firstName), Fragment.lit(\", \"), Fragment.encode(PgTypes.text, unsaved.lastName), Fragment.lit(\", \"), Fragment.encode(PgTypes.numeric.nullable(), unsaved.salary), Fragment.lit(\", \"), Fragment.encode(PgTypes.date.nullable(), unsaved.hiredAt), Fragment.lit(\", \"), Fragment.encode(KotlinDbTypes.PgTypes.bool.nullable(), unsaved.active), Fragment.lit(\", \"), Fragment.encode(PgTypes.timestamp.nullable(), unsaved.createdAt), Fragment.lit(\", \"), Fragment.encode(PgTypes.textArray.nullable(), unsaved.skills), Fragment.lit(\", \"), Fragment.encode(PgTypes.textArray.nullable(), unsaved.certifications), Fragment.lit(\", \"), Fragment.encode(PgTypes.jsonb.nullable(), unsaved.metadata), Fragment.lit(\", \"), Fragment.encode(KotlinDbTypes.PgTypes.hstore.nullable(), unsaved.settings), Fragment.lit(\", \"), Fragment.encode(PgTypes.boolArray.nullable(), unsaved.workSchedule), Fragment.lit(\", \"), Fragment.encode(PgTypes.inet.nullable(), unsaved.ipAddress), Fragment.lit(\", \"), Fragment.encode(PgTypes.cidr.nullable(), unsaved.networkCidr), Fragment.lit(\", \"), Fragment.encode(PgTypes.macaddr.nullable(), unsaved.macAddress), Fragment.lit(\", \"), Fragment.encode(PgTypes.interval.nullable(), unsaved.probationPeriod), Fragment.lit(\", \"), Fragment.encode(PgTypes.bytea.nullable(), unsaved.photo), Fragment.lit(\")\\non conflict (\\\"id\\\")\\ndo update set\\n \\\"department_id\\\" = EXCLUDED.\\\"department_id\\\",\\n\\\"manager_id\\\" = EXCLUDED.\\\"manager_id\\\",\\n\\\"email\\\" = EXCLUDED.\\\"email\\\",\\n\\\"first_name\\\" = EXCLUDED.\\\"first_name\\\",\\n\\\"last_name\\\" = EXCLUDED.\\\"last_name\\\",\\n\\\"salary\\\" = EXCLUDED.\\\"salary\\\",\\n\\\"hired_at\\\" = EXCLUDED.\\\"hired_at\\\",\\n\\\"active\\\" = EXCLUDED.\\\"active\\\",\\n\\\"created_at\\\" = EXCLUDED.\\\"created_at\\\",\\n\\\"skills\\\" = EXCLUDED.\\\"skills\\\",\\n\\\"certifications\\\" = EXCLUDED.\\\"certifications\\\",\\n\\\"metadata\\\" = EXCLUDED.\\\"metadata\\\",\\n\\\"settings\\\" = EXCLUDED.\\\"settings\\\",\\n\\\"work_schedule\\\" = EXCLUDED.\\\"work_schedule\\\",\\n\\\"ip_address\\\" = EXCLUDED.\\\"ip_address\\\",\\n\\\"network_cidr\\\" = EXCLUDED.\\\"network_cidr\\\",\\n\\\"mac_address\\\" = EXCLUDED.\\\"mac_address\\\",\\n\\\"probation_period\\\" = EXCLUDED.\\\"probation_period\\\",\\n\\\"photo\\\" = EXCLUDED.\\\"photo\\\"\\nreturning \\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"skills\\\", \\\"certifications\\\", \\\"metadata\\\", \\\"settings\\\", \\\"work_schedule\\\", \\\"ip_address\\\", \\\"network_cidr\\\", \\\"mac_address\\\", \\\"probation_period\\\", \\\"photo\\\"\"))\n .updateReturning(EmployeeRow._rowParser.exactlyOne())\n .runUnchecked(c)\n\n override fun upsertBatch(\n unsaved: Iterator,\n c: Connection\n ): List = Fragment.interpolate(Fragment.lit(\"insert into \\\"showcase\\\".\\\"employee\\\"(\\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"skills\\\", \\\"certifications\\\", \\\"metadata\\\", \\\"settings\\\", \\\"work_schedule\\\", \\\"ip_address\\\", \\\"network_cidr\\\", \\\"mac_address\\\", \\\"probation_period\\\", \\\"photo\\\")\\nvalues (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\\non conflict (\\\"id\\\")\\ndo update set\\n \\\"department_id\\\" = EXCLUDED.\\\"department_id\\\",\\n\\\"manager_id\\\" = EXCLUDED.\\\"manager_id\\\",\\n\\\"email\\\" = EXCLUDED.\\\"email\\\",\\n\\\"first_name\\\" = EXCLUDED.\\\"first_name\\\",\\n\\\"last_name\\\" = EXCLUDED.\\\"last_name\\\",\\n\\\"salary\\\" = EXCLUDED.\\\"salary\\\",\\n\\\"hired_at\\\" = EXCLUDED.\\\"hired_at\\\",\\n\\\"active\\\" = EXCLUDED.\\\"active\\\",\\n\\\"created_at\\\" = EXCLUDED.\\\"created_at\\\",\\n\\\"skills\\\" = EXCLUDED.\\\"skills\\\",\\n\\\"certifications\\\" = EXCLUDED.\\\"certifications\\\",\\n\\\"metadata\\\" = EXCLUDED.\\\"metadata\\\",\\n\\\"settings\\\" = EXCLUDED.\\\"settings\\\",\\n\\\"work_schedule\\\" = EXCLUDED.\\\"work_schedule\\\",\\n\\\"ip_address\\\" = EXCLUDED.\\\"ip_address\\\",\\n\\\"network_cidr\\\" = EXCLUDED.\\\"network_cidr\\\",\\n\\\"mac_address\\\" = EXCLUDED.\\\"mac_address\\\",\\n\\\"probation_period\\\" = EXCLUDED.\\\"probation_period\\\",\\n\\\"photo\\\" = EXCLUDED.\\\"photo\\\"\\nreturning \\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"skills\\\", \\\"certifications\\\", \\\"metadata\\\", \\\"settings\\\", \\\"work_schedule\\\", \\\"ip_address\\\", \\\"network_cidr\\\", \\\"mac_address\\\", \\\"probation_period\\\", \\\"photo\\\"\"))\n .updateManyReturning(EmployeeRow._rowParser, unsaved)\n .runUnchecked(c)\n\n /** NOTE: this functionality is not safe if you use auto-commit mode! it runs 3 SQL statements */\n override fun upsertStreaming(\n unsaved: Iterator,\n batchSize: Int,\n c: Connection\n ): Int {\n Fragment.interpolate(Fragment.lit(\"create temporary table employee_TEMP (like \\\"showcase\\\".\\\"employee\\\") on commit drop\")).update().runUnchecked(c)\n streamingInsert.insertUnchecked(\"copy employee_TEMP(\\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"skills\\\", \\\"certifications\\\", \\\"metadata\\\", \\\"settings\\\", \\\"work_schedule\\\", \\\"ip_address\\\", \\\"network_cidr\\\", \\\"mac_address\\\", \\\"probation_period\\\", \\\"photo\\\") from stdin\", batchSize, unsaved, c, EmployeeRow.pgText)\n return Fragment.interpolate(Fragment.lit(\"insert into \\\"showcase\\\".\\\"employee\\\"(\\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"skills\\\", \\\"certifications\\\", \\\"metadata\\\", \\\"settings\\\", \\\"work_schedule\\\", \\\"ip_address\\\", \\\"network_cidr\\\", \\\"mac_address\\\", \\\"probation_period\\\", \\\"photo\\\")\\nselect * from employee_TEMP\\non conflict (\\\"id\\\")\\ndo update set\\n \\\"department_id\\\" = EXCLUDED.\\\"department_id\\\",\\n\\\"manager_id\\\" = EXCLUDED.\\\"manager_id\\\",\\n\\\"email\\\" = EXCLUDED.\\\"email\\\",\\n\\\"first_name\\\" = EXCLUDED.\\\"first_name\\\",\\n\\\"last_name\\\" = EXCLUDED.\\\"last_name\\\",\\n\\\"salary\\\" = EXCLUDED.\\\"salary\\\",\\n\\\"hired_at\\\" = EXCLUDED.\\\"hired_at\\\",\\n\\\"active\\\" = EXCLUDED.\\\"active\\\",\\n\\\"created_at\\\" = EXCLUDED.\\\"created_at\\\",\\n\\\"skills\\\" = EXCLUDED.\\\"skills\\\",\\n\\\"certifications\\\" = EXCLUDED.\\\"certifications\\\",\\n\\\"metadata\\\" = EXCLUDED.\\\"metadata\\\",\\n\\\"settings\\\" = EXCLUDED.\\\"settings\\\",\\n\\\"work_schedule\\\" = EXCLUDED.\\\"work_schedule\\\",\\n\\\"ip_address\\\" = EXCLUDED.\\\"ip_address\\\",\\n\\\"network_cidr\\\" = EXCLUDED.\\\"network_cidr\\\",\\n\\\"mac_address\\\" = EXCLUDED.\\\"mac_address\\\",\\n\\\"probation_period\\\" = EXCLUDED.\\\"probation_period\\\",\\n\\\"photo\\\" = EXCLUDED.\\\"photo\\\"\\n;\\ndrop table employee_TEMP;\")).update().runUnchecked(c)\n }\n}", - "EmployeeRepoMock": "package showcase.showcase.employee\n\nimport dev.typr.foundations.kotlin.DeleteBuilder\nimport dev.typr.foundations.kotlin.DeleteBuilderMock\nimport dev.typr.foundations.kotlin.DeleteParams\nimport dev.typr.foundations.kotlin.SelectBuilder\nimport dev.typr.foundations.kotlin.SelectBuilderMock\nimport dev.typr.foundations.kotlin.SelectParams\nimport dev.typr.foundations.kotlin.UpdateBuilder\nimport dev.typr.foundations.kotlin.UpdateBuilderMock\nimport dev.typr.foundations.kotlin.UpdateParams\nimport java.lang.RuntimeException\nimport java.sql.Connection\nimport java.util.ArrayList\nimport kotlin.collections.Iterator\nimport kotlin.collections.List\nimport kotlin.collections.Map\nimport kotlin.collections.MutableMap\n\ndata class EmployeeRepoMock(\n val toRow: (EmployeeRowUnsaved) -> EmployeeRow,\n val map: MutableMap = mutableMapOf()\n) : EmployeeRepo {\n override fun delete(): DeleteBuilder = DeleteBuilderMock(EmployeeFields.structure, { map.values.toList() }, DeleteParams.empty(), { row -> row.id }, { id -> map.remove(id) })\n\n override fun deleteById(\n id: EmployeeId,\n c: Connection\n ): Boolean = map.remove(id) != null\n\n override fun deleteByIds(\n ids: Array,\n c: Connection\n ): Int {\n var count = 0\n for (id in ids) {\n if (map.remove(id) != null) {\n count = count + 1\n }\n }\n return count\n }\n\n override fun insert(\n unsaved: EmployeeRow,\n c: Connection\n ): EmployeeRow {\n if (map.containsKey(unsaved.id)) {\n throw RuntimeException(\"id \" + unsaved.id + \" already exists\")\n }\n map[unsaved.id] = unsaved\n return unsaved\n }\n\n override fun insert(\n unsaved: EmployeeRowUnsaved,\n c: Connection\n ): EmployeeRow = insert(toRow(unsaved), c)\n\n override fun insertStreaming(\n unsaved: Iterator,\n batchSize: Int,\n c: Connection\n ): Long {\n var count = 0L\n while (unsaved.hasNext()) {\n val row = unsaved.next()\n map[row.id] = row\n count = count + 1L\n }\n return count\n }\n\n /** NOTE: this functionality requires PostgreSQL 16 or later! */\n override fun insertUnsavedStreaming(\n unsaved: Iterator,\n batchSize: Int,\n c: Connection\n ): Long {\n var count = 0L\n while (unsaved.hasNext()) {\n val unsavedRow = unsaved.next()\n val row = toRow(unsavedRow)\n map[row.id] = row\n count = count + 1L\n }\n return count\n }\n\n override fun select(): SelectBuilder = SelectBuilderMock(EmployeeFields.structure, { map.values.toList() }, SelectParams.empty())\n\n override fun selectAll(c: Connection): List = map.values.toList()\n\n override fun selectById(\n id: EmployeeId,\n c: Connection\n ): EmployeeRow? = map[id]\n\n override fun selectByIds(\n ids: Array,\n c: Connection\n ): List {\n val result = ArrayList()\n for (id in ids) {\n val opt = map[id]\n if (opt != null) {\n result.add(opt!!)\n }\n }\n return result\n }\n\n override fun selectByIdsTracked(\n ids: Array,\n c: Connection\n ): Map = selectByIds(ids, c).associateBy({ row: EmployeeRow -> row.id })\n\n override fun selectByUniqueEmail(\n email: String,\n c: Connection\n ): EmployeeRow? = map.values.toList().find({ v -> (email == v.email) })\n\n override fun update(): UpdateBuilder = UpdateBuilderMock(EmployeeFields.structure, { map.values.toList() }, UpdateParams.empty(), { row -> row })\n\n override fun update(\n row: EmployeeRow,\n c: Connection\n ): Boolean {\n val shouldUpdate = map[row.id]?.takeIf({ oldRow -> (oldRow != row) }) != null\n if (shouldUpdate) {\n map[row.id] = row\n }\n return shouldUpdate\n }\n\n override fun upsert(\n unsaved: EmployeeRow,\n c: Connection\n ): EmployeeRow {\n map[unsaved.id] = unsaved\n return unsaved\n }\n\n override fun upsertBatch(\n unsaved: Iterator,\n c: Connection\n ): List {\n val result = ArrayList()\n while (unsaved.hasNext()) {\n val row = unsaved.next()\n map[row.id] = row\n result.add(row)\n }\n return result\n }\n\n /** NOTE: this functionality is not safe if you use auto-commit mode! it runs 3 SQL statements */\n override fun upsertStreaming(\n unsaved: Iterator,\n batchSize: Int,\n c: Connection\n ): Int {\n var count = 0\n while (unsaved.hasNext()) {\n val row = unsaved.next()\n map[row.id] = row\n count = count + 1\n }\n return count\n }\n}", - "EmployeeFields": "package showcase.showcase.employee\n\nimport dev.typr.foundations.PgTypes\nimport dev.typr.foundations.RowParser\nimport dev.typr.foundations.data.Cidr\nimport dev.typr.foundations.data.Inet\nimport dev.typr.foundations.data.Jsonb\nimport dev.typr.foundations.data.MacAddr\nimport dev.typr.foundations.dsl.FieldsExpr\nimport dev.typr.foundations.dsl.Path\nimport dev.typr.foundations.dsl.SqlExpr.FieldLike\nimport dev.typr.foundations.kotlin.ForeignKey\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.RelationStructure\nimport dev.typr.foundations.kotlin.SqlExpr.Field\nimport dev.typr.foundations.kotlin.SqlExpr.IdField\nimport dev.typr.foundations.kotlin.SqlExpr.OptField\nimport java.math.BigDecimal\nimport java.time.LocalDate\nimport java.time.LocalDateTime\nimport kotlin.collections.List\nimport kotlin.collections.Map\nimport org.postgresql.util.PGInterval\nimport showcase.showcase.department.DepartmentFields\nimport showcase.showcase.department.DepartmentId\nimport showcase.showcase.department.DepartmentRow\n\ninterface EmployeeFields : FieldsExpr {\n abstract fun active(): OptField\n\n abstract fun certifications(): OptField, EmployeeRow>\n\n abstract override fun columns(): List>\n\n abstract fun createdAt(): OptField\n\n abstract fun departmentId(): Field\n\n abstract fun email(): Field\n\n abstract fun firstName(): Field\n\n fun fkDepartment(): ForeignKey = ForeignKey.of(\"employee_department_fk\").withColumnPair(departmentId(), DepartmentFields::id)\n\n fun fkEmployee(): ForeignKey = ForeignKey.of(\"employee_manager_fk\").withColumnPair(managerId(), EmployeeFields::id)\n\n abstract fun hiredAt(): OptField\n\n abstract fun id(): IdField\n\n abstract fun ipAddress(): OptField\n\n abstract fun lastName(): Field\n\n abstract fun macAddress(): OptField\n\n abstract fun managerId(): OptField\n\n abstract fun metadata(): OptField\n\n abstract fun networkCidr(): OptField\n\n abstract fun photo(): OptField\n\n abstract fun probationPeriod(): OptField\n\n override fun rowParser(): RowParser = EmployeeRow._rowParser.underlying\n\n abstract fun salary(): OptField\n\n abstract fun settings(): OptField, EmployeeRow>\n\n abstract fun skills(): OptField, EmployeeRow>\n\n abstract fun workSchedule(): OptField, EmployeeRow>\n\n companion object {\n data class Impl(val _path: List) : EmployeeFields, RelationStructure {\n override fun id(): IdField = IdField(_path, \"id\", EmployeeRow::id, null, null, { row, value -> row.copy(id = value) }, EmployeeId.pgType)\n\n override fun departmentId(): Field = Field(_path, \"department_id\", EmployeeRow::departmentId, null, null, { row, value -> row.copy(departmentId = value) }, DepartmentId.pgType)\n\n override fun managerId(): OptField = OptField(_path, \"manager_id\", EmployeeRow::managerId, null, null, { row, value -> row.copy(managerId = value) }, EmployeeId.pgType)\n\n override fun email(): Field = Field(_path, \"email\", EmployeeRow::email, null, null, { row, value -> row.copy(email = value) }, PgTypes.text)\n\n override fun firstName(): Field = Field(_path, \"first_name\", EmployeeRow::firstName, null, null, { row, value -> row.copy(firstName = value) }, PgTypes.text)\n\n override fun lastName(): Field = Field(_path, \"last_name\", EmployeeRow::lastName, null, null, { row, value -> row.copy(lastName = value) }, PgTypes.text)\n\n override fun salary(): OptField = OptField(_path, \"salary\", EmployeeRow::salary, null, null, { row, value -> row.copy(salary = value) }, PgTypes.numeric)\n\n override fun hiredAt(): OptField = OptField(_path, \"hired_at\", EmployeeRow::hiredAt, null, null, { row, value -> row.copy(hiredAt = value) }, PgTypes.date)\n\n override fun active(): OptField = OptField(_path, \"active\", EmployeeRow::active, null, null, { row, value -> row.copy(active = value) }, KotlinDbTypes.PgTypes.bool)\n\n override fun createdAt(): OptField = OptField(_path, \"created_at\", EmployeeRow::createdAt, null, null, { row, value -> row.copy(createdAt = value) }, PgTypes.timestamp)\n\n override fun skills(): OptField, EmployeeRow> = OptField, EmployeeRow>(_path, \"skills\", EmployeeRow::skills, null, null, { row, value -> row.copy(skills = value) }, PgTypes.textArray)\n\n override fun certifications(): OptField, EmployeeRow> = OptField, EmployeeRow>(_path, \"certifications\", EmployeeRow::certifications, null, null, { row, value -> row.copy(certifications = value) }, PgTypes.textArray)\n\n override fun metadata(): OptField = OptField(_path, \"metadata\", EmployeeRow::metadata, null, null, { row, value -> row.copy(metadata = value) }, PgTypes.jsonb)\n\n override fun settings(): OptField, EmployeeRow> = OptField, EmployeeRow>(_path, \"settings\", EmployeeRow::settings, null, null, { row, value -> row.copy(settings = value) }, KotlinDbTypes.PgTypes.hstore)\n\n override fun workSchedule(): OptField, EmployeeRow> = OptField, EmployeeRow>(_path, \"work_schedule\", EmployeeRow::workSchedule, null, null, { row, value -> row.copy(workSchedule = value) }, PgTypes.boolArray)\n\n override fun ipAddress(): OptField = OptField(_path, \"ip_address\", EmployeeRow::ipAddress, null, null, { row, value -> row.copy(ipAddress = value) }, PgTypes.inet)\n\n override fun networkCidr(): OptField = OptField(_path, \"network_cidr\", EmployeeRow::networkCidr, null, null, { row, value -> row.copy(networkCidr = value) }, PgTypes.cidr)\n\n override fun macAddress(): OptField = OptField(_path, \"mac_address\", EmployeeRow::macAddress, null, null, { row, value -> row.copy(macAddress = value) }, PgTypes.macaddr)\n\n override fun probationPeriod(): OptField = OptField(_path, \"probation_period\", EmployeeRow::probationPeriod, null, null, { row, value -> row.copy(probationPeriod = value) }, PgTypes.interval)\n\n override fun photo(): OptField = OptField(_path, \"photo\", EmployeeRow::photo, null, null, { row, value -> row.copy(photo = value) }, PgTypes.bytea)\n\n override fun _path(): List = _path\n\n override fun columns(): List> = listOf(this.id().underlying, this.departmentId().underlying, this.managerId().underlying, this.email().underlying, this.firstName().underlying, this.lastName().underlying, this.salary().underlying, this.hiredAt().underlying, this.active().underlying, this.createdAt().underlying, this.skills().underlying, this.certifications().underlying, this.metadata().underlying, this.settings().underlying, this.workSchedule().underlying, this.ipAddress().underlying, this.networkCidr().underlying, this.macAddress().underlying, this.probationPeriod().underlying, this.photo().underlying)\n\n override fun withPaths(_path: List): RelationStructure = Impl(_path)\n }\n\n val structure: Impl = Impl(emptyList())\n }\n}", - "DepartmentRow": "package showcase.showcase.department\n\nimport dev.typr.foundations.PgText\nimport dev.typr.foundations.PgTypes\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport dev.typr.foundations.kotlin.nullable\nimport java.math.BigDecimal\nimport showcase.showcase.company.CompanyId\n\n/** Table: showcase.department\n * Primary key: id\n */\ndata class DepartmentRow(\n val id: DepartmentId,\n /** Points to [showcase.showcase.company.CompanyRow.id] */\n val companyId: CompanyId,\n val name: String,\n val budget: BigDecimal?\n) {\n companion object {\n val _rowParser: RowParser = RowParsers.of(DepartmentId.pgType, CompanyId.pgType, PgTypes.text, PgTypes.numeric.nullable(), { t0, t1, t2, t3 -> DepartmentRow(t0, t1, t2, t3) }, { row -> arrayOf(row.id, row.companyId, row.name, row.budget) })\n\n val pgText: PgText =\n PgText.from(_rowParser.underlying)\n }\n}", - "DepartmentId": "package showcase.showcase.department\n\nimport dev.typr.foundations.PgType\nimport dev.typr.foundations.PgTypes\nimport dev.typr.foundations.internal.arrayMap\nimport dev.typr.foundations.kotlin.Bijection\n\n/** Type for the primary key of table `showcase.department` */\ndata class DepartmentId(val value: String) {\n override fun toString(): kotlin.String {\n return value.toString()\n }\n\n companion object {\n val bijection: Bijection =\n Bijection.of(DepartmentId::value, ::DepartmentId)\n\n val pgType: PgType =\n PgTypes.text.bimap(::DepartmentId, DepartmentId::value)\n\n val pgTypeArray: PgType> =\n PgTypes.textArray.bimap({ xs -> arrayMap.map(xs, ::DepartmentId, DepartmentId::class.java) }, { xs -> arrayMap.map(xs, DepartmentId::value, String::class.java) })\n }\n}", - "DepartmentRepo": "package showcase.showcase.department\n\nimport dev.typr.foundations.kotlin.DeleteBuilder\nimport dev.typr.foundations.kotlin.SelectBuilder\nimport dev.typr.foundations.kotlin.UpdateBuilder\nimport java.sql.Connection\nimport kotlin.collections.Iterator\nimport kotlin.collections.List\nimport kotlin.collections.Map\n\ninterface DepartmentRepo {\n abstract fun delete(): DeleteBuilder\n\n abstract fun deleteById(\n id: DepartmentId,\n c: Connection\n ): Boolean\n\n abstract fun deleteByIds(\n ids: Array,\n c: Connection\n ): Int\n\n abstract fun insert(\n unsaved: DepartmentRow,\n c: Connection\n ): DepartmentRow\n\n abstract fun insertStreaming(\n unsaved: Iterator,\n batchSize: Int,\n c: Connection\n ): Long\n\n abstract fun select(): SelectBuilder\n\n abstract fun selectAll(c: Connection): List\n\n abstract fun selectById(\n id: DepartmentId,\n c: Connection\n ): DepartmentRow?\n\n abstract fun selectByIds(\n ids: Array,\n c: Connection\n ): List\n\n abstract fun selectByIdsTracked(\n ids: Array,\n c: Connection\n ): Map\n\n abstract fun update(): UpdateBuilder\n\n abstract fun update(\n row: DepartmentRow,\n c: Connection\n ): Boolean\n\n abstract fun upsert(\n unsaved: DepartmentRow,\n c: Connection\n ): DepartmentRow\n\n abstract fun upsertBatch(\n unsaved: Iterator,\n c: Connection\n ): List\n\n /** NOTE: this functionality is not safe if you use auto-commit mode! it runs 3 SQL statements */\n abstract fun upsertStreaming(\n unsaved: Iterator,\n batchSize: Int,\n c: Connection\n ): Int\n}", - "DepartmentRepoMock": "package showcase.showcase.department\n\nimport dev.typr.foundations.kotlin.DeleteBuilder\nimport dev.typr.foundations.kotlin.DeleteBuilderMock\nimport dev.typr.foundations.kotlin.DeleteParams\nimport dev.typr.foundations.kotlin.SelectBuilder\nimport dev.typr.foundations.kotlin.SelectBuilderMock\nimport dev.typr.foundations.kotlin.SelectParams\nimport dev.typr.foundations.kotlin.UpdateBuilder\nimport dev.typr.foundations.kotlin.UpdateBuilderMock\nimport dev.typr.foundations.kotlin.UpdateParams\nimport java.lang.RuntimeException\nimport java.sql.Connection\nimport java.util.ArrayList\nimport kotlin.collections.Iterator\nimport kotlin.collections.List\nimport kotlin.collections.Map\nimport kotlin.collections.MutableMap\n\ndata class DepartmentRepoMock(val map: MutableMap = mutableMapOf()) : DepartmentRepo {\n override fun delete(): DeleteBuilder = DeleteBuilderMock(DepartmentFields.structure, { map.values.toList() }, DeleteParams.empty(), { row -> row.id }, { id -> map.remove(id) })\n\n override fun deleteById(\n id: DepartmentId,\n c: Connection\n ): Boolean = map.remove(id) != null\n\n override fun deleteByIds(\n ids: Array,\n c: Connection\n ): Int {\n var count = 0\n for (id in ids) {\n if (map.remove(id) != null) {\n count = count + 1\n }\n }\n return count\n }\n\n override fun insert(\n unsaved: DepartmentRow,\n c: Connection\n ): DepartmentRow {\n if (map.containsKey(unsaved.id)) {\n throw RuntimeException(\"id \" + unsaved.id + \" already exists\")\n }\n map[unsaved.id] = unsaved\n return unsaved\n }\n\n override fun insertStreaming(\n unsaved: Iterator,\n batchSize: Int,\n c: Connection\n ): Long {\n var count = 0L\n while (unsaved.hasNext()) {\n val row = unsaved.next()\n map[row.id] = row\n count = count + 1L\n }\n return count\n }\n\n override fun select(): SelectBuilder = SelectBuilderMock(DepartmentFields.structure, { map.values.toList() }, SelectParams.empty())\n\n override fun selectAll(c: Connection): List = map.values.toList()\n\n override fun selectById(\n id: DepartmentId,\n c: Connection\n ): DepartmentRow? = map[id]\n\n override fun selectByIds(\n ids: Array,\n c: Connection\n ): List {\n val result = ArrayList()\n for (id in ids) {\n val opt = map[id]\n if (opt != null) {\n result.add(opt!!)\n }\n }\n return result\n }\n\n override fun selectByIdsTracked(\n ids: Array,\n c: Connection\n ): Map = selectByIds(ids, c).associateBy({ row: DepartmentRow -> row.id })\n\n override fun update(): UpdateBuilder = UpdateBuilderMock(DepartmentFields.structure, { map.values.toList() }, UpdateParams.empty(), { row -> row })\n\n override fun update(\n row: DepartmentRow,\n c: Connection\n ): Boolean {\n val shouldUpdate = map[row.id]?.takeIf({ oldRow -> (oldRow != row) }) != null\n if (shouldUpdate) {\n map[row.id] = row\n }\n return shouldUpdate\n }\n\n override fun upsert(\n unsaved: DepartmentRow,\n c: Connection\n ): DepartmentRow {\n map[unsaved.id] = unsaved\n return unsaved\n }\n\n override fun upsertBatch(\n unsaved: Iterator,\n c: Connection\n ): List {\n val result = ArrayList()\n while (unsaved.hasNext()) {\n val row = unsaved.next()\n map[row.id] = row\n result.add(row)\n }\n return result\n }\n\n /** NOTE: this functionality is not safe if you use auto-commit mode! it runs 3 SQL statements */\n override fun upsertStreaming(\n unsaved: Iterator,\n batchSize: Int,\n c: Connection\n ): Int {\n var count = 0\n while (unsaved.hasNext()) {\n val row = unsaved.next()\n map[row.id] = row\n count = count + 1\n }\n return count\n }\n}", - "ProjectAssignmentRow": "package showcase.showcase.project_assignment\n\nimport dev.typr.foundations.PgText\nimport dev.typr.foundations.PgTypes\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport dev.typr.foundations.kotlin.nullable\nimport java.time.LocalDate\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.employee.EmployeeId\nimport showcase.showcase.project.ProjectId\n\n/** Table: showcase.project_assignment\n * Composite primary key: employee_id, project_id\n */\ndata class ProjectAssignmentRow(\n /** Points to [showcase.showcase.employee.EmployeeRow.id] */\n val employeeId: EmployeeId,\n /** Points to [showcase.showcase.project.ProjectRow.id] */\n val projectId: ProjectId,\n val role: String,\n /** Default: 0 */\n val hoursAllocated: Int?,\n val startDate: LocalDate?,\n val endDate: LocalDate?\n) {\n fun compositeId(): ProjectAssignmentId = ProjectAssignmentId(employeeId, projectId)\n\n fun id(): ProjectAssignmentId = this.compositeId()\n\n fun toUnsavedRow(hoursAllocated: Defaulted): ProjectAssignmentRowUnsaved = ProjectAssignmentRowUnsaved(employeeId, projectId, role, startDate, endDate, hoursAllocated)\n\n companion object {\n val _rowParser: RowParser = RowParsers.of(EmployeeId.pgType, ProjectId.pgType, PgTypes.text, KotlinDbTypes.PgTypes.int4.nullable(), PgTypes.date.nullable(), PgTypes.date.nullable(), { t0, t1, t2, t3, t4, t5 -> ProjectAssignmentRow(t0, t1, t2, t3, t4, t5) }, { row -> arrayOf(row.employeeId, row.projectId, row.role, row.hoursAllocated, row.startDate, row.endDate) })\n\n fun apply(\n compositeId: ProjectAssignmentId,\n role: String,\n hoursAllocated: Int?,\n startDate: LocalDate?,\n endDate: LocalDate?\n ): ProjectAssignmentRow = ProjectAssignmentRow(compositeId.employeeId, compositeId.projectId, role, hoursAllocated, startDate, endDate)\n\n val pgText: PgText =\n PgText.from(_rowParser.underlying)\n }\n}", - "ProjectAssignmentRowUnsaved": "package showcase.showcase.project_assignment\n\nimport dev.typr.foundations.PgText\nimport dev.typr.foundations.PgTypes\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.nullable\nimport java.time.LocalDate\nimport showcase.customtypes.Defaulted\nimport showcase.customtypes.Defaulted.UseDefault\nimport showcase.showcase.employee.EmployeeId\nimport showcase.showcase.project.ProjectId\n\n/** This class corresponds to a row in table `showcase.project_assignment` which has not been persisted yet */\ndata class ProjectAssignmentRowUnsaved(\n /** Points to [showcase.showcase.employee.EmployeeRow.id] */\n val employeeId: EmployeeId,\n /** Points to [showcase.showcase.project.ProjectRow.id] */\n val projectId: ProjectId,\n val role: String,\n val startDate: LocalDate? = null,\n val endDate: LocalDate? = null,\n /** Default: 0 */\n val hoursAllocated: Defaulted = UseDefault()\n) {\n fun toRow(hoursAllocatedDefault: () -> Int?): ProjectAssignmentRow = ProjectAssignmentRow(employeeId = employeeId, projectId = projectId, role = role, hoursAllocated = hoursAllocated.getOrElse(hoursAllocatedDefault), startDate = startDate, endDate = endDate)\n\n companion object {\n val pgText: PgText =\n PgText.instance({ row, sb -> EmployeeId.pgType.text().unsafeEncode(row.employeeId, sb)\n sb.append(PgText.DELIMETER)\n ProjectId.pgType.text().unsafeEncode(row.projectId, sb)\n sb.append(PgText.DELIMETER)\n PgTypes.text.text().unsafeEncode(row.role, sb)\n sb.append(PgText.DELIMETER)\n PgTypes.date.nullable().text().unsafeEncode(row.startDate, sb)\n sb.append(PgText.DELIMETER)\n PgTypes.date.nullable().text().unsafeEncode(row.endDate, sb)\n sb.append(PgText.DELIMETER)\n Defaulted.pgText(KotlinDbTypes.PgTypes.int4.nullable().text()).unsafeEncode(row.hoursAllocated, sb) })\n }\n}", - "ProjectAssignmentId": "package showcase.showcase.project_assignment\n\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport showcase.showcase.employee.EmployeeId\nimport showcase.showcase.project.ProjectId\n\n/** Type for the composite primary key of table `showcase.project_assignment` */\ndata class ProjectAssignmentId(\n val employeeId: EmployeeId,\n val projectId: ProjectId\n) {\n companion object {\n val _rowParser: RowParser = RowParsers.of(EmployeeId.pgType, ProjectId.pgType, { t0, t1 -> ProjectAssignmentId(t0, t1) }, { row -> arrayOf(row.employeeId, row.projectId) })\n }\n}", - "ProjectAssignmentRepo": "package showcase.showcase.project_assignment\n\nimport dev.typr.foundations.kotlin.DeleteBuilder\nimport dev.typr.foundations.kotlin.SelectBuilder\nimport dev.typr.foundations.kotlin.UpdateBuilder\nimport java.sql.Connection\nimport kotlin.collections.Iterator\nimport kotlin.collections.List\nimport kotlin.collections.Map\n\ninterface ProjectAssignmentRepo {\n abstract fun delete(): DeleteBuilder\n\n abstract fun deleteById(\n compositeId: ProjectAssignmentId,\n c: Connection\n ): Boolean\n\n abstract fun deleteByIds(\n compositeIds: Array,\n c: Connection\n ): Int\n\n abstract fun insert(\n unsaved: ProjectAssignmentRow,\n c: Connection\n ): ProjectAssignmentRow\n\n abstract fun insert(\n unsaved: ProjectAssignmentRowUnsaved,\n c: Connection\n ): ProjectAssignmentRow\n\n abstract fun insertStreaming(\n unsaved: Iterator,\n batchSize: Int,\n c: Connection\n ): Long\n\n /** NOTE: this functionality requires PostgreSQL 16 or later! */\n abstract fun insertUnsavedStreaming(\n unsaved: Iterator,\n batchSize: Int,\n c: Connection\n ): Long\n\n abstract fun select(): SelectBuilder\n\n abstract fun selectAll(c: Connection): List\n\n abstract fun selectById(\n compositeId: ProjectAssignmentId,\n c: Connection\n ): ProjectAssignmentRow?\n\n abstract fun selectByIds(\n compositeIds: Array,\n c: Connection\n ): List\n\n abstract fun selectByIdsTracked(\n compositeIds: Array,\n c: Connection\n ): Map\n\n abstract fun update(): UpdateBuilder\n\n abstract fun update(\n row: ProjectAssignmentRow,\n c: Connection\n ): Boolean\n\n abstract fun upsert(\n unsaved: ProjectAssignmentRow,\n c: Connection\n ): ProjectAssignmentRow\n\n abstract fun upsertBatch(\n unsaved: Iterator,\n c: Connection\n ): List\n\n /** NOTE: this functionality is not safe if you use auto-commit mode! it runs 3 SQL statements */\n abstract fun upsertStreaming(\n unsaved: Iterator,\n batchSize: Int,\n c: Connection\n ): Int\n}", - "ProjectRow": "package showcase.showcase.project\n\nimport dev.typr.foundations.PgText\nimport dev.typr.foundations.PgTypes\nimport dev.typr.foundations.data.Jsonb\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport dev.typr.foundations.kotlin.nullable\nimport java.math.BigDecimal\nimport java.time.LocalDate\nimport java.time.LocalDateTime\nimport java.util.UUID\nimport kotlin.collections.Map\nimport org.postgresql.util.PGInterval\nimport showcase.customtypes.Defaulted\n\n/** Table: showcase.project\n * Primary key: id\n */\ndata class ProjectRow(\n val id: ProjectId,\n val name: String,\n val description: /* max 1000 chars */ String?,\n val startDate: LocalDate?,\n val endDate: LocalDate?,\n val budget: BigDecimal?,\n /** Default: 'planning' */\n val status: /* max 20 chars */ String?,\n /** Default: CURRENT_TIMESTAMP */\n val createdAt: LocalDateTime?,\n val projectUid: UUID?,\n val milestones: Array?,\n val budgetSnapshots: Array?,\n val teamMembers: Array?,\n val metadata: Jsonb?,\n val config: Map?,\n val estimatedDuration: PGInterval?,\n val actualDuration: PGInterval?\n) {\n fun toUnsavedRow(\n status: Defaulted,\n createdAt: Defaulted\n ): ProjectRowUnsaved = ProjectRowUnsaved(id, name, description, startDate, endDate, budget, projectUid, milestones, budgetSnapshots, teamMembers, metadata, config, estimatedDuration, actualDuration, status, createdAt)\n\n companion object {\n val _rowParser: RowParser = RowParsers.of(ProjectId.pgType, PgTypes.text, PgTypes.text.nullable(), PgTypes.date.nullable(), PgTypes.date.nullable(), PgTypes.numeric.nullable(), PgTypes.text.nullable(), PgTypes.timestamp.nullable(), PgTypes.uuid.nullable(), PgTypes.textArray.nullable(), PgTypes.numericArray.nullable(), PgTypes.textArray.nullable(), PgTypes.jsonb.nullable(), KotlinDbTypes.PgTypes.hstore.nullable(), PgTypes.interval.nullable(), PgTypes.interval.nullable(), { t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15 -> ProjectRow(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15) }, { row -> arrayOf(row.id, row.name, row.description, row.startDate, row.endDate, row.budget, row.status, row.createdAt, row.projectUid, row.milestones, row.budgetSnapshots, row.teamMembers, row.metadata, row.config, row.estimatedDuration, row.actualDuration) })\n\n val pgText: PgText =\n PgText.from(_rowParser.underlying)\n }\n}", - "ProjectId": "package showcase.showcase.project\n\nimport dev.typr.foundations.PgType\nimport dev.typr.foundations.PgTypes\nimport dev.typr.foundations.internal.arrayMap\nimport dev.typr.foundations.kotlin.Bijection\n\n/** Type for the primary key of table `showcase.project` */\ndata class ProjectId(val value: String) {\n override fun toString(): kotlin.String {\n return value.toString()\n }\n\n companion object {\n val bijection: Bijection =\n Bijection.of(ProjectId::value, ::ProjectId)\n\n val pgType: PgType =\n PgTypes.text.bimap(::ProjectId, ProjectId::value)\n\n val pgTypeArray: PgType> =\n PgTypes.textArray.bimap({ xs -> arrayMap.map(xs, ::ProjectId, ProjectId::class.java) }, { xs -> arrayMap.map(xs, ProjectId::value, String::class.java) })\n }\n}", - "EmployeeSummaryViewRow": "package showcase.showcase.employee_summary\n\nimport dev.typr.foundations.PgTypes\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport dev.typr.foundations.kotlin.nullable\nimport java.math.BigDecimal\nimport java.time.LocalDate\nimport showcase.showcase.company.CompanyId\nimport showcase.showcase.department.DepartmentId\nimport showcase.showcase.employee.EmployeeId\n\n/** View: showcase.employee_summary\n * Summary view of employees with their department and company information\n */\ndata class EmployeeSummaryViewRow(\n /** Points to [showcase.showcase.employee.EmployeeRow.id] */\n val employeeId: EmployeeId,\n val email: String,\n val firstName: String,\n val lastName: String,\n val salary: BigDecimal?,\n val hiredAt: LocalDate?,\n val active: Boolean?,\n /** Points to [showcase.showcase.department.DepartmentRow.id] */\n val departmentId: DepartmentId,\n val departmentName: String,\n val departmentBudget: BigDecimal?,\n /** Points to [showcase.showcase.company.CompanyRow.id] */\n val companyId: CompanyId,\n val companyName: String,\n val managerId: String?,\n val managerFirstName: /* max 50 chars */ String?,\n val managerLastName: /* max 50 chars */ String?\n) {\n companion object {\n val _rowParser: RowParser = RowParsers.of(EmployeeId.pgType, PgTypes.text, PgTypes.text, PgTypes.text, PgTypes.numeric.nullable(), PgTypes.date.nullable(), KotlinDbTypes.PgTypes.bool.nullable(), DepartmentId.pgType, PgTypes.text, PgTypes.numeric.nullable(), CompanyId.pgType, PgTypes.text, PgTypes.text.nullable(), PgTypes.text.nullable(), PgTypes.text.nullable(), { t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14 -> EmployeeSummaryViewRow(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14) }, { row -> arrayOf(row.employeeId, row.email, row.firstName, row.lastName, row.salary, row.hiredAt, row.active, row.departmentId, row.departmentName, row.departmentBudget, row.companyId, row.companyName, row.managerId, row.managerFirstName, row.managerLastName) })\n }\n}", - "EmployeeSummaryViewRepo": "package showcase.showcase.employee_summary\n\nimport dev.typr.foundations.kotlin.SelectBuilder\nimport java.sql.Connection\nimport kotlin.collections.List\n\ninterface EmployeeSummaryViewRepo {\n abstract fun select(): SelectBuilder\n\n abstract fun selectAll(c: Connection): List\n}", - "CustomerOrderRow": "package showcase.showcase.customer_order\n\nimport dev.typr.foundations.PgText\nimport dev.typr.foundations.PgTypes\nimport dev.typr.foundations.data.Inet\nimport dev.typr.foundations.data.Jsonb\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport dev.typr.foundations.kotlin.nullable\nimport java.math.BigDecimal\nimport java.time.LocalDateTime\nimport java.util.UUID\nimport org.postgresql.util.PGInterval\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.address.AddressId\nimport showcase.showcase.customer.CustomerId\n\n/** Table: showcase.customer_order\n * Primary key: id\n */\ndata class CustomerOrderRow(\n val id: CustomerOrderId,\n /** Points to [showcase.showcase.customer.CustomerRow.id] */\n val customerId: CustomerId,\n /** Points to [showcase.showcase.address.AddressRow.id] */\n val shippingAddressId: AddressId?,\n /** Points to [showcase.showcase.address.AddressRow.id] */\n val billingAddressId: AddressId?,\n /** Default: 'pending' */\n val status: /* max 20 chars */ String?,\n val subtotal: BigDecimal,\n /** Default: 0 */\n val tax: BigDecimal?,\n /** Default: 0 */\n val shipping: BigDecimal?,\n val total: BigDecimal,\n val notes: /* max 1000 chars */ String?,\n /** Default: CURRENT_TIMESTAMP */\n val createdAt: LocalDateTime?,\n val shippedAt: LocalDateTime?,\n val deliveredAt: LocalDateTime?,\n val orderUid: UUID?,\n val metadata: Jsonb?,\n val tags: Array?,\n val fulfillmentTimes: Array?,\n val ipAddress: Inet?,\n val processingTime: PGInterval?\n) {\n fun toUnsavedRow(\n status: Defaulted,\n tax: Defaulted,\n shipping: Defaulted,\n createdAt: Defaulted\n ): CustomerOrderRowUnsaved = CustomerOrderRowUnsaved(id, customerId, shippingAddressId, billingAddressId, subtotal, total, notes, shippedAt, deliveredAt, orderUid, metadata, tags, fulfillmentTimes, ipAddress, processingTime, status, tax, shipping, createdAt)\n\n companion object {\n val _rowParser: RowParser = RowParsers.of(CustomerOrderId.pgType, CustomerId.pgType, AddressId.pgType.nullable(), AddressId.pgType.nullable(), PgTypes.text.nullable(), PgTypes.numeric, PgTypes.numeric.nullable(), PgTypes.numeric.nullable(), PgTypes.numeric, PgTypes.text.nullable(), PgTypes.timestamp.nullable(), PgTypes.timestamp.nullable(), PgTypes.timestamp.nullable(), PgTypes.uuid.nullable(), PgTypes.jsonb.nullable(), PgTypes.textArray.nullable(), PgTypes.timestampArray.nullable(), PgTypes.inet.nullable(), PgTypes.interval.nullable(), { t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17, t18 -> CustomerOrderRow(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17, t18) }, { row -> arrayOf(row.id, row.customerId, row.shippingAddressId, row.billingAddressId, row.status, row.subtotal, row.tax, row.shipping, row.total, row.notes, row.createdAt, row.shippedAt, row.deliveredAt, row.orderUid, row.metadata, row.tags, row.fulfillmentTimes, row.ipAddress, row.processingTime) })\n\n val pgText: PgText =\n PgText.from(_rowParser.underlying)\n }\n}", - "CustomerOrderRepo": "package showcase.showcase.customer_order\n\nimport dev.typr.foundations.kotlin.DeleteBuilder\nimport dev.typr.foundations.kotlin.SelectBuilder\nimport dev.typr.foundations.kotlin.UpdateBuilder\nimport java.sql.Connection\nimport kotlin.collections.Iterator\nimport kotlin.collections.List\nimport kotlin.collections.Map\n\ninterface CustomerOrderRepo {\n abstract fun delete(): DeleteBuilder\n\n abstract fun deleteById(\n id: CustomerOrderId,\n c: Connection\n ): Boolean\n\n abstract fun deleteByIds(\n ids: Array,\n c: Connection\n ): Int\n\n abstract fun insert(\n unsaved: CustomerOrderRow,\n c: Connection\n ): CustomerOrderRow\n\n abstract fun insert(\n unsaved: CustomerOrderRowUnsaved,\n c: Connection\n ): CustomerOrderRow\n\n abstract fun insertStreaming(\n unsaved: Iterator,\n batchSize: Int,\n c: Connection\n ): Long\n\n /** NOTE: this functionality requires PostgreSQL 16 or later! */\n abstract fun insertUnsavedStreaming(\n unsaved: Iterator,\n batchSize: Int,\n c: Connection\n ): Long\n\n abstract fun select(): SelectBuilder\n\n abstract fun selectAll(c: Connection): List\n\n abstract fun selectById(\n id: CustomerOrderId,\n c: Connection\n ): CustomerOrderRow?\n\n abstract fun selectByIds(\n ids: Array,\n c: Connection\n ): List\n\n abstract fun selectByIdsTracked(\n ids: Array,\n c: Connection\n ): Map\n\n abstract fun update(): UpdateBuilder\n\n abstract fun update(\n row: CustomerOrderRow,\n c: Connection\n ): Boolean\n\n abstract fun upsert(\n unsaved: CustomerOrderRow,\n c: Connection\n ): CustomerOrderRow\n\n abstract fun upsertBatch(\n unsaved: Iterator,\n c: Connection\n ): List\n\n /** NOTE: this functionality is not safe if you use auto-commit mode! it runs 3 SQL statements */\n abstract fun upsertStreaming(\n unsaved: Iterator,\n batchSize: Int,\n c: Connection\n ): Int\n}", - "OrderItemRow": "package showcase.showcase.order_item\n\nimport dev.typr.foundations.PgText\nimport dev.typr.foundations.PgTypes\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport dev.typr.foundations.kotlin.nullable\nimport java.math.BigDecimal\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.customer_order.CustomerOrderId\nimport showcase.showcase.product.ProductId\n\n/** Table: showcase.order_item\n * Composite primary key: order_id, product_id\n */\ndata class OrderItemRow(\n /** Points to [showcase.showcase.customer_order.CustomerOrderRow.id] */\n val orderId: CustomerOrderId,\n /** Points to [showcase.showcase.product.ProductRow.id] */\n val productId: ProductId,\n val quantity: Int,\n val unitPrice: BigDecimal,\n /** Default: 0 */\n val discount: BigDecimal?\n) {\n fun compositeId(): OrderItemId = OrderItemId(orderId, productId)\n\n fun id(): OrderItemId = this.compositeId()\n\n fun toUnsavedRow(discount: Defaulted): OrderItemRowUnsaved = OrderItemRowUnsaved(orderId, productId, quantity, unitPrice, discount)\n\n companion object {\n val _rowParser: RowParser = RowParsers.of(CustomerOrderId.pgType, ProductId.pgType, KotlinDbTypes.PgTypes.int4, PgTypes.numeric, PgTypes.numeric.nullable(), { t0, t1, t2, t3, t4 -> OrderItemRow(t0, t1, t2, t3, t4) }, { row -> arrayOf(row.orderId, row.productId, row.quantity, row.unitPrice, row.discount) })\n\n fun apply(\n compositeId: OrderItemId,\n quantity: Int,\n unitPrice: BigDecimal,\n discount: BigDecimal?\n ): OrderItemRow = OrderItemRow(compositeId.orderId, compositeId.productId, quantity, unitPrice, discount)\n\n val pgText: PgText =\n PgText.from(_rowParser.underlying)\n }\n}", - "OrderItemId": "package showcase.showcase.order_item\n\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport showcase.showcase.customer_order.CustomerOrderId\nimport showcase.showcase.product.ProductId\n\n/** Type for the composite primary key of table `showcase.order_item` */\ndata class OrderItemId(\n val orderId: CustomerOrderId,\n val productId: ProductId\n) {\n companion object {\n val _rowParser: RowParser = RowParsers.of(CustomerOrderId.pgType, ProductId.pgType, { t0, t1 -> OrderItemId(t0, t1) }, { row -> arrayOf(row.orderId, row.productId) })\n }\n}", - "ProductRow": "package showcase.showcase.product\n\nimport dev.typr.foundations.PgText\nimport dev.typr.foundations.PgTypes\nimport dev.typr.foundations.data.Jsonb\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport dev.typr.foundations.kotlin.nullable\nimport java.math.BigDecimal\nimport java.time.LocalDateTime\nimport java.util.UUID\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.category.CategoryId\n\n/** Table: showcase.product\n * Primary key: id\n */\ndata class ProductRow(\n val id: ProductId,\n /** Points to [showcase.showcase.category.CategoryRow.id] */\n val categoryId: CategoryId?,\n val name: String,\n val sku: String,\n val price: BigDecimal,\n val cost: BigDecimal?,\n /** Default: true */\n val inStock: Boolean?,\n /** Default: 0 */\n val quantity: Int?,\n val weight: BigDecimal?,\n /** Default: CURRENT_TIMESTAMP */\n val createdAt: LocalDateTime?,\n val tags: Array?,\n val images: Array?,\n val relatedSkus: Array?,\n val priceHistory: Array?,\n val attributes: Jsonb?,\n val specifications: Jsonb?,\n val seoMetadata: Jsonb?,\n val searchVector: String?,\n val productUid: UUID?\n) {\n fun toUnsavedRow(\n inStock: Defaulted,\n quantity: Defaulted,\n createdAt: Defaulted\n ): ProductRowUnsaved = ProductRowUnsaved(id, categoryId, name, sku, price, cost, weight, tags, images, relatedSkus, priceHistory, attributes, specifications, seoMetadata, searchVector, productUid, inStock, quantity, createdAt)\n\n companion object {\n val _rowParser: RowParser = RowParsers.of(ProductId.pgType, CategoryId.pgType.nullable(), PgTypes.text, PgTypes.text, PgTypes.numeric, PgTypes.numeric.nullable(), KotlinDbTypes.PgTypes.bool.nullable(), KotlinDbTypes.PgTypes.int4.nullable(), PgTypes.numeric.nullable(), PgTypes.timestamp.nullable(), PgTypes.textArray.nullable(), PgTypes.textArray.nullable(), PgTypes.textArray.nullable(), PgTypes.numericArray.nullable(), PgTypes.jsonb.nullable(), PgTypes.jsonb.nullable(), PgTypes.jsonb.nullable(), PgTypes.text.nullable(), PgTypes.uuid.nullable(), { t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17, t18 -> ProductRow(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17, t18) }, { row -> arrayOf(row.id, row.categoryId, row.name, row.sku, row.price, row.cost, row.inStock, row.quantity, row.weight, row.createdAt, row.tags, row.images, row.relatedSkus, row.priceHistory, row.attributes, row.specifications, row.seoMetadata, row.searchVector, row.productUid) })\n\n val pgText: PgText =\n PgText.from(_rowParser.underlying)\n }\n}", - "ProductId": "package showcase.showcase.product\n\nimport dev.typr.foundations.PgType\nimport dev.typr.foundations.PgTypes\nimport dev.typr.foundations.internal.arrayMap\nimport dev.typr.foundations.kotlin.Bijection\n\n/** Type for the primary key of table `showcase.product` */\ndata class ProductId(val value: String) {\n override fun toString(): kotlin.String {\n return value.toString()\n }\n\n companion object {\n val bijection: Bijection =\n Bijection.of(ProductId::value, ::ProductId)\n\n val pgType: PgType =\n PgTypes.text.bimap(::ProductId, ProductId::value)\n\n val pgTypeArray: PgType> =\n PgTypes.textArray.bimap({ xs -> arrayMap.map(xs, ::ProductId, ProductId::class.java) }, { xs -> arrayMap.map(xs, ProductId::value, String::class.java) })\n }\n}", - "CategoryRow": "package showcase.showcase.category\n\nimport dev.typr.foundations.PgText\nimport dev.typr.foundations.PgTypes\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport dev.typr.foundations.kotlin.nullable\n\n/** Table: showcase.category\n * Primary key: id\n */\ndata class CategoryRow(\n val id: CategoryId,\n /** Points to [showcase.showcase.category.CategoryRow.id] */\n val parentId: CategoryId?,\n val name: String,\n val description: /* max 500 chars */ String?\n) {\n companion object {\n val _rowParser: RowParser = RowParsers.of(CategoryId.pgType, CategoryId.pgType.nullable(), PgTypes.text, PgTypes.text.nullable(), { t0, t1, t2, t3 -> CategoryRow(t0, t1, t2, t3) }, { row -> arrayOf(row.id, row.parentId, row.name, row.description) })\n\n val pgText: PgText =\n PgText.from(_rowParser.underlying)\n }\n}", - "CategoryId": "package showcase.showcase.category\n\nimport dev.typr.foundations.PgType\nimport dev.typr.foundations.PgTypes\nimport dev.typr.foundations.internal.arrayMap\nimport dev.typr.foundations.kotlin.Bijection\n\n/** Type for the primary key of table `showcase.category` */\ndata class CategoryId(val value: String) {\n override fun toString(): kotlin.String {\n return value.toString()\n }\n\n companion object {\n val bijection: Bijection =\n Bijection.of(CategoryId::value, ::CategoryId)\n\n val pgType: PgType =\n PgTypes.text.bimap(::CategoryId, CategoryId::value)\n\n val pgTypeArray: PgType> =\n PgTypes.textArray.bimap({ xs -> arrayMap.map(xs, ::CategoryId, CategoryId::class.java) }, { xs -> arrayMap.map(xs, CategoryId::value, String::class.java) })\n }\n}", - "AddressRow": "package showcase.showcase.address\n\nimport dev.typr.foundations.PgText\nimport dev.typr.foundations.PgTypes\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport dev.typr.foundations.kotlin.nullable\nimport org.postgresql.geometric.PGbox\nimport org.postgresql.geometric.PGpoint\nimport org.postgresql.geometric.PGpolygon\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.customer.CustomerId\n\n/** Table: showcase.address\n * Primary key: id\n */\ndata class AddressRow(\n val id: AddressId,\n /** Points to [showcase.showcase.customer.CustomerRow.id] */\n val customerId: CustomerId,\n val addressType: String,\n val street: String,\n val city: String,\n val state: /* max 100 chars */ String?,\n val postalCode: /* max 20 chars */ String?,\n val country: String,\n /** Default: false */\n val isDefault: Boolean?,\n val location: PGpoint?,\n val boundary: PGbox?,\n val deliveryZone: PGpolygon?\n) {\n fun toUnsavedRow(isDefault: Defaulted): AddressRowUnsaved = AddressRowUnsaved(id, customerId, addressType, street, city, state, postalCode, country, location, boundary, deliveryZone, isDefault)\n\n companion object {\n val _rowParser: RowParser = RowParsers.of(AddressId.pgType, CustomerId.pgType, PgTypes.text, PgTypes.text, PgTypes.text, PgTypes.text.nullable(), PgTypes.text.nullable(), PgTypes.text, KotlinDbTypes.PgTypes.bool.nullable(), PgTypes.point.nullable(), PgTypes.box.nullable(), PgTypes.polygon.nullable(), { t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11 -> AddressRow(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11) }, { row -> arrayOf(row.id, row.customerId, row.addressType, row.street, row.city, row.state, row.postalCode, row.country, row.isDefault, row.location, row.boundary, row.deliveryZone) })\n\n val pgText: PgText =\n PgText.from(_rowParser.underlying)\n }\n}", - "AddressId": "package showcase.showcase.address\n\nimport dev.typr.foundations.PgType\nimport dev.typr.foundations.PgTypes\nimport dev.typr.foundations.internal.arrayMap\nimport dev.typr.foundations.kotlin.Bijection\n\n/** Type for the primary key of table `showcase.address` */\ndata class AddressId(val value: String) {\n override fun toString(): kotlin.String {\n return value.toString()\n }\n\n companion object {\n val bijection: Bijection =\n Bijection.of(AddressId::value, ::AddressId)\n\n val pgType: PgType =\n PgTypes.text.bimap(::AddressId, AddressId::value)\n\n val pgTypeArray: PgType> =\n PgTypes.textArray.bimap({ xs -> arrayMap.map(xs, ::AddressId, AddressId::class.java) }, { xs -> arrayMap.map(xs, AddressId::value, String::class.java) })\n }\n}", - "Defaulted": "package showcase.customtypes\n\nimport dev.typr.foundations.DbText\nimport dev.typr.foundations.PgText\n\n/** This signals a value where if you don't provide it, postgres will generate it for you */\nsealed interface Defaulted {\n data class Provided(val value: T) : Defaulted {\n override fun fold(\n onDefault: () -> U,\n onProvided: (T) -> U\n ): U = onProvided(value)\n\n override fun getOrElse(onDefault: () -> T): T = value\n\n override fun visit(\n onDefault: () -> Unit,\n onProvided: (T) -> Unit\n ) {\n onProvided(value)\n }\n }\n\n class UseDefault : Defaulted {\n override fun fold(\n onDefault: () -> U,\n onProvided: (T) -> U\n ): U = onDefault()\n\n override fun getOrElse(onDefault: () -> T): T = onDefault()\n\n override fun visit(\n onDefault: () -> Unit,\n onProvided: (T) -> Unit\n ) {\n onDefault()\n }\n }\n\n companion object {\n fun pgText(t: DbText): PgText> {\n return PgText.instance({ ot, sb -> ot.visit({ sb.append(\"__DEFAULT_VALUE__\") }, { value -> t.unsafeEncode(value, sb) }) })\n }\n }\n\n abstract fun fold(\n onDefault: () -> U,\n onProvided: (T) -> U\n ): U\n\n abstract fun getOrElse(onDefault: () -> T): T\n\n abstract fun visit(\n onDefault: () -> Unit,\n onProvided: (T) -> Unit\n )\n}", - "TestInsert": "package showcase\n\nimport dev.typr.foundations.data.Cidr\nimport dev.typr.foundations.data.Inet\nimport dev.typr.foundations.data.Jsonb\nimport dev.typr.foundations.data.MacAddr\nimport java.math.BigDecimal\nimport java.sql.Connection\nimport java.time.LocalDate\nimport java.time.LocalDateTime\nimport java.util.Random\nimport java.util.UUID\nimport kotlin.collections.Map\nimport org.postgresql.geometric.PGbox\nimport org.postgresql.geometric.PGpoint\nimport org.postgresql.geometric.PGpolygon\nimport org.postgresql.util.PGInterval\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.address.AddressId\nimport showcase.showcase.address.AddressRepoImpl\nimport showcase.showcase.address.AddressRow\nimport showcase.showcase.address.AddressRowUnsaved\nimport showcase.showcase.audit_log.AuditLogId\nimport showcase.showcase.audit_log.AuditLogRepoImpl\nimport showcase.showcase.audit_log.AuditLogRow\nimport showcase.showcase.audit_log.AuditLogRowUnsaved\nimport showcase.showcase.category.CategoryId\nimport showcase.showcase.category.CategoryRepoImpl\nimport showcase.showcase.category.CategoryRow\nimport showcase.showcase.company.CompanyId\nimport showcase.showcase.company.CompanyRepoImpl\nimport showcase.showcase.company.CompanyRow\nimport showcase.showcase.company.CompanyRowUnsaved\nimport showcase.showcase.customer.CustomerId\nimport showcase.showcase.customer.CustomerRepoImpl\nimport showcase.showcase.customer.CustomerRow\nimport showcase.showcase.customer.CustomerRowUnsaved\nimport showcase.showcase.customer_order.CustomerOrderId\nimport showcase.showcase.customer_order.CustomerOrderRepoImpl\nimport showcase.showcase.customer_order.CustomerOrderRow\nimport showcase.showcase.customer_order.CustomerOrderRowUnsaved\nimport showcase.showcase.department.DepartmentId\nimport showcase.showcase.department.DepartmentRepoImpl\nimport showcase.showcase.department.DepartmentRow\nimport showcase.showcase.employee.EmployeeId\nimport showcase.showcase.employee.EmployeeRepoImpl\nimport showcase.showcase.employee.EmployeeRow\nimport showcase.showcase.employee.EmployeeRowUnsaved\nimport showcase.showcase.order_item.OrderItemRepoImpl\nimport showcase.showcase.order_item.OrderItemRow\nimport showcase.showcase.order_item.OrderItemRowUnsaved\nimport showcase.showcase.product.ProductId\nimport showcase.showcase.product.ProductRepoImpl\nimport showcase.showcase.product.ProductRow\nimport showcase.showcase.product.ProductRowUnsaved\nimport showcase.showcase.project.ProjectId\nimport showcase.showcase.project.ProjectRepoImpl\nimport showcase.showcase.project.ProjectRow\nimport showcase.showcase.project.ProjectRowUnsaved\nimport showcase.showcase.project_assignment.ProjectAssignmentRepoImpl\nimport showcase.showcase.project_assignment.ProjectAssignmentRow\nimport showcase.showcase.project_assignment.ProjectAssignmentRowUnsaved\n\n/** Methods to generate random data for `Ident(TestInsert)` */\ndata class TestInsert(val random: Random) {\n fun showcaseAddress(\n id: AddressId,\n customerId: CustomerId,\n addressType: String,\n street: String,\n city: String,\n country: String,\n state: /* max 100 chars */ String?,\n postalCode: /* max 20 chars */ String?,\n location: PGpoint?,\n boundary: PGbox?,\n deliveryZone: PGpolygon?,\n isDefault: Defaulted,\n c: Connection\n ): AddressRow = (AddressRepoImpl()).insert(AddressRowUnsaved(id = id, customerId = customerId, addressType = addressType, street = street, city = city, state = state, postalCode = postalCode, country = country, location = location, boundary = boundary, deliveryZone = deliveryZone, isDefault = isDefault), c)\n\n fun showcaseAuditLog(\n id: AuditLogId,\n tableName: String,\n recordId: String,\n action: String,\n oldValues: /* max 4000 chars */ String?,\n newValues: /* max 4000 chars */ String?,\n changedBy: EmployeeId?,\n changedAt: Defaulted,\n c: Connection\n ): AuditLogRow = (AuditLogRepoImpl()).insert(AuditLogRowUnsaved(id = id, tableName = tableName, recordId = recordId, action = action, oldValues = oldValues, newValues = newValues, changedBy = changedBy, changedAt = changedAt), c)\n\n fun showcaseCategory(\n id: CategoryId,\n name: String,\n parentId: CategoryId?,\n description: /* max 500 chars */ String?,\n c: Connection\n ): CategoryRow = (CategoryRepoImpl()).insert(CategoryRow(id = id, parentId = parentId, name = name, description = description), c)\n\n fun showcaseCompany(\n id: CompanyId,\n name: String,\n foundedYear: Int?,\n active: Defaulted,\n createdAt: Defaulted,\n c: Connection\n ): CompanyRow = (CompanyRepoImpl()).insert(CompanyRowUnsaved(id = id, name = name, foundedYear = foundedYear, active = active, createdAt = createdAt), c)\n\n fun showcaseCustomer(\n id: CustomerId,\n email: String,\n firstName: String,\n lastName: String,\n phone: /* max 20 chars */ String?,\n interests: Array?,\n preferences: Jsonb?,\n metadata: Map?,\n customerUid: UUID?,\n avatar: ByteArray?,\n verified: Defaulted,\n createdAt: Defaulted,\n c: Connection\n ): CustomerRow = (CustomerRepoImpl()).insert(CustomerRowUnsaved(id = id, email = email, firstName = firstName, lastName = lastName, phone = phone, interests = interests, preferences = preferences, metadata = metadata, customerUid = customerUid, avatar = avatar, verified = verified, createdAt = createdAt), c)\n\n fun showcaseCustomerOrder(\n id: CustomerOrderId,\n customerId: CustomerId,\n shippingAddressId: AddressId?,\n billingAddressId: AddressId?,\n subtotal: BigDecimal,\n total: BigDecimal,\n notes: /* max 1000 chars */ String?,\n shippedAt: LocalDateTime?,\n deliveredAt: LocalDateTime?,\n orderUid: UUID?,\n metadata: Jsonb?,\n tags: Array?,\n fulfillmentTimes: Array?,\n ipAddress: Inet?,\n processingTime: PGInterval?,\n status: Defaulted,\n tax: Defaulted,\n shipping: Defaulted,\n createdAt: Defaulted,\n c: Connection\n ): CustomerOrderRow = (CustomerOrderRepoImpl()).insert(CustomerOrderRowUnsaved(id = id, customerId = customerId, shippingAddressId = shippingAddressId, billingAddressId = billingAddressId, subtotal = subtotal, total = total, notes = notes, shippedAt = shippedAt, deliveredAt = deliveredAt, orderUid = orderUid, metadata = metadata, tags = tags, fulfillmentTimes = fulfillmentTimes, ipAddress = ipAddress, processingTime = processingTime, status = status, tax = tax, shipping = shipping, createdAt = createdAt), c)\n\n fun showcaseDepartment(\n id: DepartmentId,\n companyId: CompanyId,\n name: String,\n budget: BigDecimal?,\n c: Connection\n ): DepartmentRow = (DepartmentRepoImpl()).insert(DepartmentRow(id = id, companyId = companyId, name = name, budget = budget), c)\n\n fun showcaseEmployee(\n id: EmployeeId,\n departmentId: DepartmentId,\n email: String,\n firstName: String,\n lastName: String,\n managerId: EmployeeId?,\n salary: BigDecimal?,\n hiredAt: LocalDate?,\n skills: Array?,\n certifications: Array?,\n metadata: Jsonb?,\n settings: Map?,\n workSchedule: Array?,\n ipAddress: Inet?,\n networkCidr: Cidr?,\n macAddress: MacAddr?,\n probationPeriod: PGInterval?,\n photo: ByteArray?,\n active: Defaulted,\n createdAt: Defaulted,\n c: Connection\n ): EmployeeRow = (EmployeeRepoImpl()).insert(EmployeeRowUnsaved(id = id, departmentId = departmentId, managerId = managerId, email = email, firstName = firstName, lastName = lastName, salary = salary, hiredAt = hiredAt, skills = skills, certifications = certifications, metadata = metadata, settings = settings, workSchedule = workSchedule, ipAddress = ipAddress, networkCidr = networkCidr, macAddress = macAddress, probationPeriod = probationPeriod, photo = photo, active = active, createdAt = createdAt), c)\n\n fun showcaseOrderItem(\n orderId: CustomerOrderId,\n productId: ProductId,\n quantity: Int,\n unitPrice: BigDecimal,\n discount: Defaulted,\n c: Connection\n ): OrderItemRow = (OrderItemRepoImpl()).insert(OrderItemRowUnsaved(orderId = orderId, productId = productId, quantity = quantity, unitPrice = unitPrice, discount = discount), c)\n\n fun showcaseProduct(\n id: ProductId,\n name: String,\n sku: String,\n categoryId: CategoryId?,\n price: BigDecimal,\n cost: BigDecimal?,\n weight: BigDecimal?,\n tags: Array?,\n images: Array?,\n relatedSkus: Array?,\n priceHistory: Array?,\n attributes: Jsonb?,\n specifications: Jsonb?,\n seoMetadata: Jsonb?,\n searchVector: String?,\n productUid: UUID?,\n inStock: Defaulted,\n quantity: Defaulted,\n createdAt: Defaulted,\n c: Connection\n ): ProductRow = (ProductRepoImpl()).insert(ProductRowUnsaved(id = id, categoryId = categoryId, name = name, sku = sku, price = price, cost = cost, weight = weight, tags = tags, images = images, relatedSkus = relatedSkus, priceHistory = priceHistory, attributes = attributes, specifications = specifications, seoMetadata = seoMetadata, searchVector = searchVector, productUid = productUid, inStock = inStock, quantity = quantity, createdAt = createdAt), c)\n\n fun showcaseProject(\n id: ProjectId,\n name: String,\n description: /* max 1000 chars */ String?,\n startDate: LocalDate?,\n endDate: LocalDate?,\n budget: BigDecimal?,\n projectUid: UUID?,\n milestones: Array?,\n budgetSnapshots: Array?,\n teamMembers: Array?,\n metadata: Jsonb?,\n config: Map?,\n estimatedDuration: PGInterval?,\n actualDuration: PGInterval?,\n status: Defaulted,\n createdAt: Defaulted,\n c: Connection\n ): ProjectRow = (ProjectRepoImpl()).insert(ProjectRowUnsaved(id = id, name = name, description = description, startDate = startDate, endDate = endDate, budget = budget, projectUid = projectUid, milestones = milestones, budgetSnapshots = budgetSnapshots, teamMembers = teamMembers, metadata = metadata, config = config, estimatedDuration = estimatedDuration, actualDuration = actualDuration, status = status, createdAt = createdAt), c)\n\n fun showcaseProjectAssignment(\n employeeId: EmployeeId,\n projectId: ProjectId,\n role: String,\n startDate: LocalDate?,\n endDate: LocalDate?,\n hoursAllocated: Defaulted,\n c: Connection\n ): ProjectAssignmentRow = (ProjectAssignmentRepoImpl()).insert(ProjectAssignmentRowUnsaved(employeeId = employeeId, projectId = projectId, role = role, startDate = startDate, endDate = endDate, hoursAllocated = hoursAllocated), c)\n}" - }, - "scala": { - "CompanyRow": "package showcase.showcase.company\n\nimport dev.typr.foundations.PgText\nimport dev.typr.foundations.PgTypes\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport java.time.LocalDateTime\nimport showcase.customtypes.Defaulted\n\n/** Table: showcase.company\n * Primary key: id\n */\ncase class CompanyRow(\n id: CompanyId,\n name: String,\n foundedYear: Option[Int],\n /** Default: true */\n active: Option[Boolean],\n /** Default: CURRENT_TIMESTAMP */\n createdAt: Option[LocalDateTime]\n) {\n def toUnsavedRow(\n active: Defaulted[Option[Boolean]] = Defaulted.Provided(this.active),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.Provided(this.createdAt)\n ): CompanyRowUnsaved = {\n new CompanyRowUnsaved(\n id,\n name,\n foundedYear,\n active,\n createdAt\n )\n }\n}\n\nobject CompanyRow {\n val `_rowParser`: RowParser[CompanyRow] = RowParsers.of(CompanyId.pgType, PgTypes.text, ScalaDbTypes.PgTypes.int4.nullable, ScalaDbTypes.PgTypes.bool.nullable, PgTypes.timestamp.nullable)(CompanyRow.apply)(row => Array[Any](row.id, row.name, row.foundedYear, row.active, row.createdAt))\n\n given pgText: PgText[CompanyRow] = PgText.from(`_rowParser`.underlying)\n}", - "CompanyRowUnsaved": "package showcase.showcase.company\n\nimport dev.typr.foundations.PgText\nimport dev.typr.foundations.PgTypes\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport java.time.LocalDateTime\nimport showcase.customtypes.Defaulted\nimport showcase.customtypes.Defaulted.UseDefault\n\n/** This class corresponds to a row in table `showcase.company` which has not been persisted yet */\ncase class CompanyRowUnsaved(\n id: CompanyId,\n name: String,\n foundedYear: Option[Int] = None,\n /** Default: true */\n active: Defaulted[Option[Boolean]] = new UseDefault(),\n /** Default: CURRENT_TIMESTAMP */\n createdAt: Defaulted[Option[LocalDateTime]] = new UseDefault()\n) {\n def toRow(\n activeDefault: => Option[Boolean],\n createdAtDefault: => Option[LocalDateTime]\n ): CompanyRow = {\n new CompanyRow(\n id = id,\n name = name,\n foundedYear = foundedYear,\n active = active.getOrElse(activeDefault),\n createdAt = createdAt.getOrElse(createdAtDefault)\n )\n }\n}\n\nobject CompanyRowUnsaved {\n given pgText: PgText[CompanyRowUnsaved] = PgText.instance((row, sb) => { CompanyId.pgType.text.unsafeEncode(row.id, sb); sb.append(PgText.DELIMETER); PgTypes.text.text.unsafeEncode(row.name, sb); sb.append(PgText.DELIMETER); ScalaDbTypes.PgTypes.int4.nullable.text.unsafeEncode(row.foundedYear, sb); sb.append(PgText.DELIMETER); Defaulted.pgText(using ScalaDbTypes.PgTypes.bool.nullable.text).unsafeEncode(row.active, sb); sb.append(PgText.DELIMETER); Defaulted.pgText(using PgTypes.timestamp.nullable.text).unsafeEncode(row.createdAt, sb) })\n}", - "CompanyId": "package showcase.showcase.company\n\nimport dev.typr.foundations.PgType\nimport dev.typr.foundations.PgTypes\nimport dev.typr.foundations.scala.Bijection\n\n/** Type for the primary key of table `showcase.company` */\ncase class CompanyId(value: String) extends scala.AnyVal\n\nobject CompanyId {\n given bijection: Bijection[CompanyId, String] = Bijection.apply[CompanyId, String](_.value)(CompanyId.apply)\n\n given pgType: PgType[CompanyId] = PgTypes.text.bimap(CompanyId.apply, _.value)\n\n given pgTypeArray: PgType[Array[CompanyId]] = PgTypes.textArray.bimap(xs => xs.map(CompanyId.apply), xs => xs.map(_.value))\n}", - "CompanyRepo": "package showcase.showcase.company\n\nimport dev.typr.foundations.scala.DeleteBuilder\nimport dev.typr.foundations.scala.SelectBuilder\nimport dev.typr.foundations.scala.UpdateBuilder\nimport java.sql.Connection\n\ntrait CompanyRepo {\n def delete: DeleteBuilder[CompanyFields, CompanyRow]\n\n def deleteById(id: CompanyId)(using c: Connection): Boolean\n\n def deleteByIds(ids: Array[CompanyId])(using c: Connection): Int\n\n def insert(unsaved: CompanyRow)(using c: Connection): CompanyRow\n\n def insert(unsaved: CompanyRowUnsaved)(using c: Connection): CompanyRow\n\n def insertStreaming(\n unsaved: Iterator[CompanyRow],\n batchSize: Int = 10000\n )(using c: Connection): Long\n\n /** NOTE: this functionality requires PostgreSQL 16 or later! */\n def insertUnsavedStreaming(\n unsaved: Iterator[CompanyRowUnsaved],\n batchSize: Int = 10000\n )(using c: Connection): Long\n\n def select: SelectBuilder[CompanyFields, CompanyRow]\n\n def selectAll(using c: Connection): List[CompanyRow]\n\n def selectById(id: CompanyId)(using c: Connection): Option[CompanyRow]\n\n def selectByIds(ids: Array[CompanyId])(using c: Connection): List[CompanyRow]\n\n def selectByIdsTracked(ids: Array[CompanyId])(using c: Connection): Map[CompanyId, CompanyRow]\n\n def update: UpdateBuilder[CompanyFields, CompanyRow]\n\n def update(row: CompanyRow)(using c: Connection): Boolean\n\n def upsert(unsaved: CompanyRow)(using c: Connection): CompanyRow\n\n def upsertBatch(unsaved: Iterator[CompanyRow])(using c: Connection): List[CompanyRow]\n\n /** NOTE: this functionality is not safe if you use auto-commit mode! it runs 3 SQL statements */\n def upsertStreaming(\n unsaved: Iterator[CompanyRow],\n batchSize: Int = 10000\n )(using c: Connection): Int\n}", - "CompanyRepoMock": "package showcase.showcase.company\n\nimport dev.typr.foundations.scala.DeleteBuilder\nimport dev.typr.foundations.scala.DeleteBuilderMock\nimport dev.typr.foundations.scala.DeleteParams\nimport dev.typr.foundations.scala.SelectBuilder\nimport dev.typr.foundations.scala.SelectBuilderMock\nimport dev.typr.foundations.scala.SelectParams\nimport dev.typr.foundations.scala.UpdateBuilder\nimport dev.typr.foundations.scala.UpdateBuilderMock\nimport dev.typr.foundations.scala.UpdateParams\nimport java.lang.RuntimeException\nimport java.sql.Connection\n\ncase class CompanyRepoMock(\n toRow: CompanyRowUnsaved => CompanyRow,\n map: scala.collection.mutable.Map[CompanyId, CompanyRow] = scala.collection.mutable.Map.empty[CompanyId, CompanyRow]\n) extends CompanyRepo {\n override def delete: DeleteBuilder[CompanyFields, CompanyRow] = DeleteBuilderMock(CompanyFields.structure, () => map.values.toList, DeleteParams.empty(), row => row.id, id => map.remove(id): @scala.annotation.nowarn)\n\n override def deleteById(id: CompanyId)(using c: Connection): Boolean = map.remove(id).isDefined\n\n override def deleteByIds(ids: Array[CompanyId])(using c: Connection): Int = {\n var count = 0\n ids.foreach { id => if (map.remove(id).isDefined) {\n count = count + 1\n } }\n return count\n }\n\n override def insert(unsaved: CompanyRow)(using c: Connection): CompanyRow = {\n if (map.contains(unsaved.id)) {\n throw new RuntimeException(s\"id ${unsaved.id} already exists\")\n }\n map.put(unsaved.id, unsaved): @scala.annotation.nowarn\n return unsaved\n }\n\n override def insert(unsaved: CompanyRowUnsaved)(using c: Connection): CompanyRow = insert(toRow(unsaved))(using c)\n\n override def insertStreaming(\n unsaved: Iterator[CompanyRow],\n batchSize: Int = 10000\n )(using c: Connection): Long = {\n unsaved.map { row =>\n map.put(row.id, row): @scala.annotation.nowarn\n 1L\n }.sum\n }\n\n /** NOTE: this functionality requires PostgreSQL 16 or later! */\n override def insertUnsavedStreaming(\n unsaved: Iterator[CompanyRowUnsaved],\n batchSize: Int = 10000\n )(using c: Connection): Long = {\n unsaved.map { unsavedRow =>\n val row = toRow(unsavedRow)\n map.put(row.id, row): @scala.annotation.nowarn\n 1L\n }.sum\n }\n\n override def select: SelectBuilder[CompanyFields, CompanyRow] = SelectBuilderMock(CompanyFields.structure, () => map.values.toList, SelectParams.empty())\n\n override def selectAll(using c: Connection): List[CompanyRow] = map.values.toList\n\n override def selectById(id: CompanyId)(using c: Connection): Option[CompanyRow] = map.get(id)\n\n override def selectByIds(ids: Array[CompanyId])(using c: Connection): List[CompanyRow] = ids.flatMap(map.get(_)).toList\n\n override def selectByIdsTracked(ids: Array[CompanyId])(using c: Connection): Map[CompanyId, CompanyRow] = selectByIds(ids)(using c).map(x => (((row: CompanyRow) => row.id).apply(x), x)).toMap\n\n override def update: UpdateBuilder[CompanyFields, CompanyRow] = UpdateBuilderMock(CompanyFields.structure, () => map.values.toList, UpdateParams.empty(), row => row)\n\n override def update(row: CompanyRow)(using c: Connection): Boolean = {\n val shouldUpdate = map.get(row.id).filter(oldRow => (oldRow != row)).isDefined\n if (shouldUpdate) {\n map.put(row.id, row): @scala.annotation.nowarn\n }\n return shouldUpdate\n }\n\n override def upsert(unsaved: CompanyRow)(using c: Connection): CompanyRow = {\n map.put(unsaved.id, unsaved): @scala.annotation.nowarn\n return unsaved\n }\n\n override def upsertBatch(unsaved: Iterator[CompanyRow])(using c: Connection): List[CompanyRow] = {\n unsaved.map { row =>\n map.put(row.id, row): @scala.annotation.nowarn\n row\n }.toList\n }\n\n /** NOTE: this functionality is not safe if you use auto-commit mode! it runs 3 SQL statements */\n override def upsertStreaming(\n unsaved: Iterator[CompanyRow],\n batchSize: Int = 10000\n )(using c: Connection): Int = {\n unsaved.map { row =>\n map.put(row.id, row): @scala.annotation.nowarn\n 1\n }.sum\n }\n}", - "EmployeeRow": "package showcase.showcase.employee\n\nimport dev.typr.foundations.PgText\nimport dev.typr.foundations.PgTypes\nimport dev.typr.foundations.data.Cidr\nimport dev.typr.foundations.data.Inet\nimport dev.typr.foundations.data.Jsonb\nimport dev.typr.foundations.data.MacAddr\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport java.time.LocalDate\nimport java.time.LocalDateTime\nimport org.postgresql.util.PGInterval\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.department.DepartmentId\n\n/** Table: showcase.employee\n * Primary key: id\n */\ncase class EmployeeRow(\n id: EmployeeId,\n /** Points to [[showcase.showcase.department.DepartmentRow.id]] */\n departmentId: DepartmentId,\n /** Points to [[showcase.showcase.employee.EmployeeRow.id]] */\n managerId: Option[EmployeeId],\n email: String,\n firstName: String,\n lastName: String,\n salary: Option[BigDecimal],\n hiredAt: Option[LocalDate],\n /** Default: true */\n active: Option[Boolean],\n /** Default: CURRENT_TIMESTAMP */\n createdAt: Option[LocalDateTime],\n skills: Option[Array[String]],\n certifications: Option[Array[String]],\n metadata: Option[Jsonb],\n settings: Option[Map[String, String]],\n workSchedule: Option[Array[Boolean]],\n ipAddress: Option[Inet],\n networkCidr: Option[Cidr],\n macAddress: Option[MacAddr],\n probationPeriod: Option[PGInterval],\n photo: Option[Array[Byte]]\n) {\n def toUnsavedRow(\n active: Defaulted[Option[Boolean]] = Defaulted.Provided(this.active),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.Provided(this.createdAt)\n ): EmployeeRowUnsaved = {\n new EmployeeRowUnsaved(\n id,\n departmentId,\n managerId,\n email,\n firstName,\n lastName,\n salary,\n hiredAt,\n skills,\n certifications,\n metadata,\n settings,\n workSchedule,\n ipAddress,\n networkCidr,\n macAddress,\n probationPeriod,\n photo,\n active,\n createdAt\n )\n }\n}\n\nobject EmployeeRow {\n val `_rowParser`: RowParser[EmployeeRow] = RowParsers.of(EmployeeId.pgType, DepartmentId.pgType, EmployeeId.pgType.nullable, PgTypes.text, PgTypes.text, PgTypes.text, ScalaDbTypes.PgTypes.numeric.nullable, PgTypes.date.nullable, ScalaDbTypes.PgTypes.bool.nullable, PgTypes.timestamp.nullable, PgTypes.textArray.nullable, PgTypes.textArray.nullable, PgTypes.jsonb.nullable, ScalaDbTypes.PgTypes.hstore.nullable, PgTypes.boolArrayUnboxed.nullable, PgTypes.inet.nullable, PgTypes.cidr.nullable, PgTypes.macaddr.nullable, PgTypes.interval.nullable, PgTypes.bytea.nullable)(EmployeeRow.apply)(row => Array[Any](row.id, row.departmentId, row.managerId, row.email, row.firstName, row.lastName, row.salary, row.hiredAt, row.active, row.createdAt, row.skills, row.certifications, row.metadata, row.settings, row.workSchedule, row.ipAddress, row.networkCidr, row.macAddress, row.probationPeriod, row.photo))\n\n given pgText: PgText[EmployeeRow] = PgText.from(`_rowParser`.underlying)\n}", - "EmployeeRowUnsaved": "package showcase.showcase.employee\n\nimport dev.typr.foundations.PgText\nimport dev.typr.foundations.PgTypes\nimport dev.typr.foundations.data.Cidr\nimport dev.typr.foundations.data.Inet\nimport dev.typr.foundations.data.Jsonb\nimport dev.typr.foundations.data.MacAddr\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport java.time.LocalDate\nimport java.time.LocalDateTime\nimport org.postgresql.util.PGInterval\nimport showcase.customtypes.Defaulted\nimport showcase.customtypes.Defaulted.UseDefault\nimport showcase.showcase.department.DepartmentId\n\n/** This class corresponds to a row in table `showcase.employee` which has not been persisted yet */\ncase class EmployeeRowUnsaved(\n id: EmployeeId,\n /** Points to [[showcase.showcase.department.DepartmentRow.id]] */\n departmentId: DepartmentId,\n /** Points to [[showcase.showcase.employee.EmployeeRow.id]] */\n managerId: Option[EmployeeId] = None,\n email: String,\n firstName: String,\n lastName: String,\n salary: Option[BigDecimal] = None,\n hiredAt: Option[LocalDate] = None,\n skills: Option[Array[String]] = None,\n certifications: Option[Array[String]] = None,\n metadata: Option[Jsonb] = None,\n settings: Option[Map[String, String]] = None,\n workSchedule: Option[Array[Boolean]] = None,\n ipAddress: Option[Inet] = None,\n networkCidr: Option[Cidr] = None,\n macAddress: Option[MacAddr] = None,\n probationPeriod: Option[PGInterval] = None,\n photo: Option[Array[Byte]] = None,\n /** Default: true */\n active: Defaulted[Option[Boolean]] = new UseDefault(),\n /** Default: CURRENT_TIMESTAMP */\n createdAt: Defaulted[Option[LocalDateTime]] = new UseDefault()\n) {\n def toRow(\n activeDefault: => Option[Boolean],\n createdAtDefault: => Option[LocalDateTime]\n ): EmployeeRow = {\n new EmployeeRow(\n id = id,\n departmentId = departmentId,\n managerId = managerId,\n email = email,\n firstName = firstName,\n lastName = lastName,\n salary = salary,\n hiredAt = hiredAt,\n active = active.getOrElse(activeDefault),\n createdAt = createdAt.getOrElse(createdAtDefault),\n skills = skills,\n certifications = certifications,\n metadata = metadata,\n settings = settings,\n workSchedule = workSchedule,\n ipAddress = ipAddress,\n networkCidr = networkCidr,\n macAddress = macAddress,\n probationPeriod = probationPeriod,\n photo = photo\n )\n }\n}\n\nobject EmployeeRowUnsaved {\n given pgText: PgText[EmployeeRowUnsaved] = PgText.instance((row, sb) => { EmployeeId.pgType.text.unsafeEncode(row.id, sb); sb.append(PgText.DELIMETER); DepartmentId.pgType.text.unsafeEncode(row.departmentId, sb); sb.append(PgText.DELIMETER); EmployeeId.pgType.nullable.text.unsafeEncode(row.managerId, sb); sb.append(PgText.DELIMETER); PgTypes.text.text.unsafeEncode(row.email, sb); sb.append(PgText.DELIMETER); PgTypes.text.text.unsafeEncode(row.firstName, sb); sb.append(PgText.DELIMETER); PgTypes.text.text.unsafeEncode(row.lastName, sb); sb.append(PgText.DELIMETER); ScalaDbTypes.PgTypes.numeric.nullable.text.unsafeEncode(row.salary, sb); sb.append(PgText.DELIMETER); PgTypes.date.nullable.text.unsafeEncode(row.hiredAt, sb); sb.append(PgText.DELIMETER); PgTypes.textArray.nullable.text.unsafeEncode(row.skills, sb); sb.append(PgText.DELIMETER); PgTypes.textArray.nullable.text.unsafeEncode(row.certifications, sb); sb.append(PgText.DELIMETER); PgTypes.jsonb.nullable.text.unsafeEncode(row.metadata, sb); sb.append(PgText.DELIMETER); ScalaDbTypes.PgTypes.hstore.nullable.text.unsafeEncode(row.settings, sb); sb.append(PgText.DELIMETER); PgTypes.boolArrayUnboxed.nullable.text.unsafeEncode(row.workSchedule, sb); sb.append(PgText.DELIMETER); PgTypes.inet.nullable.text.unsafeEncode(row.ipAddress, sb); sb.append(PgText.DELIMETER); PgTypes.cidr.nullable.text.unsafeEncode(row.networkCidr, sb); sb.append(PgText.DELIMETER); PgTypes.macaddr.nullable.text.unsafeEncode(row.macAddress, sb); sb.append(PgText.DELIMETER); PgTypes.interval.nullable.text.unsafeEncode(row.probationPeriod, sb); sb.append(PgText.DELIMETER); PgTypes.bytea.nullable.text.unsafeEncode(row.photo, sb); sb.append(PgText.DELIMETER); Defaulted.pgText(using ScalaDbTypes.PgTypes.bool.nullable.text).unsafeEncode(row.active, sb); sb.append(PgText.DELIMETER); Defaulted.pgText(using PgTypes.timestamp.nullable.text).unsafeEncode(row.createdAt, sb) })\n}", - "EmployeeId": "package showcase.showcase.employee\n\nimport dev.typr.foundations.PgType\nimport dev.typr.foundations.PgTypes\nimport dev.typr.foundations.scala.Bijection\n\n/** Type for the primary key of table `showcase.employee` */\ncase class EmployeeId(value: String) extends scala.AnyVal\n\nobject EmployeeId {\n given bijection: Bijection[EmployeeId, String] = Bijection.apply[EmployeeId, String](_.value)(EmployeeId.apply)\n\n given pgType: PgType[EmployeeId] = PgTypes.text.bimap(EmployeeId.apply, _.value)\n\n given pgTypeArray: PgType[Array[EmployeeId]] = PgTypes.textArray.bimap(xs => xs.map(EmployeeId.apply), xs => xs.map(_.value))\n}", - "EmployeeRepo": "package showcase.showcase.employee\n\nimport dev.typr.foundations.scala.DeleteBuilder\nimport dev.typr.foundations.scala.SelectBuilder\nimport dev.typr.foundations.scala.UpdateBuilder\nimport java.sql.Connection\n\ntrait EmployeeRepo {\n def delete: DeleteBuilder[EmployeeFields, EmployeeRow]\n\n def deleteById(id: EmployeeId)(using c: Connection): Boolean\n\n def deleteByIds(ids: Array[EmployeeId])(using c: Connection): Int\n\n def insert(unsaved: EmployeeRow)(using c: Connection): EmployeeRow\n\n def insert(unsaved: EmployeeRowUnsaved)(using c: Connection): EmployeeRow\n\n def insertStreaming(\n unsaved: Iterator[EmployeeRow],\n batchSize: Int = 10000\n )(using c: Connection): Long\n\n /** NOTE: this functionality requires PostgreSQL 16 or later! */\n def insertUnsavedStreaming(\n unsaved: Iterator[EmployeeRowUnsaved],\n batchSize: Int = 10000\n )(using c: Connection): Long\n\n def select: SelectBuilder[EmployeeFields, EmployeeRow]\n\n def selectAll(using c: Connection): List[EmployeeRow]\n\n def selectById(id: EmployeeId)(using c: Connection): Option[EmployeeRow]\n\n def selectByIds(ids: Array[EmployeeId])(using c: Connection): List[EmployeeRow]\n\n def selectByIdsTracked(ids: Array[EmployeeId])(using c: Connection): Map[EmployeeId, EmployeeRow]\n\n def selectByUniqueEmail(email: String)(using c: Connection): Option[EmployeeRow]\n\n def update: UpdateBuilder[EmployeeFields, EmployeeRow]\n\n def update(row: EmployeeRow)(using c: Connection): Boolean\n\n def upsert(unsaved: EmployeeRow)(using c: Connection): EmployeeRow\n\n def upsertBatch(unsaved: Iterator[EmployeeRow])(using c: Connection): List[EmployeeRow]\n\n /** NOTE: this functionality is not safe if you use auto-commit mode! it runs 3 SQL statements */\n def upsertStreaming(\n unsaved: Iterator[EmployeeRow],\n batchSize: Int = 10000\n )(using c: Connection): Int\n}", - "EmployeeRepoImpl": "package showcase.showcase.employee\n\nimport dev.typr.foundations.PgTypes\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.DeleteBuilder\nimport dev.typr.foundations.scala.Dialect\nimport dev.typr.foundations.scala.Fragment\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport dev.typr.foundations.scala.ScalaIteratorOps\nimport dev.typr.foundations.scala.SelectBuilder\nimport dev.typr.foundations.scala.UpdateBuilder\nimport dev.typr.foundations.streamingInsert\nimport java.sql.Connection\nimport scala.collection.mutable.ListBuffer\nimport showcase.showcase.department.DepartmentId\nimport dev.typr.foundations.scala.Fragment.sql\n\nclass EmployeeRepoImpl extends EmployeeRepo {\n override def delete: DeleteBuilder[EmployeeFields, EmployeeRow] = DeleteBuilder.of(\"\"\"\"showcase\".\"employee\"\"\"\", EmployeeFields.structure, Dialect.POSTGRESQL)\n\n override def deleteById(id: EmployeeId)(using c: Connection): Boolean = sql\"\"\"delete from \"showcase\".\"employee\" where \"id\" = ${Fragment.encode(EmployeeId.pgType, id)}\"\"\".update().runUnchecked(c) > 0\n\n override def deleteByIds(ids: Array[EmployeeId])(using c: Connection): Int = {\n sql\"\"\"delete\n from \"showcase\".\"employee\"\n where \"id\" = ANY(${Fragment.encode(EmployeeId.pgTypeArray, ids)})\"\"\"\n .update()\n .runUnchecked(c)\n }\n\n override def insert(unsaved: EmployeeRow)(using c: Connection): EmployeeRow = {\n sql\"\"\"insert into \"showcase\".\"employee\"(\"id\", \"department_id\", \"manager_id\", \"email\", \"first_name\", \"last_name\", \"salary\", \"hired_at\", \"active\", \"created_at\", \"skills\", \"certifications\", \"metadata\", \"settings\", \"work_schedule\", \"ip_address\", \"network_cidr\", \"mac_address\", \"probation_period\", \"photo\")\n values (${Fragment.encode(EmployeeId.pgType, unsaved.id)}, ${Fragment.encode(DepartmentId.pgType, unsaved.departmentId)}, ${Fragment.encode(EmployeeId.pgType.nullable, unsaved.managerId)}, ${Fragment.encode(PgTypes.text, unsaved.email)}, ${Fragment.encode(PgTypes.text, unsaved.firstName)}, ${Fragment.encode(PgTypes.text, unsaved.lastName)}, ${Fragment.encode(ScalaDbTypes.PgTypes.numeric.nullable, unsaved.salary)}, ${Fragment.encode(PgTypes.date.nullable, unsaved.hiredAt)}, ${Fragment.encode(ScalaDbTypes.PgTypes.bool.nullable, unsaved.active)}, ${Fragment.encode(PgTypes.timestamp.nullable, unsaved.createdAt)}, ${Fragment.encode(PgTypes.textArray.nullable, unsaved.skills)}, ${Fragment.encode(PgTypes.textArray.nullable, unsaved.certifications)}, ${Fragment.encode(PgTypes.jsonb.nullable, unsaved.metadata)}, ${Fragment.encode(ScalaDbTypes.PgTypes.hstore.nullable, unsaved.settings)}, ${Fragment.encode(PgTypes.boolArrayUnboxed.nullable, unsaved.workSchedule)}, ${Fragment.encode(PgTypes.inet.nullable, unsaved.ipAddress)}, ${Fragment.encode(PgTypes.cidr.nullable, unsaved.networkCidr)}, ${Fragment.encode(PgTypes.macaddr.nullable, unsaved.macAddress)}, ${Fragment.encode(PgTypes.interval.nullable, unsaved.probationPeriod)}, ${Fragment.encode(PgTypes.bytea.nullable, unsaved.photo)})\n RETURNING \"id\", \"department_id\", \"manager_id\", \"email\", \"first_name\", \"last_name\", \"salary\", \"hired_at\", \"active\", \"created_at\", \"skills\", \"certifications\", \"metadata\", \"settings\", \"work_schedule\", \"ip_address\", \"network_cidr\", \"mac_address\", \"probation_period\", \"photo\"\n \"\"\"\n .updateReturning(EmployeeRow.`_rowParser`.exactlyOne()).runUnchecked(c)\n }\n\n override def insert(unsaved: EmployeeRowUnsaved)(using c: Connection): EmployeeRow = {\n val columns: ListBuffer[Fragment] = ListBuffer()\n val values: ListBuffer[Fragment] = ListBuffer()\n columns.addOne(Fragment.lit(\"\"\"\"id\"\"\"\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(EmployeeId.pgType, unsaved.id)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"\"\"\"department_id\"\"\"\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(DepartmentId.pgType, unsaved.departmentId)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"\"\"\"manager_id\"\"\"\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(EmployeeId.pgType.nullable, unsaved.managerId)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"\"\"\"email\"\"\"\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(PgTypes.text, unsaved.email)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"\"\"\"first_name\"\"\"\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(PgTypes.text, unsaved.firstName)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"\"\"\"last_name\"\"\"\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(PgTypes.text, unsaved.lastName)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"\"\"\"salary\"\"\"\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(ScalaDbTypes.PgTypes.numeric.nullable, unsaved.salary)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"\"\"\"hired_at\"\"\"\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(PgTypes.date.nullable, unsaved.hiredAt)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"\"\"\"skills\"\"\"\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(PgTypes.textArray.nullable, unsaved.skills)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"\"\"\"certifications\"\"\"\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(PgTypes.textArray.nullable, unsaved.certifications)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"\"\"\"metadata\"\"\"\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(PgTypes.jsonb.nullable, unsaved.metadata)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"\"\"\"settings\"\"\"\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(ScalaDbTypes.PgTypes.hstore.nullable, unsaved.settings)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"\"\"\"work_schedule\"\"\"\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(PgTypes.boolArrayUnboxed.nullable, unsaved.workSchedule)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"\"\"\"ip_address\"\"\"\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(PgTypes.inet.nullable, unsaved.ipAddress)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"\"\"\"network_cidr\"\"\"\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(PgTypes.cidr.nullable, unsaved.networkCidr)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"\"\"\"mac_address\"\"\"\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(PgTypes.macaddr.nullable, unsaved.macAddress)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"\"\"\"probation_period\"\"\"\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(PgTypes.interval.nullable, unsaved.probationPeriod)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"\"\"\"photo\"\"\"\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(PgTypes.bytea.nullable, unsaved.photo)}\"): @scala.annotation.nowarn\n unsaved.active.visit(\n { },\n value => { columns.addOne(Fragment.lit(\"\"\"\"active\"\"\"\")): @scala.annotation.nowarn; values.addOne(sql\"${Fragment.encode(ScalaDbTypes.PgTypes.bool.nullable, value)}\"): @scala.annotation.nowarn }\n );\n unsaved.createdAt.visit(\n { },\n value => { columns.addOne(Fragment.lit(\"\"\"\"created_at\"\"\"\")): @scala.annotation.nowarn; values.addOne(sql\"${Fragment.encode(PgTypes.timestamp.nullable, value)}\"): @scala.annotation.nowarn }\n );\n val q: Fragment = {\n sql\"\"\"insert into \"showcase\".\"employee\"(${Fragment.comma(columns)})\n values (${Fragment.comma(values)})\n RETURNING \"id\", \"department_id\", \"manager_id\", \"email\", \"first_name\", \"last_name\", \"salary\", \"hired_at\", \"active\", \"created_at\", \"skills\", \"certifications\", \"metadata\", \"settings\", \"work_schedule\", \"ip_address\", \"network_cidr\", \"mac_address\", \"probation_period\", \"photo\"\n \"\"\"\n }\n return q.updateReturning(EmployeeRow.`_rowParser`.exactlyOne()).runUnchecked(c)\n }\n\n override def insertStreaming(\n unsaved: Iterator[EmployeeRow],\n batchSize: Int = 10000\n )(using c: Connection): Long = streamingInsert.insertUnchecked(s\"\"\"COPY \"showcase\".\"employee\"(\"id\", \"department_id\", \"manager_id\", \"email\", \"first_name\", \"last_name\", \"salary\", \"hired_at\", \"active\", \"created_at\", \"skills\", \"certifications\", \"metadata\", \"settings\", \"work_schedule\", \"ip_address\", \"network_cidr\", \"mac_address\", \"probation_period\", \"photo\") FROM STDIN\"\"\", batchSize, unsaved.toJavaIterator, c, EmployeeRow.pgText)\n\n /** NOTE: this functionality requires PostgreSQL 16 or later! */\n override def insertUnsavedStreaming(\n unsaved: Iterator[EmployeeRowUnsaved],\n batchSize: Int = 10000\n )(using c: Connection): Long = streamingInsert.insertUnchecked(s\"\"\"COPY \"showcase\".\"employee\"(\"id\", \"department_id\", \"manager_id\", \"email\", \"first_name\", \"last_name\", \"salary\", \"hired_at\", \"skills\", \"certifications\", \"metadata\", \"settings\", \"work_schedule\", \"ip_address\", \"network_cidr\", \"mac_address\", \"probation_period\", \"photo\", \"active\", \"created_at\") FROM STDIN (DEFAULT '__DEFAULT_VALUE__')\"\"\", batchSize, unsaved.toJavaIterator, c, EmployeeRowUnsaved.pgText)\n\n override def select: SelectBuilder[EmployeeFields, EmployeeRow] = SelectBuilder.of(\"\"\"\"showcase\".\"employee\"\"\"\", EmployeeFields.structure, EmployeeRow.`_rowParser`, Dialect.POSTGRESQL)\n\n override def selectAll(using c: Connection): List[EmployeeRow] = {\n sql\"\"\"select \"id\", \"department_id\", \"manager_id\", \"email\", \"first_name\", \"last_name\", \"salary\", \"hired_at\", \"active\", \"created_at\", \"skills\", \"certifications\", \"metadata\", \"settings\", \"work_schedule\", \"ip_address\", \"network_cidr\", \"mac_address\", \"probation_period\", \"photo\"\n from \"showcase\".\"employee\"\n \"\"\".query(EmployeeRow.`_rowParser`.all()).runUnchecked(c)\n }\n\n override def selectById(id: EmployeeId)(using c: Connection): Option[EmployeeRow] = {\n sql\"\"\"select \"id\", \"department_id\", \"manager_id\", \"email\", \"first_name\", \"last_name\", \"salary\", \"hired_at\", \"active\", \"created_at\", \"skills\", \"certifications\", \"metadata\", \"settings\", \"work_schedule\", \"ip_address\", \"network_cidr\", \"mac_address\", \"probation_period\", \"photo\"\n from \"showcase\".\"employee\"\n where \"id\" = ${Fragment.encode(EmployeeId.pgType, id)}\"\"\".query(EmployeeRow.`_rowParser`.first()).runUnchecked(c)\n }\n\n override def selectByIds(ids: Array[EmployeeId])(using c: Connection): List[EmployeeRow] = {\n sql\"\"\"select \"id\", \"department_id\", \"manager_id\", \"email\", \"first_name\", \"last_name\", \"salary\", \"hired_at\", \"active\", \"created_at\", \"skills\", \"certifications\", \"metadata\", \"settings\", \"work_schedule\", \"ip_address\", \"network_cidr\", \"mac_address\", \"probation_period\", \"photo\"\n from \"showcase\".\"employee\"\n where \"id\" = ANY(${Fragment.encode(EmployeeId.pgTypeArray, ids)})\"\"\".query(EmployeeRow.`_rowParser`.all()).runUnchecked(c)\n }\n\n override def selectByIdsTracked(ids: Array[EmployeeId])(using c: Connection): Map[EmployeeId, EmployeeRow] = {\n val ret: scala.collection.mutable.Map[EmployeeId, EmployeeRow] = scala.collection.mutable.Map.empty[EmployeeId, EmployeeRow]\n selectByIds(ids)(using c).foreach(row => ret.put(row.id, row): @scala.annotation.nowarn)\n return ret.toMap\n }\n\n override def selectByUniqueEmail(email: String)(using c: Connection): Option[EmployeeRow] = {\n sql\"\"\"select \"id\", \"department_id\", \"manager_id\", \"email\", \"first_name\", \"last_name\", \"salary\", \"hired_at\", \"active\", \"created_at\", \"skills\", \"certifications\", \"metadata\", \"settings\", \"work_schedule\", \"ip_address\", \"network_cidr\", \"mac_address\", \"probation_period\", \"photo\"\n from \"showcase\".\"employee\"\n where \"email\" = ${Fragment.encode(PgTypes.text, email)}\n \"\"\".query(EmployeeRow.`_rowParser`.first()).runUnchecked(c)\n }\n\n override def update: UpdateBuilder[EmployeeFields, EmployeeRow] = UpdateBuilder.of(\"\"\"\"showcase\".\"employee\"\"\"\", EmployeeFields.structure, EmployeeRow.`_rowParser`, Dialect.POSTGRESQL)\n\n override def update(row: EmployeeRow)(using c: Connection): Boolean = {\n val id: EmployeeId = row.id\n return sql\"\"\"update \"showcase\".\"employee\"\n set \"department_id\" = ${Fragment.encode(DepartmentId.pgType, row.departmentId)},\n \"manager_id\" = ${Fragment.encode(EmployeeId.pgType.nullable, row.managerId)},\n \"email\" = ${Fragment.encode(PgTypes.text, row.email)},\n \"first_name\" = ${Fragment.encode(PgTypes.text, row.firstName)},\n \"last_name\" = ${Fragment.encode(PgTypes.text, row.lastName)},\n \"salary\" = ${Fragment.encode(ScalaDbTypes.PgTypes.numeric.nullable, row.salary)},\n \"hired_at\" = ${Fragment.encode(PgTypes.date.nullable, row.hiredAt)},\n \"active\" = ${Fragment.encode(ScalaDbTypes.PgTypes.bool.nullable, row.active)},\n \"created_at\" = ${Fragment.encode(PgTypes.timestamp.nullable, row.createdAt)},\n \"skills\" = ${Fragment.encode(PgTypes.textArray.nullable, row.skills)},\n \"certifications\" = ${Fragment.encode(PgTypes.textArray.nullable, row.certifications)},\n \"metadata\" = ${Fragment.encode(PgTypes.jsonb.nullable, row.metadata)},\n \"settings\" = ${Fragment.encode(ScalaDbTypes.PgTypes.hstore.nullable, row.settings)},\n \"work_schedule\" = ${Fragment.encode(PgTypes.boolArrayUnboxed.nullable, row.workSchedule)},\n \"ip_address\" = ${Fragment.encode(PgTypes.inet.nullable, row.ipAddress)},\n \"network_cidr\" = ${Fragment.encode(PgTypes.cidr.nullable, row.networkCidr)},\n \"mac_address\" = ${Fragment.encode(PgTypes.macaddr.nullable, row.macAddress)},\n \"probation_period\" = ${Fragment.encode(PgTypes.interval.nullable, row.probationPeriod)},\n \"photo\" = ${Fragment.encode(PgTypes.bytea.nullable, row.photo)}\n where \"id\" = ${Fragment.encode(EmployeeId.pgType, id)}\"\"\".update().runUnchecked(c) > 0\n }\n\n override def upsert(unsaved: EmployeeRow)(using c: Connection): EmployeeRow = {\n sql\"\"\"insert into \"showcase\".\"employee\"(\"id\", \"department_id\", \"manager_id\", \"email\", \"first_name\", \"last_name\", \"salary\", \"hired_at\", \"active\", \"created_at\", \"skills\", \"certifications\", \"metadata\", \"settings\", \"work_schedule\", \"ip_address\", \"network_cidr\", \"mac_address\", \"probation_period\", \"photo\")\n values (${Fragment.encode(EmployeeId.pgType, unsaved.id)}, ${Fragment.encode(DepartmentId.pgType, unsaved.departmentId)}, ${Fragment.encode(EmployeeId.pgType.nullable, unsaved.managerId)}, ${Fragment.encode(PgTypes.text, unsaved.email)}, ${Fragment.encode(PgTypes.text, unsaved.firstName)}, ${Fragment.encode(PgTypes.text, unsaved.lastName)}, ${Fragment.encode(ScalaDbTypes.PgTypes.numeric.nullable, unsaved.salary)}, ${Fragment.encode(PgTypes.date.nullable, unsaved.hiredAt)}, ${Fragment.encode(ScalaDbTypes.PgTypes.bool.nullable, unsaved.active)}, ${Fragment.encode(PgTypes.timestamp.nullable, unsaved.createdAt)}, ${Fragment.encode(PgTypes.textArray.nullable, unsaved.skills)}, ${Fragment.encode(PgTypes.textArray.nullable, unsaved.certifications)}, ${Fragment.encode(PgTypes.jsonb.nullable, unsaved.metadata)}, ${Fragment.encode(ScalaDbTypes.PgTypes.hstore.nullable, unsaved.settings)}, ${Fragment.encode(PgTypes.boolArrayUnboxed.nullable, unsaved.workSchedule)}, ${Fragment.encode(PgTypes.inet.nullable, unsaved.ipAddress)}, ${Fragment.encode(PgTypes.cidr.nullable, unsaved.networkCidr)}, ${Fragment.encode(PgTypes.macaddr.nullable, unsaved.macAddress)}, ${Fragment.encode(PgTypes.interval.nullable, unsaved.probationPeriod)}, ${Fragment.encode(PgTypes.bytea.nullable, unsaved.photo)})\n on conflict (\"id\")\n do update set\n \"department_id\" = EXCLUDED.\"department_id\",\n \"manager_id\" = EXCLUDED.\"manager_id\",\n \"email\" = EXCLUDED.\"email\",\n \"first_name\" = EXCLUDED.\"first_name\",\n \"last_name\" = EXCLUDED.\"last_name\",\n \"salary\" = EXCLUDED.\"salary\",\n \"hired_at\" = EXCLUDED.\"hired_at\",\n \"active\" = EXCLUDED.\"active\",\n \"created_at\" = EXCLUDED.\"created_at\",\n \"skills\" = EXCLUDED.\"skills\",\n \"certifications\" = EXCLUDED.\"certifications\",\n \"metadata\" = EXCLUDED.\"metadata\",\n \"settings\" = EXCLUDED.\"settings\",\n \"work_schedule\" = EXCLUDED.\"work_schedule\",\n \"ip_address\" = EXCLUDED.\"ip_address\",\n \"network_cidr\" = EXCLUDED.\"network_cidr\",\n \"mac_address\" = EXCLUDED.\"mac_address\",\n \"probation_period\" = EXCLUDED.\"probation_period\",\n \"photo\" = EXCLUDED.\"photo\"\n returning \"id\", \"department_id\", \"manager_id\", \"email\", \"first_name\", \"last_name\", \"salary\", \"hired_at\", \"active\", \"created_at\", \"skills\", \"certifications\", \"metadata\", \"settings\", \"work_schedule\", \"ip_address\", \"network_cidr\", \"mac_address\", \"probation_period\", \"photo\"\"\"\"\n .updateReturning(EmployeeRow.`_rowParser`.exactlyOne())\n .runUnchecked(c)\n }\n\n override def upsertBatch(unsaved: Iterator[EmployeeRow])(using c: Connection): List[EmployeeRow] = {\n sql\"\"\"insert into \"showcase\".\"employee\"(\"id\", \"department_id\", \"manager_id\", \"email\", \"first_name\", \"last_name\", \"salary\", \"hired_at\", \"active\", \"created_at\", \"skills\", \"certifications\", \"metadata\", \"settings\", \"work_schedule\", \"ip_address\", \"network_cidr\", \"mac_address\", \"probation_period\", \"photo\")\n values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n on conflict (\"id\")\n do update set\n \"department_id\" = EXCLUDED.\"department_id\",\n \"manager_id\" = EXCLUDED.\"manager_id\",\n \"email\" = EXCLUDED.\"email\",\n \"first_name\" = EXCLUDED.\"first_name\",\n \"last_name\" = EXCLUDED.\"last_name\",\n \"salary\" = EXCLUDED.\"salary\",\n \"hired_at\" = EXCLUDED.\"hired_at\",\n \"active\" = EXCLUDED.\"active\",\n \"created_at\" = EXCLUDED.\"created_at\",\n \"skills\" = EXCLUDED.\"skills\",\n \"certifications\" = EXCLUDED.\"certifications\",\n \"metadata\" = EXCLUDED.\"metadata\",\n \"settings\" = EXCLUDED.\"settings\",\n \"work_schedule\" = EXCLUDED.\"work_schedule\",\n \"ip_address\" = EXCLUDED.\"ip_address\",\n \"network_cidr\" = EXCLUDED.\"network_cidr\",\n \"mac_address\" = EXCLUDED.\"mac_address\",\n \"probation_period\" = EXCLUDED.\"probation_period\",\n \"photo\" = EXCLUDED.\"photo\"\n returning \"id\", \"department_id\", \"manager_id\", \"email\", \"first_name\", \"last_name\", \"salary\", \"hired_at\", \"active\", \"created_at\", \"skills\", \"certifications\", \"metadata\", \"settings\", \"work_schedule\", \"ip_address\", \"network_cidr\", \"mac_address\", \"probation_period\", \"photo\"\"\"\"\n .updateManyReturning(EmployeeRow.`_rowParser`, unsaved)\n .runUnchecked(c)\n }\n\n /** NOTE: this functionality is not safe if you use auto-commit mode! it runs 3 SQL statements */\n override def upsertStreaming(\n unsaved: Iterator[EmployeeRow],\n batchSize: Int = 10000\n )(using c: Connection): Int = {\n sql\"\"\"create temporary table employee_TEMP (like \"showcase\".\"employee\") on commit drop\"\"\".update().runUnchecked(c): @scala.annotation.nowarn\n streamingInsert.insertUnchecked(s\"\"\"copy employee_TEMP(\"id\", \"department_id\", \"manager_id\", \"email\", \"first_name\", \"last_name\", \"salary\", \"hired_at\", \"active\", \"created_at\", \"skills\", \"certifications\", \"metadata\", \"settings\", \"work_schedule\", \"ip_address\", \"network_cidr\", \"mac_address\", \"probation_period\", \"photo\") from stdin\"\"\", batchSize, unsaved.toJavaIterator, c, EmployeeRow.pgText): @scala.annotation.nowarn\n return sql\"\"\"insert into \"showcase\".\"employee\"(\"id\", \"department_id\", \"manager_id\", \"email\", \"first_name\", \"last_name\", \"salary\", \"hired_at\", \"active\", \"created_at\", \"skills\", \"certifications\", \"metadata\", \"settings\", \"work_schedule\", \"ip_address\", \"network_cidr\", \"mac_address\", \"probation_period\", \"photo\")\n select * from employee_TEMP\n on conflict (\"id\")\n do update set\n \"department_id\" = EXCLUDED.\"department_id\",\n \"manager_id\" = EXCLUDED.\"manager_id\",\n \"email\" = EXCLUDED.\"email\",\n \"first_name\" = EXCLUDED.\"first_name\",\n \"last_name\" = EXCLUDED.\"last_name\",\n \"salary\" = EXCLUDED.\"salary\",\n \"hired_at\" = EXCLUDED.\"hired_at\",\n \"active\" = EXCLUDED.\"active\",\n \"created_at\" = EXCLUDED.\"created_at\",\n \"skills\" = EXCLUDED.\"skills\",\n \"certifications\" = EXCLUDED.\"certifications\",\n \"metadata\" = EXCLUDED.\"metadata\",\n \"settings\" = EXCLUDED.\"settings\",\n \"work_schedule\" = EXCLUDED.\"work_schedule\",\n \"ip_address\" = EXCLUDED.\"ip_address\",\n \"network_cidr\" = EXCLUDED.\"network_cidr\",\n \"mac_address\" = EXCLUDED.\"mac_address\",\n \"probation_period\" = EXCLUDED.\"probation_period\",\n \"photo\" = EXCLUDED.\"photo\"\n ;\n drop table employee_TEMP;\"\"\".update().runUnchecked(c)\n }\n}", - "EmployeeRepoMock": "package showcase.showcase.employee\n\nimport dev.typr.foundations.scala.DeleteBuilder\nimport dev.typr.foundations.scala.DeleteBuilderMock\nimport dev.typr.foundations.scala.DeleteParams\nimport dev.typr.foundations.scala.SelectBuilder\nimport dev.typr.foundations.scala.SelectBuilderMock\nimport dev.typr.foundations.scala.SelectParams\nimport dev.typr.foundations.scala.UpdateBuilder\nimport dev.typr.foundations.scala.UpdateBuilderMock\nimport dev.typr.foundations.scala.UpdateParams\nimport java.lang.RuntimeException\nimport java.sql.Connection\n\ncase class EmployeeRepoMock(\n toRow: EmployeeRowUnsaved => EmployeeRow,\n map: scala.collection.mutable.Map[EmployeeId, EmployeeRow] = scala.collection.mutable.Map.empty[EmployeeId, EmployeeRow]\n) extends EmployeeRepo {\n override def delete: DeleteBuilder[EmployeeFields, EmployeeRow] = DeleteBuilderMock(EmployeeFields.structure, () => map.values.toList, DeleteParams.empty(), row => row.id, id => map.remove(id): @scala.annotation.nowarn)\n\n override def deleteById(id: EmployeeId)(using c: Connection): Boolean = map.remove(id).isDefined\n\n override def deleteByIds(ids: Array[EmployeeId])(using c: Connection): Int = {\n var count = 0\n ids.foreach { id => if (map.remove(id).isDefined) {\n count = count + 1\n } }\n return count\n }\n\n override def insert(unsaved: EmployeeRow)(using c: Connection): EmployeeRow = {\n if (map.contains(unsaved.id)) {\n throw new RuntimeException(s\"id ${unsaved.id} already exists\")\n }\n map.put(unsaved.id, unsaved): @scala.annotation.nowarn\n return unsaved\n }\n\n override def insert(unsaved: EmployeeRowUnsaved)(using c: Connection): EmployeeRow = insert(toRow(unsaved))(using c)\n\n override def insertStreaming(\n unsaved: Iterator[EmployeeRow],\n batchSize: Int = 10000\n )(using c: Connection): Long = {\n unsaved.map { row =>\n map.put(row.id, row): @scala.annotation.nowarn\n 1L\n }.sum\n }\n\n /** NOTE: this functionality requires PostgreSQL 16 or later! */\n override def insertUnsavedStreaming(\n unsaved: Iterator[EmployeeRowUnsaved],\n batchSize: Int = 10000\n )(using c: Connection): Long = {\n unsaved.map { unsavedRow =>\n val row = toRow(unsavedRow)\n map.put(row.id, row): @scala.annotation.nowarn\n 1L\n }.sum\n }\n\n override def select: SelectBuilder[EmployeeFields, EmployeeRow] = SelectBuilderMock(EmployeeFields.structure, () => map.values.toList, SelectParams.empty())\n\n override def selectAll(using c: Connection): List[EmployeeRow] = map.values.toList\n\n override def selectById(id: EmployeeId)(using c: Connection): Option[EmployeeRow] = map.get(id)\n\n override def selectByIds(ids: Array[EmployeeId])(using c: Connection): List[EmployeeRow] = ids.flatMap(map.get(_)).toList\n\n override def selectByIdsTracked(ids: Array[EmployeeId])(using c: Connection): Map[EmployeeId, EmployeeRow] = selectByIds(ids)(using c).map(x => (((row: EmployeeRow) => row.id).apply(x), x)).toMap\n\n override def selectByUniqueEmail(email: String)(using c: Connection): Option[EmployeeRow] = map.values.toList.find(v => (email == v.email))\n\n override def update: UpdateBuilder[EmployeeFields, EmployeeRow] = UpdateBuilderMock(EmployeeFields.structure, () => map.values.toList, UpdateParams.empty(), row => row)\n\n override def update(row: EmployeeRow)(using c: Connection): Boolean = {\n val shouldUpdate = map.get(row.id).filter(oldRow => (oldRow != row)).isDefined\n if (shouldUpdate) {\n map.put(row.id, row): @scala.annotation.nowarn\n }\n return shouldUpdate\n }\n\n override def upsert(unsaved: EmployeeRow)(using c: Connection): EmployeeRow = {\n map.put(unsaved.id, unsaved): @scala.annotation.nowarn\n return unsaved\n }\n\n override def upsertBatch(unsaved: Iterator[EmployeeRow])(using c: Connection): List[EmployeeRow] = {\n unsaved.map { row =>\n map.put(row.id, row): @scala.annotation.nowarn\n row\n }.toList\n }\n\n /** NOTE: this functionality is not safe if you use auto-commit mode! it runs 3 SQL statements */\n override def upsertStreaming(\n unsaved: Iterator[EmployeeRow],\n batchSize: Int = 10000\n )(using c: Connection): Int = {\n unsaved.map { row =>\n map.put(row.id, row): @scala.annotation.nowarn\n 1\n }.sum\n }\n}", - "EmployeeFields": "package showcase.showcase.employee\n\nimport dev.typr.foundations.PgTypes\nimport dev.typr.foundations.RowParser\nimport dev.typr.foundations.data.Cidr\nimport dev.typr.foundations.data.Inet\nimport dev.typr.foundations.data.Jsonb\nimport dev.typr.foundations.data.MacAddr\nimport dev.typr.foundations.dsl.FieldsExpr0\nimport dev.typr.foundations.dsl.Path\nimport dev.typr.foundations.dsl.SqlExpr.FieldLike\nimport dev.typr.foundations.scala.ForeignKey\nimport dev.typr.foundations.scala.RelationStructure\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport dev.typr.foundations.scala.SqlExpr.Field\nimport dev.typr.foundations.scala.SqlExpr.IdField\nimport dev.typr.foundations.scala.SqlExpr.OptField\nimport java.time.LocalDate\nimport java.time.LocalDateTime\nimport org.postgresql.util.PGInterval\nimport showcase.showcase.department.DepartmentFields\nimport showcase.showcase.department.DepartmentId\nimport showcase.showcase.department.DepartmentRow\n\ntrait EmployeeFields extends FieldsExpr0[EmployeeRow] {\n def id: IdField[EmployeeId, EmployeeRow]\n\n def departmentId: Field[DepartmentId, EmployeeRow]\n\n def managerId: OptField[EmployeeId, EmployeeRow]\n\n def email: Field[String, EmployeeRow]\n\n def firstName: Field[String, EmployeeRow]\n\n def lastName: Field[String, EmployeeRow]\n\n def salary: OptField[BigDecimal, EmployeeRow]\n\n def hiredAt: OptField[LocalDate, EmployeeRow]\n\n def active: OptField[Boolean, EmployeeRow]\n\n def createdAt: OptField[LocalDateTime, EmployeeRow]\n\n def skills: OptField[Array[String], EmployeeRow]\n\n def certifications: OptField[Array[String], EmployeeRow]\n\n def metadata: OptField[Jsonb, EmployeeRow]\n\n def settings: OptField[Map[String, String], EmployeeRow]\n\n def workSchedule: OptField[Array[Boolean], EmployeeRow]\n\n def ipAddress: OptField[Inet, EmployeeRow]\n\n def networkCidr: OptField[Cidr, EmployeeRow]\n\n def macAddress: OptField[MacAddr, EmployeeRow]\n\n def probationPeriod: OptField[PGInterval, EmployeeRow]\n\n def photo: OptField[Array[Byte], EmployeeRow]\n\n def fkDepartment: ForeignKey[DepartmentFields, DepartmentRow] = ForeignKey.of[DepartmentFields, DepartmentRow](\"employee_department_fk\").withColumnPair[DepartmentId](departmentId, _.id)\n\n def fkEmployee: ForeignKey[EmployeeFields, EmployeeRow] = ForeignKey.of[EmployeeFields, EmployeeRow](\"employee_manager_fk\").withColumnPair[EmployeeId](managerId, _.id)\n\n override def columns: java.util.List[FieldLike[?, EmployeeRow]]\n\n override def rowParser: RowParser[EmployeeRow] = EmployeeRow._rowParser.underlying\n}\n\nobject EmployeeFields {\n case class Impl(val `_path`: java.util.List[Path]) extends EmployeeFields with RelationStructure[EmployeeFields, EmployeeRow] {\n\n override def id: IdField[EmployeeId, EmployeeRow] = {\n new IdField[EmployeeId, EmployeeRow](\n _path,\n \"id\",\n _.id,\n None,\n None,\n (row, value) => row.copy(id = value),\n EmployeeId.pgType\n )\n }\n\n override def departmentId: Field[DepartmentId, EmployeeRow] = {\n new Field[DepartmentId, EmployeeRow](\n _path,\n \"department_id\",\n _.departmentId,\n None,\n None,\n (row, value) => row.copy(departmentId = value),\n DepartmentId.pgType\n )\n }\n\n override def managerId: OptField[EmployeeId, EmployeeRow] = {\n new OptField[EmployeeId, EmployeeRow](\n _path,\n \"manager_id\",\n _.managerId,\n None,\n None,\n (row, value) => row.copy(managerId = value),\n EmployeeId.pgType\n )\n }\n\n override def email: Field[String, EmployeeRow] = {\n new Field[String, EmployeeRow](\n _path,\n \"email\",\n _.email,\n None,\n None,\n (row, value) => row.copy(email = value),\n PgTypes.text\n )\n }\n\n override def firstName: Field[String, EmployeeRow] = {\n new Field[String, EmployeeRow](\n _path,\n \"first_name\",\n _.firstName,\n None,\n None,\n (row, value) => row.copy(firstName = value),\n PgTypes.text\n )\n }\n\n override def lastName: Field[String, EmployeeRow] = {\n new Field[String, EmployeeRow](\n _path,\n \"last_name\",\n _.lastName,\n None,\n None,\n (row, value) => row.copy(lastName = value),\n PgTypes.text\n )\n }\n\n override def salary: OptField[BigDecimal, EmployeeRow] = {\n new OptField[BigDecimal, EmployeeRow](\n _path,\n \"salary\",\n _.salary,\n None,\n None,\n (row, value) => row.copy(salary = value),\n ScalaDbTypes.PgTypes.numeric\n )\n }\n\n override def hiredAt: OptField[LocalDate, EmployeeRow] = {\n new OptField[LocalDate, EmployeeRow](\n _path,\n \"hired_at\",\n _.hiredAt,\n None,\n None,\n (row, value) => row.copy(hiredAt = value),\n PgTypes.date\n )\n }\n\n override def active: OptField[Boolean, EmployeeRow] = {\n new OptField[Boolean, EmployeeRow](\n _path,\n \"active\",\n _.active,\n None,\n None,\n (row, value) => row.copy(active = value),\n ScalaDbTypes.PgTypes.bool\n )\n }\n\n override def createdAt: OptField[LocalDateTime, EmployeeRow] = {\n new OptField[LocalDateTime, EmployeeRow](\n _path,\n \"created_at\",\n _.createdAt,\n None,\n None,\n (row, value) => row.copy(createdAt = value),\n PgTypes.timestamp\n )\n }\n\n override def skills: OptField[Array[String], EmployeeRow] = {\n new OptField[Array[String], EmployeeRow](\n _path,\n \"skills\",\n _.skills,\n None,\n None,\n (row, value) => row.copy(skills = value),\n PgTypes.textArray\n )\n }\n\n override def certifications: OptField[Array[String], EmployeeRow] = {\n new OptField[Array[String], EmployeeRow](\n _path,\n \"certifications\",\n _.certifications,\n None,\n None,\n (row, value) => row.copy(certifications = value),\n PgTypes.textArray\n )\n }\n\n override def metadata: OptField[Jsonb, EmployeeRow] = {\n new OptField[Jsonb, EmployeeRow](\n _path,\n \"metadata\",\n _.metadata,\n None,\n None,\n (row, value) => row.copy(metadata = value),\n PgTypes.jsonb\n )\n }\n\n override def settings: OptField[Map[String, String], EmployeeRow] = {\n new OptField[Map[String, String], EmployeeRow](\n _path,\n \"settings\",\n _.settings,\n None,\n None,\n (row, value) => row.copy(settings = value),\n ScalaDbTypes.PgTypes.hstore\n )\n }\n\n override def workSchedule: OptField[Array[Boolean], EmployeeRow] = {\n new OptField[Array[Boolean], EmployeeRow](\n _path,\n \"work_schedule\",\n _.workSchedule,\n None,\n None,\n (row, value) => row.copy(workSchedule = value),\n PgTypes.boolArrayUnboxed\n )\n }\n\n override def ipAddress: OptField[Inet, EmployeeRow] = {\n new OptField[Inet, EmployeeRow](\n _path,\n \"ip_address\",\n _.ipAddress,\n None,\n None,\n (row, value) => row.copy(ipAddress = value),\n PgTypes.inet\n )\n }\n\n override def networkCidr: OptField[Cidr, EmployeeRow] = {\n new OptField[Cidr, EmployeeRow](\n _path,\n \"network_cidr\",\n _.networkCidr,\n None,\n None,\n (row, value) => row.copy(networkCidr = value),\n PgTypes.cidr\n )\n }\n\n override def macAddress: OptField[MacAddr, EmployeeRow] = {\n new OptField[MacAddr, EmployeeRow](\n _path,\n \"mac_address\",\n _.macAddress,\n None,\n None,\n (row, value) => row.copy(macAddress = value),\n PgTypes.macaddr\n )\n }\n\n override def probationPeriod: OptField[PGInterval, EmployeeRow] = {\n new OptField[PGInterval, EmployeeRow](\n _path,\n \"probation_period\",\n _.probationPeriod,\n None,\n None,\n (row, value) => row.copy(probationPeriod = value),\n PgTypes.interval\n )\n }\n\n override def photo: OptField[Array[Byte], EmployeeRow] = {\n new OptField[Array[Byte], EmployeeRow](\n _path,\n \"photo\",\n _.photo,\n None,\n None,\n (row, value) => row.copy(photo = value),\n PgTypes.bytea\n )\n }\n\n override def columns: java.util.List[FieldLike[?, EmployeeRow]] = java.util.List.of(this.id.underlying, this.departmentId.underlying, this.managerId.underlying, this.email.underlying, this.firstName.underlying, this.lastName.underlying, this.salary.underlying, this.hiredAt.underlying, this.active.underlying, this.createdAt.underlying, this.skills.underlying, this.certifications.underlying, this.metadata.underlying, this.settings.underlying, this.workSchedule.underlying, this.ipAddress.underlying, this.networkCidr.underlying, this.macAddress.underlying, this.probationPeriod.underlying, this.photo.underlying)\n\n override def withPaths(`_path`: java.util.List[Path]): RelationStructure[EmployeeFields, EmployeeRow] = new Impl(`_path`)\n }\n\n def structure: Impl = new Impl(java.util.Collections.emptyList())\n}", - "DepartmentRow": "package showcase.showcase.department\n\nimport dev.typr.foundations.PgText\nimport dev.typr.foundations.PgTypes\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport showcase.showcase.company.CompanyId\n\n/** Table: showcase.department\n * Primary key: id\n */\ncase class DepartmentRow(\n id: DepartmentId,\n /** Points to [[showcase.showcase.company.CompanyRow.id]] */\n companyId: CompanyId,\n name: String,\n budget: Option[BigDecimal]\n)\n\nobject DepartmentRow {\n val `_rowParser`: RowParser[DepartmentRow] = RowParsers.of(DepartmentId.pgType, CompanyId.pgType, PgTypes.text, ScalaDbTypes.PgTypes.numeric.nullable)(DepartmentRow.apply)(row => Array[Any](row.id, row.companyId, row.name, row.budget))\n\n given pgText: PgText[DepartmentRow] = PgText.from(`_rowParser`.underlying)\n}", - "DepartmentId": "package showcase.showcase.department\n\nimport dev.typr.foundations.PgType\nimport dev.typr.foundations.PgTypes\nimport dev.typr.foundations.scala.Bijection\n\n/** Type for the primary key of table `showcase.department` */\ncase class DepartmentId(value: String) extends scala.AnyVal\n\nobject DepartmentId {\n given bijection: Bijection[DepartmentId, String] = Bijection.apply[DepartmentId, String](_.value)(DepartmentId.apply)\n\n given pgType: PgType[DepartmentId] = PgTypes.text.bimap(DepartmentId.apply, _.value)\n\n given pgTypeArray: PgType[Array[DepartmentId]] = PgTypes.textArray.bimap(xs => xs.map(DepartmentId.apply), xs => xs.map(_.value))\n}", - "DepartmentRepo": "package showcase.showcase.department\n\nimport dev.typr.foundations.scala.DeleteBuilder\nimport dev.typr.foundations.scala.SelectBuilder\nimport dev.typr.foundations.scala.UpdateBuilder\nimport java.sql.Connection\n\ntrait DepartmentRepo {\n def delete: DeleteBuilder[DepartmentFields, DepartmentRow]\n\n def deleteById(id: DepartmentId)(using c: Connection): Boolean\n\n def deleteByIds(ids: Array[DepartmentId])(using c: Connection): Int\n\n def insert(unsaved: DepartmentRow)(using c: Connection): DepartmentRow\n\n def insertStreaming(\n unsaved: Iterator[DepartmentRow],\n batchSize: Int = 10000\n )(using c: Connection): Long\n\n def select: SelectBuilder[DepartmentFields, DepartmentRow]\n\n def selectAll(using c: Connection): List[DepartmentRow]\n\n def selectById(id: DepartmentId)(using c: Connection): Option[DepartmentRow]\n\n def selectByIds(ids: Array[DepartmentId])(using c: Connection): List[DepartmentRow]\n\n def selectByIdsTracked(ids: Array[DepartmentId])(using c: Connection): Map[DepartmentId, DepartmentRow]\n\n def update: UpdateBuilder[DepartmentFields, DepartmentRow]\n\n def update(row: DepartmentRow)(using c: Connection): Boolean\n\n def upsert(unsaved: DepartmentRow)(using c: Connection): DepartmentRow\n\n def upsertBatch(unsaved: Iterator[DepartmentRow])(using c: Connection): List[DepartmentRow]\n\n /** NOTE: this functionality is not safe if you use auto-commit mode! it runs 3 SQL statements */\n def upsertStreaming(\n unsaved: Iterator[DepartmentRow],\n batchSize: Int = 10000\n )(using c: Connection): Int\n}", - "DepartmentRepoMock": "package showcase.showcase.department\n\nimport dev.typr.foundations.scala.DeleteBuilder\nimport dev.typr.foundations.scala.DeleteBuilderMock\nimport dev.typr.foundations.scala.DeleteParams\nimport dev.typr.foundations.scala.SelectBuilder\nimport dev.typr.foundations.scala.SelectBuilderMock\nimport dev.typr.foundations.scala.SelectParams\nimport dev.typr.foundations.scala.UpdateBuilder\nimport dev.typr.foundations.scala.UpdateBuilderMock\nimport dev.typr.foundations.scala.UpdateParams\nimport java.lang.RuntimeException\nimport java.sql.Connection\n\ncase class DepartmentRepoMock(map: scala.collection.mutable.Map[DepartmentId, DepartmentRow] = scala.collection.mutable.Map.empty[DepartmentId, DepartmentRow]) extends DepartmentRepo {\n override def delete: DeleteBuilder[DepartmentFields, DepartmentRow] = DeleteBuilderMock(DepartmentFields.structure, () => map.values.toList, DeleteParams.empty(), row => row.id, id => map.remove(id): @scala.annotation.nowarn)\n\n override def deleteById(id: DepartmentId)(using c: Connection): Boolean = map.remove(id).isDefined\n\n override def deleteByIds(ids: Array[DepartmentId])(using c: Connection): Int = {\n var count = 0\n ids.foreach { id => if (map.remove(id).isDefined) {\n count = count + 1\n } }\n return count\n }\n\n override def insert(unsaved: DepartmentRow)(using c: Connection): DepartmentRow = {\n if (map.contains(unsaved.id)) {\n throw new RuntimeException(s\"id ${unsaved.id} already exists\")\n }\n map.put(unsaved.id, unsaved): @scala.annotation.nowarn\n return unsaved\n }\n\n override def insertStreaming(\n unsaved: Iterator[DepartmentRow],\n batchSize: Int = 10000\n )(using c: Connection): Long = {\n unsaved.map { row =>\n map.put(row.id, row): @scala.annotation.nowarn\n 1L\n }.sum\n }\n\n override def select: SelectBuilder[DepartmentFields, DepartmentRow] = SelectBuilderMock(DepartmentFields.structure, () => map.values.toList, SelectParams.empty())\n\n override def selectAll(using c: Connection): List[DepartmentRow] = map.values.toList\n\n override def selectById(id: DepartmentId)(using c: Connection): Option[DepartmentRow] = map.get(id)\n\n override def selectByIds(ids: Array[DepartmentId])(using c: Connection): List[DepartmentRow] = ids.flatMap(map.get(_)).toList\n\n override def selectByIdsTracked(ids: Array[DepartmentId])(using c: Connection): Map[DepartmentId, DepartmentRow] = selectByIds(ids)(using c).map(x => (((row: DepartmentRow) => row.id).apply(x), x)).toMap\n\n override def update: UpdateBuilder[DepartmentFields, DepartmentRow] = UpdateBuilderMock(DepartmentFields.structure, () => map.values.toList, UpdateParams.empty(), row => row)\n\n override def update(row: DepartmentRow)(using c: Connection): Boolean = {\n val shouldUpdate = map.get(row.id).filter(oldRow => (oldRow != row)).isDefined\n if (shouldUpdate) {\n map.put(row.id, row): @scala.annotation.nowarn\n }\n return shouldUpdate\n }\n\n override def upsert(unsaved: DepartmentRow)(using c: Connection): DepartmentRow = {\n map.put(unsaved.id, unsaved): @scala.annotation.nowarn\n return unsaved\n }\n\n override def upsertBatch(unsaved: Iterator[DepartmentRow])(using c: Connection): List[DepartmentRow] = {\n unsaved.map { row =>\n map.put(row.id, row): @scala.annotation.nowarn\n row\n }.toList\n }\n\n /** NOTE: this functionality is not safe if you use auto-commit mode! it runs 3 SQL statements */\n override def upsertStreaming(\n unsaved: Iterator[DepartmentRow],\n batchSize: Int = 10000\n )(using c: Connection): Int = {\n unsaved.map { row =>\n map.put(row.id, row): @scala.annotation.nowarn\n 1\n }.sum\n }\n}", - "ProjectAssignmentRow": "package showcase.showcase.project_assignment\n\nimport dev.typr.foundations.PgText\nimport dev.typr.foundations.PgTypes\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport java.time.LocalDate\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.employee.EmployeeId\nimport showcase.showcase.project.ProjectId\n\n/** Table: showcase.project_assignment\n * Composite primary key: employee_id, project_id\n */\ncase class ProjectAssignmentRow(\n /** Points to [[showcase.showcase.employee.EmployeeRow.id]] */\n employeeId: EmployeeId,\n /** Points to [[showcase.showcase.project.ProjectRow.id]] */\n projectId: ProjectId,\n role: String,\n /** Default: 0 */\n hoursAllocated: Option[Int],\n startDate: Option[LocalDate],\n endDate: Option[LocalDate]\n) {\n def compositeId: ProjectAssignmentId = new ProjectAssignmentId(employeeId, projectId)\n\n def id: ProjectAssignmentId = this.compositeId\n\n def toUnsavedRow(hoursAllocated: Defaulted[Option[Int]] = Defaulted.Provided(this.hoursAllocated)): ProjectAssignmentRowUnsaved = {\n new ProjectAssignmentRowUnsaved(\n employeeId,\n projectId,\n role,\n startDate,\n endDate,\n hoursAllocated\n )\n }\n}\n\nobject ProjectAssignmentRow {\n val `_rowParser`: RowParser[ProjectAssignmentRow] = RowParsers.of(EmployeeId.pgType, ProjectId.pgType, PgTypes.text, ScalaDbTypes.PgTypes.int4.nullable, PgTypes.date.nullable, PgTypes.date.nullable)(ProjectAssignmentRow.apply)(row => Array[Any](row.employeeId, row.projectId, row.role, row.hoursAllocated, row.startDate, row.endDate))\n\n def apply(\n compositeId: ProjectAssignmentId,\n role: String,\n hoursAllocated: Option[Int],\n startDate: Option[LocalDate],\n endDate: Option[LocalDate]\n ): ProjectAssignmentRow = {\n new ProjectAssignmentRow(\n compositeId.employeeId,\n compositeId.projectId,\n role,\n hoursAllocated,\n startDate,\n endDate\n )\n }\n\n given pgText: PgText[ProjectAssignmentRow] = PgText.from(`_rowParser`.underlying)\n}", - "ProjectAssignmentRowUnsaved": "package showcase.showcase.project_assignment\n\nimport dev.typr.foundations.PgText\nimport dev.typr.foundations.PgTypes\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport java.time.LocalDate\nimport showcase.customtypes.Defaulted\nimport showcase.customtypes.Defaulted.UseDefault\nimport showcase.showcase.employee.EmployeeId\nimport showcase.showcase.project.ProjectId\n\n/** This class corresponds to a row in table `showcase.project_assignment` which has not been persisted yet */\ncase class ProjectAssignmentRowUnsaved(\n /** Points to [[showcase.showcase.employee.EmployeeRow.id]] */\n employeeId: EmployeeId,\n /** Points to [[showcase.showcase.project.ProjectRow.id]] */\n projectId: ProjectId,\n role: String,\n startDate: Option[LocalDate] = None,\n endDate: Option[LocalDate] = None,\n /** Default: 0 */\n hoursAllocated: Defaulted[Option[Int]] = new UseDefault()\n) {\n def toRow(hoursAllocatedDefault: => Option[Int]): ProjectAssignmentRow = {\n new ProjectAssignmentRow(\n employeeId = employeeId,\n projectId = projectId,\n role = role,\n hoursAllocated = hoursAllocated.getOrElse(hoursAllocatedDefault),\n startDate = startDate,\n endDate = endDate\n )\n }\n}\n\nobject ProjectAssignmentRowUnsaved {\n given pgText: PgText[ProjectAssignmentRowUnsaved] = PgText.instance((row, sb) => { EmployeeId.pgType.text.unsafeEncode(row.employeeId, sb); sb.append(PgText.DELIMETER); ProjectId.pgType.text.unsafeEncode(row.projectId, sb); sb.append(PgText.DELIMETER); PgTypes.text.text.unsafeEncode(row.role, sb); sb.append(PgText.DELIMETER); PgTypes.date.nullable.text.unsafeEncode(row.startDate, sb); sb.append(PgText.DELIMETER); PgTypes.date.nullable.text.unsafeEncode(row.endDate, sb); sb.append(PgText.DELIMETER); Defaulted.pgText(using ScalaDbTypes.PgTypes.int4.nullable.text).unsafeEncode(row.hoursAllocated, sb) })\n}", - "ProjectAssignmentId": "package showcase.showcase.project_assignment\n\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport showcase.showcase.employee.EmployeeId\nimport showcase.showcase.project.ProjectId\n\n/** Type for the composite primary key of table `showcase.project_assignment` */\ncase class ProjectAssignmentId(\n employeeId: EmployeeId,\n projectId: ProjectId\n)\n\nobject ProjectAssignmentId {\n val `_rowParser`: RowParser[ProjectAssignmentId] = RowParsers.of(EmployeeId.pgType, ProjectId.pgType)(ProjectAssignmentId.apply)(row => Array[Any](row.employeeId, row.projectId))\n}", - "ProjectAssignmentRepo": "package showcase.showcase.project_assignment\n\nimport dev.typr.foundations.scala.DeleteBuilder\nimport dev.typr.foundations.scala.SelectBuilder\nimport dev.typr.foundations.scala.UpdateBuilder\nimport java.sql.Connection\n\ntrait ProjectAssignmentRepo {\n def delete: DeleteBuilder[ProjectAssignmentFields, ProjectAssignmentRow]\n\n def deleteById(compositeId: ProjectAssignmentId)(using c: Connection): Boolean\n\n def deleteByIds(compositeIds: Array[ProjectAssignmentId])(using c: Connection): Int\n\n def insert(unsaved: ProjectAssignmentRow)(using c: Connection): ProjectAssignmentRow\n\n def insert(unsaved: ProjectAssignmentRowUnsaved)(using c: Connection): ProjectAssignmentRow\n\n def insertStreaming(\n unsaved: Iterator[ProjectAssignmentRow],\n batchSize: Int = 10000\n )(using c: Connection): Long\n\n /** NOTE: this functionality requires PostgreSQL 16 or later! */\n def insertUnsavedStreaming(\n unsaved: Iterator[ProjectAssignmentRowUnsaved],\n batchSize: Int = 10000\n )(using c: Connection): Long\n\n def select: SelectBuilder[ProjectAssignmentFields, ProjectAssignmentRow]\n\n def selectAll(using c: Connection): List[ProjectAssignmentRow]\n\n def selectById(compositeId: ProjectAssignmentId)(using c: Connection): Option[ProjectAssignmentRow]\n\n def selectByIds(compositeIds: Array[ProjectAssignmentId])(using c: Connection): List[ProjectAssignmentRow]\n\n def selectByIdsTracked(compositeIds: Array[ProjectAssignmentId])(using c: Connection): Map[ProjectAssignmentId, ProjectAssignmentRow]\n\n def update: UpdateBuilder[ProjectAssignmentFields, ProjectAssignmentRow]\n\n def update(row: ProjectAssignmentRow)(using c: Connection): Boolean\n\n def upsert(unsaved: ProjectAssignmentRow)(using c: Connection): ProjectAssignmentRow\n\n def upsertBatch(unsaved: Iterator[ProjectAssignmentRow])(using c: Connection): List[ProjectAssignmentRow]\n\n /** NOTE: this functionality is not safe if you use auto-commit mode! it runs 3 SQL statements */\n def upsertStreaming(\n unsaved: Iterator[ProjectAssignmentRow],\n batchSize: Int = 10000\n )(using c: Connection): Int\n}", - "ProjectRow": "package showcase.showcase.project\n\nimport dev.typr.foundations.PgText\nimport dev.typr.foundations.PgTypes\nimport dev.typr.foundations.data.Jsonb\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport java.time.LocalDate\nimport java.time.LocalDateTime\nimport java.util.UUID\nimport org.postgresql.util.PGInterval\nimport showcase.customtypes.Defaulted\n\n/** Table: showcase.project\n * Primary key: id\n */\ncase class ProjectRow(\n id: ProjectId,\n name: String,\n description: Option[/* max 1000 chars */ String],\n startDate: Option[LocalDate],\n endDate: Option[LocalDate],\n budget: Option[BigDecimal],\n /** Default: 'planning' */\n status: Option[/* max 20 chars */ String],\n /** Default: CURRENT_TIMESTAMP */\n createdAt: Option[LocalDateTime],\n projectUid: Option[UUID],\n milestones: Option[Array[String]],\n budgetSnapshots: Option[Array[BigDecimal]],\n teamMembers: Option[Array[String]],\n metadata: Option[Jsonb],\n config: Option[Map[String, String]],\n estimatedDuration: Option[PGInterval],\n actualDuration: Option[PGInterval]\n) {\n def toUnsavedRow(\n status: Defaulted[Option[/* max 20 chars */ String]] = Defaulted.Provided(this.status),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.Provided(this.createdAt)\n ): ProjectRowUnsaved = {\n new ProjectRowUnsaved(\n id,\n name,\n description,\n startDate,\n endDate,\n budget,\n projectUid,\n milestones,\n budgetSnapshots,\n teamMembers,\n metadata,\n config,\n estimatedDuration,\n actualDuration,\n status,\n createdAt\n )\n }\n}\n\nobject ProjectRow {\n val `_rowParser`: RowParser[ProjectRow] = RowParsers.of(ProjectId.pgType, PgTypes.text, PgTypes.text.nullable, PgTypes.date.nullable, PgTypes.date.nullable, ScalaDbTypes.PgTypes.numeric.nullable, PgTypes.text.nullable, PgTypes.timestamp.nullable, PgTypes.uuid.nullable, PgTypes.textArray.nullable, ScalaDbTypes.PgTypes.numericArray.nullable, PgTypes.textArray.nullable, PgTypes.jsonb.nullable, ScalaDbTypes.PgTypes.hstore.nullable, PgTypes.interval.nullable, PgTypes.interval.nullable)(ProjectRow.apply)(row => Array[Any](row.id, row.name, row.description, row.startDate, row.endDate, row.budget, row.status, row.createdAt, row.projectUid, row.milestones, row.budgetSnapshots, row.teamMembers, row.metadata, row.config, row.estimatedDuration, row.actualDuration))\n\n given pgText: PgText[ProjectRow] = PgText.from(`_rowParser`.underlying)\n}", - "ProjectId": "package showcase.showcase.project\n\nimport dev.typr.foundations.PgType\nimport dev.typr.foundations.PgTypes\nimport dev.typr.foundations.scala.Bijection\n\n/** Type for the primary key of table `showcase.project` */\ncase class ProjectId(value: String) extends scala.AnyVal\n\nobject ProjectId {\n given bijection: Bijection[ProjectId, String] = Bijection.apply[ProjectId, String](_.value)(ProjectId.apply)\n\n given pgType: PgType[ProjectId] = PgTypes.text.bimap(ProjectId.apply, _.value)\n\n given pgTypeArray: PgType[Array[ProjectId]] = PgTypes.textArray.bimap(xs => xs.map(ProjectId.apply), xs => xs.map(_.value))\n}", - "EmployeeSummaryViewRow": "package showcase.showcase.employee_summary\n\nimport dev.typr.foundations.PgTypes\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport java.time.LocalDate\nimport showcase.showcase.company.CompanyId\nimport showcase.showcase.department.DepartmentId\nimport showcase.showcase.employee.EmployeeId\n\n/** View: showcase.employee_summary\n * Summary view of employees with their department and company information\n */\ncase class EmployeeSummaryViewRow(\n /** Points to [[showcase.showcase.employee.EmployeeRow.id]] */\n employeeId: EmployeeId,\n email: String,\n firstName: String,\n lastName: String,\n salary: Option[BigDecimal],\n hiredAt: Option[LocalDate],\n active: Option[Boolean],\n /** Points to [[showcase.showcase.department.DepartmentRow.id]] */\n departmentId: DepartmentId,\n departmentName: String,\n departmentBudget: Option[BigDecimal],\n /** Points to [[showcase.showcase.company.CompanyRow.id]] */\n companyId: CompanyId,\n companyName: String,\n managerId: Option[String],\n managerFirstName: Option[/* max 50 chars */ String],\n managerLastName: Option[/* max 50 chars */ String]\n)\n\nobject EmployeeSummaryViewRow {\n val `_rowParser`: RowParser[EmployeeSummaryViewRow] = RowParsers.of(EmployeeId.pgType, PgTypes.text, PgTypes.text, PgTypes.text, ScalaDbTypes.PgTypes.numeric.nullable, PgTypes.date.nullable, ScalaDbTypes.PgTypes.bool.nullable, DepartmentId.pgType, PgTypes.text, ScalaDbTypes.PgTypes.numeric.nullable, CompanyId.pgType, PgTypes.text, PgTypes.text.nullable, PgTypes.text.nullable, PgTypes.text.nullable)(EmployeeSummaryViewRow.apply)(row => Array[Any](row.employeeId, row.email, row.firstName, row.lastName, row.salary, row.hiredAt, row.active, row.departmentId, row.departmentName, row.departmentBudget, row.companyId, row.companyName, row.managerId, row.managerFirstName, row.managerLastName))\n}", - "EmployeeSummaryViewRepo": "package showcase.showcase.employee_summary\n\nimport dev.typr.foundations.scala.SelectBuilder\nimport java.sql.Connection\n\ntrait EmployeeSummaryViewRepo {\n def select: SelectBuilder[EmployeeSummaryViewFields, EmployeeSummaryViewRow]\n\n def selectAll(using c: Connection): List[EmployeeSummaryViewRow]\n}", - "CustomerOrderRow": "package showcase.showcase.customer_order\n\nimport dev.typr.foundations.PgText\nimport dev.typr.foundations.PgTypes\nimport dev.typr.foundations.data.Inet\nimport dev.typr.foundations.data.Jsonb\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport java.time.LocalDateTime\nimport java.util.UUID\nimport org.postgresql.util.PGInterval\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.address.AddressId\nimport showcase.showcase.customer.CustomerId\n\n/** Table: showcase.customer_order\n * Primary key: id\n */\ncase class CustomerOrderRow(\n id: CustomerOrderId,\n /** Points to [[showcase.showcase.customer.CustomerRow.id]] */\n customerId: CustomerId,\n /** Points to [[showcase.showcase.address.AddressRow.id]] */\n shippingAddressId: Option[AddressId],\n /** Points to [[showcase.showcase.address.AddressRow.id]] */\n billingAddressId: Option[AddressId],\n /** Default: 'pending' */\n status: Option[/* max 20 chars */ String],\n subtotal: BigDecimal,\n /** Default: 0 */\n tax: Option[BigDecimal],\n /** Default: 0 */\n shipping: Option[BigDecimal],\n total: BigDecimal,\n notes: Option[/* max 1000 chars */ String],\n /** Default: CURRENT_TIMESTAMP */\n createdAt: Option[LocalDateTime],\n shippedAt: Option[LocalDateTime],\n deliveredAt: Option[LocalDateTime],\n orderUid: Option[UUID],\n metadata: Option[Jsonb],\n tags: Option[Array[String]],\n fulfillmentTimes: Option[Array[LocalDateTime]],\n ipAddress: Option[Inet],\n processingTime: Option[PGInterval]\n) {\n def toUnsavedRow(\n status: Defaulted[Option[/* max 20 chars */ String]] = Defaulted.Provided(this.status),\n tax: Defaulted[Option[BigDecimal]] = Defaulted.Provided(this.tax),\n shipping: Defaulted[Option[BigDecimal]] = Defaulted.Provided(this.shipping),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.Provided(this.createdAt)\n ): CustomerOrderRowUnsaved = {\n new CustomerOrderRowUnsaved(\n id,\n customerId,\n shippingAddressId,\n billingAddressId,\n subtotal,\n total,\n notes,\n shippedAt,\n deliveredAt,\n orderUid,\n metadata,\n tags,\n fulfillmentTimes,\n ipAddress,\n processingTime,\n status,\n tax,\n shipping,\n createdAt\n )\n }\n}\n\nobject CustomerOrderRow {\n val `_rowParser`: RowParser[CustomerOrderRow] = RowParsers.of(CustomerOrderId.pgType, CustomerId.pgType, AddressId.pgType.nullable, AddressId.pgType.nullable, PgTypes.text.nullable, ScalaDbTypes.PgTypes.numeric, ScalaDbTypes.PgTypes.numeric.nullable, ScalaDbTypes.PgTypes.numeric.nullable, ScalaDbTypes.PgTypes.numeric, PgTypes.text.nullable, PgTypes.timestamp.nullable, PgTypes.timestamp.nullable, PgTypes.timestamp.nullable, PgTypes.uuid.nullable, PgTypes.jsonb.nullable, PgTypes.textArray.nullable, PgTypes.timestampArray.nullable, PgTypes.inet.nullable, PgTypes.interval.nullable)(CustomerOrderRow.apply)(row => Array[Any](row.id, row.customerId, row.shippingAddressId, row.billingAddressId, row.status, row.subtotal, row.tax, row.shipping, row.total, row.notes, row.createdAt, row.shippedAt, row.deliveredAt, row.orderUid, row.metadata, row.tags, row.fulfillmentTimes, row.ipAddress, row.processingTime))\n\n given pgText: PgText[CustomerOrderRow] = PgText.from(`_rowParser`.underlying)\n}", - "CustomerOrderRepo": "package showcase.showcase.customer_order\n\nimport dev.typr.foundations.scala.DeleteBuilder\nimport dev.typr.foundations.scala.SelectBuilder\nimport dev.typr.foundations.scala.UpdateBuilder\nimport java.sql.Connection\n\ntrait CustomerOrderRepo {\n def delete: DeleteBuilder[CustomerOrderFields, CustomerOrderRow]\n\n def deleteById(id: CustomerOrderId)(using c: Connection): Boolean\n\n def deleteByIds(ids: Array[CustomerOrderId])(using c: Connection): Int\n\n def insert(unsaved: CustomerOrderRow)(using c: Connection): CustomerOrderRow\n\n def insert(unsaved: CustomerOrderRowUnsaved)(using c: Connection): CustomerOrderRow\n\n def insertStreaming(\n unsaved: Iterator[CustomerOrderRow],\n batchSize: Int = 10000\n )(using c: Connection): Long\n\n /** NOTE: this functionality requires PostgreSQL 16 or later! */\n def insertUnsavedStreaming(\n unsaved: Iterator[CustomerOrderRowUnsaved],\n batchSize: Int = 10000\n )(using c: Connection): Long\n\n def select: SelectBuilder[CustomerOrderFields, CustomerOrderRow]\n\n def selectAll(using c: Connection): List[CustomerOrderRow]\n\n def selectById(id: CustomerOrderId)(using c: Connection): Option[CustomerOrderRow]\n\n def selectByIds(ids: Array[CustomerOrderId])(using c: Connection): List[CustomerOrderRow]\n\n def selectByIdsTracked(ids: Array[CustomerOrderId])(using c: Connection): Map[CustomerOrderId, CustomerOrderRow]\n\n def update: UpdateBuilder[CustomerOrderFields, CustomerOrderRow]\n\n def update(row: CustomerOrderRow)(using c: Connection): Boolean\n\n def upsert(unsaved: CustomerOrderRow)(using c: Connection): CustomerOrderRow\n\n def upsertBatch(unsaved: Iterator[CustomerOrderRow])(using c: Connection): List[CustomerOrderRow]\n\n /** NOTE: this functionality is not safe if you use auto-commit mode! it runs 3 SQL statements */\n def upsertStreaming(\n unsaved: Iterator[CustomerOrderRow],\n batchSize: Int = 10000\n )(using c: Connection): Int\n}", - "OrderItemRow": "package showcase.showcase.order_item\n\nimport dev.typr.foundations.PgText\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.customer_order.CustomerOrderId\nimport showcase.showcase.product.ProductId\n\n/** Table: showcase.order_item\n * Composite primary key: order_id, product_id\n */\ncase class OrderItemRow(\n /** Points to [[showcase.showcase.customer_order.CustomerOrderRow.id]] */\n orderId: CustomerOrderId,\n /** Points to [[showcase.showcase.product.ProductRow.id]] */\n productId: ProductId,\n quantity: Int,\n unitPrice: BigDecimal,\n /** Default: 0 */\n discount: Option[BigDecimal]\n) {\n def compositeId: OrderItemId = new OrderItemId(orderId, productId)\n\n def id: OrderItemId = this.compositeId\n\n def toUnsavedRow(discount: Defaulted[Option[BigDecimal]] = Defaulted.Provided(this.discount)): OrderItemRowUnsaved = {\n new OrderItemRowUnsaved(\n orderId,\n productId,\n quantity,\n unitPrice,\n discount\n )\n }\n}\n\nobject OrderItemRow {\n val `_rowParser`: RowParser[OrderItemRow] = RowParsers.of(CustomerOrderId.pgType, ProductId.pgType, ScalaDbTypes.PgTypes.int4, ScalaDbTypes.PgTypes.numeric, ScalaDbTypes.PgTypes.numeric.nullable)(OrderItemRow.apply)(row => Array[Any](row.orderId, row.productId, row.quantity, row.unitPrice, row.discount))\n\n def apply(\n compositeId: OrderItemId,\n quantity: Int,\n unitPrice: BigDecimal,\n discount: Option[BigDecimal]\n ): OrderItemRow = {\n new OrderItemRow(\n compositeId.orderId,\n compositeId.productId,\n quantity,\n unitPrice,\n discount\n )\n }\n\n given pgText: PgText[OrderItemRow] = PgText.from(`_rowParser`.underlying)\n}", - "OrderItemId": "package showcase.showcase.order_item\n\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport showcase.showcase.customer_order.CustomerOrderId\nimport showcase.showcase.product.ProductId\n\n/** Type for the composite primary key of table `showcase.order_item` */\ncase class OrderItemId(\n orderId: CustomerOrderId,\n productId: ProductId\n)\n\nobject OrderItemId {\n val `_rowParser`: RowParser[OrderItemId] = RowParsers.of(CustomerOrderId.pgType, ProductId.pgType)(OrderItemId.apply)(row => Array[Any](row.orderId, row.productId))\n}", - "ProductRow": "package showcase.showcase.product\n\nimport dev.typr.foundations.PgText\nimport dev.typr.foundations.PgTypes\nimport dev.typr.foundations.data.Jsonb\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport java.time.LocalDateTime\nimport java.util.UUID\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.category.CategoryId\n\n/** Table: showcase.product\n * Primary key: id\n */\ncase class ProductRow(\n id: ProductId,\n /** Points to [[showcase.showcase.category.CategoryRow.id]] */\n categoryId: Option[CategoryId],\n name: String,\n sku: String,\n price: BigDecimal,\n cost: Option[BigDecimal],\n /** Default: true */\n inStock: Option[Boolean],\n /** Default: 0 */\n quantity: Option[Int],\n weight: Option[BigDecimal],\n /** Default: CURRENT_TIMESTAMP */\n createdAt: Option[LocalDateTime],\n tags: Option[Array[String]],\n images: Option[Array[String]],\n relatedSkus: Option[Array[String]],\n priceHistory: Option[Array[BigDecimal]],\n attributes: Option[Jsonb],\n specifications: Option[Jsonb],\n seoMetadata: Option[Jsonb],\n searchVector: Option[String],\n productUid: Option[UUID]\n) {\n def toUnsavedRow(\n inStock: Defaulted[Option[Boolean]] = Defaulted.Provided(this.inStock),\n quantity: Defaulted[Option[Int]] = Defaulted.Provided(this.quantity),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.Provided(this.createdAt)\n ): ProductRowUnsaved = {\n new ProductRowUnsaved(\n id,\n categoryId,\n name,\n sku,\n price,\n cost,\n weight,\n tags,\n images,\n relatedSkus,\n priceHistory,\n attributes,\n specifications,\n seoMetadata,\n searchVector,\n productUid,\n inStock,\n quantity,\n createdAt\n )\n }\n}\n\nobject ProductRow {\n val `_rowParser`: RowParser[ProductRow] = RowParsers.of(ProductId.pgType, CategoryId.pgType.nullable, PgTypes.text, PgTypes.text, ScalaDbTypes.PgTypes.numeric, ScalaDbTypes.PgTypes.numeric.nullable, ScalaDbTypes.PgTypes.bool.nullable, ScalaDbTypes.PgTypes.int4.nullable, ScalaDbTypes.PgTypes.numeric.nullable, PgTypes.timestamp.nullable, PgTypes.textArray.nullable, PgTypes.textArray.nullable, PgTypes.textArray.nullable, ScalaDbTypes.PgTypes.numericArray.nullable, PgTypes.jsonb.nullable, PgTypes.jsonb.nullable, PgTypes.jsonb.nullable, PgTypes.text.nullable, PgTypes.uuid.nullable)(ProductRow.apply)(row => Array[Any](row.id, row.categoryId, row.name, row.sku, row.price, row.cost, row.inStock, row.quantity, row.weight, row.createdAt, row.tags, row.images, row.relatedSkus, row.priceHistory, row.attributes, row.specifications, row.seoMetadata, row.searchVector, row.productUid))\n\n given pgText: PgText[ProductRow] = PgText.from(`_rowParser`.underlying)\n}", - "ProductId": "package showcase.showcase.product\n\nimport dev.typr.foundations.PgType\nimport dev.typr.foundations.PgTypes\nimport dev.typr.foundations.scala.Bijection\n\n/** Type for the primary key of table `showcase.product` */\ncase class ProductId(value: String) extends scala.AnyVal\n\nobject ProductId {\n given bijection: Bijection[ProductId, String] = Bijection.apply[ProductId, String](_.value)(ProductId.apply)\n\n given pgType: PgType[ProductId] = PgTypes.text.bimap(ProductId.apply, _.value)\n\n given pgTypeArray: PgType[Array[ProductId]] = PgTypes.textArray.bimap(xs => xs.map(ProductId.apply), xs => xs.map(_.value))\n}", - "CategoryRow": "package showcase.showcase.category\n\nimport dev.typr.foundations.PgText\nimport dev.typr.foundations.PgTypes\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\n\n/** Table: showcase.category\n * Primary key: id\n */\ncase class CategoryRow(\n id: CategoryId,\n /** Points to [[showcase.showcase.category.CategoryRow.id]] */\n parentId: Option[CategoryId],\n name: String,\n description: Option[/* max 500 chars */ String]\n)\n\nobject CategoryRow {\n val `_rowParser`: RowParser[CategoryRow] = RowParsers.of(CategoryId.pgType, CategoryId.pgType.nullable, PgTypes.text, PgTypes.text.nullable)(CategoryRow.apply)(row => Array[Any](row.id, row.parentId, row.name, row.description))\n\n given pgText: PgText[CategoryRow] = PgText.from(`_rowParser`.underlying)\n}", - "CategoryId": "package showcase.showcase.category\n\nimport dev.typr.foundations.PgType\nimport dev.typr.foundations.PgTypes\nimport dev.typr.foundations.scala.Bijection\n\n/** Type for the primary key of table `showcase.category` */\ncase class CategoryId(value: String) extends scala.AnyVal\n\nobject CategoryId {\n given bijection: Bijection[CategoryId, String] = Bijection.apply[CategoryId, String](_.value)(CategoryId.apply)\n\n given pgType: PgType[CategoryId] = PgTypes.text.bimap(CategoryId.apply, _.value)\n\n given pgTypeArray: PgType[Array[CategoryId]] = PgTypes.textArray.bimap(xs => xs.map(CategoryId.apply), xs => xs.map(_.value))\n}", - "AddressRow": "package showcase.showcase.address\n\nimport dev.typr.foundations.PgText\nimport dev.typr.foundations.PgTypes\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport org.postgresql.geometric.PGbox\nimport org.postgresql.geometric.PGpoint\nimport org.postgresql.geometric.PGpolygon\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.customer.CustomerId\n\n/** Table: showcase.address\n * Primary key: id\n */\ncase class AddressRow(\n id: AddressId,\n /** Points to [[showcase.showcase.customer.CustomerRow.id]] */\n customerId: CustomerId,\n addressType: String,\n street: String,\n city: String,\n state: Option[/* max 100 chars */ String],\n postalCode: Option[/* max 20 chars */ String],\n country: String,\n /** Default: false */\n isDefault: Option[Boolean],\n location: Option[PGpoint],\n boundary: Option[PGbox],\n deliveryZone: Option[PGpolygon]\n) {\n def toUnsavedRow(isDefault: Defaulted[Option[Boolean]] = Defaulted.Provided(this.isDefault)): AddressRowUnsaved = {\n new AddressRowUnsaved(\n id,\n customerId,\n addressType,\n street,\n city,\n state,\n postalCode,\n country,\n location,\n boundary,\n deliveryZone,\n isDefault\n )\n }\n}\n\nobject AddressRow {\n val `_rowParser`: RowParser[AddressRow] = RowParsers.of(AddressId.pgType, CustomerId.pgType, PgTypes.text, PgTypes.text, PgTypes.text, PgTypes.text.nullable, PgTypes.text.nullable, PgTypes.text, ScalaDbTypes.PgTypes.bool.nullable, PgTypes.point.nullable, PgTypes.box.nullable, PgTypes.polygon.nullable)(AddressRow.apply)(row => Array[Any](row.id, row.customerId, row.addressType, row.street, row.city, row.state, row.postalCode, row.country, row.isDefault, row.location, row.boundary, row.deliveryZone))\n\n given pgText: PgText[AddressRow] = PgText.from(`_rowParser`.underlying)\n}", - "AddressId": "package showcase.showcase.address\n\nimport dev.typr.foundations.PgType\nimport dev.typr.foundations.PgTypes\nimport dev.typr.foundations.scala.Bijection\n\n/** Type for the primary key of table `showcase.address` */\ncase class AddressId(value: String) extends scala.AnyVal\n\nobject AddressId {\n given bijection: Bijection[AddressId, String] = Bijection.apply[AddressId, String](_.value)(AddressId.apply)\n\n given pgType: PgType[AddressId] = PgTypes.text.bimap(AddressId.apply, _.value)\n\n given pgTypeArray: PgType[Array[AddressId]] = PgTypes.textArray.bimap(xs => xs.map(AddressId.apply), xs => xs.map(_.value))\n}", - "Defaulted": "package showcase.customtypes\n\nimport dev.typr.foundations.DbText\nimport dev.typr.foundations.PgText\n\n/** This signals a value where if you don't provide it, postgres will generate it for you */\nsealed trait Defaulted[T] {\n def fold[U](\n onDefault: => U,\n onProvided: T => U\n ): U\n\n def getOrElse(onDefault: => T): T\n\n def visit(\n onDefault: => Unit,\n onProvided: T => Unit\n ): Unit\n}\n\nobject Defaulted {\n given pgText[T](using t: DbText[T]): PgText[Defaulted[T]] = PgText.instance((ot, sb) => ot.visit({ sb.append(\"__DEFAULT_VALUE__\"): @scala.annotation.nowarn }, value => t.unsafeEncode(value, sb)))\n\n case class Provided[T](value: T) extends Defaulted[T] {\n override def fold[U](\n onDefault: => U,\n onProvided: T => U\n ): U = onProvided(value)\n\n override def getOrElse(onDefault: => T): T = value\n\n override def visit(\n onDefault: => Unit,\n onProvided: T => Unit\n ): Unit = onProvided(value)\n }\n\n case class UseDefault[T]() extends Defaulted[T] {\n override def fold[U](\n onDefault: => U,\n onProvided: T => U\n ): U = onDefault\n\n override def getOrElse(onDefault: => T): T = onDefault\n\n override def visit(\n onDefault: => Unit,\n onProvided: T => Unit\n ): Unit = onDefault\n }\n}", - "TestInsert": "package showcase\n\nimport dev.typr.foundations.data.Cidr\nimport dev.typr.foundations.data.Inet\nimport dev.typr.foundations.data.Jsonb\nimport dev.typr.foundations.data.MacAddr\nimport java.sql.Connection\nimport java.time.LocalDate\nimport java.time.LocalDateTime\nimport java.util.UUID\nimport org.postgresql.geometric.PGbox\nimport org.postgresql.geometric.PGpoint\nimport org.postgresql.geometric.PGpolygon\nimport org.postgresql.util.PGInterval\nimport scala.util.Random\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.address.AddressId\nimport showcase.showcase.address.AddressRepoImpl\nimport showcase.showcase.address.AddressRow\nimport showcase.showcase.address.AddressRowUnsaved\nimport showcase.showcase.audit_log.AuditLogId\nimport showcase.showcase.audit_log.AuditLogRepoImpl\nimport showcase.showcase.audit_log.AuditLogRow\nimport showcase.showcase.audit_log.AuditLogRowUnsaved\nimport showcase.showcase.category.CategoryId\nimport showcase.showcase.category.CategoryRepoImpl\nimport showcase.showcase.category.CategoryRow\nimport showcase.showcase.company.CompanyId\nimport showcase.showcase.company.CompanyRepoImpl\nimport showcase.showcase.company.CompanyRow\nimport showcase.showcase.company.CompanyRowUnsaved\nimport showcase.showcase.customer.CustomerId\nimport showcase.showcase.customer.CustomerRepoImpl\nimport showcase.showcase.customer.CustomerRow\nimport showcase.showcase.customer.CustomerRowUnsaved\nimport showcase.showcase.customer_order.CustomerOrderId\nimport showcase.showcase.customer_order.CustomerOrderRepoImpl\nimport showcase.showcase.customer_order.CustomerOrderRow\nimport showcase.showcase.customer_order.CustomerOrderRowUnsaved\nimport showcase.showcase.department.DepartmentId\nimport showcase.showcase.department.DepartmentRepoImpl\nimport showcase.showcase.department.DepartmentRow\nimport showcase.showcase.employee.EmployeeId\nimport showcase.showcase.employee.EmployeeRepoImpl\nimport showcase.showcase.employee.EmployeeRow\nimport showcase.showcase.employee.EmployeeRowUnsaved\nimport showcase.showcase.order_item.OrderItemRepoImpl\nimport showcase.showcase.order_item.OrderItemRow\nimport showcase.showcase.order_item.OrderItemRowUnsaved\nimport showcase.showcase.product.ProductId\nimport showcase.showcase.product.ProductRepoImpl\nimport showcase.showcase.product.ProductRow\nimport showcase.showcase.product.ProductRowUnsaved\nimport showcase.showcase.project.ProjectId\nimport showcase.showcase.project.ProjectRepoImpl\nimport showcase.showcase.project.ProjectRow\nimport showcase.showcase.project.ProjectRowUnsaved\nimport showcase.showcase.project_assignment.ProjectAssignmentRepoImpl\nimport showcase.showcase.project_assignment.ProjectAssignmentRow\nimport showcase.showcase.project_assignment.ProjectAssignmentRowUnsaved\n\n/** Methods to generate random data for `Ident(TestInsert)` */\ncase class TestInsert(random: Random) {\n def showcaseAddress(\n customerId: CustomerId,\n id: AddressId = AddressId(random.alphanumeric.take(20).mkString),\n addressType: String = random.alphanumeric.take(20).mkString,\n street: String = random.alphanumeric.take(20).mkString,\n city: String = random.alphanumeric.take(20).mkString,\n state: Option[/* max 100 chars */ String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n postalCode: Option[/* max 20 chars */ String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n country: String = random.alphanumeric.take(20).mkString,\n location: Option[PGpoint] = None,\n boundary: Option[PGbox] = None,\n deliveryZone: Option[PGpolygon] = None,\n isDefault: Defaulted[Option[Boolean]] = Defaulted.UseDefault()\n )(using c: Connection): AddressRow = {\n (new AddressRepoImpl()).insert(new AddressRowUnsaved(\n id = id,\n customerId = customerId,\n addressType = addressType,\n street = street,\n city = city,\n state = state,\n postalCode = postalCode,\n country = country,\n location = location,\n boundary = boundary,\n deliveryZone = deliveryZone,\n isDefault = isDefault\n ))(using c)\n }\n\n def showcaseAuditLog(\n id: AuditLogId = AuditLogId(random.alphanumeric.take(20).mkString),\n tableName: String = random.alphanumeric.take(20).mkString,\n recordId: String = random.alphanumeric.take(20).mkString,\n action: String = random.alphanumeric.take(20).mkString,\n oldValues: Option[/* max 4000 chars */ String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n newValues: Option[/* max 4000 chars */ String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n changedBy: Option[EmployeeId] = None,\n changedAt: Defaulted[Option[LocalDateTime]] = Defaulted.UseDefault()\n )(using c: Connection): AuditLogRow = {\n (new AuditLogRepoImpl()).insert(new AuditLogRowUnsaved(\n id = id,\n tableName = tableName,\n recordId = recordId,\n action = action,\n oldValues = oldValues,\n newValues = newValues,\n changedBy = changedBy,\n changedAt = changedAt\n ))(using c)\n }\n\n def showcaseCategory(\n id: CategoryId = CategoryId(random.alphanumeric.take(20).mkString),\n parentId: Option[CategoryId] = None,\n name: String = random.alphanumeric.take(20).mkString,\n description: Option[/* max 500 chars */ String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString)\n )(using c: Connection): CategoryRow = {\n (new CategoryRepoImpl()).insert(new CategoryRow(\n id = id,\n parentId = parentId,\n name = name,\n description = description\n ))(using c)\n }\n\n def showcaseCompany(\n id: CompanyId = CompanyId(random.alphanumeric.take(20).mkString),\n name: String = random.alphanumeric.take(20).mkString,\n foundedYear: Option[Int] = if (random.nextBoolean()) None else Some(random.nextInt()),\n active: Defaulted[Option[Boolean]] = Defaulted.UseDefault(),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.UseDefault()\n )(using c: Connection): CompanyRow = {\n (new CompanyRepoImpl()).insert(new CompanyRowUnsaved(\n id = id,\n name = name,\n foundedYear = foundedYear,\n active = active,\n createdAt = createdAt\n ))(using c)\n }\n\n def showcaseCustomer(\n id: CustomerId = CustomerId(random.alphanumeric.take(20).mkString),\n email: String = random.alphanumeric.take(20).mkString,\n firstName: String = random.alphanumeric.take(20).mkString,\n lastName: String = random.alphanumeric.take(20).mkString,\n phone: Option[/* max 20 chars */ String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n interests: Option[Array[String]] = if (random.nextBoolean()) None else Some(Array.fill(random.nextInt(3))(random.alphanumeric.take(20).mkString)),\n preferences: Option[Jsonb] = None,\n metadata: Option[Map[String, String]] = None,\n customerUid: Option[UUID] = if (random.nextBoolean()) None else Some(UUID.nameUUIDFromBytes{val bs = Array.ofDim[Byte](16); random.nextBytes(bs); bs}),\n avatar: Option[Array[Byte]] = None,\n verified: Defaulted[Option[Boolean]] = Defaulted.UseDefault(),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.UseDefault()\n )(using c: Connection): CustomerRow = {\n (new CustomerRepoImpl()).insert(new CustomerRowUnsaved(\n id = id,\n email = email,\n firstName = firstName,\n lastName = lastName,\n phone = phone,\n interests = interests,\n preferences = preferences,\n metadata = metadata,\n customerUid = customerUid,\n avatar = avatar,\n verified = verified,\n createdAt = createdAt\n ))(using c)\n }\n\n def showcaseCustomerOrder(\n customerId: CustomerId,\n id: CustomerOrderId = CustomerOrderId(random.alphanumeric.take(20).mkString),\n shippingAddressId: Option[AddressId] = None,\n billingAddressId: Option[AddressId] = None,\n subtotal: BigDecimal = BigDecimal.decimal(random.nextDouble()),\n total: BigDecimal = BigDecimal.decimal(random.nextDouble()),\n notes: Option[/* max 1000 chars */ String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n shippedAt: Option[LocalDateTime] = None,\n deliveredAt: Option[LocalDateTime] = None,\n orderUid: Option[UUID] = if (random.nextBoolean()) None else Some(UUID.nameUUIDFromBytes{val bs = Array.ofDim[Byte](16); random.nextBytes(bs); bs}),\n metadata: Option[Jsonb] = None,\n tags: Option[Array[String]] = if (random.nextBoolean()) None else Some(Array.fill(random.nextInt(3))(random.alphanumeric.take(20).mkString)),\n fulfillmentTimes: Option[Array[LocalDateTime]] = None,\n ipAddress: Option[Inet] = None,\n processingTime: Option[PGInterval] = None,\n status: Defaulted[Option[/* max 20 chars */ String]] = Defaulted.UseDefault(),\n tax: Defaulted[Option[BigDecimal]] = Defaulted.UseDefault(),\n shipping: Defaulted[Option[BigDecimal]] = Defaulted.UseDefault(),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.UseDefault()\n )(using c: Connection): CustomerOrderRow = {\n (new CustomerOrderRepoImpl()).insert(new CustomerOrderRowUnsaved(\n id = id,\n customerId = customerId,\n shippingAddressId = shippingAddressId,\n billingAddressId = billingAddressId,\n subtotal = subtotal,\n total = total,\n notes = notes,\n shippedAt = shippedAt,\n deliveredAt = deliveredAt,\n orderUid = orderUid,\n metadata = metadata,\n tags = tags,\n fulfillmentTimes = fulfillmentTimes,\n ipAddress = ipAddress,\n processingTime = processingTime,\n status = status,\n tax = tax,\n shipping = shipping,\n createdAt = createdAt\n ))(using c)\n }\n\n def showcaseDepartment(\n companyId: CompanyId,\n id: DepartmentId = DepartmentId(random.alphanumeric.take(20).mkString),\n name: String = random.alphanumeric.take(20).mkString,\n budget: Option[BigDecimal] = if (random.nextBoolean()) None else Some(BigDecimal.decimal(random.nextDouble()))\n )(using c: Connection): DepartmentRow = {\n (new DepartmentRepoImpl()).insert(new DepartmentRow(\n id = id,\n companyId = companyId,\n name = name,\n budget = budget\n ))(using c)\n }\n\n def showcaseEmployee(\n departmentId: DepartmentId,\n id: EmployeeId = EmployeeId(random.alphanumeric.take(20).mkString),\n managerId: Option[EmployeeId] = None,\n email: String = random.alphanumeric.take(20).mkString,\n firstName: String = random.alphanumeric.take(20).mkString,\n lastName: String = random.alphanumeric.take(20).mkString,\n salary: Option[BigDecimal] = if (random.nextBoolean()) None else Some(BigDecimal.decimal(random.nextDouble())),\n hiredAt: Option[LocalDate] = None,\n skills: Option[Array[String]] = if (random.nextBoolean()) None else Some(Array.fill(random.nextInt(3))(random.alphanumeric.take(20).mkString)),\n certifications: Option[Array[String]] = if (random.nextBoolean()) None else Some(Array.fill(random.nextInt(3))(random.alphanumeric.take(20).mkString)),\n metadata: Option[Jsonb] = None,\n settings: Option[Map[String, String]] = None,\n workSchedule: Option[Array[Boolean]] = if (random.nextBoolean()) None else Some(Array.fill(random.nextInt(3))(random.nextBoolean())),\n ipAddress: Option[Inet] = None,\n networkCidr: Option[Cidr] = None,\n macAddress: Option[MacAddr] = None,\n probationPeriod: Option[PGInterval] = None,\n photo: Option[Array[Byte]] = None,\n active: Defaulted[Option[Boolean]] = Defaulted.UseDefault(),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.UseDefault()\n )(using c: Connection): EmployeeRow = {\n (new EmployeeRepoImpl()).insert(new EmployeeRowUnsaved(\n id = id,\n departmentId = departmentId,\n managerId = managerId,\n email = email,\n firstName = firstName,\n lastName = lastName,\n salary = salary,\n hiredAt = hiredAt,\n skills = skills,\n certifications = certifications,\n metadata = metadata,\n settings = settings,\n workSchedule = workSchedule,\n ipAddress = ipAddress,\n networkCidr = networkCidr,\n macAddress = macAddress,\n probationPeriod = probationPeriod,\n photo = photo,\n active = active,\n createdAt = createdAt\n ))(using c)\n }\n\n def showcaseOrderItem(\n orderId: CustomerOrderId,\n productId: ProductId,\n quantity: Int = random.nextInt(),\n unitPrice: BigDecimal = BigDecimal.decimal(random.nextDouble()),\n discount: Defaulted[Option[BigDecimal]] = Defaulted.UseDefault()\n )(using c: Connection): OrderItemRow = {\n (new OrderItemRepoImpl()).insert(new OrderItemRowUnsaved(\n orderId = orderId,\n productId = productId,\n quantity = quantity,\n unitPrice = unitPrice,\n discount = discount\n ))(using c)\n }\n\n def showcaseProduct(\n id: ProductId = ProductId(random.alphanumeric.take(20).mkString),\n categoryId: Option[CategoryId] = None,\n name: String = random.alphanumeric.take(20).mkString,\n sku: String = random.alphanumeric.take(20).mkString,\n price: BigDecimal = BigDecimal.decimal(random.nextDouble()),\n cost: Option[BigDecimal] = if (random.nextBoolean()) None else Some(BigDecimal.decimal(random.nextDouble())),\n weight: Option[BigDecimal] = if (random.nextBoolean()) None else Some(BigDecimal.decimal(random.nextDouble())),\n tags: Option[Array[String]] = if (random.nextBoolean()) None else Some(Array.fill(random.nextInt(3))(random.alphanumeric.take(20).mkString)),\n images: Option[Array[String]] = if (random.nextBoolean()) None else Some(Array.fill(random.nextInt(3))(random.alphanumeric.take(20).mkString)),\n relatedSkus: Option[Array[String]] = if (random.nextBoolean()) None else Some(Array.fill(random.nextInt(3))(random.alphanumeric.take(20).mkString)),\n priceHistory: Option[Array[BigDecimal]] = if (random.nextBoolean()) None else Some(Array.fill(random.nextInt(3))(BigDecimal.decimal(random.nextDouble()))),\n attributes: Option[Jsonb] = None,\n specifications: Option[Jsonb] = None,\n seoMetadata: Option[Jsonb] = None,\n searchVector: Option[String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n productUid: Option[UUID] = if (random.nextBoolean()) None else Some(UUID.nameUUIDFromBytes{val bs = Array.ofDim[Byte](16); random.nextBytes(bs); bs}),\n inStock: Defaulted[Option[Boolean]] = Defaulted.UseDefault(),\n quantity: Defaulted[Option[Int]] = Defaulted.UseDefault(),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.UseDefault()\n )(using c: Connection): ProductRow = {\n (new ProductRepoImpl()).insert(new ProductRowUnsaved(\n id = id,\n categoryId = categoryId,\n name = name,\n sku = sku,\n price = price,\n cost = cost,\n weight = weight,\n tags = tags,\n images = images,\n relatedSkus = relatedSkus,\n priceHistory = priceHistory,\n attributes = attributes,\n specifications = specifications,\n seoMetadata = seoMetadata,\n searchVector = searchVector,\n productUid = productUid,\n inStock = inStock,\n quantity = quantity,\n createdAt = createdAt\n ))(using c)\n }\n\n def showcaseProject(\n id: ProjectId = ProjectId(random.alphanumeric.take(20).mkString),\n name: String = random.alphanumeric.take(20).mkString,\n description: Option[/* max 1000 chars */ String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n startDate: Option[LocalDate] = None,\n endDate: Option[LocalDate] = None,\n budget: Option[BigDecimal] = if (random.nextBoolean()) None else Some(BigDecimal.decimal(random.nextDouble())),\n projectUid: Option[UUID] = if (random.nextBoolean()) None else Some(UUID.nameUUIDFromBytes{val bs = Array.ofDim[Byte](16); random.nextBytes(bs); bs}),\n milestones: Option[Array[String]] = if (random.nextBoolean()) None else Some(Array.fill(random.nextInt(3))(random.alphanumeric.take(20).mkString)),\n budgetSnapshots: Option[Array[BigDecimal]] = if (random.nextBoolean()) None else Some(Array.fill(random.nextInt(3))(BigDecimal.decimal(random.nextDouble()))),\n teamMembers: Option[Array[String]] = if (random.nextBoolean()) None else Some(Array.fill(random.nextInt(3))(random.alphanumeric.take(20).mkString)),\n metadata: Option[Jsonb] = None,\n config: Option[Map[String, String]] = None,\n estimatedDuration: Option[PGInterval] = None,\n actualDuration: Option[PGInterval] = None,\n status: Defaulted[Option[/* max 20 chars */ String]] = Defaulted.UseDefault(),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.UseDefault()\n )(using c: Connection): ProjectRow = {\n (new ProjectRepoImpl()).insert(new ProjectRowUnsaved(\n id = id,\n name = name,\n description = description,\n startDate = startDate,\n endDate = endDate,\n budget = budget,\n projectUid = projectUid,\n milestones = milestones,\n budgetSnapshots = budgetSnapshots,\n teamMembers = teamMembers,\n metadata = metadata,\n config = config,\n estimatedDuration = estimatedDuration,\n actualDuration = actualDuration,\n status = status,\n createdAt = createdAt\n ))(using c)\n }\n\n def showcaseProjectAssignment(\n employeeId: EmployeeId,\n projectId: ProjectId,\n role: String = random.alphanumeric.take(20).mkString,\n startDate: Option[LocalDate] = None,\n endDate: Option[LocalDate] = None,\n hoursAllocated: Defaulted[Option[Int]] = Defaulted.UseDefault()\n )(using c: Connection): ProjectAssignmentRow = {\n (new ProjectAssignmentRepoImpl()).insert(new ProjectAssignmentRowUnsaved(\n employeeId = employeeId,\n projectId = projectId,\n role = role,\n startDate = startDate,\n endDate = endDate,\n hoursAllocated = hoursAllocated\n ))(using c)\n }\n}" - } - }, - "mariadb": { - "java": { - "CompanyRow": "package showcase.showcase.company;\n\nimport dev.typr.foundations.MariaTypes;\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport java.time.LocalDateTime;\nimport java.util.Optional;\nimport showcase.customtypes.Defaulted;\n\n/** Table: showcase.company\n * Primary key: id\n */\npublic record CompanyRow(\n CompanyId id,\n String name,\n Optional foundedYear,\n /** Default: true */\n Optional active,\n /** Default: CURRENT_TIMESTAMP */\n Optional createdAt\n) {\n public CompanyRow withId(CompanyId id) {\n return new CompanyRow(id, name, foundedYear, active, createdAt);\n };\n\n public CompanyRow withName(String name) {\n return new CompanyRow(id, name, foundedYear, active, createdAt);\n };\n\n public CompanyRow withFoundedYear(Optional foundedYear) {\n return new CompanyRow(id, name, foundedYear, active, createdAt);\n };\n\n /** Default: true */\n public CompanyRow withActive(Optional active) {\n return new CompanyRow(id, name, foundedYear, active, createdAt);\n };\n\n /** Default: CURRENT_TIMESTAMP */\n public CompanyRow withCreatedAt(Optional createdAt) {\n return new CompanyRow(id, name, foundedYear, active, createdAt);\n };\n\n public static RowParser _rowParser = RowParsers.of(CompanyId.pgType, MariaTypes.varchar, MariaTypes.int_.opt(), MariaTypes.bool.opt(), MariaTypes.timestamp.opt(), CompanyRow::new, row -> new Object[]{row.id(), row.name(), row.foundedYear(), row.active(), row.createdAt()});;\n\n public CompanyRowUnsaved toUnsavedRow(\n Defaulted> active,\n Defaulted> createdAt\n ) {\n return new CompanyRowUnsaved(id, name, foundedYear, active, createdAt);\n };\n}", - "CompanyRowUnsaved": "package showcase.showcase.company;\n\nimport java.time.LocalDateTime;\nimport java.util.Optional;\nimport showcase.customtypes.Defaulted;\nimport showcase.customtypes.Defaulted.UseDefault;\n\n/** This class corresponds to a row in table `showcase.company` which has not been persisted yet */\npublic record CompanyRowUnsaved(\n CompanyId id,\n String name,\n Optional foundedYear,\n /** Default: true */\n Defaulted> active,\n /** Default: CURRENT_TIMESTAMP */\n Defaulted> createdAt\n) {\n public CompanyRowUnsaved(\n CompanyId id,\n String name\n ) {\n this(id, name, Optional.empty(), new UseDefault<>(), new UseDefault<>());\n };\n\n public CompanyRowUnsaved withId(CompanyId id) {\n return new CompanyRowUnsaved(id, name, foundedYear, active, createdAt);\n };\n\n public CompanyRowUnsaved withName(String name) {\n return new CompanyRowUnsaved(id, name, foundedYear, active, createdAt);\n };\n\n public CompanyRowUnsaved withFoundedYear(Optional foundedYear) {\n return new CompanyRowUnsaved(id, name, foundedYear, active, createdAt);\n };\n\n /** Default: true */\n public CompanyRowUnsaved withActive(Defaulted> active) {\n return new CompanyRowUnsaved(id, name, foundedYear, active, createdAt);\n };\n\n /** Default: CURRENT_TIMESTAMP */\n public CompanyRowUnsaved withCreatedAt(Defaulted> createdAt) {\n return new CompanyRowUnsaved(id, name, foundedYear, active, createdAt);\n };\n\n public CompanyRow toRow(\n java.util.function.Supplier> activeDefault,\n java.util.function.Supplier> createdAtDefault\n ) {\n return new CompanyRow(id, name, foundedYear, active.getOrElse(activeDefault), createdAt.getOrElse(createdAtDefault));\n };\n}", - "CompanyId": "package showcase.showcase.company;\n\nimport dev.typr.foundations.MariaType;\nimport dev.typr.foundations.MariaTypes;\nimport dev.typr.foundations.dsl.Bijection;\n\n/** Type for the primary key of table `showcase.company` */\npublic record CompanyId(String value) {\n public CompanyId withValue(String value) {\n return new CompanyId(value);\n };\n\n @Override\n public java.lang.String toString() {\n return value.toString();\n };\n\n static public Bijection bijection =\n Bijection.of(CompanyId::value, CompanyId::new);\n\n static public MariaType pgType =\n MariaTypes.varchar.bimap(CompanyId::new, CompanyId::value);\n}", - "CompanyRepo": "package showcase.showcase.company;\n\nimport dev.typr.foundations.dsl.DeleteBuilder;\nimport dev.typr.foundations.dsl.SelectBuilder;\nimport dev.typr.foundations.dsl.UpdateBuilder;\nimport java.sql.Connection;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\n\npublic interface CompanyRepo {\n DeleteBuilder delete();\n\n Boolean deleteById(\n CompanyId id,\n Connection c\n );\n\n Integer deleteByIds(\n CompanyId[] ids,\n Connection c\n );\n\n CompanyRow insert(\n CompanyRow unsaved,\n Connection c\n );\n\n CompanyRow insert(\n CompanyRowUnsaved unsaved,\n Connection c\n );\n\n SelectBuilder select();\n\n List selectAll(Connection c);\n\n Optional selectById(\n CompanyId id,\n Connection c\n );\n\n List selectByIds(\n CompanyId[] ids,\n Connection c\n );\n\n Map selectByIdsTracked(\n CompanyId[] ids,\n Connection c\n );\n\n UpdateBuilder update();\n\n Boolean update(\n CompanyRow row,\n Connection c\n );\n\n CompanyRow upsert(\n CompanyRow unsaved,\n Connection c\n );\n\n List upsertBatch(\n Iterator unsaved,\n Connection c\n );\n}", - "CompanyRepoMock": "package showcase.showcase.company;\n\nimport dev.typr.foundations.dsl.DeleteBuilder;\nimport dev.typr.foundations.dsl.DeleteBuilderMock;\nimport dev.typr.foundations.dsl.DeleteParams;\nimport dev.typr.foundations.dsl.SelectBuilder;\nimport dev.typr.foundations.dsl.SelectBuilderMock;\nimport dev.typr.foundations.dsl.SelectParams;\nimport dev.typr.foundations.dsl.UpdateBuilder;\nimport dev.typr.foundations.dsl.UpdateBuilderMock;\nimport dev.typr.foundations.dsl.UpdateParams;\nimport java.lang.RuntimeException;\nimport java.sql.Connection;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\nimport java.util.function.Function;\nimport java.util.stream.Collectors;\n\npublic record CompanyRepoMock(\n java.util.function.Function toRow,\n HashMap map\n) implements CompanyRepo {\n public CompanyRepoMock(java.util.function.Function toRow) {\n this(toRow, new HashMap());\n };\n\n public CompanyRepoMock withToRow(java.util.function.Function toRow) {\n return new CompanyRepoMock(toRow, map);\n };\n\n public CompanyRepoMock withMap(HashMap map) {\n return new CompanyRepoMock(toRow, map);\n };\n\n @Override\n public DeleteBuilder delete() {\n return new DeleteBuilderMock<>(CompanyFields.structure(), () -> new ArrayList<>(map.values()), DeleteParams.empty(), row -> row.id(), id -> map.remove(id));\n };\n\n @Override\n public Boolean deleteById(\n CompanyId id,\n Connection c\n ) {\n return Optional.ofNullable(map.remove(id)).isPresent();\n };\n\n @Override\n public Integer deleteByIds(\n CompanyId[] ids,\n Connection c\n ) {\n var count = 0;\n for (var id : ids) {\n if (Optional.ofNullable(map.remove(id)).isPresent()) {\n count = count + 1;;\n };\n };\n return count;\n };\n\n @Override\n public CompanyRow insert(\n CompanyRow unsaved,\n Connection c\n ) {\n if (map.containsKey(unsaved.id())) {\n throw new RuntimeException(\"id \" + unsaved.id() + \" already exists\");\n };\n map.put(unsaved.id(), unsaved);\n return unsaved;\n };\n\n @Override\n public CompanyRow insert(\n CompanyRowUnsaved unsaved,\n Connection c\n ) {\n return insert(toRow.apply(unsaved), c);\n };\n\n @Override\n public SelectBuilder select() {\n return new SelectBuilderMock<>(CompanyFields.structure(), () -> new ArrayList<>(map.values()), SelectParams.empty());\n };\n\n @Override\n public List selectAll(Connection c) {\n return new ArrayList<>(map.values());\n };\n\n @Override\n public Optional selectById(\n CompanyId id,\n Connection c\n ) {\n return Optional.ofNullable(map.get(id));\n };\n\n @Override\n public List selectByIds(\n CompanyId[] ids,\n Connection c\n ) {\n var result = new ArrayList();\n for (var id : ids) {\n var opt = Optional.ofNullable(map.get(id));\n if (opt.isPresent()) {\n result.add(opt.get());\n };\n };\n return result;\n };\n\n @Override\n public Map selectByIdsTracked(\n CompanyId[] ids,\n Connection c\n ) {\n return selectByIds(ids, c).stream().collect(Collectors.toMap((CompanyRow row) -> row.id(), Function.identity()));\n };\n\n @Override\n public UpdateBuilder update() {\n return new UpdateBuilderMock<>(CompanyFields.structure(), () -> new ArrayList<>(map.values()), UpdateParams.empty(), row -> row);\n };\n\n @Override\n public Boolean update(\n CompanyRow row,\n Connection c\n ) {\n var shouldUpdate = Optional.ofNullable(map.get(row.id())).filter(oldRow -> !oldRow.equals(row)).isPresent();\n if (shouldUpdate) {\n map.put(row.id(), row);;\n };\n return shouldUpdate;\n };\n\n @Override\n public CompanyRow upsert(\n CompanyRow unsaved,\n Connection c\n ) {\n map.put(unsaved.id(), unsaved);\n return unsaved;\n };\n\n @Override\n public List upsertBatch(\n Iterator unsaved,\n Connection c\n ) {\n var result = new ArrayList();\n while (unsaved.hasNext()) {\n var row = unsaved.next();\n map.put(row.id(), row);\n result.add(row);\n };\n return result;\n };\n}", - "EmployeeRow": "package showcase.showcase.employee;\n\nimport dev.typr.foundations.MariaTypes;\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport dev.typr.foundations.data.Json;\nimport dev.typr.foundations.data.maria.Inet4;\nimport dev.typr.foundations.data.maria.MariaSet;\nimport java.math.BigDecimal;\nimport java.time.LocalDate;\nimport java.time.LocalDateTime;\nimport java.util.Optional;\nimport showcase.customtypes.Defaulted;\nimport showcase.showcase.department.DepartmentId;\n\n/** Table: showcase.employee\n * Primary key: id\n */\npublic record EmployeeRow(\n EmployeeId id,\n /** Points to {@link showcase.showcase.department.DepartmentRow#id()} */\n DepartmentId departmentId,\n /** Points to {@link showcase.showcase.employee.EmployeeRow#id()} */\n Optional managerId,\n String email,\n String firstName,\n String lastName,\n Optional salary,\n Optional hiredAt,\n /** Default: true */\n Optional active,\n /** Default: CURRENT_TIMESTAMP */\n Optional createdAt,\n Optional metadata,\n Optional photo,\n Optional ipAddress,\n Optional permissions\n) {\n public EmployeeRow withId(EmployeeId id) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, metadata, photo, ipAddress, permissions);\n };\n\n /** Points to {@link showcase.showcase.department.DepartmentRow#id()} */\n public EmployeeRow withDepartmentId(DepartmentId departmentId) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, metadata, photo, ipAddress, permissions);\n };\n\n /** Points to {@link showcase.showcase.employee.EmployeeRow#id()} */\n public EmployeeRow withManagerId(Optional managerId) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, metadata, photo, ipAddress, permissions);\n };\n\n public EmployeeRow withEmail(String email) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, metadata, photo, ipAddress, permissions);\n };\n\n public EmployeeRow withFirstName(String firstName) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, metadata, photo, ipAddress, permissions);\n };\n\n public EmployeeRow withLastName(String lastName) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, metadata, photo, ipAddress, permissions);\n };\n\n public EmployeeRow withSalary(Optional salary) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, metadata, photo, ipAddress, permissions);\n };\n\n public EmployeeRow withHiredAt(Optional hiredAt) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, metadata, photo, ipAddress, permissions);\n };\n\n /** Default: true */\n public EmployeeRow withActive(Optional active) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, metadata, photo, ipAddress, permissions);\n };\n\n /** Default: CURRENT_TIMESTAMP */\n public EmployeeRow withCreatedAt(Optional createdAt) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, metadata, photo, ipAddress, permissions);\n };\n\n public EmployeeRow withMetadata(Optional metadata) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, metadata, photo, ipAddress, permissions);\n };\n\n public EmployeeRow withPhoto(Optional photo) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, metadata, photo, ipAddress, permissions);\n };\n\n public EmployeeRow withIpAddress(Optional ipAddress) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, metadata, photo, ipAddress, permissions);\n };\n\n public EmployeeRow withPermissions(Optional permissions) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, metadata, photo, ipAddress, permissions);\n };\n\n public static RowParser _rowParser = RowParsers.of(EmployeeId.pgType, DepartmentId.pgType, EmployeeId.pgType.opt(), MariaTypes.varchar, MariaTypes.varchar, MariaTypes.varchar, MariaTypes.numeric.opt(), MariaTypes.date.opt(), MariaTypes.bool.opt(), MariaTypes.timestamp.opt(), MariaTypes.json.opt(), MariaTypes.mediumblob.opt(), MariaTypes.inet4.opt(), MariaTypes.set.opt(), EmployeeRow::new, row -> new Object[]{row.id(), row.departmentId(), row.managerId(), row.email(), row.firstName(), row.lastName(), row.salary(), row.hiredAt(), row.active(), row.createdAt(), row.metadata(), row.photo(), row.ipAddress(), row.permissions()});;\n\n public EmployeeRowUnsaved toUnsavedRow(\n Defaulted> active,\n Defaulted> createdAt\n ) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, metadata, photo, ipAddress, permissions, active, createdAt);\n };\n}", - "EmployeeRowUnsaved": "package showcase.showcase.employee;\n\nimport dev.typr.foundations.data.Json;\nimport dev.typr.foundations.data.maria.Inet4;\nimport dev.typr.foundations.data.maria.MariaSet;\nimport java.math.BigDecimal;\nimport java.time.LocalDate;\nimport java.time.LocalDateTime;\nimport java.util.Optional;\nimport showcase.customtypes.Defaulted;\nimport showcase.customtypes.Defaulted.UseDefault;\nimport showcase.showcase.department.DepartmentId;\n\n/** This class corresponds to a row in table `showcase.employee` which has not been persisted yet */\npublic record EmployeeRowUnsaved(\n EmployeeId id,\n /** Points to {@link showcase.showcase.department.DepartmentRow#id()} */\n DepartmentId departmentId,\n /** Points to {@link showcase.showcase.employee.EmployeeRow#id()} */\n Optional managerId,\n String email,\n String firstName,\n String lastName,\n Optional salary,\n Optional hiredAt,\n Optional metadata,\n Optional photo,\n Optional ipAddress,\n Optional permissions,\n /** Default: true */\n Defaulted> active,\n /** Default: CURRENT_TIMESTAMP */\n Defaulted> createdAt\n) {\n public EmployeeRowUnsaved(\n EmployeeId id,\n /** Points to {@link showcase.showcase.department.DepartmentRow#id()} */\n DepartmentId departmentId,\n String email,\n String firstName,\n String lastName\n ) {\n this(id, departmentId, Optional.empty(), email, firstName, lastName, Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), new UseDefault<>(), new UseDefault<>());\n };\n\n public EmployeeRowUnsaved withId(EmployeeId id) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, metadata, photo, ipAddress, permissions, active, createdAt);\n };\n\n /** Points to {@link showcase.showcase.department.DepartmentRow#id()} */\n public EmployeeRowUnsaved withDepartmentId(DepartmentId departmentId) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, metadata, photo, ipAddress, permissions, active, createdAt);\n };\n\n /** Points to {@link showcase.showcase.employee.EmployeeRow#id()} */\n public EmployeeRowUnsaved withManagerId(Optional managerId) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, metadata, photo, ipAddress, permissions, active, createdAt);\n };\n\n public EmployeeRowUnsaved withEmail(String email) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, metadata, photo, ipAddress, permissions, active, createdAt);\n };\n\n public EmployeeRowUnsaved withFirstName(String firstName) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, metadata, photo, ipAddress, permissions, active, createdAt);\n };\n\n public EmployeeRowUnsaved withLastName(String lastName) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, metadata, photo, ipAddress, permissions, active, createdAt);\n };\n\n public EmployeeRowUnsaved withSalary(Optional salary) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, metadata, photo, ipAddress, permissions, active, createdAt);\n };\n\n public EmployeeRowUnsaved withHiredAt(Optional hiredAt) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, metadata, photo, ipAddress, permissions, active, createdAt);\n };\n\n public EmployeeRowUnsaved withMetadata(Optional metadata) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, metadata, photo, ipAddress, permissions, active, createdAt);\n };\n\n public EmployeeRowUnsaved withPhoto(Optional photo) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, metadata, photo, ipAddress, permissions, active, createdAt);\n };\n\n public EmployeeRowUnsaved withIpAddress(Optional ipAddress) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, metadata, photo, ipAddress, permissions, active, createdAt);\n };\n\n public EmployeeRowUnsaved withPermissions(Optional permissions) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, metadata, photo, ipAddress, permissions, active, createdAt);\n };\n\n /** Default: true */\n public EmployeeRowUnsaved withActive(Defaulted> active) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, metadata, photo, ipAddress, permissions, active, createdAt);\n };\n\n /** Default: CURRENT_TIMESTAMP */\n public EmployeeRowUnsaved withCreatedAt(Defaulted> createdAt) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, metadata, photo, ipAddress, permissions, active, createdAt);\n };\n\n public EmployeeRow toRow(\n java.util.function.Supplier> activeDefault,\n java.util.function.Supplier> createdAtDefault\n ) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active.getOrElse(activeDefault), createdAt.getOrElse(createdAtDefault), metadata, photo, ipAddress, permissions);\n };\n}", - "EmployeeId": "package showcase.showcase.employee;\n\nimport dev.typr.foundations.MariaType;\nimport dev.typr.foundations.MariaTypes;\nimport dev.typr.foundations.dsl.Bijection;\n\n/** Type for the primary key of table `showcase.employee` */\npublic record EmployeeId(String value) {\n public EmployeeId withValue(String value) {\n return new EmployeeId(value);\n };\n\n @Override\n public java.lang.String toString() {\n return value.toString();\n };\n\n static public Bijection bijection =\n Bijection.of(EmployeeId::value, EmployeeId::new);\n\n static public MariaType pgType =\n MariaTypes.varchar.bimap(EmployeeId::new, EmployeeId::value);\n}", - "EmployeeRepo": "package showcase.showcase.employee;\n\nimport dev.typr.foundations.dsl.DeleteBuilder;\nimport dev.typr.foundations.dsl.SelectBuilder;\nimport dev.typr.foundations.dsl.UpdateBuilder;\nimport java.sql.Connection;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\n\npublic interface EmployeeRepo {\n DeleteBuilder delete();\n\n Boolean deleteById(\n EmployeeId id,\n Connection c\n );\n\n Integer deleteByIds(\n EmployeeId[] ids,\n Connection c\n );\n\n EmployeeRow insert(\n EmployeeRow unsaved,\n Connection c\n );\n\n EmployeeRow insert(\n EmployeeRowUnsaved unsaved,\n Connection c\n );\n\n SelectBuilder select();\n\n List selectAll(Connection c);\n\n Optional selectById(\n EmployeeId id,\n Connection c\n );\n\n List selectByIds(\n EmployeeId[] ids,\n Connection c\n );\n\n Map selectByIdsTracked(\n EmployeeId[] ids,\n Connection c\n );\n\n Optional selectByUniqueEmail(\n String email,\n Connection c\n );\n\n UpdateBuilder update();\n\n Boolean update(\n EmployeeRow row,\n Connection c\n );\n\n EmployeeRow upsert(\n EmployeeRow unsaved,\n Connection c\n );\n\n List upsertBatch(\n Iterator unsaved,\n Connection c\n );\n}", - "EmployeeRepoImpl": "package showcase.showcase.employee;\n\nimport dev.typr.foundations.Fragment;\nimport dev.typr.foundations.MariaTypes;\nimport dev.typr.foundations.dsl.DeleteBuilder;\nimport dev.typr.foundations.dsl.Dialect;\nimport dev.typr.foundations.dsl.SelectBuilder;\nimport dev.typr.foundations.dsl.UpdateBuilder;\nimport java.sql.Connection;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\nimport showcase.showcase.department.DepartmentId;\nimport static dev.typr.foundations.Fragment.interpolate;\n\npublic class EmployeeRepoImpl implements EmployeeRepo {\n @Override\n public DeleteBuilder delete() {\n return DeleteBuilder.of(\"`showcase`.`employee`\", EmployeeFields.structure(), Dialect.MARIADB);\n };\n\n @Override\n public Boolean deleteById(\n EmployeeId id,\n Connection c\n ) {\n return interpolate(Fragment.lit(\"delete from `showcase`.`employee` where `id` = \"), Fragment.encode(EmployeeId.pgType, id), Fragment.lit(\"\")).update().runUnchecked(c) > 0;\n };\n\n @Override\n public Integer deleteByIds(\n EmployeeId[] ids,\n Connection c\n ) {\n ArrayList fragments = new ArrayList<>();\n for (var id : ids) { fragments.add(Fragment.encode(EmployeeId.pgType, id)); };\n return Fragment.interpolate(Fragment.lit(\"delete from `showcase`.`employee` where `id` in (\"), Fragment.comma(fragments), Fragment.lit(\")\")).update().runUnchecked(c);\n };\n\n @Override\n public EmployeeRow insert(\n EmployeeRow unsaved,\n Connection c\n ) {\n return interpolate(Fragment.lit(\"insert into `showcase`.`employee`(`id`, `department_id`, `manager_id`, `email`, `first_name`, `last_name`, `salary`, `hired_at`, `active`, `created_at`, `metadata`, `photo`, `ip_address`, `permissions`)\\nvalues (\"), Fragment.encode(EmployeeId.pgType, unsaved.id()), Fragment.lit(\", \"), Fragment.encode(DepartmentId.pgType, unsaved.departmentId()), Fragment.lit(\", \"), Fragment.encode(EmployeeId.pgType.opt(), unsaved.managerId()), Fragment.lit(\", \"), Fragment.encode(MariaTypes.varchar, unsaved.email()), Fragment.lit(\", \"), Fragment.encode(MariaTypes.varchar, unsaved.firstName()), Fragment.lit(\", \"), Fragment.encode(MariaTypes.varchar, unsaved.lastName()), Fragment.lit(\", \"), Fragment.encode(MariaTypes.numeric.opt(), unsaved.salary()), Fragment.lit(\", \"), Fragment.encode(MariaTypes.date.opt(), unsaved.hiredAt()), Fragment.lit(\", \"), Fragment.encode(MariaTypes.bool.opt(), unsaved.active()), Fragment.lit(\", \"), Fragment.encode(MariaTypes.timestamp.opt(), unsaved.createdAt()), Fragment.lit(\", \"), Fragment.encode(MariaTypes.json.opt(), unsaved.metadata()), Fragment.lit(\", \"), Fragment.encode(MariaTypes.mediumblob.opt(), unsaved.photo()), Fragment.lit(\", \"), Fragment.encode(MariaTypes.inet4.opt(), unsaved.ipAddress()), Fragment.lit(\", \"), Fragment.encode(MariaTypes.set.opt(), unsaved.permissions()), Fragment.lit(\")\\nRETURNING `id`, `department_id`, `manager_id`, `email`, `first_name`, `last_name`, `salary`, `hired_at`, `active`, `created_at`, `metadata`, `photo`, `ip_address`, `permissions`\\n\"))\n .updateReturning(EmployeeRow._rowParser.exactlyOne()).runUnchecked(c);\n };\n\n @Override\n public EmployeeRow insert(\n EmployeeRowUnsaved unsaved,\n Connection c\n ) {\n ArrayList columns = new ArrayList<>();;\n ArrayList values = new ArrayList<>();;\n columns.add(Fragment.lit(\"`id`\"));\n values.add(interpolate(Fragment.encode(EmployeeId.pgType, unsaved.id()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"`department_id`\"));\n values.add(interpolate(Fragment.encode(DepartmentId.pgType, unsaved.departmentId()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"`manager_id`\"));\n values.add(interpolate(Fragment.encode(EmployeeId.pgType.opt(), unsaved.managerId()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"`email`\"));\n values.add(interpolate(Fragment.encode(MariaTypes.varchar, unsaved.email()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"`first_name`\"));\n values.add(interpolate(Fragment.encode(MariaTypes.varchar, unsaved.firstName()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"`last_name`\"));\n values.add(interpolate(Fragment.encode(MariaTypes.varchar, unsaved.lastName()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"`salary`\"));\n values.add(interpolate(Fragment.encode(MariaTypes.numeric.opt(), unsaved.salary()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"`hired_at`\"));\n values.add(interpolate(Fragment.encode(MariaTypes.date.opt(), unsaved.hiredAt()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"`metadata`\"));\n values.add(interpolate(Fragment.encode(MariaTypes.json.opt(), unsaved.metadata()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"`photo`\"));\n values.add(interpolate(Fragment.encode(MariaTypes.mediumblob.opt(), unsaved.photo()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"`ip_address`\"));\n values.add(interpolate(Fragment.encode(MariaTypes.inet4.opt(), unsaved.ipAddress()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"`permissions`\"));\n values.add(interpolate(Fragment.encode(MariaTypes.set.opt(), unsaved.permissions()), Fragment.lit(\"\")));\n unsaved.active().visit(\n () -> {\n \n },\n value -> {\n columns.add(Fragment.lit(\"`active`\"));\n values.add(interpolate(Fragment.encode(MariaTypes.bool.opt(), value), Fragment.lit(\"\")));\n }\n );;\n unsaved.createdAt().visit(\n () -> {\n \n },\n value -> {\n columns.add(Fragment.lit(\"`created_at`\"));\n values.add(interpolate(Fragment.encode(MariaTypes.timestamp.opt(), value), Fragment.lit(\"\")));\n }\n );;\n Fragment q = interpolate(Fragment.lit(\"insert into `showcase`.`employee`(\"), Fragment.comma(columns), Fragment.lit(\")\\nvalues (\"), Fragment.comma(values), Fragment.lit(\")\\nRETURNING `id`, `department_id`, `manager_id`, `email`, `first_name`, `last_name`, `salary`, `hired_at`, `active`, `created_at`, `metadata`, `photo`, `ip_address`, `permissions`\\n\"));;\n return q.updateReturning(EmployeeRow._rowParser.exactlyOne()).runUnchecked(c);\n };\n\n @Override\n public SelectBuilder select() {\n return SelectBuilder.of(\"`showcase`.`employee`\", EmployeeFields.structure(), EmployeeRow._rowParser, Dialect.MARIADB);\n };\n\n @Override\n public List selectAll(Connection c) {\n return interpolate(Fragment.lit(\"select `id`, `department_id`, `manager_id`, `email`, `first_name`, `last_name`, `salary`, `hired_at`, `active`, `created_at`, `metadata`, `photo`, `ip_address`, `permissions`\\nfrom `showcase`.`employee`\\n\")).query(EmployeeRow._rowParser.all()).runUnchecked(c);\n };\n\n @Override\n public Optional selectById(\n EmployeeId id,\n Connection c\n ) {\n return interpolate(Fragment.lit(\"select `id`, `department_id`, `manager_id`, `email`, `first_name`, `last_name`, `salary`, `hired_at`, `active`, `created_at`, `metadata`, `photo`, `ip_address`, `permissions`\\nfrom `showcase`.`employee`\\nwhere `id` = \"), Fragment.encode(EmployeeId.pgType, id), Fragment.lit(\"\")).query(EmployeeRow._rowParser.first()).runUnchecked(c);\n };\n\n @Override\n public List selectByIds(\n EmployeeId[] ids,\n Connection c\n ) {\n ArrayList fragments = new ArrayList<>();\n for (var id : ids) { fragments.add(Fragment.encode(EmployeeId.pgType, id)); };\n return Fragment.interpolate(Fragment.lit(\"select `id`, `department_id`, `manager_id`, `email`, `first_name`, `last_name`, `salary`, `hired_at`, `active`, `created_at`, `metadata`, `photo`, `ip_address`, `permissions` from `showcase`.`employee` where `id` in (\"), Fragment.comma(fragments), Fragment.lit(\")\")).query(EmployeeRow._rowParser.all()).runUnchecked(c);\n };\n\n @Override\n public Map selectByIdsTracked(\n EmployeeId[] ids,\n Connection c\n ) {\n HashMap ret = new HashMap();\n selectByIds(ids, c).forEach(row -> ret.put(row.id(), row));\n return ret;\n };\n\n @Override\n public Optional selectByUniqueEmail(\n String email,\n Connection c\n ) {\n return interpolate(Fragment.lit(\"select `id`, `department_id`, `manager_id`, `email`, `first_name`, `last_name`, `salary`, `hired_at`, `active`, `created_at`, `metadata`, `photo`, `ip_address`, `permissions`\\nfrom `showcase`.`employee`\\nwhere `email` = \"), Fragment.encode(MariaTypes.varchar, email), Fragment.lit(\"\\n\")).query(EmployeeRow._rowParser.first()).runUnchecked(c);\n };\n\n @Override\n public UpdateBuilder update() {\n return UpdateBuilder.of(\"`showcase`.`employee`\", EmployeeFields.structure(), EmployeeRow._rowParser, Dialect.MARIADB);\n };\n\n @Override\n public Boolean update(\n EmployeeRow row,\n Connection c\n ) {\n EmployeeId id = row.id();;\n return interpolate(Fragment.lit(\"update `showcase`.`employee`\\nset `department_id` = \"), Fragment.encode(DepartmentId.pgType, row.departmentId()), Fragment.lit(\",\\n`manager_id` = \"), Fragment.encode(EmployeeId.pgType.opt(), row.managerId()), Fragment.lit(\",\\n`email` = \"), Fragment.encode(MariaTypes.varchar, row.email()), Fragment.lit(\",\\n`first_name` = \"), Fragment.encode(MariaTypes.varchar, row.firstName()), Fragment.lit(\",\\n`last_name` = \"), Fragment.encode(MariaTypes.varchar, row.lastName()), Fragment.lit(\",\\n`salary` = \"), Fragment.encode(MariaTypes.numeric.opt(), row.salary()), Fragment.lit(\",\\n`hired_at` = \"), Fragment.encode(MariaTypes.date.opt(), row.hiredAt()), Fragment.lit(\",\\n`active` = \"), Fragment.encode(MariaTypes.bool.opt(), row.active()), Fragment.lit(\",\\n`created_at` = \"), Fragment.encode(MariaTypes.timestamp.opt(), row.createdAt()), Fragment.lit(\",\\n`metadata` = \"), Fragment.encode(MariaTypes.json.opt(), row.metadata()), Fragment.lit(\",\\n`photo` = \"), Fragment.encode(MariaTypes.mediumblob.opt(), row.photo()), Fragment.lit(\",\\n`ip_address` = \"), Fragment.encode(MariaTypes.inet4.opt(), row.ipAddress()), Fragment.lit(\",\\n`permissions` = \"), Fragment.encode(MariaTypes.set.opt(), row.permissions()), Fragment.lit(\"\\nwhere `id` = \"), Fragment.encode(EmployeeId.pgType, id), Fragment.lit(\"\")).update().runUnchecked(c) > 0;\n };\n\n @Override\n public EmployeeRow upsert(\n EmployeeRow unsaved,\n Connection c\n ) {\n return interpolate(Fragment.lit(\"INSERT INTO `showcase`.`employee`(`id`, `department_id`, `manager_id`, `email`, `first_name`, `last_name`, `salary`, `hired_at`, `active`, `created_at`, `metadata`, `photo`, `ip_address`, `permissions`)\\nVALUES (\"), Fragment.encode(EmployeeId.pgType, unsaved.id()), Fragment.lit(\", \"), Fragment.encode(DepartmentId.pgType, unsaved.departmentId()), Fragment.lit(\", \"), Fragment.encode(EmployeeId.pgType.opt(), unsaved.managerId()), Fragment.lit(\", \"), Fragment.encode(MariaTypes.varchar, unsaved.email()), Fragment.lit(\", \"), Fragment.encode(MariaTypes.varchar, unsaved.firstName()), Fragment.lit(\", \"), Fragment.encode(MariaTypes.varchar, unsaved.lastName()), Fragment.lit(\", \"), Fragment.encode(MariaTypes.numeric.opt(), unsaved.salary()), Fragment.lit(\", \"), Fragment.encode(MariaTypes.date.opt(), unsaved.hiredAt()), Fragment.lit(\", \"), Fragment.encode(MariaTypes.bool.opt(), unsaved.active()), Fragment.lit(\", \"), Fragment.encode(MariaTypes.timestamp.opt(), unsaved.createdAt()), Fragment.lit(\", \"), Fragment.encode(MariaTypes.json.opt(), unsaved.metadata()), Fragment.lit(\", \"), Fragment.encode(MariaTypes.mediumblob.opt(), unsaved.photo()), Fragment.lit(\", \"), Fragment.encode(MariaTypes.inet4.opt(), unsaved.ipAddress()), Fragment.lit(\", \"), Fragment.encode(MariaTypes.set.opt(), unsaved.permissions()), Fragment.lit(\")\\nON DUPLICATE KEY UPDATE `department_id` = VALUES(`department_id`),\\n`manager_id` = VALUES(`manager_id`),\\n`email` = VALUES(`email`),\\n`first_name` = VALUES(`first_name`),\\n`last_name` = VALUES(`last_name`),\\n`salary` = VALUES(`salary`),\\n`hired_at` = VALUES(`hired_at`),\\n`active` = VALUES(`active`),\\n`created_at` = VALUES(`created_at`),\\n`metadata` = VALUES(`metadata`),\\n`photo` = VALUES(`photo`),\\n`ip_address` = VALUES(`ip_address`),\\n`permissions` = VALUES(`permissions`)\\nRETURNING `id`, `department_id`, `manager_id`, `email`, `first_name`, `last_name`, `salary`, `hired_at`, `active`, `created_at`, `metadata`, `photo`, `ip_address`, `permissions`\"))\n .updateReturning(EmployeeRow._rowParser.exactlyOne())\n .runUnchecked(c);\n };\n\n @Override\n public List upsertBatch(\n Iterator unsaved,\n Connection c\n ) {\n return interpolate(Fragment.lit(\"INSERT INTO `showcase`.`employee`(`id`, `department_id`, `manager_id`, `email`, `first_name`, `last_name`, `salary`, `hired_at`, `active`, `created_at`, `metadata`, `photo`, `ip_address`, `permissions`)\\nVALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\\nON DUPLICATE KEY UPDATE `department_id` = VALUES(`department_id`),\\n`manager_id` = VALUES(`manager_id`),\\n`email` = VALUES(`email`),\\n`first_name` = VALUES(`first_name`),\\n`last_name` = VALUES(`last_name`),\\n`salary` = VALUES(`salary`),\\n`hired_at` = VALUES(`hired_at`),\\n`active` = VALUES(`active`),\\n`created_at` = VALUES(`created_at`),\\n`metadata` = VALUES(`metadata`),\\n`photo` = VALUES(`photo`),\\n`ip_address` = VALUES(`ip_address`),\\n`permissions` = VALUES(`permissions`)\\nRETURNING `id`, `department_id`, `manager_id`, `email`, `first_name`, `last_name`, `salary`, `hired_at`, `active`, `created_at`, `metadata`, `photo`, `ip_address`, `permissions`\"))\n .updateReturningEach(EmployeeRow._rowParser, unsaved)\n .runUnchecked(c);\n };\n}", - "EmployeeRepoMock": "package showcase.showcase.employee;\n\nimport dev.typr.foundations.dsl.DeleteBuilder;\nimport dev.typr.foundations.dsl.DeleteBuilderMock;\nimport dev.typr.foundations.dsl.DeleteParams;\nimport dev.typr.foundations.dsl.SelectBuilder;\nimport dev.typr.foundations.dsl.SelectBuilderMock;\nimport dev.typr.foundations.dsl.SelectParams;\nimport dev.typr.foundations.dsl.UpdateBuilder;\nimport dev.typr.foundations.dsl.UpdateBuilderMock;\nimport dev.typr.foundations.dsl.UpdateParams;\nimport java.lang.RuntimeException;\nimport java.sql.Connection;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\nimport java.util.function.Function;\nimport java.util.stream.Collectors;\n\npublic record EmployeeRepoMock(\n java.util.function.Function toRow,\n HashMap map\n) implements EmployeeRepo {\n public EmployeeRepoMock(java.util.function.Function toRow) {\n this(toRow, new HashMap());\n };\n\n public EmployeeRepoMock withToRow(java.util.function.Function toRow) {\n return new EmployeeRepoMock(toRow, map);\n };\n\n public EmployeeRepoMock withMap(HashMap map) {\n return new EmployeeRepoMock(toRow, map);\n };\n\n @Override\n public DeleteBuilder delete() {\n return new DeleteBuilderMock<>(EmployeeFields.structure(), () -> new ArrayList<>(map.values()), DeleteParams.empty(), row -> row.id(), id -> map.remove(id));\n };\n\n @Override\n public Boolean deleteById(\n EmployeeId id,\n Connection c\n ) {\n return Optional.ofNullable(map.remove(id)).isPresent();\n };\n\n @Override\n public Integer deleteByIds(\n EmployeeId[] ids,\n Connection c\n ) {\n var count = 0;\n for (var id : ids) {\n if (Optional.ofNullable(map.remove(id)).isPresent()) {\n count = count + 1;;\n };\n };\n return count;\n };\n\n @Override\n public EmployeeRow insert(\n EmployeeRow unsaved,\n Connection c\n ) {\n if (map.containsKey(unsaved.id())) {\n throw new RuntimeException(\"id \" + unsaved.id() + \" already exists\");\n };\n map.put(unsaved.id(), unsaved);\n return unsaved;\n };\n\n @Override\n public EmployeeRow insert(\n EmployeeRowUnsaved unsaved,\n Connection c\n ) {\n return insert(toRow.apply(unsaved), c);\n };\n\n @Override\n public SelectBuilder select() {\n return new SelectBuilderMock<>(EmployeeFields.structure(), () -> new ArrayList<>(map.values()), SelectParams.empty());\n };\n\n @Override\n public List selectAll(Connection c) {\n return new ArrayList<>(map.values());\n };\n\n @Override\n public Optional selectById(\n EmployeeId id,\n Connection c\n ) {\n return Optional.ofNullable(map.get(id));\n };\n\n @Override\n public List selectByIds(\n EmployeeId[] ids,\n Connection c\n ) {\n var result = new ArrayList();\n for (var id : ids) {\n var opt = Optional.ofNullable(map.get(id));\n if (opt.isPresent()) {\n result.add(opt.get());\n };\n };\n return result;\n };\n\n @Override\n public Map selectByIdsTracked(\n EmployeeId[] ids,\n Connection c\n ) {\n return selectByIds(ids, c).stream().collect(Collectors.toMap((EmployeeRow row) -> row.id(), Function.identity()));\n };\n\n @Override\n public Optional selectByUniqueEmail(\n String email,\n Connection c\n ) {\n return new ArrayList<>(map.values()).stream().filter(v -> email.equals(v.email())).findFirst();\n };\n\n @Override\n public UpdateBuilder update() {\n return new UpdateBuilderMock<>(EmployeeFields.structure(), () -> new ArrayList<>(map.values()), UpdateParams.empty(), row -> row);\n };\n\n @Override\n public Boolean update(\n EmployeeRow row,\n Connection c\n ) {\n var shouldUpdate = Optional.ofNullable(map.get(row.id())).filter(oldRow -> !oldRow.equals(row)).isPresent();\n if (shouldUpdate) {\n map.put(row.id(), row);;\n };\n return shouldUpdate;\n };\n\n @Override\n public EmployeeRow upsert(\n EmployeeRow unsaved,\n Connection c\n ) {\n map.put(unsaved.id(), unsaved);\n return unsaved;\n };\n\n @Override\n public List upsertBatch(\n Iterator unsaved,\n Connection c\n ) {\n var result = new ArrayList();\n while (unsaved.hasNext()) {\n var row = unsaved.next();\n map.put(row.id(), row);\n result.add(row);\n };\n return result;\n };\n}", - "EmployeeFields": "package showcase.showcase.employee;\n\nimport dev.typr.foundations.MariaTypes;\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.data.Json;\nimport dev.typr.foundations.data.maria.Inet4;\nimport dev.typr.foundations.data.maria.MariaSet;\nimport dev.typr.foundations.dsl.FieldsExpr;\nimport dev.typr.foundations.dsl.ForeignKey;\nimport dev.typr.foundations.dsl.Path;\nimport dev.typr.foundations.dsl.RelationStructure;\nimport dev.typr.foundations.dsl.SqlExpr.Field;\nimport dev.typr.foundations.dsl.SqlExpr.FieldLike;\nimport dev.typr.foundations.dsl.SqlExpr.IdField;\nimport dev.typr.foundations.dsl.SqlExpr.OptField;\nimport java.math.BigDecimal;\nimport java.time.LocalDate;\nimport java.time.LocalDateTime;\nimport java.util.List;\nimport java.util.Optional;\nimport showcase.showcase.department.DepartmentFields;\nimport showcase.showcase.department.DepartmentId;\nimport showcase.showcase.department.DepartmentRow;\n\npublic interface EmployeeFields extends FieldsExpr {\n record Impl(List _path) implements EmployeeFields, RelationStructure {\n @Override\n public IdField id() {\n return new IdField(_path, \"id\", EmployeeRow::id, Optional.empty(), Optional.empty(), (row, value) -> row.withId(value), EmployeeId.pgType);\n };\n\n @Override\n public Field departmentId() {\n return new Field(_path, \"department_id\", EmployeeRow::departmentId, Optional.empty(), Optional.empty(), (row, value) -> row.withDepartmentId(value), DepartmentId.pgType);\n };\n\n @Override\n public OptField managerId() {\n return new OptField(_path, \"manager_id\", EmployeeRow::managerId, Optional.empty(), Optional.empty(), (row, value) -> row.withManagerId(value), EmployeeId.pgType);\n };\n\n @Override\n public Field email() {\n return new Field(_path, \"email\", EmployeeRow::email, Optional.empty(), Optional.empty(), (row, value) -> row.withEmail(value), MariaTypes.varchar);\n };\n\n @Override\n public Field firstName() {\n return new Field(_path, \"first_name\", EmployeeRow::firstName, Optional.empty(), Optional.empty(), (row, value) -> row.withFirstName(value), MariaTypes.varchar);\n };\n\n @Override\n public Field lastName() {\n return new Field(_path, \"last_name\", EmployeeRow::lastName, Optional.empty(), Optional.empty(), (row, value) -> row.withLastName(value), MariaTypes.varchar);\n };\n\n @Override\n public OptField salary() {\n return new OptField(_path, \"salary\", EmployeeRow::salary, Optional.empty(), Optional.empty(), (row, value) -> row.withSalary(value), MariaTypes.numeric);\n };\n\n @Override\n public OptField hiredAt() {\n return new OptField(_path, \"hired_at\", EmployeeRow::hiredAt, Optional.empty(), Optional.empty(), (row, value) -> row.withHiredAt(value), MariaTypes.date);\n };\n\n @Override\n public OptField active() {\n return new OptField(_path, \"active\", EmployeeRow::active, Optional.empty(), Optional.empty(), (row, value) -> row.withActive(value), MariaTypes.bool);\n };\n\n @Override\n public OptField createdAt() {\n return new OptField(_path, \"created_at\", EmployeeRow::createdAt, Optional.empty(), Optional.empty(), (row, value) -> row.withCreatedAt(value), MariaTypes.timestamp);\n };\n\n @Override\n public OptField metadata() {\n return new OptField(_path, \"metadata\", EmployeeRow::metadata, Optional.empty(), Optional.empty(), (row, value) -> row.withMetadata(value), MariaTypes.json);\n };\n\n @Override\n public OptField photo() {\n return new OptField(_path, \"photo\", EmployeeRow::photo, Optional.empty(), Optional.empty(), (row, value) -> row.withPhoto(value), MariaTypes.mediumblob);\n };\n\n @Override\n public OptField ipAddress() {\n return new OptField(_path, \"ip_address\", EmployeeRow::ipAddress, Optional.empty(), Optional.empty(), (row, value) -> row.withIpAddress(value), MariaTypes.inet4);\n };\n\n @Override\n public OptField permissions() {\n return new OptField(_path, \"permissions\", EmployeeRow::permissions, Optional.empty(), Optional.empty(), (row, value) -> row.withPermissions(value), MariaTypes.set);\n };\n\n @Override\n public List> columns() {\n return java.util.List.of(this.id(), this.departmentId(), this.managerId(), this.email(), this.firstName(), this.lastName(), this.salary(), this.hiredAt(), this.active(), this.createdAt(), this.metadata(), this.photo(), this.ipAddress(), this.permissions());\n };\n\n @Override\n public RelationStructure withPaths(List _path) {\n return new Impl(_path);\n };\n };\n\n static Impl structure() {\n return new Impl(java.util.Collections.emptyList());\n };\n\n IdField id();\n\n Field departmentId();\n\n OptField managerId();\n\n Field email();\n\n Field firstName();\n\n Field lastName();\n\n OptField salary();\n\n OptField hiredAt();\n\n OptField active();\n\n OptField createdAt();\n\n OptField metadata();\n\n OptField photo();\n\n OptField ipAddress();\n\n OptField permissions();\n\n default ForeignKey fkDepartment() {\n return ForeignKey.of(\"employee_department_fk\").withColumnPair(departmentId(), DepartmentFields::id);\n };\n\n default ForeignKey fkEmployee() {\n return ForeignKey.of(\"employee_manager_fk\").withColumnPair(managerId(), EmployeeFields::id);\n };\n\n @Override\n List> columns();\n\n @Override\n default RowParser rowParser() {\n return EmployeeRow._rowParser;\n };\n}", - "DepartmentRow": "package showcase.showcase.department;\n\nimport dev.typr.foundations.MariaTypes;\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport java.math.BigDecimal;\nimport java.util.Optional;\nimport showcase.showcase.company.CompanyId;\n\n/** Table: showcase.department\n * Primary key: id\n */\npublic record DepartmentRow(\n DepartmentId id,\n /** Points to {@link showcase.showcase.company.CompanyRow#id()} */\n CompanyId companyId,\n String name,\n Optional budget\n) {\n public DepartmentRow withId(DepartmentId id) {\n return new DepartmentRow(id, companyId, name, budget);\n };\n\n /** Points to {@link showcase.showcase.company.CompanyRow#id()} */\n public DepartmentRow withCompanyId(CompanyId companyId) {\n return new DepartmentRow(id, companyId, name, budget);\n };\n\n public DepartmentRow withName(String name) {\n return new DepartmentRow(id, companyId, name, budget);\n };\n\n public DepartmentRow withBudget(Optional budget) {\n return new DepartmentRow(id, companyId, name, budget);\n };\n\n public static RowParser _rowParser = RowParsers.of(DepartmentId.pgType, CompanyId.pgType, MariaTypes.varchar, MariaTypes.numeric.opt(), DepartmentRow::new, row -> new Object[]{row.id(), row.companyId(), row.name(), row.budget()});;\n}", - "DepartmentId": "package showcase.showcase.department;\n\nimport dev.typr.foundations.MariaType;\nimport dev.typr.foundations.MariaTypes;\nimport dev.typr.foundations.dsl.Bijection;\n\n/** Type for the primary key of table `showcase.department` */\npublic record DepartmentId(String value) {\n public DepartmentId withValue(String value) {\n return new DepartmentId(value);\n };\n\n @Override\n public java.lang.String toString() {\n return value.toString();\n };\n\n static public Bijection bijection =\n Bijection.of(DepartmentId::value, DepartmentId::new);\n\n static public MariaType pgType =\n MariaTypes.varchar.bimap(DepartmentId::new, DepartmentId::value);\n}", - "DepartmentRepo": "package showcase.showcase.department;\n\nimport dev.typr.foundations.dsl.DeleteBuilder;\nimport dev.typr.foundations.dsl.SelectBuilder;\nimport dev.typr.foundations.dsl.UpdateBuilder;\nimport java.sql.Connection;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\n\npublic interface DepartmentRepo {\n DeleteBuilder delete();\n\n Boolean deleteById(\n DepartmentId id,\n Connection c\n );\n\n Integer deleteByIds(\n DepartmentId[] ids,\n Connection c\n );\n\n DepartmentRow insert(\n DepartmentRow unsaved,\n Connection c\n );\n\n SelectBuilder select();\n\n List selectAll(Connection c);\n\n Optional selectById(\n DepartmentId id,\n Connection c\n );\n\n List selectByIds(\n DepartmentId[] ids,\n Connection c\n );\n\n Map selectByIdsTracked(\n DepartmentId[] ids,\n Connection c\n );\n\n UpdateBuilder update();\n\n Boolean update(\n DepartmentRow row,\n Connection c\n );\n\n DepartmentRow upsert(\n DepartmentRow unsaved,\n Connection c\n );\n\n List upsertBatch(\n Iterator unsaved,\n Connection c\n );\n}", - "DepartmentRepoMock": "package showcase.showcase.department;\n\nimport dev.typr.foundations.dsl.DeleteBuilder;\nimport dev.typr.foundations.dsl.DeleteBuilderMock;\nimport dev.typr.foundations.dsl.DeleteParams;\nimport dev.typr.foundations.dsl.SelectBuilder;\nimport dev.typr.foundations.dsl.SelectBuilderMock;\nimport dev.typr.foundations.dsl.SelectParams;\nimport dev.typr.foundations.dsl.UpdateBuilder;\nimport dev.typr.foundations.dsl.UpdateBuilderMock;\nimport dev.typr.foundations.dsl.UpdateParams;\nimport java.lang.RuntimeException;\nimport java.sql.Connection;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\nimport java.util.function.Function;\nimport java.util.stream.Collectors;\n\npublic record DepartmentRepoMock(HashMap map) implements DepartmentRepo {\n public DepartmentRepoMock() {\n this(new HashMap());\n };\n\n public DepartmentRepoMock withMap(HashMap map) {\n return new DepartmentRepoMock(map);\n };\n\n @Override\n public DeleteBuilder delete() {\n return new DeleteBuilderMock<>(DepartmentFields.structure(), () -> new ArrayList<>(map.values()), DeleteParams.empty(), row -> row.id(), id -> map.remove(id));\n };\n\n @Override\n public Boolean deleteById(\n DepartmentId id,\n Connection c\n ) {\n return Optional.ofNullable(map.remove(id)).isPresent();\n };\n\n @Override\n public Integer deleteByIds(\n DepartmentId[] ids,\n Connection c\n ) {\n var count = 0;\n for (var id : ids) {\n if (Optional.ofNullable(map.remove(id)).isPresent()) {\n count = count + 1;;\n };\n };\n return count;\n };\n\n @Override\n public DepartmentRow insert(\n DepartmentRow unsaved,\n Connection c\n ) {\n if (map.containsKey(unsaved.id())) {\n throw new RuntimeException(\"id \" + unsaved.id() + \" already exists\");\n };\n map.put(unsaved.id(), unsaved);\n return unsaved;\n };\n\n @Override\n public SelectBuilder select() {\n return new SelectBuilderMock<>(DepartmentFields.structure(), () -> new ArrayList<>(map.values()), SelectParams.empty());\n };\n\n @Override\n public List selectAll(Connection c) {\n return new ArrayList<>(map.values());\n };\n\n @Override\n public Optional selectById(\n DepartmentId id,\n Connection c\n ) {\n return Optional.ofNullable(map.get(id));\n };\n\n @Override\n public List selectByIds(\n DepartmentId[] ids,\n Connection c\n ) {\n var result = new ArrayList();\n for (var id : ids) {\n var opt = Optional.ofNullable(map.get(id));\n if (opt.isPresent()) {\n result.add(opt.get());\n };\n };\n return result;\n };\n\n @Override\n public Map selectByIdsTracked(\n DepartmentId[] ids,\n Connection c\n ) {\n return selectByIds(ids, c).stream().collect(Collectors.toMap((DepartmentRow row) -> row.id(), Function.identity()));\n };\n\n @Override\n public UpdateBuilder update() {\n return new UpdateBuilderMock<>(DepartmentFields.structure(), () -> new ArrayList<>(map.values()), UpdateParams.empty(), row -> row);\n };\n\n @Override\n public Boolean update(\n DepartmentRow row,\n Connection c\n ) {\n var shouldUpdate = Optional.ofNullable(map.get(row.id())).filter(oldRow -> !oldRow.equals(row)).isPresent();\n if (shouldUpdate) {\n map.put(row.id(), row);;\n };\n return shouldUpdate;\n };\n\n @Override\n public DepartmentRow upsert(\n DepartmentRow unsaved,\n Connection c\n ) {\n map.put(unsaved.id(), unsaved);\n return unsaved;\n };\n\n @Override\n public List upsertBatch(\n Iterator unsaved,\n Connection c\n ) {\n var result = new ArrayList();\n while (unsaved.hasNext()) {\n var row = unsaved.next();\n map.put(row.id(), row);\n result.add(row);\n };\n return result;\n };\n}", - "ProjectAssignmentRow": "package showcase.showcase.project_assignment;\n\nimport dev.typr.foundations.MariaTypes;\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport java.time.LocalDate;\nimport java.util.Optional;\nimport showcase.customtypes.Defaulted;\nimport showcase.showcase.employee.EmployeeId;\nimport showcase.showcase.project.ProjectId;\n\n/** Table: showcase.project_assignment\n * Composite primary key: employee_id, project_id\n */\npublic record ProjectAssignmentRow(\n /** Points to {@link showcase.showcase.employee.EmployeeRow#id()} */\n EmployeeId employeeId,\n /** Points to {@link showcase.showcase.project.ProjectRow#id()} */\n ProjectId projectId,\n String role,\n /** Default: 0 */\n Optional hoursAllocated,\n Optional startDate,\n Optional endDate\n) {\n /** Points to {@link showcase.showcase.employee.EmployeeRow#id()} */\n public ProjectAssignmentRow withEmployeeId(EmployeeId employeeId) {\n return new ProjectAssignmentRow(employeeId, projectId, role, hoursAllocated, startDate, endDate);\n };\n\n /** Points to {@link showcase.showcase.project.ProjectRow#id()} */\n public ProjectAssignmentRow withProjectId(ProjectId projectId) {\n return new ProjectAssignmentRow(employeeId, projectId, role, hoursAllocated, startDate, endDate);\n };\n\n public ProjectAssignmentRow withRole(String role) {\n return new ProjectAssignmentRow(employeeId, projectId, role, hoursAllocated, startDate, endDate);\n };\n\n /** Default: 0 */\n public ProjectAssignmentRow withHoursAllocated(Optional hoursAllocated) {\n return new ProjectAssignmentRow(employeeId, projectId, role, hoursAllocated, startDate, endDate);\n };\n\n public ProjectAssignmentRow withStartDate(Optional startDate) {\n return new ProjectAssignmentRow(employeeId, projectId, role, hoursAllocated, startDate, endDate);\n };\n\n public ProjectAssignmentRow withEndDate(Optional endDate) {\n return new ProjectAssignmentRow(employeeId, projectId, role, hoursAllocated, startDate, endDate);\n };\n\n public static RowParser _rowParser = RowParsers.of(EmployeeId.pgType, ProjectId.pgType, MariaTypes.varchar, MariaTypes.int_.opt(), MariaTypes.date.opt(), MariaTypes.date.opt(), ProjectAssignmentRow::new, row -> new Object[]{row.employeeId(), row.projectId(), row.role(), row.hoursAllocated(), row.startDate(), row.endDate()});;\n\n static public ProjectAssignmentRow apply(\n ProjectAssignmentId compositeId,\n String role,\n Optional hoursAllocated,\n Optional startDate,\n Optional endDate\n ) {\n return new ProjectAssignmentRow(compositeId.employeeId(), compositeId.projectId(), role, hoursAllocated, startDate, endDate);\n };\n\n public ProjectAssignmentId compositeId() {\n return new ProjectAssignmentId(employeeId, projectId);\n };\n\n public ProjectAssignmentId id() {\n return this.compositeId();\n };\n\n public ProjectAssignmentRowUnsaved toUnsavedRow(Defaulted> hoursAllocated) {\n return new ProjectAssignmentRowUnsaved(employeeId, projectId, role, startDate, endDate, hoursAllocated);\n };\n}", - "ProjectAssignmentRowUnsaved": "package showcase.showcase.project_assignment;\n\nimport java.time.LocalDate;\nimport java.util.Optional;\nimport showcase.customtypes.Defaulted;\nimport showcase.customtypes.Defaulted.UseDefault;\nimport showcase.showcase.employee.EmployeeId;\nimport showcase.showcase.project.ProjectId;\n\n/** This class corresponds to a row in table `showcase.project_assignment` which has not been persisted yet */\npublic record ProjectAssignmentRowUnsaved(\n /** Points to {@link showcase.showcase.employee.EmployeeRow#id()} */\n EmployeeId employeeId,\n /** Points to {@link showcase.showcase.project.ProjectRow#id()} */\n ProjectId projectId,\n String role,\n Optional startDate,\n Optional endDate,\n /** Default: 0 */\n Defaulted> hoursAllocated\n) {\n public ProjectAssignmentRowUnsaved(\n /** Points to {@link showcase.showcase.employee.EmployeeRow#id()} */\n EmployeeId employeeId,\n /** Points to {@link showcase.showcase.project.ProjectRow#id()} */\n ProjectId projectId,\n String role\n ) {\n this(employeeId, projectId, role, Optional.empty(), Optional.empty(), new UseDefault<>());\n };\n\n /** Points to {@link showcase.showcase.employee.EmployeeRow#id()} */\n public ProjectAssignmentRowUnsaved withEmployeeId(EmployeeId employeeId) {\n return new ProjectAssignmentRowUnsaved(employeeId, projectId, role, startDate, endDate, hoursAllocated);\n };\n\n /** Points to {@link showcase.showcase.project.ProjectRow#id()} */\n public ProjectAssignmentRowUnsaved withProjectId(ProjectId projectId) {\n return new ProjectAssignmentRowUnsaved(employeeId, projectId, role, startDate, endDate, hoursAllocated);\n };\n\n public ProjectAssignmentRowUnsaved withRole(String role) {\n return new ProjectAssignmentRowUnsaved(employeeId, projectId, role, startDate, endDate, hoursAllocated);\n };\n\n public ProjectAssignmentRowUnsaved withStartDate(Optional startDate) {\n return new ProjectAssignmentRowUnsaved(employeeId, projectId, role, startDate, endDate, hoursAllocated);\n };\n\n public ProjectAssignmentRowUnsaved withEndDate(Optional endDate) {\n return new ProjectAssignmentRowUnsaved(employeeId, projectId, role, startDate, endDate, hoursAllocated);\n };\n\n /** Default: 0 */\n public ProjectAssignmentRowUnsaved withHoursAllocated(Defaulted> hoursAllocated) {\n return new ProjectAssignmentRowUnsaved(employeeId, projectId, role, startDate, endDate, hoursAllocated);\n };\n\n public ProjectAssignmentRow toRow(java.util.function.Supplier> hoursAllocatedDefault) {\n return new ProjectAssignmentRow(employeeId, projectId, role, hoursAllocated.getOrElse(hoursAllocatedDefault), startDate, endDate);\n };\n}", - "ProjectAssignmentId": "package showcase.showcase.project_assignment;\n\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport showcase.showcase.employee.EmployeeId;\nimport showcase.showcase.project.ProjectId;\n\n/** Type for the composite primary key of table `showcase.project_assignment` */\npublic record ProjectAssignmentId(\n EmployeeId employeeId,\n ProjectId projectId\n) {\n public ProjectAssignmentId withEmployeeId(EmployeeId employeeId) {\n return new ProjectAssignmentId(employeeId, projectId);\n };\n\n public ProjectAssignmentId withProjectId(ProjectId projectId) {\n return new ProjectAssignmentId(employeeId, projectId);\n };\n\n public static RowParser _rowParser = RowParsers.of(EmployeeId.pgType, ProjectId.pgType, ProjectAssignmentId::new, row -> new Object[]{row.employeeId(), row.projectId()});;\n}", - "ProjectAssignmentRepo": "package showcase.showcase.project_assignment;\n\nimport dev.typr.foundations.dsl.DeleteBuilder;\nimport dev.typr.foundations.dsl.SelectBuilder;\nimport dev.typr.foundations.dsl.UpdateBuilder;\nimport java.sql.Connection;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\n\npublic interface ProjectAssignmentRepo {\n DeleteBuilder delete();\n\n Boolean deleteById(\n ProjectAssignmentId compositeId,\n Connection c\n );\n\n Integer deleteByIds(\n ProjectAssignmentId[] compositeIds,\n Connection c\n );\n\n ProjectAssignmentRow insert(\n ProjectAssignmentRow unsaved,\n Connection c\n );\n\n ProjectAssignmentRow insert(\n ProjectAssignmentRowUnsaved unsaved,\n Connection c\n );\n\n SelectBuilder select();\n\n List selectAll(Connection c);\n\n Optional selectById(\n ProjectAssignmentId compositeId,\n Connection c\n );\n\n List selectByIds(\n ProjectAssignmentId[] compositeIds,\n Connection c\n );\n\n Map selectByIdsTracked(\n ProjectAssignmentId[] compositeIds,\n Connection c\n );\n\n UpdateBuilder update();\n\n Boolean update(\n ProjectAssignmentRow row,\n Connection c\n );\n\n ProjectAssignmentRow upsert(\n ProjectAssignmentRow unsaved,\n Connection c\n );\n\n List upsertBatch(\n Iterator unsaved,\n Connection c\n );\n}", - "ProjectRow": "package showcase.showcase.project;\n\nimport dev.typr.foundations.MariaTypes;\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport dev.typr.foundations.data.Json;\nimport java.math.BigDecimal;\nimport java.time.LocalDate;\nimport java.time.LocalDateTime;\nimport java.util.Optional;\nimport showcase.customtypes.Defaulted;\n\n/** Table: showcase.project\n * Primary key: id\n */\npublic record ProjectRow(\n ProjectId id,\n String name,\n Optional description,\n Optional startDate,\n Optional endDate,\n Optional budget,\n /** Default: 'planning' */\n Optional status,\n /** Default: CURRENT_TIMESTAMP */\n Optional createdAt,\n Optional metadata,\n Optional descriptionLong,\n Optional attachments,\n Optional priority\n) {\n public ProjectRow withId(ProjectId id) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, metadata, descriptionLong, attachments, priority);\n };\n\n public ProjectRow withName(String name) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, metadata, descriptionLong, attachments, priority);\n };\n\n public ProjectRow withDescription(Optional description) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, metadata, descriptionLong, attachments, priority);\n };\n\n public ProjectRow withStartDate(Optional startDate) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, metadata, descriptionLong, attachments, priority);\n };\n\n public ProjectRow withEndDate(Optional endDate) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, metadata, descriptionLong, attachments, priority);\n };\n\n public ProjectRow withBudget(Optional budget) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, metadata, descriptionLong, attachments, priority);\n };\n\n /** Default: 'planning' */\n public ProjectRow withStatus(Optional status) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, metadata, descriptionLong, attachments, priority);\n };\n\n /** Default: CURRENT_TIMESTAMP */\n public ProjectRow withCreatedAt(Optional createdAt) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, metadata, descriptionLong, attachments, priority);\n };\n\n public ProjectRow withMetadata(Optional metadata) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, metadata, descriptionLong, attachments, priority);\n };\n\n public ProjectRow withDescriptionLong(Optional descriptionLong) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, metadata, descriptionLong, attachments, priority);\n };\n\n public ProjectRow withAttachments(Optional attachments) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, metadata, descriptionLong, attachments, priority);\n };\n\n public ProjectRow withPriority(Optional priority) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, metadata, descriptionLong, attachments, priority);\n };\n\n public static RowParser _rowParser = RowParsers.of(ProjectId.pgType, MariaTypes.varchar, MariaTypes.varchar.opt(), MariaTypes.date.opt(), MariaTypes.date.opt(), MariaTypes.numeric.opt(), MariaTypes.varchar.opt(), MariaTypes.timestamp.opt(), MariaTypes.json.opt(), MariaTypes.longtext.opt(), MariaTypes.mediumblob.opt(), MariaTypes.text.opt(), ProjectRow::new, row -> new Object[]{row.id(), row.name(), row.description(), row.startDate(), row.endDate(), row.budget(), row.status(), row.createdAt(), row.metadata(), row.descriptionLong(), row.attachments(), row.priority()});;\n\n public ProjectRowUnsaved toUnsavedRow(\n Defaulted> status,\n Defaulted> createdAt\n ) {\n return new ProjectRowUnsaved(id, name, description, startDate, endDate, budget, metadata, descriptionLong, attachments, priority, status, createdAt);\n };\n}", - "ProjectId": "package showcase.showcase.project;\n\nimport dev.typr.foundations.MariaType;\nimport dev.typr.foundations.MariaTypes;\nimport dev.typr.foundations.dsl.Bijection;\n\n/** Type for the primary key of table `showcase.project` */\npublic record ProjectId(String value) {\n public ProjectId withValue(String value) {\n return new ProjectId(value);\n };\n\n @Override\n public java.lang.String toString() {\n return value.toString();\n };\n\n static public Bijection bijection =\n Bijection.of(ProjectId::value, ProjectId::new);\n\n static public MariaType pgType =\n MariaTypes.varchar.bimap(ProjectId::new, ProjectId::value);\n}", - "EmployeeSummaryViewRow": "package showcase.showcase.employee_summary;\n\nimport dev.typr.foundations.MariaTypes;\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport java.math.BigDecimal;\nimport java.time.LocalDate;\nimport java.util.Optional;\nimport showcase.showcase.company.CompanyId;\nimport showcase.showcase.department.DepartmentId;\nimport showcase.showcase.employee.EmployeeId;\n\n/** View: showcase.employee_summary\n * Summary view of employees with their department and company information\n */\npublic record EmployeeSummaryViewRow(\n /** Points to {@link showcase.showcase.employee.EmployeeRow#id()} */\n EmployeeId employeeId,\n String email,\n String firstName,\n String lastName,\n Optional salary,\n Optional hiredAt,\n Optional active,\n /** Points to {@link showcase.showcase.department.DepartmentRow#id()} */\n DepartmentId departmentId,\n String departmentName,\n Optional departmentBudget,\n /** Points to {@link showcase.showcase.company.CompanyRow#id()} */\n CompanyId companyId,\n String companyName,\n Optional managerId,\n Optional managerFirstName,\n Optional managerLastName\n) {\n /** Points to {@link showcase.showcase.employee.EmployeeRow#id()} */\n public EmployeeSummaryViewRow withEmployeeId(EmployeeId employeeId) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withEmail(String email) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withFirstName(String firstName) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withLastName(String lastName) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withSalary(Optional salary) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withHiredAt(Optional hiredAt) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withActive(Optional active) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n /** Points to {@link showcase.showcase.department.DepartmentRow#id()} */\n public EmployeeSummaryViewRow withDepartmentId(DepartmentId departmentId) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withDepartmentName(String departmentName) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withDepartmentBudget(Optional departmentBudget) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n /** Points to {@link showcase.showcase.company.CompanyRow#id()} */\n public EmployeeSummaryViewRow withCompanyId(CompanyId companyId) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withCompanyName(String companyName) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withManagerId(Optional managerId) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withManagerFirstName(Optional managerFirstName) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withManagerLastName(Optional managerLastName) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public static RowParser _rowParser = RowParsers.of(EmployeeId.pgType, MariaTypes.varchar, MariaTypes.varchar, MariaTypes.varchar, MariaTypes.numeric.opt(), MariaTypes.date.opt(), MariaTypes.bool.opt(), DepartmentId.pgType, MariaTypes.varchar, MariaTypes.numeric.opt(), CompanyId.pgType, MariaTypes.varchar, MariaTypes.varchar.opt(), MariaTypes.varchar.opt(), MariaTypes.varchar.opt(), EmployeeSummaryViewRow::new, row -> new Object[]{row.employeeId(), row.email(), row.firstName(), row.lastName(), row.salary(), row.hiredAt(), row.active(), row.departmentId(), row.departmentName(), row.departmentBudget(), row.companyId(), row.companyName(), row.managerId(), row.managerFirstName(), row.managerLastName()});;\n}", - "EmployeeSummaryViewRepo": "package showcase.showcase.employee_summary;\n\nimport dev.typr.foundations.dsl.SelectBuilder;\nimport java.sql.Connection;\nimport java.util.List;\n\npublic interface EmployeeSummaryViewRepo {\n SelectBuilder select();\n\n List selectAll(Connection c);\n}", - "CustomerOrderRow": "package showcase.showcase.customer_order;\n\nimport dev.typr.foundations.MariaTypes;\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport dev.typr.foundations.data.Json;\nimport dev.typr.foundations.data.maria.Inet4;\nimport java.math.BigDecimal;\nimport java.time.LocalDateTime;\nimport java.util.Optional;\nimport showcase.customtypes.Defaulted;\nimport showcase.showcase.address.AddressId;\nimport showcase.showcase.customer.CustomerId;\n\n/** Table: showcase.customer_order\n * Primary key: id\n */\npublic record CustomerOrderRow(\n CustomerOrderId id,\n /** Points to {@link showcase.showcase.customer.CustomerRow#id()} */\n CustomerId customerId,\n /** Points to {@link showcase.showcase.address.AddressRow#id()} */\n Optional shippingAddressId,\n /** Points to {@link showcase.showcase.address.AddressRow#id()} */\n Optional billingAddressId,\n /** Default: 'pending' */\n Optional status,\n BigDecimal subtotal,\n /** Default: 0 */\n Optional tax,\n /** Default: 0 */\n Optional shipping,\n BigDecimal total,\n Optional notes,\n /** Default: CURRENT_TIMESTAMP */\n Optional createdAt,\n Optional shippedAt,\n Optional deliveredAt,\n Optional metadata,\n Optional ipAddress,\n Optional paymentMethod\n) {\n public CustomerOrderRow withId(CustomerOrderId id) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, metadata, ipAddress, paymentMethod);\n };\n\n /** Points to {@link showcase.showcase.customer.CustomerRow#id()} */\n public CustomerOrderRow withCustomerId(CustomerId customerId) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, metadata, ipAddress, paymentMethod);\n };\n\n /** Points to {@link showcase.showcase.address.AddressRow#id()} */\n public CustomerOrderRow withShippingAddressId(Optional shippingAddressId) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, metadata, ipAddress, paymentMethod);\n };\n\n /** Points to {@link showcase.showcase.address.AddressRow#id()} */\n public CustomerOrderRow withBillingAddressId(Optional billingAddressId) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, metadata, ipAddress, paymentMethod);\n };\n\n /** Default: 'pending' */\n public CustomerOrderRow withStatus(Optional status) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, metadata, ipAddress, paymentMethod);\n };\n\n public CustomerOrderRow withSubtotal(BigDecimal subtotal) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, metadata, ipAddress, paymentMethod);\n };\n\n /** Default: 0 */\n public CustomerOrderRow withTax(Optional tax) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, metadata, ipAddress, paymentMethod);\n };\n\n /** Default: 0 */\n public CustomerOrderRow withShipping(Optional shipping) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, metadata, ipAddress, paymentMethod);\n };\n\n public CustomerOrderRow withTotal(BigDecimal total) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, metadata, ipAddress, paymentMethod);\n };\n\n public CustomerOrderRow withNotes(Optional notes) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, metadata, ipAddress, paymentMethod);\n };\n\n /** Default: CURRENT_TIMESTAMP */\n public CustomerOrderRow withCreatedAt(Optional createdAt) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, metadata, ipAddress, paymentMethod);\n };\n\n public CustomerOrderRow withShippedAt(Optional shippedAt) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, metadata, ipAddress, paymentMethod);\n };\n\n public CustomerOrderRow withDeliveredAt(Optional deliveredAt) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, metadata, ipAddress, paymentMethod);\n };\n\n public CustomerOrderRow withMetadata(Optional metadata) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, metadata, ipAddress, paymentMethod);\n };\n\n public CustomerOrderRow withIpAddress(Optional ipAddress) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, metadata, ipAddress, paymentMethod);\n };\n\n public CustomerOrderRow withPaymentMethod(Optional paymentMethod) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, metadata, ipAddress, paymentMethod);\n };\n\n public static RowParser _rowParser = RowParsers.of(CustomerOrderId.pgType, CustomerId.pgType, AddressId.pgType.opt(), AddressId.pgType.opt(), MariaTypes.varchar.opt(), MariaTypes.numeric, MariaTypes.numeric.opt(), MariaTypes.numeric.opt(), MariaTypes.numeric, MariaTypes.varchar.opt(), MariaTypes.timestamp.opt(), MariaTypes.timestamp.opt(), MariaTypes.timestamp.opt(), MariaTypes.json.opt(), MariaTypes.inet4.opt(), MariaTypes.text.opt(), CustomerOrderRow::new, row -> new Object[]{row.id(), row.customerId(), row.shippingAddressId(), row.billingAddressId(), row.status(), row.subtotal(), row.tax(), row.shipping(), row.total(), row.notes(), row.createdAt(), row.shippedAt(), row.deliveredAt(), row.metadata(), row.ipAddress(), row.paymentMethod()});;\n\n public CustomerOrderRowUnsaved toUnsavedRow(\n Defaulted> status,\n Defaulted> tax,\n Defaulted> shipping,\n Defaulted> createdAt\n ) {\n return new CustomerOrderRowUnsaved(id, customerId, shippingAddressId, billingAddressId, subtotal, total, notes, shippedAt, deliveredAt, metadata, ipAddress, paymentMethod, status, tax, shipping, createdAt);\n };\n}", - "CustomerOrderRepo": "package showcase.showcase.customer_order;\n\nimport dev.typr.foundations.dsl.DeleteBuilder;\nimport dev.typr.foundations.dsl.SelectBuilder;\nimport dev.typr.foundations.dsl.UpdateBuilder;\nimport java.sql.Connection;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\n\npublic interface CustomerOrderRepo {\n DeleteBuilder delete();\n\n Boolean deleteById(\n CustomerOrderId id,\n Connection c\n );\n\n Integer deleteByIds(\n CustomerOrderId[] ids,\n Connection c\n );\n\n CustomerOrderRow insert(\n CustomerOrderRow unsaved,\n Connection c\n );\n\n CustomerOrderRow insert(\n CustomerOrderRowUnsaved unsaved,\n Connection c\n );\n\n SelectBuilder select();\n\n List selectAll(Connection c);\n\n Optional selectById(\n CustomerOrderId id,\n Connection c\n );\n\n List selectByIds(\n CustomerOrderId[] ids,\n Connection c\n );\n\n Map selectByIdsTracked(\n CustomerOrderId[] ids,\n Connection c\n );\n\n UpdateBuilder update();\n\n Boolean update(\n CustomerOrderRow row,\n Connection c\n );\n\n CustomerOrderRow upsert(\n CustomerOrderRow unsaved,\n Connection c\n );\n\n List upsertBatch(\n Iterator unsaved,\n Connection c\n );\n}", - "OrderItemRow": "package showcase.showcase.order_item;\n\nimport dev.typr.foundations.MariaTypes;\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport java.math.BigDecimal;\nimport java.util.Optional;\nimport showcase.customtypes.Defaulted;\nimport showcase.showcase.customer_order.CustomerOrderId;\nimport showcase.showcase.product.ProductId;\n\n/** Table: showcase.order_item\n * Composite primary key: order_id, product_id\n */\npublic record OrderItemRow(\n /** Points to {@link showcase.showcase.customer_order.CustomerOrderRow#id()} */\n CustomerOrderId orderId,\n /** Points to {@link showcase.showcase.product.ProductRow#id()} */\n ProductId productId,\n Integer quantity,\n BigDecimal unitPrice,\n /** Default: 0 */\n Optional discount\n) {\n /** Points to {@link showcase.showcase.customer_order.CustomerOrderRow#id()} */\n public OrderItemRow withOrderId(CustomerOrderId orderId) {\n return new OrderItemRow(orderId, productId, quantity, unitPrice, discount);\n };\n\n /** Points to {@link showcase.showcase.product.ProductRow#id()} */\n public OrderItemRow withProductId(ProductId productId) {\n return new OrderItemRow(orderId, productId, quantity, unitPrice, discount);\n };\n\n public OrderItemRow withQuantity(Integer quantity) {\n return new OrderItemRow(orderId, productId, quantity, unitPrice, discount);\n };\n\n public OrderItemRow withUnitPrice(BigDecimal unitPrice) {\n return new OrderItemRow(orderId, productId, quantity, unitPrice, discount);\n };\n\n /** Default: 0 */\n public OrderItemRow withDiscount(Optional discount) {\n return new OrderItemRow(orderId, productId, quantity, unitPrice, discount);\n };\n\n public static RowParser _rowParser = RowParsers.of(CustomerOrderId.pgType, ProductId.pgType, MariaTypes.int_, MariaTypes.numeric, MariaTypes.numeric.opt(), OrderItemRow::new, row -> new Object[]{row.orderId(), row.productId(), row.quantity(), row.unitPrice(), row.discount()});;\n\n static public OrderItemRow apply(\n OrderItemId compositeId,\n Integer quantity,\n BigDecimal unitPrice,\n Optional discount\n ) {\n return new OrderItemRow(compositeId.orderId(), compositeId.productId(), quantity, unitPrice, discount);\n };\n\n public OrderItemId compositeId() {\n return new OrderItemId(orderId, productId);\n };\n\n public OrderItemId id() {\n return this.compositeId();\n };\n\n public OrderItemRowUnsaved toUnsavedRow(Defaulted> discount) {\n return new OrderItemRowUnsaved(orderId, productId, quantity, unitPrice, discount);\n };\n}", - "OrderItemId": "package showcase.showcase.order_item;\n\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport showcase.showcase.customer_order.CustomerOrderId;\nimport showcase.showcase.product.ProductId;\n\n/** Type for the composite primary key of table `showcase.order_item` */\npublic record OrderItemId(\n CustomerOrderId orderId,\n ProductId productId\n) {\n public OrderItemId withOrderId(CustomerOrderId orderId) {\n return new OrderItemId(orderId, productId);\n };\n\n public OrderItemId withProductId(ProductId productId) {\n return new OrderItemId(orderId, productId);\n };\n\n public static RowParser _rowParser = RowParsers.of(CustomerOrderId.pgType, ProductId.pgType, OrderItemId::new, row -> new Object[]{row.orderId(), row.productId()});;\n}", - "ProductRow": "package showcase.showcase.product;\n\nimport dev.typr.foundations.MariaTypes;\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport dev.typr.foundations.data.Json;\nimport java.math.BigDecimal;\nimport java.time.LocalDateTime;\nimport java.util.Optional;\nimport showcase.customtypes.Defaulted;\nimport showcase.showcase.category.CategoryId;\n\n/** Table: showcase.product\n * Primary key: id\n */\npublic record ProductRow(\n ProductId id,\n /** Points to {@link showcase.showcase.category.CategoryRow#id()} */\n Optional categoryId,\n String name,\n String sku,\n BigDecimal price,\n Optional cost,\n /** Default: true */\n Optional inStock,\n /** Default: 0 */\n Optional quantity,\n Optional weight,\n /** Default: CURRENT_TIMESTAMP */\n Optional createdAt,\n Optional attributes,\n Optional specifications,\n Optional seoMetadata,\n Optional descriptionLong,\n Optional thumbnail\n) {\n public ProductRow withId(ProductId id) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, attributes, specifications, seoMetadata, descriptionLong, thumbnail);\n };\n\n /** Points to {@link showcase.showcase.category.CategoryRow#id()} */\n public ProductRow withCategoryId(Optional categoryId) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, attributes, specifications, seoMetadata, descriptionLong, thumbnail);\n };\n\n public ProductRow withName(String name) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, attributes, specifications, seoMetadata, descriptionLong, thumbnail);\n };\n\n public ProductRow withSku(String sku) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, attributes, specifications, seoMetadata, descriptionLong, thumbnail);\n };\n\n public ProductRow withPrice(BigDecimal price) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, attributes, specifications, seoMetadata, descriptionLong, thumbnail);\n };\n\n public ProductRow withCost(Optional cost) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, attributes, specifications, seoMetadata, descriptionLong, thumbnail);\n };\n\n /** Default: true */\n public ProductRow withInStock(Optional inStock) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, attributes, specifications, seoMetadata, descriptionLong, thumbnail);\n };\n\n /** Default: 0 */\n public ProductRow withQuantity(Optional quantity) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, attributes, specifications, seoMetadata, descriptionLong, thumbnail);\n };\n\n public ProductRow withWeight(Optional weight) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, attributes, specifications, seoMetadata, descriptionLong, thumbnail);\n };\n\n /** Default: CURRENT_TIMESTAMP */\n public ProductRow withCreatedAt(Optional createdAt) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, attributes, specifications, seoMetadata, descriptionLong, thumbnail);\n };\n\n public ProductRow withAttributes(Optional attributes) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, attributes, specifications, seoMetadata, descriptionLong, thumbnail);\n };\n\n public ProductRow withSpecifications(Optional specifications) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, attributes, specifications, seoMetadata, descriptionLong, thumbnail);\n };\n\n public ProductRow withSeoMetadata(Optional seoMetadata) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, attributes, specifications, seoMetadata, descriptionLong, thumbnail);\n };\n\n public ProductRow withDescriptionLong(Optional descriptionLong) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, attributes, specifications, seoMetadata, descriptionLong, thumbnail);\n };\n\n public ProductRow withThumbnail(Optional thumbnail) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, attributes, specifications, seoMetadata, descriptionLong, thumbnail);\n };\n\n public static RowParser _rowParser = RowParsers.of(ProductId.pgType, CategoryId.pgType.opt(), MariaTypes.varchar, MariaTypes.varchar, MariaTypes.numeric, MariaTypes.numeric.opt(), MariaTypes.bool.opt(), MariaTypes.int_.opt(), MariaTypes.numeric.opt(), MariaTypes.timestamp.opt(), MariaTypes.json.opt(), MariaTypes.json.opt(), MariaTypes.json.opt(), MariaTypes.longtext.opt(), MariaTypes.mediumblob.opt(), ProductRow::new, row -> new Object[]{row.id(), row.categoryId(), row.name(), row.sku(), row.price(), row.cost(), row.inStock(), row.quantity(), row.weight(), row.createdAt(), row.attributes(), row.specifications(), row.seoMetadata(), row.descriptionLong(), row.thumbnail()});;\n\n public ProductRowUnsaved toUnsavedRow(\n Defaulted> inStock,\n Defaulted> quantity,\n Defaulted> createdAt\n ) {\n return new ProductRowUnsaved(id, categoryId, name, sku, price, cost, weight, attributes, specifications, seoMetadata, descriptionLong, thumbnail, inStock, quantity, createdAt);\n };\n}", - "ProductId": "package showcase.showcase.product;\n\nimport dev.typr.foundations.MariaType;\nimport dev.typr.foundations.MariaTypes;\nimport dev.typr.foundations.dsl.Bijection;\n\n/** Type for the primary key of table `showcase.product` */\npublic record ProductId(String value) {\n public ProductId withValue(String value) {\n return new ProductId(value);\n };\n\n @Override\n public java.lang.String toString() {\n return value.toString();\n };\n\n static public Bijection bijection =\n Bijection.of(ProductId::value, ProductId::new);\n\n static public MariaType pgType =\n MariaTypes.varchar.bimap(ProductId::new, ProductId::value);\n}", - "CategoryRow": "package showcase.showcase.category;\n\nimport dev.typr.foundations.MariaTypes;\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport java.util.Optional;\n\n/** Table: showcase.category\n * Primary key: id\n */\npublic record CategoryRow(\n CategoryId id,\n /** Points to {@link showcase.showcase.category.CategoryRow#id()} */\n Optional parentId,\n String name,\n Optional description\n) {\n public CategoryRow withId(CategoryId id) {\n return new CategoryRow(id, parentId, name, description);\n };\n\n /** Points to {@link showcase.showcase.category.CategoryRow#id()} */\n public CategoryRow withParentId(Optional parentId) {\n return new CategoryRow(id, parentId, name, description);\n };\n\n public CategoryRow withName(String name) {\n return new CategoryRow(id, parentId, name, description);\n };\n\n public CategoryRow withDescription(Optional description) {\n return new CategoryRow(id, parentId, name, description);\n };\n\n public static RowParser _rowParser = RowParsers.of(CategoryId.pgType, CategoryId.pgType.opt(), MariaTypes.varchar, MariaTypes.varchar.opt(), CategoryRow::new, row -> new Object[]{row.id(), row.parentId(), row.name(), row.description()});;\n}", - "CategoryId": "package showcase.showcase.category;\n\nimport dev.typr.foundations.MariaType;\nimport dev.typr.foundations.MariaTypes;\nimport dev.typr.foundations.dsl.Bijection;\n\n/** Type for the primary key of table `showcase.category` */\npublic record CategoryId(String value) {\n public CategoryId withValue(String value) {\n return new CategoryId(value);\n };\n\n @Override\n public java.lang.String toString() {\n return value.toString();\n };\n\n static public Bijection bijection =\n Bijection.of(CategoryId::value, CategoryId::new);\n\n static public MariaType pgType =\n MariaTypes.varchar.bimap(CategoryId::new, CategoryId::value);\n}", - "AddressRow": "package showcase.showcase.address;\n\nimport dev.typr.foundations.MariaTypes;\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport java.util.Optional;\nimport org.mariadb.jdbc.type.Point;\nimport org.mariadb.jdbc.type.Polygon;\nimport showcase.customtypes.Defaulted;\nimport showcase.showcase.customer.CustomerId;\n\n/** Table: showcase.address\n * Primary key: id\n */\npublic record AddressRow(\n AddressId id,\n /** Points to {@link showcase.showcase.customer.CustomerRow#id()} */\n CustomerId customerId,\n String addressType,\n String street,\n String city,\n Optional state,\n Optional postalCode,\n String country,\n /** Default: false */\n Optional isDefault,\n Optional location,\n Optional deliveryZone\n) {\n public AddressRow withId(AddressId id) {\n return new AddressRow(id, customerId, addressType, street, city, state, postalCode, country, isDefault, location, deliveryZone);\n };\n\n /** Points to {@link showcase.showcase.customer.CustomerRow#id()} */\n public AddressRow withCustomerId(CustomerId customerId) {\n return new AddressRow(id, customerId, addressType, street, city, state, postalCode, country, isDefault, location, deliveryZone);\n };\n\n public AddressRow withAddressType(String addressType) {\n return new AddressRow(id, customerId, addressType, street, city, state, postalCode, country, isDefault, location, deliveryZone);\n };\n\n public AddressRow withStreet(String street) {\n return new AddressRow(id, customerId, addressType, street, city, state, postalCode, country, isDefault, location, deliveryZone);\n };\n\n public AddressRow withCity(String city) {\n return new AddressRow(id, customerId, addressType, street, city, state, postalCode, country, isDefault, location, deliveryZone);\n };\n\n public AddressRow withState(Optional state) {\n return new AddressRow(id, customerId, addressType, street, city, state, postalCode, country, isDefault, location, deliveryZone);\n };\n\n public AddressRow withPostalCode(Optional postalCode) {\n return new AddressRow(id, customerId, addressType, street, city, state, postalCode, country, isDefault, location, deliveryZone);\n };\n\n public AddressRow withCountry(String country) {\n return new AddressRow(id, customerId, addressType, street, city, state, postalCode, country, isDefault, location, deliveryZone);\n };\n\n /** Default: false */\n public AddressRow withIsDefault(Optional isDefault) {\n return new AddressRow(id, customerId, addressType, street, city, state, postalCode, country, isDefault, location, deliveryZone);\n };\n\n public AddressRow withLocation(Optional location) {\n return new AddressRow(id, customerId, addressType, street, city, state, postalCode, country, isDefault, location, deliveryZone);\n };\n\n public AddressRow withDeliveryZone(Optional deliveryZone) {\n return new AddressRow(id, customerId, addressType, street, city, state, postalCode, country, isDefault, location, deliveryZone);\n };\n\n public static RowParser _rowParser = RowParsers.of(AddressId.pgType, CustomerId.pgType, MariaTypes.varchar, MariaTypes.varchar, MariaTypes.varchar, MariaTypes.varchar.opt(), MariaTypes.varchar.opt(), MariaTypes.varchar, MariaTypes.bool.opt(), MariaTypes.point.opt(), MariaTypes.polygon.opt(), AddressRow::new, row -> new Object[]{row.id(), row.customerId(), row.addressType(), row.street(), row.city(), row.state(), row.postalCode(), row.country(), row.isDefault(), row.location(), row.deliveryZone()});;\n\n public AddressRowUnsaved toUnsavedRow(Defaulted> isDefault) {\n return new AddressRowUnsaved(id, customerId, addressType, street, city, state, postalCode, country, location, deliveryZone, isDefault);\n };\n}", - "AddressId": "package showcase.showcase.address;\n\nimport dev.typr.foundations.MariaType;\nimport dev.typr.foundations.MariaTypes;\nimport dev.typr.foundations.dsl.Bijection;\n\n/** Type for the primary key of table `showcase.address` */\npublic record AddressId(String value) {\n public AddressId withValue(String value) {\n return new AddressId(value);\n };\n\n @Override\n public java.lang.String toString() {\n return value.toString();\n };\n\n static public Bijection bijection =\n Bijection.of(AddressId::value, AddressId::new);\n\n static public MariaType pgType =\n MariaTypes.varchar.bimap(AddressId::new, AddressId::value);\n}", - "Defaulted": "package showcase.customtypes;\n\n\n\n/** This signals a value where if you don't provide it, postgres will generate it for you */\npublic sealed interface Defaulted permits Defaulted.Provided, Defaulted.UseDefault {\n record Provided(T value) implements Defaulted {\n public Provided withValue(T value) {\n return new Provided<>(value);\n };\n\n @Override\n public U fold(\n java.util.function.Supplier onDefault,\n java.util.function.Function onProvided\n ) {\n return onProvided.apply(value);\n };\n\n @Override\n public T getOrElse(java.util.function.Supplier onDefault) {\n return value;\n };\n\n @Override\n public void visit(\n java.lang.Runnable onDefault,\n java.util.function.Consumer onProvided\n ) {\n onProvided.accept(value);\n };\n };\n\n record UseDefault() implements Defaulted {\n @Override\n public U fold(\n java.util.function.Supplier onDefault,\n java.util.function.Function onProvided\n ) {\n return onDefault.get();\n };\n\n @Override\n public T getOrElse(java.util.function.Supplier onDefault) {\n return onDefault.get();\n };\n\n @Override\n public void visit(\n java.lang.Runnable onDefault,\n java.util.function.Consumer onProvided\n ) {\n onDefault.run();\n };\n };\n\n U fold(\n java.util.function.Supplier onDefault,\n java.util.function.Function onProvided\n );\n\n T getOrElse(java.util.function.Supplier onDefault);\n\n void visit(\n java.lang.Runnable onDefault,\n java.util.function.Consumer onProvided\n );\n}", - "TestInsert": "package showcase;\n\nimport dev.typr.foundations.data.Json;\nimport dev.typr.foundations.data.maria.Inet4;\nimport dev.typr.foundations.data.maria.MariaSet;\nimport dev.typr.foundations.internal.RandomHelper;\nimport java.math.BigDecimal;\nimport java.sql.Connection;\nimport java.time.LocalDate;\nimport java.time.LocalDateTime;\nimport java.util.Optional;\nimport java.util.Random;\nimport org.mariadb.jdbc.type.Point;\nimport org.mariadb.jdbc.type.Polygon;\nimport showcase.customtypes.Defaulted;\nimport showcase.showcase.address.AddressId;\nimport showcase.showcase.address.AddressRepoImpl;\nimport showcase.showcase.address.AddressRow;\nimport showcase.showcase.address.AddressRowUnsaved;\nimport showcase.showcase.audit_log.AuditLogId;\nimport showcase.showcase.audit_log.AuditLogRepoImpl;\nimport showcase.showcase.audit_log.AuditLogRow;\nimport showcase.showcase.audit_log.AuditLogRowUnsaved;\nimport showcase.showcase.category.CategoryId;\nimport showcase.showcase.category.CategoryRepoImpl;\nimport showcase.showcase.category.CategoryRow;\nimport showcase.showcase.company.CompanyId;\nimport showcase.showcase.company.CompanyRepoImpl;\nimport showcase.showcase.company.CompanyRow;\nimport showcase.showcase.company.CompanyRowUnsaved;\nimport showcase.showcase.customer.CustomerId;\nimport showcase.showcase.customer.CustomerRepoImpl;\nimport showcase.showcase.customer.CustomerRow;\nimport showcase.showcase.customer.CustomerRowUnsaved;\nimport showcase.showcase.customer_order.CustomerOrderId;\nimport showcase.showcase.customer_order.CustomerOrderRepoImpl;\nimport showcase.showcase.customer_order.CustomerOrderRow;\nimport showcase.showcase.customer_order.CustomerOrderRowUnsaved;\nimport showcase.showcase.department.DepartmentId;\nimport showcase.showcase.department.DepartmentRepoImpl;\nimport showcase.showcase.department.DepartmentRow;\nimport showcase.showcase.employee.EmployeeId;\nimport showcase.showcase.employee.EmployeeRepoImpl;\nimport showcase.showcase.employee.EmployeeRow;\nimport showcase.showcase.employee.EmployeeRowUnsaved;\nimport showcase.showcase.order_item.OrderItemRepoImpl;\nimport showcase.showcase.order_item.OrderItemRow;\nimport showcase.showcase.order_item.OrderItemRowUnsaved;\nimport showcase.showcase.product.ProductId;\nimport showcase.showcase.product.ProductRepoImpl;\nimport showcase.showcase.product.ProductRow;\nimport showcase.showcase.product.ProductRowUnsaved;\nimport showcase.showcase.project.ProjectId;\nimport showcase.showcase.project.ProjectRepoImpl;\nimport showcase.showcase.project.ProjectRow;\nimport showcase.showcase.project.ProjectRowUnsaved;\nimport showcase.showcase.project_assignment.ProjectAssignmentRepoImpl;\nimport showcase.showcase.project_assignment.ProjectAssignmentRow;\nimport showcase.showcase.project_assignment.ProjectAssignmentRowUnsaved;\n\n/** Methods to generate random data for `Ident(TestInsert)` */\npublic record TestInsert(Random random) {\n public TestInsert withRandom(Random random) {\n return new TestInsert(random);\n };\n\n public AddressRow showcaseAddress(\n CustomerId customerId,\n AddressId id,\n String addressType,\n String street,\n String city,\n Optional state,\n Optional postalCode,\n String country,\n Optional location,\n Optional deliveryZone,\n Defaulted> isDefault,\n Connection c\n ) {\n return (new AddressRepoImpl()).insert(new AddressRowUnsaved(id, customerId, addressType, street, city, state, postalCode, country, location, deliveryZone, isDefault), c);\n };\n\n public AuditLogRow showcaseAuditLog(\n AuditLogId id,\n String tableName,\n String recordId,\n String action,\n Optional oldValues,\n Optional newValues,\n Optional changedBy,\n Defaulted> changedAt,\n Connection c\n ) {\n return (new AuditLogRepoImpl()).insert(new AuditLogRowUnsaved(id, tableName, recordId, action, oldValues, newValues, changedBy, changedAt), c);\n };\n\n public CategoryRow showcaseCategory(\n CategoryId id,\n Optional parentId,\n String name,\n Optional description,\n Connection c\n ) {\n return (new CategoryRepoImpl()).insert(new CategoryRow(id, parentId, name, description), c);\n };\n\n public CompanyRow showcaseCompany(\n CompanyId id,\n String name,\n Optional foundedYear,\n Defaulted> active,\n Defaulted> createdAt,\n Connection c\n ) {\n return (new CompanyRepoImpl()).insert(new CompanyRowUnsaved(id, name, foundedYear, active, createdAt), c);\n };\n\n public CustomerRow showcaseCustomer(\n CustomerId id,\n String email,\n String firstName,\n String lastName,\n Optional phone,\n Optional preferences,\n Optional avatar,\n Optional customerType,\n Defaulted> verified,\n Defaulted> createdAt,\n Connection c\n ) {\n return (new CustomerRepoImpl()).insert(new CustomerRowUnsaved(id, email, firstName, lastName, phone, preferences, avatar, customerType, verified, createdAt), c);\n };\n\n public CustomerOrderRow showcaseCustomerOrder(\n CustomerId customerId,\n CustomerOrderId id,\n Optional shippingAddressId,\n Optional billingAddressId,\n BigDecimal subtotal,\n BigDecimal total,\n Optional notes,\n Optional shippedAt,\n Optional deliveredAt,\n Optional metadata,\n Optional ipAddress,\n Optional paymentMethod,\n Defaulted> status,\n Defaulted> tax,\n Defaulted> shipping,\n Defaulted> createdAt,\n Connection c\n ) {\n return (new CustomerOrderRepoImpl()).insert(new CustomerOrderRowUnsaved(id, customerId, shippingAddressId, billingAddressId, subtotal, total, notes, shippedAt, deliveredAt, metadata, ipAddress, paymentMethod, status, tax, shipping, createdAt), c);\n };\n\n public DepartmentRow showcaseDepartment(\n CompanyId companyId,\n DepartmentId id,\n String name,\n Optional budget,\n Connection c\n ) {\n return (new DepartmentRepoImpl()).insert(new DepartmentRow(id, companyId, name, budget), c);\n };\n\n public EmployeeRow showcaseEmployee(\n DepartmentId departmentId,\n EmployeeId id,\n Optional managerId,\n String email,\n String firstName,\n String lastName,\n Optional salary,\n Optional hiredAt,\n Optional metadata,\n Optional photo,\n Optional ipAddress,\n Optional permissions,\n Defaulted> active,\n Defaulted> createdAt,\n Connection c\n ) {\n return (new EmployeeRepoImpl()).insert(new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, metadata, photo, ipAddress, permissions, active, createdAt), c);\n };\n\n public OrderItemRow showcaseOrderItem(\n CustomerOrderId orderId,\n ProductId productId,\n Integer quantity,\n BigDecimal unitPrice,\n Defaulted> discount,\n Connection c\n ) {\n return (new OrderItemRepoImpl()).insert(new OrderItemRowUnsaved(orderId, productId, quantity, unitPrice, discount), c);\n };\n\n public ProductRow showcaseProduct(\n ProductId id,\n Optional categoryId,\n String name,\n String sku,\n BigDecimal price,\n Optional cost,\n Optional weight,\n Optional attributes,\n Optional specifications,\n Optional seoMetadata,\n Optional descriptionLong,\n Optional thumbnail,\n Defaulted> inStock,\n Defaulted> quantity,\n Defaulted> createdAt,\n Connection c\n ) {\n return (new ProductRepoImpl()).insert(new ProductRowUnsaved(id, categoryId, name, sku, price, cost, weight, attributes, specifications, seoMetadata, descriptionLong, thumbnail, inStock, quantity, createdAt), c);\n };\n\n public ProjectRow showcaseProject(\n ProjectId id,\n String name,\n Optional description,\n Optional startDate,\n Optional endDate,\n Optional budget,\n Optional metadata,\n Optional descriptionLong,\n Optional attachments,\n Optional priority,\n Defaulted> status,\n Defaulted> createdAt,\n Connection c\n ) {\n return (new ProjectRepoImpl()).insert(new ProjectRowUnsaved(id, name, description, startDate, endDate, budget, metadata, descriptionLong, attachments, priority, status, createdAt), c);\n };\n\n public ProjectAssignmentRow showcaseProjectAssignment(\n EmployeeId employeeId,\n ProjectId projectId,\n String role,\n Optional startDate,\n Optional endDate,\n Defaulted> hoursAllocated,\n Connection c\n ) {\n return (new ProjectAssignmentRepoImpl()).insert(new ProjectAssignmentRowUnsaved(employeeId, projectId, role, startDate, endDate, hoursAllocated), c);\n };\n}" - }, - "kotlin": { - "CompanyRow": "package showcase.showcase.company\n\nimport dev.typr.foundations.MariaTypes\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport dev.typr.foundations.kotlin.nullable\nimport java.time.LocalDateTime\nimport showcase.customtypes.Defaulted\n\n/** Table: showcase.company\n * Primary key: id\n */\ndata class CompanyRow(\n val id: CompanyId,\n val name: String,\n val foundedYear: Int?,\n /** Default: true */\n val active: Boolean?,\n /** Default: CURRENT_TIMESTAMP */\n val createdAt: LocalDateTime?\n) {\n fun toUnsavedRow(\n active: Defaulted,\n createdAt: Defaulted\n ): CompanyRowUnsaved = CompanyRowUnsaved(id, name, foundedYear, active, createdAt)\n\n companion object {\n val _rowParser: RowParser = RowParsers.of(CompanyId.pgType, MariaTypes.varchar, KotlinDbTypes.MariaTypes.int_.nullable(), KotlinDbTypes.MariaTypes.bool.nullable(), MariaTypes.timestamp.nullable(), { t0, t1, t2, t3, t4 -> CompanyRow(t0, t1, t2, t3, t4) }, { row -> arrayOf(row.id, row.name, row.foundedYear, row.active, row.createdAt) })\n }\n}", - "CompanyRowUnsaved": "package showcase.showcase.company\n\nimport java.time.LocalDateTime\nimport showcase.customtypes.Defaulted\nimport showcase.customtypes.Defaulted.UseDefault\n\n/** This class corresponds to a row in table `showcase.company` which has not been persisted yet */\ndata class CompanyRowUnsaved(\n val id: CompanyId,\n val name: String,\n val foundedYear: Int? = null,\n /** Default: true */\n val active: Defaulted = UseDefault(),\n /** Default: CURRENT_TIMESTAMP */\n val createdAt: Defaulted = UseDefault()\n) {\n fun toRow(\n activeDefault: () -> Boolean?,\n createdAtDefault: () -> LocalDateTime?\n ): CompanyRow = CompanyRow(id = id, name = name, foundedYear = foundedYear, active = active.getOrElse(activeDefault), createdAt = createdAt.getOrElse(createdAtDefault))\n}", - "CompanyId": "package showcase.showcase.company\n\nimport dev.typr.foundations.MariaType\nimport dev.typr.foundations.MariaTypes\nimport dev.typr.foundations.kotlin.Bijection\n\n/** Type for the primary key of table `showcase.company` */\ndata class CompanyId(val value: String) {\n override fun toString(): kotlin.String {\n return value.toString()\n }\n\n companion object {\n val bijection: Bijection =\n Bijection.of(CompanyId::value, ::CompanyId)\n\n val pgType: MariaType =\n MariaTypes.varchar.bimap(::CompanyId, CompanyId::value)\n }\n}", - "CompanyRepo": "package showcase.showcase.company\n\nimport dev.typr.foundations.kotlin.DeleteBuilder\nimport dev.typr.foundations.kotlin.SelectBuilder\nimport dev.typr.foundations.kotlin.UpdateBuilder\nimport java.sql.Connection\nimport kotlin.collections.Iterator\nimport kotlin.collections.List\nimport kotlin.collections.Map\n\ninterface CompanyRepo {\n abstract fun delete(): DeleteBuilder\n\n abstract fun deleteById(\n id: CompanyId,\n c: Connection\n ): Boolean\n\n abstract fun deleteByIds(\n ids: Array,\n c: Connection\n ): Int\n\n abstract fun insert(\n unsaved: CompanyRow,\n c: Connection\n ): CompanyRow\n\n abstract fun insert(\n unsaved: CompanyRowUnsaved,\n c: Connection\n ): CompanyRow\n\n abstract fun select(): SelectBuilder\n\n abstract fun selectAll(c: Connection): List\n\n abstract fun selectById(\n id: CompanyId,\n c: Connection\n ): CompanyRow?\n\n abstract fun selectByIds(\n ids: Array,\n c: Connection\n ): List\n\n abstract fun selectByIdsTracked(\n ids: Array,\n c: Connection\n ): Map\n\n abstract fun update(): UpdateBuilder\n\n abstract fun update(\n row: CompanyRow,\n c: Connection\n ): Boolean\n\n abstract fun upsert(\n unsaved: CompanyRow,\n c: Connection\n ): CompanyRow\n\n abstract fun upsertBatch(\n unsaved: Iterator,\n c: Connection\n ): List\n}", - "CompanyRepoMock": "package showcase.showcase.company\n\nimport dev.typr.foundations.kotlin.DeleteBuilder\nimport dev.typr.foundations.kotlin.DeleteBuilderMock\nimport dev.typr.foundations.kotlin.DeleteParams\nimport dev.typr.foundations.kotlin.SelectBuilder\nimport dev.typr.foundations.kotlin.SelectBuilderMock\nimport dev.typr.foundations.kotlin.SelectParams\nimport dev.typr.foundations.kotlin.UpdateBuilder\nimport dev.typr.foundations.kotlin.UpdateBuilderMock\nimport dev.typr.foundations.kotlin.UpdateParams\nimport java.lang.RuntimeException\nimport java.sql.Connection\nimport java.util.ArrayList\nimport kotlin.collections.Iterator\nimport kotlin.collections.List\nimport kotlin.collections.Map\nimport kotlin.collections.MutableMap\n\ndata class CompanyRepoMock(\n val toRow: (CompanyRowUnsaved) -> CompanyRow,\n val map: MutableMap = mutableMapOf()\n) : CompanyRepo {\n override fun delete(): DeleteBuilder = DeleteBuilderMock(CompanyFields.structure, { map.values.toList() }, DeleteParams.empty(), { row -> row.id }, { id -> map.remove(id) })\n\n override fun deleteById(\n id: CompanyId,\n c: Connection\n ): Boolean = map.remove(id) != null\n\n override fun deleteByIds(\n ids: Array,\n c: Connection\n ): Int {\n var count = 0\n for (id in ids) {\n if (map.remove(id) != null) {\n count = count + 1\n }\n }\n return count\n }\n\n override fun insert(\n unsaved: CompanyRow,\n c: Connection\n ): CompanyRow {\n if (map.containsKey(unsaved.id)) {\n throw RuntimeException(\"id \" + unsaved.id + \" already exists\")\n }\n map[unsaved.id] = unsaved\n return unsaved\n }\n\n override fun insert(\n unsaved: CompanyRowUnsaved,\n c: Connection\n ): CompanyRow = insert(toRow(unsaved), c)\n\n override fun select(): SelectBuilder = SelectBuilderMock(CompanyFields.structure, { map.values.toList() }, SelectParams.empty())\n\n override fun selectAll(c: Connection): List = map.values.toList()\n\n override fun selectById(\n id: CompanyId,\n c: Connection\n ): CompanyRow? = map[id]\n\n override fun selectByIds(\n ids: Array,\n c: Connection\n ): List {\n val result = ArrayList()\n for (id in ids) {\n val opt = map[id]\n if (opt != null) {\n result.add(opt!!)\n }\n }\n return result\n }\n\n override fun selectByIdsTracked(\n ids: Array,\n c: Connection\n ): Map = selectByIds(ids, c).associateBy({ row: CompanyRow -> row.id })\n\n override fun update(): UpdateBuilder = UpdateBuilderMock(CompanyFields.structure, { map.values.toList() }, UpdateParams.empty(), { row -> row })\n\n override fun update(\n row: CompanyRow,\n c: Connection\n ): Boolean {\n val shouldUpdate = map[row.id]?.takeIf({ oldRow -> (oldRow != row) }) != null\n if (shouldUpdate) {\n map[row.id] = row\n }\n return shouldUpdate\n }\n\n override fun upsert(\n unsaved: CompanyRow,\n c: Connection\n ): CompanyRow {\n map[unsaved.id] = unsaved\n return unsaved\n }\n\n override fun upsertBatch(\n unsaved: Iterator,\n c: Connection\n ): List {\n val result = ArrayList()\n while (unsaved.hasNext()) {\n val row = unsaved.next()\n map[row.id] = row\n result.add(row)\n }\n return result\n }\n}", - "EmployeeRow": "package showcase.showcase.employee\n\nimport dev.typr.foundations.MariaTypes\nimport dev.typr.foundations.data.Json\nimport dev.typr.foundations.data.maria.Inet4\nimport dev.typr.foundations.data.maria.MariaSet\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport dev.typr.foundations.kotlin.nullable\nimport java.math.BigDecimal\nimport java.time.LocalDate\nimport java.time.LocalDateTime\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.department.DepartmentId\n\n/** Table: showcase.employee\n * Primary key: id\n */\ndata class EmployeeRow(\n val id: EmployeeId,\n /** Points to [showcase.showcase.department.DepartmentRow.id] */\n val departmentId: DepartmentId,\n /** Points to [showcase.showcase.employee.EmployeeRow.id] */\n val managerId: EmployeeId?,\n val email: String,\n val firstName: String,\n val lastName: String,\n val salary: BigDecimal?,\n val hiredAt: LocalDate?,\n /** Default: true */\n val active: Boolean?,\n /** Default: CURRENT_TIMESTAMP */\n val createdAt: LocalDateTime?,\n val metadata: Json?,\n val photo: ByteArray?,\n val ipAddress: Inet4?,\n val permissions: MariaSet?\n) {\n fun toUnsavedRow(\n active: Defaulted,\n createdAt: Defaulted\n ): EmployeeRowUnsaved = EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, metadata, photo, ipAddress, permissions, active, createdAt)\n\n companion object {\n val _rowParser: RowParser = RowParsers.of(EmployeeId.pgType, DepartmentId.pgType, EmployeeId.pgType.nullable(), MariaTypes.varchar, MariaTypes.varchar, MariaTypes.varchar, KotlinDbTypes.MariaTypes.numeric.nullable(), MariaTypes.date.nullable(), KotlinDbTypes.MariaTypes.bool.nullable(), MariaTypes.timestamp.nullable(), MariaTypes.json.nullable(), MariaTypes.mediumblob.nullable(), MariaTypes.inet4.nullable(), MariaTypes.set.nullable(), { t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13 -> EmployeeRow(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13) }, { row -> arrayOf(row.id, row.departmentId, row.managerId, row.email, row.firstName, row.lastName, row.salary, row.hiredAt, row.active, row.createdAt, row.metadata, row.photo, row.ipAddress, row.permissions) })\n }\n}", - "EmployeeRowUnsaved": "package showcase.showcase.employee\n\nimport dev.typr.foundations.data.Json\nimport dev.typr.foundations.data.maria.Inet4\nimport dev.typr.foundations.data.maria.MariaSet\nimport java.math.BigDecimal\nimport java.time.LocalDate\nimport java.time.LocalDateTime\nimport showcase.customtypes.Defaulted\nimport showcase.customtypes.Defaulted.UseDefault\nimport showcase.showcase.department.DepartmentId\n\n/** This class corresponds to a row in table `showcase.employee` which has not been persisted yet */\ndata class EmployeeRowUnsaved(\n val id: EmployeeId,\n /** Points to [showcase.showcase.department.DepartmentRow.id] */\n val departmentId: DepartmentId,\n /** Points to [showcase.showcase.employee.EmployeeRow.id] */\n val managerId: EmployeeId? = null,\n val email: String,\n val firstName: String,\n val lastName: String,\n val salary: BigDecimal? = null,\n val hiredAt: LocalDate? = null,\n val metadata: Json? = null,\n val photo: ByteArray? = null,\n val ipAddress: Inet4? = null,\n val permissions: MariaSet? = null,\n /** Default: true */\n val active: Defaulted = UseDefault(),\n /** Default: CURRENT_TIMESTAMP */\n val createdAt: Defaulted = UseDefault()\n) {\n fun toRow(\n activeDefault: () -> Boolean?,\n createdAtDefault: () -> LocalDateTime?\n ): EmployeeRow = EmployeeRow(id = id, departmentId = departmentId, managerId = managerId, email = email, firstName = firstName, lastName = lastName, salary = salary, hiredAt = hiredAt, active = active.getOrElse(activeDefault), createdAt = createdAt.getOrElse(createdAtDefault), metadata = metadata, photo = photo, ipAddress = ipAddress, permissions = permissions)\n}", - "EmployeeId": "package showcase.showcase.employee\n\nimport dev.typr.foundations.MariaType\nimport dev.typr.foundations.MariaTypes\nimport dev.typr.foundations.kotlin.Bijection\n\n/** Type for the primary key of table `showcase.employee` */\ndata class EmployeeId(val value: String) {\n override fun toString(): kotlin.String {\n return value.toString()\n }\n\n companion object {\n val bijection: Bijection =\n Bijection.of(EmployeeId::value, ::EmployeeId)\n\n val pgType: MariaType =\n MariaTypes.varchar.bimap(::EmployeeId, EmployeeId::value)\n }\n}", - "EmployeeRepo": "package showcase.showcase.employee\n\nimport dev.typr.foundations.kotlin.DeleteBuilder\nimport dev.typr.foundations.kotlin.SelectBuilder\nimport dev.typr.foundations.kotlin.UpdateBuilder\nimport java.sql.Connection\nimport kotlin.collections.Iterator\nimport kotlin.collections.List\nimport kotlin.collections.Map\n\ninterface EmployeeRepo {\n abstract fun delete(): DeleteBuilder\n\n abstract fun deleteById(\n id: EmployeeId,\n c: Connection\n ): Boolean\n\n abstract fun deleteByIds(\n ids: Array,\n c: Connection\n ): Int\n\n abstract fun insert(\n unsaved: EmployeeRow,\n c: Connection\n ): EmployeeRow\n\n abstract fun insert(\n unsaved: EmployeeRowUnsaved,\n c: Connection\n ): EmployeeRow\n\n abstract fun select(): SelectBuilder\n\n abstract fun selectAll(c: Connection): List\n\n abstract fun selectById(\n id: EmployeeId,\n c: Connection\n ): EmployeeRow?\n\n abstract fun selectByIds(\n ids: Array,\n c: Connection\n ): List\n\n abstract fun selectByIdsTracked(\n ids: Array,\n c: Connection\n ): Map\n\n abstract fun selectByUniqueEmail(\n email: String,\n c: Connection\n ): EmployeeRow?\n\n abstract fun update(): UpdateBuilder\n\n abstract fun update(\n row: EmployeeRow,\n c: Connection\n ): Boolean\n\n abstract fun upsert(\n unsaved: EmployeeRow,\n c: Connection\n ): EmployeeRow\n\n abstract fun upsertBatch(\n unsaved: Iterator,\n c: Connection\n ): List\n}", - "EmployeeRepoImpl": "package showcase.showcase.employee\n\nimport dev.typr.foundations.MariaTypes\nimport dev.typr.foundations.kotlin.DeleteBuilder\nimport dev.typr.foundations.kotlin.Dialect\nimport dev.typr.foundations.kotlin.Fragment\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.SelectBuilder\nimport dev.typr.foundations.kotlin.UpdateBuilder\nimport dev.typr.foundations.kotlin.nullable\nimport java.sql.Connection\nimport java.util.ArrayList\nimport kotlin.collections.Iterator\nimport kotlin.collections.List\nimport kotlin.collections.Map\nimport kotlin.collections.MutableMap\nimport showcase.showcase.department.DepartmentId\n\nclass EmployeeRepoImpl() : EmployeeRepo {\n override fun delete(): DeleteBuilder = DeleteBuilder.of(\"`showcase`.`employee`\", EmployeeFields.structure, Dialect.MARIADB)\n\n override fun deleteById(\n id: EmployeeId,\n c: Connection\n ): Boolean = Fragment.interpolate(Fragment.lit(\"delete from `showcase`.`employee` where `id` = \"), Fragment.encode(EmployeeId.pgType, id), Fragment.lit(\"\")).update().runUnchecked(c) > 0\n\n override fun deleteByIds(\n ids: Array,\n c: Connection\n ): Int {\n val fragments: ArrayList = ArrayList()\n for (id in ids) { fragments.add(Fragment.encode(EmployeeId.pgType, id)) }\n return Fragment.interpolate(Fragment.lit(\"delete from `showcase`.`employee` where `id` in (\"), Fragment.comma(fragments.toMutableList()), Fragment.lit(\")\")).update().runUnchecked(c)\n }\n\n override fun insert(\n unsaved: EmployeeRow,\n c: Connection\n ): EmployeeRow = Fragment.interpolate(Fragment.lit(\"insert into `showcase`.`employee`(`id`, `department_id`, `manager_id`, `email`, `first_name`, `last_name`, `salary`, `hired_at`, `active`, `created_at`, `metadata`, `photo`, `ip_address`, `permissions`)\\nvalues (\"), Fragment.encode(EmployeeId.pgType, unsaved.id), Fragment.lit(\", \"), Fragment.encode(DepartmentId.pgType, unsaved.departmentId), Fragment.lit(\", \"), Fragment.encode(EmployeeId.pgType.nullable(), unsaved.managerId), Fragment.lit(\", \"), Fragment.encode(MariaTypes.varchar, unsaved.email), Fragment.lit(\", \"), Fragment.encode(MariaTypes.varchar, unsaved.firstName), Fragment.lit(\", \"), Fragment.encode(MariaTypes.varchar, unsaved.lastName), Fragment.lit(\", \"), Fragment.encode(KotlinDbTypes.MariaTypes.numeric.nullable(), unsaved.salary), Fragment.lit(\", \"), Fragment.encode(MariaTypes.date.nullable(), unsaved.hiredAt), Fragment.lit(\", \"), Fragment.encode(KotlinDbTypes.MariaTypes.bool.nullable(), unsaved.active), Fragment.lit(\", \"), Fragment.encode(MariaTypes.timestamp.nullable(), unsaved.createdAt), Fragment.lit(\", \"), Fragment.encode(MariaTypes.json.nullable(), unsaved.metadata), Fragment.lit(\", \"), Fragment.encode(MariaTypes.mediumblob.nullable(), unsaved.photo), Fragment.lit(\", \"), Fragment.encode(MariaTypes.inet4.nullable(), unsaved.ipAddress), Fragment.lit(\", \"), Fragment.encode(MariaTypes.set.nullable(), unsaved.permissions), Fragment.lit(\")\\nRETURNING `id`, `department_id`, `manager_id`, `email`, `first_name`, `last_name`, `salary`, `hired_at`, `active`, `created_at`, `metadata`, `photo`, `ip_address`, `permissions`\\n\"))\n .updateReturning(EmployeeRow._rowParser.exactlyOne()).runUnchecked(c)\n\n override fun insert(\n unsaved: EmployeeRowUnsaved,\n c: Connection\n ): EmployeeRow {\n val columns: ArrayList = ArrayList()\n val values: ArrayList = ArrayList()\n columns.add(Fragment.lit(\"`id`\"))\n values.add(Fragment.interpolate(Fragment.encode(EmployeeId.pgType, unsaved.id), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"`department_id`\"))\n values.add(Fragment.interpolate(Fragment.encode(DepartmentId.pgType, unsaved.departmentId), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"`manager_id`\"))\n values.add(Fragment.interpolate(Fragment.encode(EmployeeId.pgType.nullable(), unsaved.managerId), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"`email`\"))\n values.add(Fragment.interpolate(Fragment.encode(MariaTypes.varchar, unsaved.email), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"`first_name`\"))\n values.add(Fragment.interpolate(Fragment.encode(MariaTypes.varchar, unsaved.firstName), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"`last_name`\"))\n values.add(Fragment.interpolate(Fragment.encode(MariaTypes.varchar, unsaved.lastName), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"`salary`\"))\n values.add(Fragment.interpolate(Fragment.encode(KotlinDbTypes.MariaTypes.numeric.nullable(), unsaved.salary), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"`hired_at`\"))\n values.add(Fragment.interpolate(Fragment.encode(MariaTypes.date.nullable(), unsaved.hiredAt), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"`metadata`\"))\n values.add(Fragment.interpolate(Fragment.encode(MariaTypes.json.nullable(), unsaved.metadata), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"`photo`\"))\n values.add(Fragment.interpolate(Fragment.encode(MariaTypes.mediumblob.nullable(), unsaved.photo), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"`ip_address`\"))\n values.add(Fragment.interpolate(Fragment.encode(MariaTypes.inet4.nullable(), unsaved.ipAddress), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"`permissions`\"))\n values.add(Fragment.interpolate(Fragment.encode(MariaTypes.set.nullable(), unsaved.permissions), Fragment.lit(\"\")))\n unsaved.active.visit(\n { },\n { value -> columns.add(Fragment.lit(\"`active`\"))\n values.add(Fragment.interpolate(Fragment.encode(KotlinDbTypes.MariaTypes.bool.nullable(), value), Fragment.lit(\"\"))) }\n );\n unsaved.createdAt.visit(\n { },\n { value -> columns.add(Fragment.lit(\"`created_at`\"))\n values.add(Fragment.interpolate(Fragment.encode(MariaTypes.timestamp.nullable(), value), Fragment.lit(\"\"))) }\n );\n val q: Fragment = Fragment.interpolate(Fragment.lit(\"insert into `showcase`.`employee`(\"), Fragment.comma(columns.toMutableList()), Fragment.lit(\")\\nvalues (\"), Fragment.comma(values.toMutableList()), Fragment.lit(\")\\nRETURNING `id`, `department_id`, `manager_id`, `email`, `first_name`, `last_name`, `salary`, `hired_at`, `active`, `created_at`, `metadata`, `photo`, `ip_address`, `permissions`\\n\"))\n return q.updateReturning(EmployeeRow._rowParser.exactlyOne()).runUnchecked(c)\n }\n\n override fun select(): SelectBuilder = SelectBuilder.of(\"`showcase`.`employee`\", EmployeeFields.structure, EmployeeRow._rowParser, Dialect.MARIADB)\n\n override fun selectAll(c: Connection): List = Fragment.interpolate(Fragment.lit(\"select `id`, `department_id`, `manager_id`, `email`, `first_name`, `last_name`, `salary`, `hired_at`, `active`, `created_at`, `metadata`, `photo`, `ip_address`, `permissions`\\nfrom `showcase`.`employee`\\n\")).query(EmployeeRow._rowParser.all()).runUnchecked(c)\n\n override fun selectById(\n id: EmployeeId,\n c: Connection\n ): EmployeeRow? = Fragment.interpolate(Fragment.lit(\"select `id`, `department_id`, `manager_id`, `email`, `first_name`, `last_name`, `salary`, `hired_at`, `active`, `created_at`, `metadata`, `photo`, `ip_address`, `permissions`\\nfrom `showcase`.`employee`\\nwhere `id` = \"), Fragment.encode(EmployeeId.pgType, id), Fragment.lit(\"\")).query(EmployeeRow._rowParser.first()).runUnchecked(c)\n\n override fun selectByIds(\n ids: Array,\n c: Connection\n ): List {\n val fragments: ArrayList = ArrayList()\n for (id in ids) { fragments.add(Fragment.encode(EmployeeId.pgType, id)) }\n return Fragment.interpolate(Fragment.lit(\"select `id`, `department_id`, `manager_id`, `email`, `first_name`, `last_name`, `salary`, `hired_at`, `active`, `created_at`, `metadata`, `photo`, `ip_address`, `permissions` from `showcase`.`employee` where `id` in (\"), Fragment.comma(fragments.toMutableList()), Fragment.lit(\")\")).query(EmployeeRow._rowParser.all()).runUnchecked(c)\n }\n\n override fun selectByIdsTracked(\n ids: Array,\n c: Connection\n ): Map {\n val ret: MutableMap = mutableMapOf()\n selectByIds(ids, c).forEach({ row -> ret.put(row.id, row) })\n return ret.toMap()\n }\n\n override fun selectByUniqueEmail(\n email: String,\n c: Connection\n ): EmployeeRow? = Fragment.interpolate(Fragment.lit(\"select `id`, `department_id`, `manager_id`, `email`, `first_name`, `last_name`, `salary`, `hired_at`, `active`, `created_at`, `metadata`, `photo`, `ip_address`, `permissions`\\nfrom `showcase`.`employee`\\nwhere `email` = \"), Fragment.encode(MariaTypes.varchar, email), Fragment.lit(\"\\n\")).query(EmployeeRow._rowParser.first()).runUnchecked(c)\n\n override fun update(): UpdateBuilder = UpdateBuilder.of(\"`showcase`.`employee`\", EmployeeFields.structure, EmployeeRow._rowParser, Dialect.MARIADB)\n\n override fun update(\n row: EmployeeRow,\n c: Connection\n ): Boolean {\n val id: EmployeeId = row.id\n return Fragment.interpolate(Fragment.lit(\"update `showcase`.`employee`\\nset `department_id` = \"), Fragment.encode(DepartmentId.pgType, row.departmentId), Fragment.lit(\",\\n`manager_id` = \"), Fragment.encode(EmployeeId.pgType.nullable(), row.managerId), Fragment.lit(\",\\n`email` = \"), Fragment.encode(MariaTypes.varchar, row.email), Fragment.lit(\",\\n`first_name` = \"), Fragment.encode(MariaTypes.varchar, row.firstName), Fragment.lit(\",\\n`last_name` = \"), Fragment.encode(MariaTypes.varchar, row.lastName), Fragment.lit(\",\\n`salary` = \"), Fragment.encode(KotlinDbTypes.MariaTypes.numeric.nullable(), row.salary), Fragment.lit(\",\\n`hired_at` = \"), Fragment.encode(MariaTypes.date.nullable(), row.hiredAt), Fragment.lit(\",\\n`active` = \"), Fragment.encode(KotlinDbTypes.MariaTypes.bool.nullable(), row.active), Fragment.lit(\",\\n`created_at` = \"), Fragment.encode(MariaTypes.timestamp.nullable(), row.createdAt), Fragment.lit(\",\\n`metadata` = \"), Fragment.encode(MariaTypes.json.nullable(), row.metadata), Fragment.lit(\",\\n`photo` = \"), Fragment.encode(MariaTypes.mediumblob.nullable(), row.photo), Fragment.lit(\",\\n`ip_address` = \"), Fragment.encode(MariaTypes.inet4.nullable(), row.ipAddress), Fragment.lit(\",\\n`permissions` = \"), Fragment.encode(MariaTypes.set.nullable(), row.permissions), Fragment.lit(\"\\nwhere `id` = \"), Fragment.encode(EmployeeId.pgType, id), Fragment.lit(\"\")).update().runUnchecked(c) > 0\n }\n\n override fun upsert(\n unsaved: EmployeeRow,\n c: Connection\n ): EmployeeRow = Fragment.interpolate(Fragment.lit(\"INSERT INTO `showcase`.`employee`(`id`, `department_id`, `manager_id`, `email`, `first_name`, `last_name`, `salary`, `hired_at`, `active`, `created_at`, `metadata`, `photo`, `ip_address`, `permissions`)\\nVALUES (\"), Fragment.encode(EmployeeId.pgType, unsaved.id), Fragment.lit(\", \"), Fragment.encode(DepartmentId.pgType, unsaved.departmentId), Fragment.lit(\", \"), Fragment.encode(EmployeeId.pgType.nullable(), unsaved.managerId), Fragment.lit(\", \"), Fragment.encode(MariaTypes.varchar, unsaved.email), Fragment.lit(\", \"), Fragment.encode(MariaTypes.varchar, unsaved.firstName), Fragment.lit(\", \"), Fragment.encode(MariaTypes.varchar, unsaved.lastName), Fragment.lit(\", \"), Fragment.encode(KotlinDbTypes.MariaTypes.numeric.nullable(), unsaved.salary), Fragment.lit(\", \"), Fragment.encode(MariaTypes.date.nullable(), unsaved.hiredAt), Fragment.lit(\", \"), Fragment.encode(KotlinDbTypes.MariaTypes.bool.nullable(), unsaved.active), Fragment.lit(\", \"), Fragment.encode(MariaTypes.timestamp.nullable(), unsaved.createdAt), Fragment.lit(\", \"), Fragment.encode(MariaTypes.json.nullable(), unsaved.metadata), Fragment.lit(\", \"), Fragment.encode(MariaTypes.mediumblob.nullable(), unsaved.photo), Fragment.lit(\", \"), Fragment.encode(MariaTypes.inet4.nullable(), unsaved.ipAddress), Fragment.lit(\", \"), Fragment.encode(MariaTypes.set.nullable(), unsaved.permissions), Fragment.lit(\")\\nON DUPLICATE KEY UPDATE `department_id` = VALUES(`department_id`),\\n`manager_id` = VALUES(`manager_id`),\\n`email` = VALUES(`email`),\\n`first_name` = VALUES(`first_name`),\\n`last_name` = VALUES(`last_name`),\\n`salary` = VALUES(`salary`),\\n`hired_at` = VALUES(`hired_at`),\\n`active` = VALUES(`active`),\\n`created_at` = VALUES(`created_at`),\\n`metadata` = VALUES(`metadata`),\\n`photo` = VALUES(`photo`),\\n`ip_address` = VALUES(`ip_address`),\\n`permissions` = VALUES(`permissions`)\\nRETURNING `id`, `department_id`, `manager_id`, `email`, `first_name`, `last_name`, `salary`, `hired_at`, `active`, `created_at`, `metadata`, `photo`, `ip_address`, `permissions`\"))\n .updateReturning(EmployeeRow._rowParser.exactlyOne())\n .runUnchecked(c)\n\n override fun upsertBatch(\n unsaved: Iterator,\n c: Connection\n ): List = Fragment.interpolate(Fragment.lit(\"INSERT INTO `showcase`.`employee`(`id`, `department_id`, `manager_id`, `email`, `first_name`, `last_name`, `salary`, `hired_at`, `active`, `created_at`, `metadata`, `photo`, `ip_address`, `permissions`)\\nVALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\\nON DUPLICATE KEY UPDATE `department_id` = VALUES(`department_id`),\\n`manager_id` = VALUES(`manager_id`),\\n`email` = VALUES(`email`),\\n`first_name` = VALUES(`first_name`),\\n`last_name` = VALUES(`last_name`),\\n`salary` = VALUES(`salary`),\\n`hired_at` = VALUES(`hired_at`),\\n`active` = VALUES(`active`),\\n`created_at` = VALUES(`created_at`),\\n`metadata` = VALUES(`metadata`),\\n`photo` = VALUES(`photo`),\\n`ip_address` = VALUES(`ip_address`),\\n`permissions` = VALUES(`permissions`)\\nRETURNING `id`, `department_id`, `manager_id`, `email`, `first_name`, `last_name`, `salary`, `hired_at`, `active`, `created_at`, `metadata`, `photo`, `ip_address`, `permissions`\"))\n .updateReturningEach(EmployeeRow._rowParser, unsaved)\n .runUnchecked(c)\n}", - "EmployeeRepoMock": "package showcase.showcase.employee\n\nimport dev.typr.foundations.kotlin.DeleteBuilder\nimport dev.typr.foundations.kotlin.DeleteBuilderMock\nimport dev.typr.foundations.kotlin.DeleteParams\nimport dev.typr.foundations.kotlin.SelectBuilder\nimport dev.typr.foundations.kotlin.SelectBuilderMock\nimport dev.typr.foundations.kotlin.SelectParams\nimport dev.typr.foundations.kotlin.UpdateBuilder\nimport dev.typr.foundations.kotlin.UpdateBuilderMock\nimport dev.typr.foundations.kotlin.UpdateParams\nimport java.lang.RuntimeException\nimport java.sql.Connection\nimport java.util.ArrayList\nimport kotlin.collections.Iterator\nimport kotlin.collections.List\nimport kotlin.collections.Map\nimport kotlin.collections.MutableMap\n\ndata class EmployeeRepoMock(\n val toRow: (EmployeeRowUnsaved) -> EmployeeRow,\n val map: MutableMap = mutableMapOf()\n) : EmployeeRepo {\n override fun delete(): DeleteBuilder = DeleteBuilderMock(EmployeeFields.structure, { map.values.toList() }, DeleteParams.empty(), { row -> row.id }, { id -> map.remove(id) })\n\n override fun deleteById(\n id: EmployeeId,\n c: Connection\n ): Boolean = map.remove(id) != null\n\n override fun deleteByIds(\n ids: Array,\n c: Connection\n ): Int {\n var count = 0\n for (id in ids) {\n if (map.remove(id) != null) {\n count = count + 1\n }\n }\n return count\n }\n\n override fun insert(\n unsaved: EmployeeRow,\n c: Connection\n ): EmployeeRow {\n if (map.containsKey(unsaved.id)) {\n throw RuntimeException(\"id \" + unsaved.id + \" already exists\")\n }\n map[unsaved.id] = unsaved\n return unsaved\n }\n\n override fun insert(\n unsaved: EmployeeRowUnsaved,\n c: Connection\n ): EmployeeRow = insert(toRow(unsaved), c)\n\n override fun select(): SelectBuilder = SelectBuilderMock(EmployeeFields.structure, { map.values.toList() }, SelectParams.empty())\n\n override fun selectAll(c: Connection): List = map.values.toList()\n\n override fun selectById(\n id: EmployeeId,\n c: Connection\n ): EmployeeRow? = map[id]\n\n override fun selectByIds(\n ids: Array,\n c: Connection\n ): List {\n val result = ArrayList()\n for (id in ids) {\n val opt = map[id]\n if (opt != null) {\n result.add(opt!!)\n }\n }\n return result\n }\n\n override fun selectByIdsTracked(\n ids: Array,\n c: Connection\n ): Map = selectByIds(ids, c).associateBy({ row: EmployeeRow -> row.id })\n\n override fun selectByUniqueEmail(\n email: String,\n c: Connection\n ): EmployeeRow? = map.values.toList().find({ v -> (email == v.email) })\n\n override fun update(): UpdateBuilder = UpdateBuilderMock(EmployeeFields.structure, { map.values.toList() }, UpdateParams.empty(), { row -> row })\n\n override fun update(\n row: EmployeeRow,\n c: Connection\n ): Boolean {\n val shouldUpdate = map[row.id]?.takeIf({ oldRow -> (oldRow != row) }) != null\n if (shouldUpdate) {\n map[row.id] = row\n }\n return shouldUpdate\n }\n\n override fun upsert(\n unsaved: EmployeeRow,\n c: Connection\n ): EmployeeRow {\n map[unsaved.id] = unsaved\n return unsaved\n }\n\n override fun upsertBatch(\n unsaved: Iterator,\n c: Connection\n ): List {\n val result = ArrayList()\n while (unsaved.hasNext()) {\n val row = unsaved.next()\n map[row.id] = row\n result.add(row)\n }\n return result\n }\n}", - "EmployeeFields": "package showcase.showcase.employee\n\nimport dev.typr.foundations.MariaTypes\nimport dev.typr.foundations.RowParser\nimport dev.typr.foundations.data.Json\nimport dev.typr.foundations.data.maria.Inet4\nimport dev.typr.foundations.data.maria.MariaSet\nimport dev.typr.foundations.dsl.FieldsExpr\nimport dev.typr.foundations.dsl.Path\nimport dev.typr.foundations.dsl.SqlExpr.FieldLike\nimport dev.typr.foundations.kotlin.ForeignKey\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.RelationStructure\nimport dev.typr.foundations.kotlin.SqlExpr.Field\nimport dev.typr.foundations.kotlin.SqlExpr.IdField\nimport dev.typr.foundations.kotlin.SqlExpr.OptField\nimport java.math.BigDecimal\nimport java.time.LocalDate\nimport java.time.LocalDateTime\nimport kotlin.collections.List\nimport showcase.showcase.department.DepartmentFields\nimport showcase.showcase.department.DepartmentId\nimport showcase.showcase.department.DepartmentRow\n\ninterface EmployeeFields : FieldsExpr {\n abstract fun active(): OptField\n\n abstract override fun columns(): List>\n\n abstract fun createdAt(): OptField\n\n abstract fun departmentId(): Field\n\n abstract fun email(): Field\n\n abstract fun firstName(): Field\n\n fun fkDepartment(): ForeignKey = ForeignKey.of(\"employee_department_fk\").withColumnPair(departmentId(), DepartmentFields::id)\n\n fun fkEmployee(): ForeignKey = ForeignKey.of(\"employee_manager_fk\").withColumnPair(managerId(), EmployeeFields::id)\n\n abstract fun hiredAt(): OptField\n\n abstract fun id(): IdField\n\n abstract fun ipAddress(): OptField\n\n abstract fun lastName(): Field\n\n abstract fun managerId(): OptField\n\n abstract fun metadata(): OptField\n\n abstract fun permissions(): OptField\n\n abstract fun photo(): OptField\n\n override fun rowParser(): RowParser = EmployeeRow._rowParser.underlying\n\n abstract fun salary(): OptField\n\n companion object {\n data class Impl(val _path: List) : EmployeeFields, RelationStructure {\n override fun id(): IdField = IdField(_path, \"id\", EmployeeRow::id, null, null, { row, value -> row.copy(id = value) }, EmployeeId.pgType)\n\n override fun departmentId(): Field = Field(_path, \"department_id\", EmployeeRow::departmentId, null, null, { row, value -> row.copy(departmentId = value) }, DepartmentId.pgType)\n\n override fun managerId(): OptField = OptField(_path, \"manager_id\", EmployeeRow::managerId, null, null, { row, value -> row.copy(managerId = value) }, EmployeeId.pgType)\n\n override fun email(): Field = Field(_path, \"email\", EmployeeRow::email, null, null, { row, value -> row.copy(email = value) }, MariaTypes.varchar)\n\n override fun firstName(): Field = Field(_path, \"first_name\", EmployeeRow::firstName, null, null, { row, value -> row.copy(firstName = value) }, MariaTypes.varchar)\n\n override fun lastName(): Field = Field(_path, \"last_name\", EmployeeRow::lastName, null, null, { row, value -> row.copy(lastName = value) }, MariaTypes.varchar)\n\n override fun salary(): OptField = OptField(_path, \"salary\", EmployeeRow::salary, null, null, { row, value -> row.copy(salary = value) }, KotlinDbTypes.MariaTypes.numeric)\n\n override fun hiredAt(): OptField = OptField(_path, \"hired_at\", EmployeeRow::hiredAt, null, null, { row, value -> row.copy(hiredAt = value) }, MariaTypes.date)\n\n override fun active(): OptField = OptField(_path, \"active\", EmployeeRow::active, null, null, { row, value -> row.copy(active = value) }, KotlinDbTypes.MariaTypes.bool)\n\n override fun createdAt(): OptField = OptField(_path, \"created_at\", EmployeeRow::createdAt, null, null, { row, value -> row.copy(createdAt = value) }, MariaTypes.timestamp)\n\n override fun metadata(): OptField = OptField(_path, \"metadata\", EmployeeRow::metadata, null, null, { row, value -> row.copy(metadata = value) }, MariaTypes.json)\n\n override fun photo(): OptField = OptField(_path, \"photo\", EmployeeRow::photo, null, null, { row, value -> row.copy(photo = value) }, MariaTypes.mediumblob)\n\n override fun ipAddress(): OptField = OptField(_path, \"ip_address\", EmployeeRow::ipAddress, null, null, { row, value -> row.copy(ipAddress = value) }, MariaTypes.inet4)\n\n override fun permissions(): OptField = OptField(_path, \"permissions\", EmployeeRow::permissions, null, null, { row, value -> row.copy(permissions = value) }, MariaTypes.set)\n\n override fun _path(): List = _path\n\n override fun columns(): List> = listOf(this.id().underlying, this.departmentId().underlying, this.managerId().underlying, this.email().underlying, this.firstName().underlying, this.lastName().underlying, this.salary().underlying, this.hiredAt().underlying, this.active().underlying, this.createdAt().underlying, this.metadata().underlying, this.photo().underlying, this.ipAddress().underlying, this.permissions().underlying)\n\n override fun withPaths(_path: List): RelationStructure = Impl(_path)\n }\n\n val structure: Impl = Impl(emptyList())\n }\n}", - "DepartmentRow": "package showcase.showcase.department\n\nimport dev.typr.foundations.MariaTypes\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport dev.typr.foundations.kotlin.nullable\nimport java.math.BigDecimal\nimport showcase.showcase.company.CompanyId\n\n/** Table: showcase.department\n * Primary key: id\n */\ndata class DepartmentRow(\n val id: DepartmentId,\n /** Points to [showcase.showcase.company.CompanyRow.id] */\n val companyId: CompanyId,\n val name: String,\n val budget: BigDecimal?\n) {\n companion object {\n val _rowParser: RowParser = RowParsers.of(DepartmentId.pgType, CompanyId.pgType, MariaTypes.varchar, KotlinDbTypes.MariaTypes.numeric.nullable(), { t0, t1, t2, t3 -> DepartmentRow(t0, t1, t2, t3) }, { row -> arrayOf(row.id, row.companyId, row.name, row.budget) })\n }\n}", - "DepartmentId": "package showcase.showcase.department\n\nimport dev.typr.foundations.MariaType\nimport dev.typr.foundations.MariaTypes\nimport dev.typr.foundations.kotlin.Bijection\n\n/** Type for the primary key of table `showcase.department` */\ndata class DepartmentId(val value: String) {\n override fun toString(): kotlin.String {\n return value.toString()\n }\n\n companion object {\n val bijection: Bijection =\n Bijection.of(DepartmentId::value, ::DepartmentId)\n\n val pgType: MariaType =\n MariaTypes.varchar.bimap(::DepartmentId, DepartmentId::value)\n }\n}", - "DepartmentRepo": "package showcase.showcase.department\n\nimport dev.typr.foundations.kotlin.DeleteBuilder\nimport dev.typr.foundations.kotlin.SelectBuilder\nimport dev.typr.foundations.kotlin.UpdateBuilder\nimport java.sql.Connection\nimport kotlin.collections.Iterator\nimport kotlin.collections.List\nimport kotlin.collections.Map\n\ninterface DepartmentRepo {\n abstract fun delete(): DeleteBuilder\n\n abstract fun deleteById(\n id: DepartmentId,\n c: Connection\n ): Boolean\n\n abstract fun deleteByIds(\n ids: Array,\n c: Connection\n ): Int\n\n abstract fun insert(\n unsaved: DepartmentRow,\n c: Connection\n ): DepartmentRow\n\n abstract fun select(): SelectBuilder\n\n abstract fun selectAll(c: Connection): List\n\n abstract fun selectById(\n id: DepartmentId,\n c: Connection\n ): DepartmentRow?\n\n abstract fun selectByIds(\n ids: Array,\n c: Connection\n ): List\n\n abstract fun selectByIdsTracked(\n ids: Array,\n c: Connection\n ): Map\n\n abstract fun update(): UpdateBuilder\n\n abstract fun update(\n row: DepartmentRow,\n c: Connection\n ): Boolean\n\n abstract fun upsert(\n unsaved: DepartmentRow,\n c: Connection\n ): DepartmentRow\n\n abstract fun upsertBatch(\n unsaved: Iterator,\n c: Connection\n ): List\n}", - "DepartmentRepoMock": "package showcase.showcase.department\n\nimport dev.typr.foundations.kotlin.DeleteBuilder\nimport dev.typr.foundations.kotlin.DeleteBuilderMock\nimport dev.typr.foundations.kotlin.DeleteParams\nimport dev.typr.foundations.kotlin.SelectBuilder\nimport dev.typr.foundations.kotlin.SelectBuilderMock\nimport dev.typr.foundations.kotlin.SelectParams\nimport dev.typr.foundations.kotlin.UpdateBuilder\nimport dev.typr.foundations.kotlin.UpdateBuilderMock\nimport dev.typr.foundations.kotlin.UpdateParams\nimport java.lang.RuntimeException\nimport java.sql.Connection\nimport java.util.ArrayList\nimport kotlin.collections.Iterator\nimport kotlin.collections.List\nimport kotlin.collections.Map\nimport kotlin.collections.MutableMap\n\ndata class DepartmentRepoMock(val map: MutableMap = mutableMapOf()) : DepartmentRepo {\n override fun delete(): DeleteBuilder = DeleteBuilderMock(DepartmentFields.structure, { map.values.toList() }, DeleteParams.empty(), { row -> row.id }, { id -> map.remove(id) })\n\n override fun deleteById(\n id: DepartmentId,\n c: Connection\n ): Boolean = map.remove(id) != null\n\n override fun deleteByIds(\n ids: Array,\n c: Connection\n ): Int {\n var count = 0\n for (id in ids) {\n if (map.remove(id) != null) {\n count = count + 1\n }\n }\n return count\n }\n\n override fun insert(\n unsaved: DepartmentRow,\n c: Connection\n ): DepartmentRow {\n if (map.containsKey(unsaved.id)) {\n throw RuntimeException(\"id \" + unsaved.id + \" already exists\")\n }\n map[unsaved.id] = unsaved\n return unsaved\n }\n\n override fun select(): SelectBuilder = SelectBuilderMock(DepartmentFields.structure, { map.values.toList() }, SelectParams.empty())\n\n override fun selectAll(c: Connection): List = map.values.toList()\n\n override fun selectById(\n id: DepartmentId,\n c: Connection\n ): DepartmentRow? = map[id]\n\n override fun selectByIds(\n ids: Array,\n c: Connection\n ): List {\n val result = ArrayList()\n for (id in ids) {\n val opt = map[id]\n if (opt != null) {\n result.add(opt!!)\n }\n }\n return result\n }\n\n override fun selectByIdsTracked(\n ids: Array,\n c: Connection\n ): Map = selectByIds(ids, c).associateBy({ row: DepartmentRow -> row.id })\n\n override fun update(): UpdateBuilder = UpdateBuilderMock(DepartmentFields.structure, { map.values.toList() }, UpdateParams.empty(), { row -> row })\n\n override fun update(\n row: DepartmentRow,\n c: Connection\n ): Boolean {\n val shouldUpdate = map[row.id]?.takeIf({ oldRow -> (oldRow != row) }) != null\n if (shouldUpdate) {\n map[row.id] = row\n }\n return shouldUpdate\n }\n\n override fun upsert(\n unsaved: DepartmentRow,\n c: Connection\n ): DepartmentRow {\n map[unsaved.id] = unsaved\n return unsaved\n }\n\n override fun upsertBatch(\n unsaved: Iterator,\n c: Connection\n ): List {\n val result = ArrayList()\n while (unsaved.hasNext()) {\n val row = unsaved.next()\n map[row.id] = row\n result.add(row)\n }\n return result\n }\n}", - "ProjectAssignmentRow": "package showcase.showcase.project_assignment\n\nimport dev.typr.foundations.MariaTypes\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport dev.typr.foundations.kotlin.nullable\nimport java.time.LocalDate\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.employee.EmployeeId\nimport showcase.showcase.project.ProjectId\n\n/** Table: showcase.project_assignment\n * Composite primary key: employee_id, project_id\n */\ndata class ProjectAssignmentRow(\n /** Points to [showcase.showcase.employee.EmployeeRow.id] */\n val employeeId: EmployeeId,\n /** Points to [showcase.showcase.project.ProjectRow.id] */\n val projectId: ProjectId,\n val role: String,\n /** Default: 0 */\n val hoursAllocated: Int?,\n val startDate: LocalDate?,\n val endDate: LocalDate?\n) {\n fun compositeId(): ProjectAssignmentId = ProjectAssignmentId(employeeId, projectId)\n\n fun id(): ProjectAssignmentId = this.compositeId()\n\n fun toUnsavedRow(hoursAllocated: Defaulted): ProjectAssignmentRowUnsaved = ProjectAssignmentRowUnsaved(employeeId, projectId, role, startDate, endDate, hoursAllocated)\n\n companion object {\n val _rowParser: RowParser = RowParsers.of(EmployeeId.pgType, ProjectId.pgType, MariaTypes.varchar, KotlinDbTypes.MariaTypes.int_.nullable(), MariaTypes.date.nullable(), MariaTypes.date.nullable(), { t0, t1, t2, t3, t4, t5 -> ProjectAssignmentRow(t0, t1, t2, t3, t4, t5) }, { row -> arrayOf(row.employeeId, row.projectId, row.role, row.hoursAllocated, row.startDate, row.endDate) })\n\n fun apply(\n compositeId: ProjectAssignmentId,\n role: String,\n hoursAllocated: Int?,\n startDate: LocalDate?,\n endDate: LocalDate?\n ): ProjectAssignmentRow = ProjectAssignmentRow(compositeId.employeeId, compositeId.projectId, role, hoursAllocated, startDate, endDate)\n }\n}", - "ProjectAssignmentRowUnsaved": "package showcase.showcase.project_assignment\n\nimport java.time.LocalDate\nimport showcase.customtypes.Defaulted\nimport showcase.customtypes.Defaulted.UseDefault\nimport showcase.showcase.employee.EmployeeId\nimport showcase.showcase.project.ProjectId\n\n/** This class corresponds to a row in table `showcase.project_assignment` which has not been persisted yet */\ndata class ProjectAssignmentRowUnsaved(\n /** Points to [showcase.showcase.employee.EmployeeRow.id] */\n val employeeId: EmployeeId,\n /** Points to [showcase.showcase.project.ProjectRow.id] */\n val projectId: ProjectId,\n val role: String,\n val startDate: LocalDate? = null,\n val endDate: LocalDate? = null,\n /** Default: 0 */\n val hoursAllocated: Defaulted = UseDefault()\n) {\n fun toRow(hoursAllocatedDefault: () -> Int?): ProjectAssignmentRow = ProjectAssignmentRow(employeeId = employeeId, projectId = projectId, role = role, hoursAllocated = hoursAllocated.getOrElse(hoursAllocatedDefault), startDate = startDate, endDate = endDate)\n}", - "ProjectAssignmentId": "package showcase.showcase.project_assignment\n\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport showcase.showcase.employee.EmployeeId\nimport showcase.showcase.project.ProjectId\n\n/** Type for the composite primary key of table `showcase.project_assignment` */\ndata class ProjectAssignmentId(\n val employeeId: EmployeeId,\n val projectId: ProjectId\n) {\n companion object {\n val _rowParser: RowParser = RowParsers.of(EmployeeId.pgType, ProjectId.pgType, { t0, t1 -> ProjectAssignmentId(t0, t1) }, { row -> arrayOf(row.employeeId, row.projectId) })\n }\n}", - "ProjectAssignmentRepo": "package showcase.showcase.project_assignment\n\nimport dev.typr.foundations.kotlin.DeleteBuilder\nimport dev.typr.foundations.kotlin.SelectBuilder\nimport dev.typr.foundations.kotlin.UpdateBuilder\nimport java.sql.Connection\nimport kotlin.collections.Iterator\nimport kotlin.collections.List\nimport kotlin.collections.Map\n\ninterface ProjectAssignmentRepo {\n abstract fun delete(): DeleteBuilder\n\n abstract fun deleteById(\n compositeId: ProjectAssignmentId,\n c: Connection\n ): Boolean\n\n abstract fun deleteByIds(\n compositeIds: Array,\n c: Connection\n ): Int\n\n abstract fun insert(\n unsaved: ProjectAssignmentRow,\n c: Connection\n ): ProjectAssignmentRow\n\n abstract fun insert(\n unsaved: ProjectAssignmentRowUnsaved,\n c: Connection\n ): ProjectAssignmentRow\n\n abstract fun select(): SelectBuilder\n\n abstract fun selectAll(c: Connection): List\n\n abstract fun selectById(\n compositeId: ProjectAssignmentId,\n c: Connection\n ): ProjectAssignmentRow?\n\n abstract fun selectByIds(\n compositeIds: Array,\n c: Connection\n ): List\n\n abstract fun selectByIdsTracked(\n compositeIds: Array,\n c: Connection\n ): Map\n\n abstract fun update(): UpdateBuilder\n\n abstract fun update(\n row: ProjectAssignmentRow,\n c: Connection\n ): Boolean\n\n abstract fun upsert(\n unsaved: ProjectAssignmentRow,\n c: Connection\n ): ProjectAssignmentRow\n\n abstract fun upsertBatch(\n unsaved: Iterator,\n c: Connection\n ): List\n}", - "ProjectRow": "package showcase.showcase.project\n\nimport dev.typr.foundations.MariaTypes\nimport dev.typr.foundations.data.Json\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport dev.typr.foundations.kotlin.nullable\nimport java.math.BigDecimal\nimport java.time.LocalDate\nimport java.time.LocalDateTime\nimport showcase.customtypes.Defaulted\n\n/** Table: showcase.project\n * Primary key: id\n */\ndata class ProjectRow(\n val id: ProjectId,\n val name: String,\n val description: String?,\n val startDate: LocalDate?,\n val endDate: LocalDate?,\n val budget: BigDecimal?,\n /** Default: 'planning' */\n val status: String?,\n /** Default: CURRENT_TIMESTAMP */\n val createdAt: LocalDateTime?,\n val metadata: Json?,\n val descriptionLong: String?,\n val attachments: ByteArray?,\n val priority: String?\n) {\n fun toUnsavedRow(\n status: Defaulted,\n createdAt: Defaulted\n ): ProjectRowUnsaved = ProjectRowUnsaved(id, name, description, startDate, endDate, budget, metadata, descriptionLong, attachments, priority, status, createdAt)\n\n companion object {\n val _rowParser: RowParser = RowParsers.of(ProjectId.pgType, MariaTypes.varchar, MariaTypes.varchar.nullable(), MariaTypes.date.nullable(), MariaTypes.date.nullable(), KotlinDbTypes.MariaTypes.numeric.nullable(), MariaTypes.varchar.nullable(), MariaTypes.timestamp.nullable(), MariaTypes.json.nullable(), MariaTypes.longtext.nullable(), MariaTypes.mediumblob.nullable(), MariaTypes.text.nullable(), { t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11 -> ProjectRow(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11) }, { row -> arrayOf(row.id, row.name, row.description, row.startDate, row.endDate, row.budget, row.status, row.createdAt, row.metadata, row.descriptionLong, row.attachments, row.priority) })\n }\n}", - "ProjectId": "package showcase.showcase.project\n\nimport dev.typr.foundations.MariaType\nimport dev.typr.foundations.MariaTypes\nimport dev.typr.foundations.kotlin.Bijection\n\n/** Type for the primary key of table `showcase.project` */\ndata class ProjectId(val value: String) {\n override fun toString(): kotlin.String {\n return value.toString()\n }\n\n companion object {\n val bijection: Bijection =\n Bijection.of(ProjectId::value, ::ProjectId)\n\n val pgType: MariaType =\n MariaTypes.varchar.bimap(::ProjectId, ProjectId::value)\n }\n}", - "EmployeeSummaryViewRow": "package showcase.showcase.employee_summary\n\nimport dev.typr.foundations.MariaTypes\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport dev.typr.foundations.kotlin.nullable\nimport java.math.BigDecimal\nimport java.time.LocalDate\nimport showcase.showcase.company.CompanyId\nimport showcase.showcase.department.DepartmentId\nimport showcase.showcase.employee.EmployeeId\n\n/** View: showcase.employee_summary\n * Summary view of employees with their department and company information\n */\ndata class EmployeeSummaryViewRow(\n /** Points to [showcase.showcase.employee.EmployeeRow.id] */\n val employeeId: EmployeeId,\n val email: String,\n val firstName: String,\n val lastName: String,\n val salary: BigDecimal?,\n val hiredAt: LocalDate?,\n val active: Boolean?,\n /** Points to [showcase.showcase.department.DepartmentRow.id] */\n val departmentId: DepartmentId,\n val departmentName: String,\n val departmentBudget: BigDecimal?,\n /** Points to [showcase.showcase.company.CompanyRow.id] */\n val companyId: CompanyId,\n val companyName: String,\n val managerId: String?,\n val managerFirstName: String?,\n val managerLastName: String?\n) {\n companion object {\n val _rowParser: RowParser = RowParsers.of(EmployeeId.pgType, MariaTypes.varchar, MariaTypes.varchar, MariaTypes.varchar, KotlinDbTypes.MariaTypes.numeric.nullable(), MariaTypes.date.nullable(), KotlinDbTypes.MariaTypes.bool.nullable(), DepartmentId.pgType, MariaTypes.varchar, KotlinDbTypes.MariaTypes.numeric.nullable(), CompanyId.pgType, MariaTypes.varchar, MariaTypes.varchar.nullable(), MariaTypes.varchar.nullable(), MariaTypes.varchar.nullable(), { t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14 -> EmployeeSummaryViewRow(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14) }, { row -> arrayOf(row.employeeId, row.email, row.firstName, row.lastName, row.salary, row.hiredAt, row.active, row.departmentId, row.departmentName, row.departmentBudget, row.companyId, row.companyName, row.managerId, row.managerFirstName, row.managerLastName) })\n }\n}", - "EmployeeSummaryViewRepo": "package showcase.showcase.employee_summary\n\nimport dev.typr.foundations.kotlin.SelectBuilder\nimport java.sql.Connection\nimport kotlin.collections.List\n\ninterface EmployeeSummaryViewRepo {\n abstract fun select(): SelectBuilder\n\n abstract fun selectAll(c: Connection): List\n}", - "CustomerOrderRow": "package showcase.showcase.customer_order\n\nimport dev.typr.foundations.MariaTypes\nimport dev.typr.foundations.data.Json\nimport dev.typr.foundations.data.maria.Inet4\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport dev.typr.foundations.kotlin.nullable\nimport java.math.BigDecimal\nimport java.time.LocalDateTime\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.address.AddressId\nimport showcase.showcase.customer.CustomerId\n\n/** Table: showcase.customer_order\n * Primary key: id\n */\ndata class CustomerOrderRow(\n val id: CustomerOrderId,\n /** Points to [showcase.showcase.customer.CustomerRow.id] */\n val customerId: CustomerId,\n /** Points to [showcase.showcase.address.AddressRow.id] */\n val shippingAddressId: AddressId?,\n /** Points to [showcase.showcase.address.AddressRow.id] */\n val billingAddressId: AddressId?,\n /** Default: 'pending' */\n val status: String?,\n val subtotal: BigDecimal,\n /** Default: 0 */\n val tax: BigDecimal?,\n /** Default: 0 */\n val shipping: BigDecimal?,\n val total: BigDecimal,\n val notes: String?,\n /** Default: CURRENT_TIMESTAMP */\n val createdAt: LocalDateTime?,\n val shippedAt: LocalDateTime?,\n val deliveredAt: LocalDateTime?,\n val metadata: Json?,\n val ipAddress: Inet4?,\n val paymentMethod: String?\n) {\n fun toUnsavedRow(\n status: Defaulted,\n tax: Defaulted,\n shipping: Defaulted,\n createdAt: Defaulted\n ): CustomerOrderRowUnsaved = CustomerOrderRowUnsaved(id, customerId, shippingAddressId, billingAddressId, subtotal, total, notes, shippedAt, deliveredAt, metadata, ipAddress, paymentMethod, status, tax, shipping, createdAt)\n\n companion object {\n val _rowParser: RowParser = RowParsers.of(CustomerOrderId.pgType, CustomerId.pgType, AddressId.pgType.nullable(), AddressId.pgType.nullable(), MariaTypes.varchar.nullable(), KotlinDbTypes.MariaTypes.numeric, KotlinDbTypes.MariaTypes.numeric.nullable(), KotlinDbTypes.MariaTypes.numeric.nullable(), KotlinDbTypes.MariaTypes.numeric, MariaTypes.varchar.nullable(), MariaTypes.timestamp.nullable(), MariaTypes.timestamp.nullable(), MariaTypes.timestamp.nullable(), MariaTypes.json.nullable(), MariaTypes.inet4.nullable(), MariaTypes.text.nullable(), { t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15 -> CustomerOrderRow(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15) }, { row -> arrayOf(row.id, row.customerId, row.shippingAddressId, row.billingAddressId, row.status, row.subtotal, row.tax, row.shipping, row.total, row.notes, row.createdAt, row.shippedAt, row.deliveredAt, row.metadata, row.ipAddress, row.paymentMethod) })\n }\n}", - "CustomerOrderRepo": "package showcase.showcase.customer_order\n\nimport dev.typr.foundations.kotlin.DeleteBuilder\nimport dev.typr.foundations.kotlin.SelectBuilder\nimport dev.typr.foundations.kotlin.UpdateBuilder\nimport java.sql.Connection\nimport kotlin.collections.Iterator\nimport kotlin.collections.List\nimport kotlin.collections.Map\n\ninterface CustomerOrderRepo {\n abstract fun delete(): DeleteBuilder\n\n abstract fun deleteById(\n id: CustomerOrderId,\n c: Connection\n ): Boolean\n\n abstract fun deleteByIds(\n ids: Array,\n c: Connection\n ): Int\n\n abstract fun insert(\n unsaved: CustomerOrderRow,\n c: Connection\n ): CustomerOrderRow\n\n abstract fun insert(\n unsaved: CustomerOrderRowUnsaved,\n c: Connection\n ): CustomerOrderRow\n\n abstract fun select(): SelectBuilder\n\n abstract fun selectAll(c: Connection): List\n\n abstract fun selectById(\n id: CustomerOrderId,\n c: Connection\n ): CustomerOrderRow?\n\n abstract fun selectByIds(\n ids: Array,\n c: Connection\n ): List\n\n abstract fun selectByIdsTracked(\n ids: Array,\n c: Connection\n ): Map\n\n abstract fun update(): UpdateBuilder\n\n abstract fun update(\n row: CustomerOrderRow,\n c: Connection\n ): Boolean\n\n abstract fun upsert(\n unsaved: CustomerOrderRow,\n c: Connection\n ): CustomerOrderRow\n\n abstract fun upsertBatch(\n unsaved: Iterator,\n c: Connection\n ): List\n}", - "OrderItemRow": "package showcase.showcase.order_item\n\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport dev.typr.foundations.kotlin.nullable\nimport java.math.BigDecimal\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.customer_order.CustomerOrderId\nimport showcase.showcase.product.ProductId\n\n/** Table: showcase.order_item\n * Composite primary key: order_id, product_id\n */\ndata class OrderItemRow(\n /** Points to [showcase.showcase.customer_order.CustomerOrderRow.id] */\n val orderId: CustomerOrderId,\n /** Points to [showcase.showcase.product.ProductRow.id] */\n val productId: ProductId,\n val quantity: Int,\n val unitPrice: BigDecimal,\n /** Default: 0 */\n val discount: BigDecimal?\n) {\n fun compositeId(): OrderItemId = OrderItemId(orderId, productId)\n\n fun id(): OrderItemId = this.compositeId()\n\n fun toUnsavedRow(discount: Defaulted): OrderItemRowUnsaved = OrderItemRowUnsaved(orderId, productId, quantity, unitPrice, discount)\n\n companion object {\n val _rowParser: RowParser = RowParsers.of(CustomerOrderId.pgType, ProductId.pgType, KotlinDbTypes.MariaTypes.int_, KotlinDbTypes.MariaTypes.numeric, KotlinDbTypes.MariaTypes.numeric.nullable(), { t0, t1, t2, t3, t4 -> OrderItemRow(t0, t1, t2, t3, t4) }, { row -> arrayOf(row.orderId, row.productId, row.quantity, row.unitPrice, row.discount) })\n\n fun apply(\n compositeId: OrderItemId,\n quantity: Int,\n unitPrice: BigDecimal,\n discount: BigDecimal?\n ): OrderItemRow = OrderItemRow(compositeId.orderId, compositeId.productId, quantity, unitPrice, discount)\n }\n}", - "OrderItemId": "package showcase.showcase.order_item\n\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport showcase.showcase.customer_order.CustomerOrderId\nimport showcase.showcase.product.ProductId\n\n/** Type for the composite primary key of table `showcase.order_item` */\ndata class OrderItemId(\n val orderId: CustomerOrderId,\n val productId: ProductId\n) {\n companion object {\n val _rowParser: RowParser = RowParsers.of(CustomerOrderId.pgType, ProductId.pgType, { t0, t1 -> OrderItemId(t0, t1) }, { row -> arrayOf(row.orderId, row.productId) })\n }\n}", - "ProductRow": "package showcase.showcase.product\n\nimport dev.typr.foundations.MariaTypes\nimport dev.typr.foundations.data.Json\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport dev.typr.foundations.kotlin.nullable\nimport java.math.BigDecimal\nimport java.time.LocalDateTime\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.category.CategoryId\n\n/** Table: showcase.product\n * Primary key: id\n */\ndata class ProductRow(\n val id: ProductId,\n /** Points to [showcase.showcase.category.CategoryRow.id] */\n val categoryId: CategoryId?,\n val name: String,\n val sku: String,\n val price: BigDecimal,\n val cost: BigDecimal?,\n /** Default: true */\n val inStock: Boolean?,\n /** Default: 0 */\n val quantity: Int?,\n val weight: BigDecimal?,\n /** Default: CURRENT_TIMESTAMP */\n val createdAt: LocalDateTime?,\n val attributes: Json?,\n val specifications: Json?,\n val seoMetadata: Json?,\n val descriptionLong: String?,\n val thumbnail: ByteArray?\n) {\n fun toUnsavedRow(\n inStock: Defaulted,\n quantity: Defaulted,\n createdAt: Defaulted\n ): ProductRowUnsaved = ProductRowUnsaved(id, categoryId, name, sku, price, cost, weight, attributes, specifications, seoMetadata, descriptionLong, thumbnail, inStock, quantity, createdAt)\n\n companion object {\n val _rowParser: RowParser = RowParsers.of(ProductId.pgType, CategoryId.pgType.nullable(), MariaTypes.varchar, MariaTypes.varchar, KotlinDbTypes.MariaTypes.numeric, KotlinDbTypes.MariaTypes.numeric.nullable(), KotlinDbTypes.MariaTypes.bool.nullable(), KotlinDbTypes.MariaTypes.int_.nullable(), KotlinDbTypes.MariaTypes.numeric.nullable(), MariaTypes.timestamp.nullable(), MariaTypes.json.nullable(), MariaTypes.json.nullable(), MariaTypes.json.nullable(), MariaTypes.longtext.nullable(), MariaTypes.mediumblob.nullable(), { t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14 -> ProductRow(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14) }, { row -> arrayOf(row.id, row.categoryId, row.name, row.sku, row.price, row.cost, row.inStock, row.quantity, row.weight, row.createdAt, row.attributes, row.specifications, row.seoMetadata, row.descriptionLong, row.thumbnail) })\n }\n}", - "ProductId": "package showcase.showcase.product\n\nimport dev.typr.foundations.MariaType\nimport dev.typr.foundations.MariaTypes\nimport dev.typr.foundations.kotlin.Bijection\n\n/** Type for the primary key of table `showcase.product` */\ndata class ProductId(val value: String) {\n override fun toString(): kotlin.String {\n return value.toString()\n }\n\n companion object {\n val bijection: Bijection =\n Bijection.of(ProductId::value, ::ProductId)\n\n val pgType: MariaType =\n MariaTypes.varchar.bimap(::ProductId, ProductId::value)\n }\n}", - "CategoryRow": "package showcase.showcase.category\n\nimport dev.typr.foundations.MariaTypes\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport dev.typr.foundations.kotlin.nullable\n\n/** Table: showcase.category\n * Primary key: id\n */\ndata class CategoryRow(\n val id: CategoryId,\n /** Points to [showcase.showcase.category.CategoryRow.id] */\n val parentId: CategoryId?,\n val name: String,\n val description: String?\n) {\n companion object {\n val _rowParser: RowParser = RowParsers.of(CategoryId.pgType, CategoryId.pgType.nullable(), MariaTypes.varchar, MariaTypes.varchar.nullable(), { t0, t1, t2, t3 -> CategoryRow(t0, t1, t2, t3) }, { row -> arrayOf(row.id, row.parentId, row.name, row.description) })\n }\n}", - "CategoryId": "package showcase.showcase.category\n\nimport dev.typr.foundations.MariaType\nimport dev.typr.foundations.MariaTypes\nimport dev.typr.foundations.kotlin.Bijection\n\n/** Type for the primary key of table `showcase.category` */\ndata class CategoryId(val value: String) {\n override fun toString(): kotlin.String {\n return value.toString()\n }\n\n companion object {\n val bijection: Bijection =\n Bijection.of(CategoryId::value, ::CategoryId)\n\n val pgType: MariaType =\n MariaTypes.varchar.bimap(::CategoryId, CategoryId::value)\n }\n}", - "AddressRow": "package showcase.showcase.address\n\nimport dev.typr.foundations.MariaTypes\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport dev.typr.foundations.kotlin.nullable\nimport org.mariadb.jdbc.type.Point\nimport org.mariadb.jdbc.type.Polygon\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.customer.CustomerId\n\n/** Table: showcase.address\n * Primary key: id\n */\ndata class AddressRow(\n val id: AddressId,\n /** Points to [showcase.showcase.customer.CustomerRow.id] */\n val customerId: CustomerId,\n val addressType: String,\n val street: String,\n val city: String,\n val state: String?,\n val postalCode: String?,\n val country: String,\n /** Default: false */\n val isDefault: Boolean?,\n val location: Point?,\n val deliveryZone: Polygon?\n) {\n fun toUnsavedRow(isDefault: Defaulted): AddressRowUnsaved = AddressRowUnsaved(id, customerId, addressType, street, city, state, postalCode, country, location, deliveryZone, isDefault)\n\n companion object {\n val _rowParser: RowParser = RowParsers.of(AddressId.pgType, CustomerId.pgType, MariaTypes.varchar, MariaTypes.varchar, MariaTypes.varchar, MariaTypes.varchar.nullable(), MariaTypes.varchar.nullable(), MariaTypes.varchar, KotlinDbTypes.MariaTypes.bool.nullable(), MariaTypes.point.nullable(), MariaTypes.polygon.nullable(), { t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10 -> AddressRow(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10) }, { row -> arrayOf(row.id, row.customerId, row.addressType, row.street, row.city, row.state, row.postalCode, row.country, row.isDefault, row.location, row.deliveryZone) })\n }\n}", - "AddressId": "package showcase.showcase.address\n\nimport dev.typr.foundations.MariaType\nimport dev.typr.foundations.MariaTypes\nimport dev.typr.foundations.kotlin.Bijection\n\n/** Type for the primary key of table `showcase.address` */\ndata class AddressId(val value: String) {\n override fun toString(): kotlin.String {\n return value.toString()\n }\n\n companion object {\n val bijection: Bijection =\n Bijection.of(AddressId::value, ::AddressId)\n\n val pgType: MariaType =\n MariaTypes.varchar.bimap(::AddressId, AddressId::value)\n }\n}", - "Defaulted": "package showcase.customtypes\n\n\n\n/** This signals a value where if you don't provide it, postgres will generate it for you */\nsealed interface Defaulted {\n data class Provided(val value: T) : Defaulted {\n override fun fold(\n onDefault: () -> U,\n onProvided: (T) -> U\n ): U = onProvided(value)\n\n override fun getOrElse(onDefault: () -> T): T = value\n\n override fun visit(\n onDefault: () -> Unit,\n onProvided: (T) -> Unit\n ) {\n onProvided(value)\n }\n }\n\n class UseDefault : Defaulted {\n override fun fold(\n onDefault: () -> U,\n onProvided: (T) -> U\n ): U = onDefault()\n\n override fun getOrElse(onDefault: () -> T): T = onDefault()\n\n override fun visit(\n onDefault: () -> Unit,\n onProvided: (T) -> Unit\n ) {\n onDefault()\n }\n }\n\n abstract fun fold(\n onDefault: () -> U,\n onProvided: (T) -> U\n ): U\n\n abstract fun getOrElse(onDefault: () -> T): T\n\n abstract fun visit(\n onDefault: () -> Unit,\n onProvided: (T) -> Unit\n )\n}", - "TestInsert": "package showcase\n\nimport dev.typr.foundations.data.Json\nimport dev.typr.foundations.data.maria.Inet4\nimport dev.typr.foundations.data.maria.MariaSet\nimport java.math.BigDecimal\nimport java.sql.Connection\nimport java.time.LocalDate\nimport java.time.LocalDateTime\nimport java.util.Random\nimport org.mariadb.jdbc.type.Point\nimport org.mariadb.jdbc.type.Polygon\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.address.AddressId\nimport showcase.showcase.address.AddressRepoImpl\nimport showcase.showcase.address.AddressRow\nimport showcase.showcase.address.AddressRowUnsaved\nimport showcase.showcase.audit_log.AuditLogId\nimport showcase.showcase.audit_log.AuditLogRepoImpl\nimport showcase.showcase.audit_log.AuditLogRow\nimport showcase.showcase.audit_log.AuditLogRowUnsaved\nimport showcase.showcase.category.CategoryId\nimport showcase.showcase.category.CategoryRepoImpl\nimport showcase.showcase.category.CategoryRow\nimport showcase.showcase.company.CompanyId\nimport showcase.showcase.company.CompanyRepoImpl\nimport showcase.showcase.company.CompanyRow\nimport showcase.showcase.company.CompanyRowUnsaved\nimport showcase.showcase.customer.CustomerId\nimport showcase.showcase.customer.CustomerRepoImpl\nimport showcase.showcase.customer.CustomerRow\nimport showcase.showcase.customer.CustomerRowUnsaved\nimport showcase.showcase.customer_order.CustomerOrderId\nimport showcase.showcase.customer_order.CustomerOrderRepoImpl\nimport showcase.showcase.customer_order.CustomerOrderRow\nimport showcase.showcase.customer_order.CustomerOrderRowUnsaved\nimport showcase.showcase.department.DepartmentId\nimport showcase.showcase.department.DepartmentRepoImpl\nimport showcase.showcase.department.DepartmentRow\nimport showcase.showcase.employee.EmployeeId\nimport showcase.showcase.employee.EmployeeRepoImpl\nimport showcase.showcase.employee.EmployeeRow\nimport showcase.showcase.employee.EmployeeRowUnsaved\nimport showcase.showcase.order_item.OrderItemRepoImpl\nimport showcase.showcase.order_item.OrderItemRow\nimport showcase.showcase.order_item.OrderItemRowUnsaved\nimport showcase.showcase.product.ProductId\nimport showcase.showcase.product.ProductRepoImpl\nimport showcase.showcase.product.ProductRow\nimport showcase.showcase.product.ProductRowUnsaved\nimport showcase.showcase.project.ProjectId\nimport showcase.showcase.project.ProjectRepoImpl\nimport showcase.showcase.project.ProjectRow\nimport showcase.showcase.project.ProjectRowUnsaved\nimport showcase.showcase.project_assignment.ProjectAssignmentRepoImpl\nimport showcase.showcase.project_assignment.ProjectAssignmentRow\nimport showcase.showcase.project_assignment.ProjectAssignmentRowUnsaved\n\n/** Methods to generate random data for `Ident(TestInsert)` */\ndata class TestInsert(val random: Random) {\n fun showcaseAddress(\n id: AddressId,\n customerId: CustomerId,\n addressType: String,\n street: String,\n city: String,\n country: String,\n state: String?,\n postalCode: String?,\n location: Point?,\n deliveryZone: Polygon?,\n isDefault: Defaulted,\n c: Connection\n ): AddressRow = (AddressRepoImpl()).insert(AddressRowUnsaved(id = id, customerId = customerId, addressType = addressType, street = street, city = city, state = state, postalCode = postalCode, country = country, location = location, deliveryZone = deliveryZone, isDefault = isDefault), c)\n\n fun showcaseAuditLog(\n id: AuditLogId,\n tableName: String,\n recordId: String,\n action: String,\n oldValues: String?,\n newValues: String?,\n changedBy: EmployeeId?,\n changedAt: Defaulted,\n c: Connection\n ): AuditLogRow = (AuditLogRepoImpl()).insert(AuditLogRowUnsaved(id = id, tableName = tableName, recordId = recordId, action = action, oldValues = oldValues, newValues = newValues, changedBy = changedBy, changedAt = changedAt), c)\n\n fun showcaseCategory(\n id: CategoryId,\n name: String,\n parentId: CategoryId?,\n description: String?,\n c: Connection\n ): CategoryRow = (CategoryRepoImpl()).insert(CategoryRow(id = id, parentId = parentId, name = name, description = description), c)\n\n fun showcaseCompany(\n id: CompanyId,\n name: String,\n foundedYear: Int?,\n active: Defaulted,\n createdAt: Defaulted,\n c: Connection\n ): CompanyRow = (CompanyRepoImpl()).insert(CompanyRowUnsaved(id = id, name = name, foundedYear = foundedYear, active = active, createdAt = createdAt), c)\n\n fun showcaseCustomer(\n id: CustomerId,\n email: String,\n firstName: String,\n lastName: String,\n phone: String?,\n preferences: Json?,\n avatar: ByteArray?,\n customerType: String?,\n verified: Defaulted,\n createdAt: Defaulted,\n c: Connection\n ): CustomerRow = (CustomerRepoImpl()).insert(CustomerRowUnsaved(id = id, email = email, firstName = firstName, lastName = lastName, phone = phone, preferences = preferences, avatar = avatar, customerType = customerType, verified = verified, createdAt = createdAt), c)\n\n fun showcaseCustomerOrder(\n id: CustomerOrderId,\n customerId: CustomerId,\n shippingAddressId: AddressId?,\n billingAddressId: AddressId?,\n subtotal: BigDecimal,\n total: BigDecimal,\n notes: String?,\n shippedAt: LocalDateTime?,\n deliveredAt: LocalDateTime?,\n metadata: Json?,\n ipAddress: Inet4?,\n paymentMethod: String?,\n status: Defaulted,\n tax: Defaulted,\n shipping: Defaulted,\n createdAt: Defaulted,\n c: Connection\n ): CustomerOrderRow = (CustomerOrderRepoImpl()).insert(CustomerOrderRowUnsaved(id = id, customerId = customerId, shippingAddressId = shippingAddressId, billingAddressId = billingAddressId, subtotal = subtotal, total = total, notes = notes, shippedAt = shippedAt, deliveredAt = deliveredAt, metadata = metadata, ipAddress = ipAddress, paymentMethod = paymentMethod, status = status, tax = tax, shipping = shipping, createdAt = createdAt), c)\n\n fun showcaseDepartment(\n id: DepartmentId,\n companyId: CompanyId,\n name: String,\n budget: BigDecimal?,\n c: Connection\n ): DepartmentRow = (DepartmentRepoImpl()).insert(DepartmentRow(id = id, companyId = companyId, name = name, budget = budget), c)\n\n fun showcaseEmployee(\n id: EmployeeId,\n departmentId: DepartmentId,\n email: String,\n firstName: String,\n lastName: String,\n managerId: EmployeeId?,\n salary: BigDecimal?,\n hiredAt: LocalDate?,\n metadata: Json?,\n photo: ByteArray?,\n ipAddress: Inet4?,\n permissions: MariaSet?,\n active: Defaulted,\n createdAt: Defaulted,\n c: Connection\n ): EmployeeRow = (EmployeeRepoImpl()).insert(EmployeeRowUnsaved(id = id, departmentId = departmentId, managerId = managerId, email = email, firstName = firstName, lastName = lastName, salary = salary, hiredAt = hiredAt, metadata = metadata, photo = photo, ipAddress = ipAddress, permissions = permissions, active = active, createdAt = createdAt), c)\n\n fun showcaseOrderItem(\n orderId: CustomerOrderId,\n productId: ProductId,\n quantity: Int,\n unitPrice: BigDecimal,\n discount: Defaulted,\n c: Connection\n ): OrderItemRow = (OrderItemRepoImpl()).insert(OrderItemRowUnsaved(orderId = orderId, productId = productId, quantity = quantity, unitPrice = unitPrice, discount = discount), c)\n\n fun showcaseProduct(\n id: ProductId,\n name: String,\n sku: String,\n categoryId: CategoryId?,\n price: BigDecimal,\n cost: BigDecimal?,\n weight: BigDecimal?,\n attributes: Json?,\n specifications: Json?,\n seoMetadata: Json?,\n descriptionLong: String?,\n thumbnail: ByteArray?,\n inStock: Defaulted,\n quantity: Defaulted,\n createdAt: Defaulted,\n c: Connection\n ): ProductRow = (ProductRepoImpl()).insert(ProductRowUnsaved(id = id, categoryId = categoryId, name = name, sku = sku, price = price, cost = cost, weight = weight, attributes = attributes, specifications = specifications, seoMetadata = seoMetadata, descriptionLong = descriptionLong, thumbnail = thumbnail, inStock = inStock, quantity = quantity, createdAt = createdAt), c)\n\n fun showcaseProject(\n id: ProjectId,\n name: String,\n description: String?,\n startDate: LocalDate?,\n endDate: LocalDate?,\n budget: BigDecimal?,\n metadata: Json?,\n descriptionLong: String?,\n attachments: ByteArray?,\n priority: String?,\n status: Defaulted,\n createdAt: Defaulted,\n c: Connection\n ): ProjectRow = (ProjectRepoImpl()).insert(ProjectRowUnsaved(id = id, name = name, description = description, startDate = startDate, endDate = endDate, budget = budget, metadata = metadata, descriptionLong = descriptionLong, attachments = attachments, priority = priority, status = status, createdAt = createdAt), c)\n\n fun showcaseProjectAssignment(\n employeeId: EmployeeId,\n projectId: ProjectId,\n role: String,\n startDate: LocalDate?,\n endDate: LocalDate?,\n hoursAllocated: Defaulted,\n c: Connection\n ): ProjectAssignmentRow = (ProjectAssignmentRepoImpl()).insert(ProjectAssignmentRowUnsaved(employeeId = employeeId, projectId = projectId, role = role, startDate = startDate, endDate = endDate, hoursAllocated = hoursAllocated), c)\n}" - }, - "scala": { - "CompanyRow": "package showcase.showcase.company\n\nimport dev.typr.foundations.MariaTypes\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport java.time.LocalDateTime\nimport showcase.customtypes.Defaulted\n\n/** Table: showcase.company\n * Primary key: id\n */\ncase class CompanyRow(\n id: CompanyId,\n name: String,\n foundedYear: Option[Int],\n /** Default: true */\n active: Option[Boolean],\n /** Default: CURRENT_TIMESTAMP */\n createdAt: Option[LocalDateTime]\n) {\n def toUnsavedRow(\n active: Defaulted[Option[Boolean]] = Defaulted.Provided(this.active),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.Provided(this.createdAt)\n ): CompanyRowUnsaved = {\n new CompanyRowUnsaved(\n id,\n name,\n foundedYear,\n active,\n createdAt\n )\n }\n}\n\nobject CompanyRow {\n val `_rowParser`: RowParser[CompanyRow] = RowParsers.of(CompanyId.pgType, MariaTypes.varchar, ScalaDbTypes.MariaTypes.int_.nullable, ScalaDbTypes.MariaTypes.bool.nullable, MariaTypes.timestamp.nullable)(CompanyRow.apply)(row => Array[Any](row.id, row.name, row.foundedYear, row.active, row.createdAt))\n}", - "CompanyRowUnsaved": "package showcase.showcase.company\n\nimport java.time.LocalDateTime\nimport showcase.customtypes.Defaulted\nimport showcase.customtypes.Defaulted.UseDefault\n\n/** This class corresponds to a row in table `showcase.company` which has not been persisted yet */\ncase class CompanyRowUnsaved(\n id: CompanyId,\n name: String,\n foundedYear: Option[Int] = None,\n /** Default: true */\n active: Defaulted[Option[Boolean]] = new UseDefault(),\n /** Default: CURRENT_TIMESTAMP */\n createdAt: Defaulted[Option[LocalDateTime]] = new UseDefault()\n) {\n def toRow(\n activeDefault: => Option[Boolean],\n createdAtDefault: => Option[LocalDateTime]\n ): CompanyRow = {\n new CompanyRow(\n id = id,\n name = name,\n foundedYear = foundedYear,\n active = active.getOrElse(activeDefault),\n createdAt = createdAt.getOrElse(createdAtDefault)\n )\n }\n}", - "CompanyId": "package showcase.showcase.company\n\nimport dev.typr.foundations.MariaType\nimport dev.typr.foundations.MariaTypes\nimport dev.typr.foundations.scala.Bijection\n\n/** Type for the primary key of table `showcase.company` */\ncase class CompanyId(value: String) extends scala.AnyVal\n\nobject CompanyId {\n given bijection: Bijection[CompanyId, String] = Bijection.apply[CompanyId, String](_.value)(CompanyId.apply)\n\n given pgType: MariaType[CompanyId] = MariaTypes.varchar.bimap(CompanyId.apply, _.value)\n}", - "CompanyRepo": "package showcase.showcase.company\n\nimport dev.typr.foundations.scala.DeleteBuilder\nimport dev.typr.foundations.scala.SelectBuilder\nimport dev.typr.foundations.scala.UpdateBuilder\nimport java.sql.Connection\n\ntrait CompanyRepo {\n def delete: DeleteBuilder[CompanyFields, CompanyRow]\n\n def deleteById(id: CompanyId)(using c: Connection): Boolean\n\n def deleteByIds(ids: Array[CompanyId])(using c: Connection): Int\n\n def insert(unsaved: CompanyRow)(using c: Connection): CompanyRow\n\n def insert(unsaved: CompanyRowUnsaved)(using c: Connection): CompanyRow\n\n def select: SelectBuilder[CompanyFields, CompanyRow]\n\n def selectAll(using c: Connection): List[CompanyRow]\n\n def selectById(id: CompanyId)(using c: Connection): Option[CompanyRow]\n\n def selectByIds(ids: Array[CompanyId])(using c: Connection): List[CompanyRow]\n\n def selectByIdsTracked(ids: Array[CompanyId])(using c: Connection): Map[CompanyId, CompanyRow]\n\n def update: UpdateBuilder[CompanyFields, CompanyRow]\n\n def update(row: CompanyRow)(using c: Connection): Boolean\n\n def upsert(unsaved: CompanyRow)(using c: Connection): CompanyRow\n\n def upsertBatch(unsaved: Iterator[CompanyRow])(using c: Connection): List[CompanyRow]\n}", - "CompanyRepoMock": "package showcase.showcase.company\n\nimport dev.typr.foundations.scala.DeleteBuilder\nimport dev.typr.foundations.scala.DeleteBuilderMock\nimport dev.typr.foundations.scala.DeleteParams\nimport dev.typr.foundations.scala.SelectBuilder\nimport dev.typr.foundations.scala.SelectBuilderMock\nimport dev.typr.foundations.scala.SelectParams\nimport dev.typr.foundations.scala.UpdateBuilder\nimport dev.typr.foundations.scala.UpdateBuilderMock\nimport dev.typr.foundations.scala.UpdateParams\nimport java.lang.RuntimeException\nimport java.sql.Connection\n\ncase class CompanyRepoMock(\n toRow: CompanyRowUnsaved => CompanyRow,\n map: scala.collection.mutable.Map[CompanyId, CompanyRow] = scala.collection.mutable.Map.empty[CompanyId, CompanyRow]\n) extends CompanyRepo {\n override def delete: DeleteBuilder[CompanyFields, CompanyRow] = DeleteBuilderMock(CompanyFields.structure, () => map.values.toList, DeleteParams.empty(), row => row.id, id => map.remove(id): @scala.annotation.nowarn)\n\n override def deleteById(id: CompanyId)(using c: Connection): Boolean = map.remove(id).isDefined\n\n override def deleteByIds(ids: Array[CompanyId])(using c: Connection): Int = {\n var count = 0\n ids.foreach { id => if (map.remove(id).isDefined) {\n count = count + 1\n } }\n return count\n }\n\n override def insert(unsaved: CompanyRow)(using c: Connection): CompanyRow = {\n if (map.contains(unsaved.id)) {\n throw new RuntimeException(s\"id ${unsaved.id} already exists\")\n }\n map.put(unsaved.id, unsaved): @scala.annotation.nowarn\n return unsaved\n }\n\n override def insert(unsaved: CompanyRowUnsaved)(using c: Connection): CompanyRow = insert(toRow(unsaved))(using c)\n\n override def select: SelectBuilder[CompanyFields, CompanyRow] = SelectBuilderMock(CompanyFields.structure, () => map.values.toList, SelectParams.empty())\n\n override def selectAll(using c: Connection): List[CompanyRow] = map.values.toList\n\n override def selectById(id: CompanyId)(using c: Connection): Option[CompanyRow] = map.get(id)\n\n override def selectByIds(ids: Array[CompanyId])(using c: Connection): List[CompanyRow] = ids.flatMap(map.get(_)).toList\n\n override def selectByIdsTracked(ids: Array[CompanyId])(using c: Connection): Map[CompanyId, CompanyRow] = selectByIds(ids)(using c).map(x => (((row: CompanyRow) => row.id).apply(x), x)).toMap\n\n override def update: UpdateBuilder[CompanyFields, CompanyRow] = UpdateBuilderMock(CompanyFields.structure, () => map.values.toList, UpdateParams.empty(), row => row)\n\n override def update(row: CompanyRow)(using c: Connection): Boolean = {\n val shouldUpdate = map.get(row.id).filter(oldRow => (oldRow != row)).isDefined\n if (shouldUpdate) {\n map.put(row.id, row): @scala.annotation.nowarn\n }\n return shouldUpdate\n }\n\n override def upsert(unsaved: CompanyRow)(using c: Connection): CompanyRow = {\n map.put(unsaved.id, unsaved): @scala.annotation.nowarn\n return unsaved\n }\n\n override def upsertBatch(unsaved: Iterator[CompanyRow])(using c: Connection): List[CompanyRow] = {\n unsaved.map { row =>\n map.put(row.id, row): @scala.annotation.nowarn\n row\n }.toList\n }\n}", - "EmployeeRow": "package showcase.showcase.employee\n\nimport dev.typr.foundations.MariaTypes\nimport dev.typr.foundations.data.Json\nimport dev.typr.foundations.data.maria.Inet4\nimport dev.typr.foundations.data.maria.MariaSet\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport java.time.LocalDate\nimport java.time.LocalDateTime\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.department.DepartmentId\n\n/** Table: showcase.employee\n * Primary key: id\n */\ncase class EmployeeRow(\n id: EmployeeId,\n /** Points to [[showcase.showcase.department.DepartmentRow.id]] */\n departmentId: DepartmentId,\n /** Points to [[showcase.showcase.employee.EmployeeRow.id]] */\n managerId: Option[EmployeeId],\n email: String,\n firstName: String,\n lastName: String,\n salary: Option[BigDecimal],\n hiredAt: Option[LocalDate],\n /** Default: true */\n active: Option[Boolean],\n /** Default: CURRENT_TIMESTAMP */\n createdAt: Option[LocalDateTime],\n metadata: Option[Json],\n photo: Option[Array[Byte]],\n ipAddress: Option[Inet4],\n permissions: Option[MariaSet]\n) {\n def toUnsavedRow(\n active: Defaulted[Option[Boolean]] = Defaulted.Provided(this.active),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.Provided(this.createdAt)\n ): EmployeeRowUnsaved = {\n new EmployeeRowUnsaved(\n id,\n departmentId,\n managerId,\n email,\n firstName,\n lastName,\n salary,\n hiredAt,\n metadata,\n photo,\n ipAddress,\n permissions,\n active,\n createdAt\n )\n }\n}\n\nobject EmployeeRow {\n val `_rowParser`: RowParser[EmployeeRow] = RowParsers.of(EmployeeId.pgType, DepartmentId.pgType, EmployeeId.pgType.nullable, MariaTypes.varchar, MariaTypes.varchar, MariaTypes.varchar, ScalaDbTypes.MariaTypes.numeric.nullable, MariaTypes.date.nullable, ScalaDbTypes.MariaTypes.bool.nullable, MariaTypes.timestamp.nullable, MariaTypes.json.nullable, MariaTypes.mediumblob.nullable, MariaTypes.inet4.nullable, MariaTypes.set.nullable)(EmployeeRow.apply)(row => Array[Any](row.id, row.departmentId, row.managerId, row.email, row.firstName, row.lastName, row.salary, row.hiredAt, row.active, row.createdAt, row.metadata, row.photo, row.ipAddress, row.permissions))\n}", - "EmployeeRowUnsaved": "package showcase.showcase.employee\n\nimport dev.typr.foundations.data.Json\nimport dev.typr.foundations.data.maria.Inet4\nimport dev.typr.foundations.data.maria.MariaSet\nimport java.time.LocalDate\nimport java.time.LocalDateTime\nimport showcase.customtypes.Defaulted\nimport showcase.customtypes.Defaulted.UseDefault\nimport showcase.showcase.department.DepartmentId\n\n/** This class corresponds to a row in table `showcase.employee` which has not been persisted yet */\ncase class EmployeeRowUnsaved(\n id: EmployeeId,\n /** Points to [[showcase.showcase.department.DepartmentRow.id]] */\n departmentId: DepartmentId,\n /** Points to [[showcase.showcase.employee.EmployeeRow.id]] */\n managerId: Option[EmployeeId] = None,\n email: String,\n firstName: String,\n lastName: String,\n salary: Option[BigDecimal] = None,\n hiredAt: Option[LocalDate] = None,\n metadata: Option[Json] = None,\n photo: Option[Array[Byte]] = None,\n ipAddress: Option[Inet4] = None,\n permissions: Option[MariaSet] = None,\n /** Default: true */\n active: Defaulted[Option[Boolean]] = new UseDefault(),\n /** Default: CURRENT_TIMESTAMP */\n createdAt: Defaulted[Option[LocalDateTime]] = new UseDefault()\n) {\n def toRow(\n activeDefault: => Option[Boolean],\n createdAtDefault: => Option[LocalDateTime]\n ): EmployeeRow = {\n new EmployeeRow(\n id = id,\n departmentId = departmentId,\n managerId = managerId,\n email = email,\n firstName = firstName,\n lastName = lastName,\n salary = salary,\n hiredAt = hiredAt,\n active = active.getOrElse(activeDefault),\n createdAt = createdAt.getOrElse(createdAtDefault),\n metadata = metadata,\n photo = photo,\n ipAddress = ipAddress,\n permissions = permissions\n )\n }\n}", - "EmployeeId": "package showcase.showcase.employee\n\nimport dev.typr.foundations.MariaType\nimport dev.typr.foundations.MariaTypes\nimport dev.typr.foundations.scala.Bijection\n\n/** Type for the primary key of table `showcase.employee` */\ncase class EmployeeId(value: String) extends scala.AnyVal\n\nobject EmployeeId {\n given bijection: Bijection[EmployeeId, String] = Bijection.apply[EmployeeId, String](_.value)(EmployeeId.apply)\n\n given pgType: MariaType[EmployeeId] = MariaTypes.varchar.bimap(EmployeeId.apply, _.value)\n}", - "EmployeeRepo": "package showcase.showcase.employee\n\nimport dev.typr.foundations.scala.DeleteBuilder\nimport dev.typr.foundations.scala.SelectBuilder\nimport dev.typr.foundations.scala.UpdateBuilder\nimport java.sql.Connection\n\ntrait EmployeeRepo {\n def delete: DeleteBuilder[EmployeeFields, EmployeeRow]\n\n def deleteById(id: EmployeeId)(using c: Connection): Boolean\n\n def deleteByIds(ids: Array[EmployeeId])(using c: Connection): Int\n\n def insert(unsaved: EmployeeRow)(using c: Connection): EmployeeRow\n\n def insert(unsaved: EmployeeRowUnsaved)(using c: Connection): EmployeeRow\n\n def select: SelectBuilder[EmployeeFields, EmployeeRow]\n\n def selectAll(using c: Connection): List[EmployeeRow]\n\n def selectById(id: EmployeeId)(using c: Connection): Option[EmployeeRow]\n\n def selectByIds(ids: Array[EmployeeId])(using c: Connection): List[EmployeeRow]\n\n def selectByIdsTracked(ids: Array[EmployeeId])(using c: Connection): Map[EmployeeId, EmployeeRow]\n\n def selectByUniqueEmail(email: String)(using c: Connection): Option[EmployeeRow]\n\n def update: UpdateBuilder[EmployeeFields, EmployeeRow]\n\n def update(row: EmployeeRow)(using c: Connection): Boolean\n\n def upsert(unsaved: EmployeeRow)(using c: Connection): EmployeeRow\n\n def upsertBatch(unsaved: Iterator[EmployeeRow])(using c: Connection): List[EmployeeRow]\n}", - "EmployeeRepoImpl": "package showcase.showcase.employee\n\nimport dev.typr.foundations.MariaTypes\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.DeleteBuilder\nimport dev.typr.foundations.scala.Dialect\nimport dev.typr.foundations.scala.Fragment\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport dev.typr.foundations.scala.SelectBuilder\nimport dev.typr.foundations.scala.UpdateBuilder\nimport java.sql.Connection\nimport scala.collection.mutable.ListBuffer\nimport showcase.showcase.department.DepartmentId\nimport dev.typr.foundations.scala.Fragment.sql\n\nclass EmployeeRepoImpl extends EmployeeRepo {\n override def delete: DeleteBuilder[EmployeeFields, EmployeeRow] = DeleteBuilder.of(\"`showcase`.`employee`\", EmployeeFields.structure, Dialect.MARIADB)\n\n override def deleteById(id: EmployeeId)(using c: Connection): Boolean = sql\"delete from `showcase`.`employee` where `id` = ${Fragment.encode(EmployeeId.pgType, id)}\".update().runUnchecked(c) > 0\n\n override def deleteByIds(ids: Array[EmployeeId])(using c: Connection): Int = {\n val fragments: ListBuffer[Fragment] = ListBuffer()\n ids.foreach { id => fragments.addOne(Fragment.encode(EmployeeId.pgType, id)): @scala.annotation.nowarn }\n return Fragment.interpolate(Fragment.lit(\"delete from `showcase`.`employee` where `id` in (\"), Fragment.comma(fragments), Fragment.lit(\")\")).update().runUnchecked(c)\n }\n\n override def insert(unsaved: EmployeeRow)(using c: Connection): EmployeeRow = {\n sql\"\"\"insert into `showcase`.`employee`(`id`, `department_id`, `manager_id`, `email`, `first_name`, `last_name`, `salary`, `hired_at`, `active`, `created_at`, `metadata`, `photo`, `ip_address`, `permissions`)\n values (${Fragment.encode(EmployeeId.pgType, unsaved.id)}, ${Fragment.encode(DepartmentId.pgType, unsaved.departmentId)}, ${Fragment.encode(EmployeeId.pgType.nullable, unsaved.managerId)}, ${Fragment.encode(MariaTypes.varchar, unsaved.email)}, ${Fragment.encode(MariaTypes.varchar, unsaved.firstName)}, ${Fragment.encode(MariaTypes.varchar, unsaved.lastName)}, ${Fragment.encode(ScalaDbTypes.MariaTypes.numeric.nullable, unsaved.salary)}, ${Fragment.encode(MariaTypes.date.nullable, unsaved.hiredAt)}, ${Fragment.encode(ScalaDbTypes.MariaTypes.bool.nullable, unsaved.active)}, ${Fragment.encode(MariaTypes.timestamp.nullable, unsaved.createdAt)}, ${Fragment.encode(MariaTypes.json.nullable, unsaved.metadata)}, ${Fragment.encode(MariaTypes.mediumblob.nullable, unsaved.photo)}, ${Fragment.encode(MariaTypes.inet4.nullable, unsaved.ipAddress)}, ${Fragment.encode(MariaTypes.set.nullable, unsaved.permissions)})\n RETURNING `id`, `department_id`, `manager_id`, `email`, `first_name`, `last_name`, `salary`, `hired_at`, `active`, `created_at`, `metadata`, `photo`, `ip_address`, `permissions`\n \"\"\"\n .updateReturning(EmployeeRow.`_rowParser`.exactlyOne()).runUnchecked(c)\n }\n\n override def insert(unsaved: EmployeeRowUnsaved)(using c: Connection): EmployeeRow = {\n val columns: ListBuffer[Fragment] = ListBuffer()\n val values: ListBuffer[Fragment] = ListBuffer()\n columns.addOne(Fragment.lit(\"`id`\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(EmployeeId.pgType, unsaved.id)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"`department_id`\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(DepartmentId.pgType, unsaved.departmentId)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"`manager_id`\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(EmployeeId.pgType.nullable, unsaved.managerId)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"`email`\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(MariaTypes.varchar, unsaved.email)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"`first_name`\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(MariaTypes.varchar, unsaved.firstName)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"`last_name`\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(MariaTypes.varchar, unsaved.lastName)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"`salary`\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(ScalaDbTypes.MariaTypes.numeric.nullable, unsaved.salary)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"`hired_at`\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(MariaTypes.date.nullable, unsaved.hiredAt)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"`metadata`\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(MariaTypes.json.nullable, unsaved.metadata)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"`photo`\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(MariaTypes.mediumblob.nullable, unsaved.photo)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"`ip_address`\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(MariaTypes.inet4.nullable, unsaved.ipAddress)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"`permissions`\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(MariaTypes.set.nullable, unsaved.permissions)}\"): @scala.annotation.nowarn\n unsaved.active.visit(\n { },\n value => { columns.addOne(Fragment.lit(\"`active`\")): @scala.annotation.nowarn; values.addOne(sql\"${Fragment.encode(ScalaDbTypes.MariaTypes.bool.nullable, value)}\"): @scala.annotation.nowarn }\n );\n unsaved.createdAt.visit(\n { },\n value => { columns.addOne(Fragment.lit(\"`created_at`\")): @scala.annotation.nowarn; values.addOne(sql\"${Fragment.encode(MariaTypes.timestamp.nullable, value)}\"): @scala.annotation.nowarn }\n );\n val q: Fragment = {\n sql\"\"\"insert into `showcase`.`employee`(${Fragment.comma(columns)})\n values (${Fragment.comma(values)})\n RETURNING `id`, `department_id`, `manager_id`, `email`, `first_name`, `last_name`, `salary`, `hired_at`, `active`, `created_at`, `metadata`, `photo`, `ip_address`, `permissions`\n \"\"\"\n }\n return q.updateReturning(EmployeeRow.`_rowParser`.exactlyOne()).runUnchecked(c)\n }\n\n override def select: SelectBuilder[EmployeeFields, EmployeeRow] = SelectBuilder.of(\"`showcase`.`employee`\", EmployeeFields.structure, EmployeeRow.`_rowParser`, Dialect.MARIADB)\n\n override def selectAll(using c: Connection): List[EmployeeRow] = {\n sql\"\"\"select `id`, `department_id`, `manager_id`, `email`, `first_name`, `last_name`, `salary`, `hired_at`, `active`, `created_at`, `metadata`, `photo`, `ip_address`, `permissions`\n from `showcase`.`employee`\n \"\"\".query(EmployeeRow.`_rowParser`.all()).runUnchecked(c)\n }\n\n override def selectById(id: EmployeeId)(using c: Connection): Option[EmployeeRow] = {\n sql\"\"\"select `id`, `department_id`, `manager_id`, `email`, `first_name`, `last_name`, `salary`, `hired_at`, `active`, `created_at`, `metadata`, `photo`, `ip_address`, `permissions`\n from `showcase`.`employee`\n where `id` = ${Fragment.encode(EmployeeId.pgType, id)}\"\"\".query(EmployeeRow.`_rowParser`.first()).runUnchecked(c)\n }\n\n override def selectByIds(ids: Array[EmployeeId])(using c: Connection): List[EmployeeRow] = {\n val fragments: ListBuffer[Fragment] = ListBuffer()\n ids.foreach { id => fragments.addOne(Fragment.encode(EmployeeId.pgType, id)): @scala.annotation.nowarn }\n return Fragment.interpolate(Fragment.lit(\"select `id`, `department_id`, `manager_id`, `email`, `first_name`, `last_name`, `salary`, `hired_at`, `active`, `created_at`, `metadata`, `photo`, `ip_address`, `permissions` from `showcase`.`employee` where `id` in (\"), Fragment.comma(fragments), Fragment.lit(\")\")).query(EmployeeRow.`_rowParser`.all()).runUnchecked(c)\n }\n\n override def selectByIdsTracked(ids: Array[EmployeeId])(using c: Connection): Map[EmployeeId, EmployeeRow] = {\n val ret: scala.collection.mutable.Map[EmployeeId, EmployeeRow] = scala.collection.mutable.Map.empty[EmployeeId, EmployeeRow]\n selectByIds(ids)(using c).foreach(row => ret.put(row.id, row): @scala.annotation.nowarn)\n return ret.toMap\n }\n\n override def selectByUniqueEmail(email: String)(using c: Connection): Option[EmployeeRow] = {\n sql\"\"\"select `id`, `department_id`, `manager_id`, `email`, `first_name`, `last_name`, `salary`, `hired_at`, `active`, `created_at`, `metadata`, `photo`, `ip_address`, `permissions`\n from `showcase`.`employee`\n where `email` = ${Fragment.encode(MariaTypes.varchar, email)}\n \"\"\".query(EmployeeRow.`_rowParser`.first()).runUnchecked(c)\n }\n\n override def update: UpdateBuilder[EmployeeFields, EmployeeRow] = UpdateBuilder.of(\"`showcase`.`employee`\", EmployeeFields.structure, EmployeeRow.`_rowParser`, Dialect.MARIADB)\n\n override def update(row: EmployeeRow)(using c: Connection): Boolean = {\n val id: EmployeeId = row.id\n return sql\"\"\"update `showcase`.`employee`\n set `department_id` = ${Fragment.encode(DepartmentId.pgType, row.departmentId)},\n `manager_id` = ${Fragment.encode(EmployeeId.pgType.nullable, row.managerId)},\n `email` = ${Fragment.encode(MariaTypes.varchar, row.email)},\n `first_name` = ${Fragment.encode(MariaTypes.varchar, row.firstName)},\n `last_name` = ${Fragment.encode(MariaTypes.varchar, row.lastName)},\n `salary` = ${Fragment.encode(ScalaDbTypes.MariaTypes.numeric.nullable, row.salary)},\n `hired_at` = ${Fragment.encode(MariaTypes.date.nullable, row.hiredAt)},\n `active` = ${Fragment.encode(ScalaDbTypes.MariaTypes.bool.nullable, row.active)},\n `created_at` = ${Fragment.encode(MariaTypes.timestamp.nullable, row.createdAt)},\n `metadata` = ${Fragment.encode(MariaTypes.json.nullable, row.metadata)},\n `photo` = ${Fragment.encode(MariaTypes.mediumblob.nullable, row.photo)},\n `ip_address` = ${Fragment.encode(MariaTypes.inet4.nullable, row.ipAddress)},\n `permissions` = ${Fragment.encode(MariaTypes.set.nullable, row.permissions)}\n where `id` = ${Fragment.encode(EmployeeId.pgType, id)}\"\"\".update().runUnchecked(c) > 0\n }\n\n override def upsert(unsaved: EmployeeRow)(using c: Connection): EmployeeRow = {\n sql\"\"\"INSERT INTO `showcase`.`employee`(`id`, `department_id`, `manager_id`, `email`, `first_name`, `last_name`, `salary`, `hired_at`, `active`, `created_at`, `metadata`, `photo`, `ip_address`, `permissions`)\n VALUES (${Fragment.encode(EmployeeId.pgType, unsaved.id)}, ${Fragment.encode(DepartmentId.pgType, unsaved.departmentId)}, ${Fragment.encode(EmployeeId.pgType.nullable, unsaved.managerId)}, ${Fragment.encode(MariaTypes.varchar, unsaved.email)}, ${Fragment.encode(MariaTypes.varchar, unsaved.firstName)}, ${Fragment.encode(MariaTypes.varchar, unsaved.lastName)}, ${Fragment.encode(ScalaDbTypes.MariaTypes.numeric.nullable, unsaved.salary)}, ${Fragment.encode(MariaTypes.date.nullable, unsaved.hiredAt)}, ${Fragment.encode(ScalaDbTypes.MariaTypes.bool.nullable, unsaved.active)}, ${Fragment.encode(MariaTypes.timestamp.nullable, unsaved.createdAt)}, ${Fragment.encode(MariaTypes.json.nullable, unsaved.metadata)}, ${Fragment.encode(MariaTypes.mediumblob.nullable, unsaved.photo)}, ${Fragment.encode(MariaTypes.inet4.nullable, unsaved.ipAddress)}, ${Fragment.encode(MariaTypes.set.nullable, unsaved.permissions)})\n ON DUPLICATE KEY UPDATE `department_id` = VALUES(`department_id`),\n `manager_id` = VALUES(`manager_id`),\n `email` = VALUES(`email`),\n `first_name` = VALUES(`first_name`),\n `last_name` = VALUES(`last_name`),\n `salary` = VALUES(`salary`),\n `hired_at` = VALUES(`hired_at`),\n `active` = VALUES(`active`),\n `created_at` = VALUES(`created_at`),\n `metadata` = VALUES(`metadata`),\n `photo` = VALUES(`photo`),\n `ip_address` = VALUES(`ip_address`),\n `permissions` = VALUES(`permissions`)\n RETURNING `id`, `department_id`, `manager_id`, `email`, `first_name`, `last_name`, `salary`, `hired_at`, `active`, `created_at`, `metadata`, `photo`, `ip_address`, `permissions`\"\"\"\n .updateReturning(EmployeeRow.`_rowParser`.exactlyOne())\n .runUnchecked(c)\n }\n\n override def upsertBatch(unsaved: Iterator[EmployeeRow])(using c: Connection): List[EmployeeRow] = {\n sql\"\"\"INSERT INTO `showcase`.`employee`(`id`, `department_id`, `manager_id`, `email`, `first_name`, `last_name`, `salary`, `hired_at`, `active`, `created_at`, `metadata`, `photo`, `ip_address`, `permissions`)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n ON DUPLICATE KEY UPDATE `department_id` = VALUES(`department_id`),\n `manager_id` = VALUES(`manager_id`),\n `email` = VALUES(`email`),\n `first_name` = VALUES(`first_name`),\n `last_name` = VALUES(`last_name`),\n `salary` = VALUES(`salary`),\n `hired_at` = VALUES(`hired_at`),\n `active` = VALUES(`active`),\n `created_at` = VALUES(`created_at`),\n `metadata` = VALUES(`metadata`),\n `photo` = VALUES(`photo`),\n `ip_address` = VALUES(`ip_address`),\n `permissions` = VALUES(`permissions`)\n RETURNING `id`, `department_id`, `manager_id`, `email`, `first_name`, `last_name`, `salary`, `hired_at`, `active`, `created_at`, `metadata`, `photo`, `ip_address`, `permissions`\"\"\"\n .updateReturningEach(EmployeeRow.`_rowParser`, unsaved)\n .runUnchecked(c)\n }\n}", - "EmployeeRepoMock": "package showcase.showcase.employee\n\nimport dev.typr.foundations.scala.DeleteBuilder\nimport dev.typr.foundations.scala.DeleteBuilderMock\nimport dev.typr.foundations.scala.DeleteParams\nimport dev.typr.foundations.scala.SelectBuilder\nimport dev.typr.foundations.scala.SelectBuilderMock\nimport dev.typr.foundations.scala.SelectParams\nimport dev.typr.foundations.scala.UpdateBuilder\nimport dev.typr.foundations.scala.UpdateBuilderMock\nimport dev.typr.foundations.scala.UpdateParams\nimport java.lang.RuntimeException\nimport java.sql.Connection\n\ncase class EmployeeRepoMock(\n toRow: EmployeeRowUnsaved => EmployeeRow,\n map: scala.collection.mutable.Map[EmployeeId, EmployeeRow] = scala.collection.mutable.Map.empty[EmployeeId, EmployeeRow]\n) extends EmployeeRepo {\n override def delete: DeleteBuilder[EmployeeFields, EmployeeRow] = DeleteBuilderMock(EmployeeFields.structure, () => map.values.toList, DeleteParams.empty(), row => row.id, id => map.remove(id): @scala.annotation.nowarn)\n\n override def deleteById(id: EmployeeId)(using c: Connection): Boolean = map.remove(id).isDefined\n\n override def deleteByIds(ids: Array[EmployeeId])(using c: Connection): Int = {\n var count = 0\n ids.foreach { id => if (map.remove(id).isDefined) {\n count = count + 1\n } }\n return count\n }\n\n override def insert(unsaved: EmployeeRow)(using c: Connection): EmployeeRow = {\n if (map.contains(unsaved.id)) {\n throw new RuntimeException(s\"id ${unsaved.id} already exists\")\n }\n map.put(unsaved.id, unsaved): @scala.annotation.nowarn\n return unsaved\n }\n\n override def insert(unsaved: EmployeeRowUnsaved)(using c: Connection): EmployeeRow = insert(toRow(unsaved))(using c)\n\n override def select: SelectBuilder[EmployeeFields, EmployeeRow] = SelectBuilderMock(EmployeeFields.structure, () => map.values.toList, SelectParams.empty())\n\n override def selectAll(using c: Connection): List[EmployeeRow] = map.values.toList\n\n override def selectById(id: EmployeeId)(using c: Connection): Option[EmployeeRow] = map.get(id)\n\n override def selectByIds(ids: Array[EmployeeId])(using c: Connection): List[EmployeeRow] = ids.flatMap(map.get(_)).toList\n\n override def selectByIdsTracked(ids: Array[EmployeeId])(using c: Connection): Map[EmployeeId, EmployeeRow] = selectByIds(ids)(using c).map(x => (((row: EmployeeRow) => row.id).apply(x), x)).toMap\n\n override def selectByUniqueEmail(email: String)(using c: Connection): Option[EmployeeRow] = map.values.toList.find(v => (email == v.email))\n\n override def update: UpdateBuilder[EmployeeFields, EmployeeRow] = UpdateBuilderMock(EmployeeFields.structure, () => map.values.toList, UpdateParams.empty(), row => row)\n\n override def update(row: EmployeeRow)(using c: Connection): Boolean = {\n val shouldUpdate = map.get(row.id).filter(oldRow => (oldRow != row)).isDefined\n if (shouldUpdate) {\n map.put(row.id, row): @scala.annotation.nowarn\n }\n return shouldUpdate\n }\n\n override def upsert(unsaved: EmployeeRow)(using c: Connection): EmployeeRow = {\n map.put(unsaved.id, unsaved): @scala.annotation.nowarn\n return unsaved\n }\n\n override def upsertBatch(unsaved: Iterator[EmployeeRow])(using c: Connection): List[EmployeeRow] = {\n unsaved.map { row =>\n map.put(row.id, row): @scala.annotation.nowarn\n row\n }.toList\n }\n}", - "EmployeeFields": "package showcase.showcase.employee\n\nimport dev.typr.foundations.MariaTypes\nimport dev.typr.foundations.RowParser\nimport dev.typr.foundations.data.Json\nimport dev.typr.foundations.data.maria.Inet4\nimport dev.typr.foundations.data.maria.MariaSet\nimport dev.typr.foundations.dsl.FieldsExpr0\nimport dev.typr.foundations.dsl.Path\nimport dev.typr.foundations.dsl.SqlExpr.FieldLike\nimport dev.typr.foundations.scala.ForeignKey\nimport dev.typr.foundations.scala.RelationStructure\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport dev.typr.foundations.scala.SqlExpr.Field\nimport dev.typr.foundations.scala.SqlExpr.IdField\nimport dev.typr.foundations.scala.SqlExpr.OptField\nimport java.time.LocalDate\nimport java.time.LocalDateTime\nimport showcase.showcase.department.DepartmentFields\nimport showcase.showcase.department.DepartmentId\nimport showcase.showcase.department.DepartmentRow\n\ntrait EmployeeFields extends FieldsExpr0[EmployeeRow] {\n def id: IdField[EmployeeId, EmployeeRow]\n\n def departmentId: Field[DepartmentId, EmployeeRow]\n\n def managerId: OptField[EmployeeId, EmployeeRow]\n\n def email: Field[String, EmployeeRow]\n\n def firstName: Field[String, EmployeeRow]\n\n def lastName: Field[String, EmployeeRow]\n\n def salary: OptField[BigDecimal, EmployeeRow]\n\n def hiredAt: OptField[LocalDate, EmployeeRow]\n\n def active: OptField[Boolean, EmployeeRow]\n\n def createdAt: OptField[LocalDateTime, EmployeeRow]\n\n def metadata: OptField[Json, EmployeeRow]\n\n def photo: OptField[Array[Byte], EmployeeRow]\n\n def ipAddress: OptField[Inet4, EmployeeRow]\n\n def permissions: OptField[MariaSet, EmployeeRow]\n\n def fkDepartment: ForeignKey[DepartmentFields, DepartmentRow] = ForeignKey.of[DepartmentFields, DepartmentRow](\"employee_department_fk\").withColumnPair[DepartmentId](departmentId, _.id)\n\n def fkEmployee: ForeignKey[EmployeeFields, EmployeeRow] = ForeignKey.of[EmployeeFields, EmployeeRow](\"employee_manager_fk\").withColumnPair[EmployeeId](managerId, _.id)\n\n override def columns: java.util.List[FieldLike[?, EmployeeRow]]\n\n override def rowParser: RowParser[EmployeeRow] = EmployeeRow._rowParser.underlying\n}\n\nobject EmployeeFields {\n case class Impl(val `_path`: java.util.List[Path]) extends EmployeeFields with RelationStructure[EmployeeFields, EmployeeRow] {\n\n override def id: IdField[EmployeeId, EmployeeRow] = {\n new IdField[EmployeeId, EmployeeRow](\n _path,\n \"id\",\n _.id,\n None,\n None,\n (row, value) => row.copy(id = value),\n EmployeeId.pgType\n )\n }\n\n override def departmentId: Field[DepartmentId, EmployeeRow] = {\n new Field[DepartmentId, EmployeeRow](\n _path,\n \"department_id\",\n _.departmentId,\n None,\n None,\n (row, value) => row.copy(departmentId = value),\n DepartmentId.pgType\n )\n }\n\n override def managerId: OptField[EmployeeId, EmployeeRow] = {\n new OptField[EmployeeId, EmployeeRow](\n _path,\n \"manager_id\",\n _.managerId,\n None,\n None,\n (row, value) => row.copy(managerId = value),\n EmployeeId.pgType\n )\n }\n\n override def email: Field[String, EmployeeRow] = {\n new Field[String, EmployeeRow](\n _path,\n \"email\",\n _.email,\n None,\n None,\n (row, value) => row.copy(email = value),\n MariaTypes.varchar\n )\n }\n\n override def firstName: Field[String, EmployeeRow] = {\n new Field[String, EmployeeRow](\n _path,\n \"first_name\",\n _.firstName,\n None,\n None,\n (row, value) => row.copy(firstName = value),\n MariaTypes.varchar\n )\n }\n\n override def lastName: Field[String, EmployeeRow] = {\n new Field[String, EmployeeRow](\n _path,\n \"last_name\",\n _.lastName,\n None,\n None,\n (row, value) => row.copy(lastName = value),\n MariaTypes.varchar\n )\n }\n\n override def salary: OptField[BigDecimal, EmployeeRow] = {\n new OptField[BigDecimal, EmployeeRow](\n _path,\n \"salary\",\n _.salary,\n None,\n None,\n (row, value) => row.copy(salary = value),\n ScalaDbTypes.MariaTypes.numeric\n )\n }\n\n override def hiredAt: OptField[LocalDate, EmployeeRow] = {\n new OptField[LocalDate, EmployeeRow](\n _path,\n \"hired_at\",\n _.hiredAt,\n None,\n None,\n (row, value) => row.copy(hiredAt = value),\n MariaTypes.date\n )\n }\n\n override def active: OptField[Boolean, EmployeeRow] = {\n new OptField[Boolean, EmployeeRow](\n _path,\n \"active\",\n _.active,\n None,\n None,\n (row, value) => row.copy(active = value),\n ScalaDbTypes.MariaTypes.bool\n )\n }\n\n override def createdAt: OptField[LocalDateTime, EmployeeRow] = {\n new OptField[LocalDateTime, EmployeeRow](\n _path,\n \"created_at\",\n _.createdAt,\n None,\n None,\n (row, value) => row.copy(createdAt = value),\n MariaTypes.timestamp\n )\n }\n\n override def metadata: OptField[Json, EmployeeRow] = {\n new OptField[Json, EmployeeRow](\n _path,\n \"metadata\",\n _.metadata,\n None,\n None,\n (row, value) => row.copy(metadata = value),\n MariaTypes.json\n )\n }\n\n override def photo: OptField[Array[Byte], EmployeeRow] = {\n new OptField[Array[Byte], EmployeeRow](\n _path,\n \"photo\",\n _.photo,\n None,\n None,\n (row, value) => row.copy(photo = value),\n MariaTypes.mediumblob\n )\n }\n\n override def ipAddress: OptField[Inet4, EmployeeRow] = {\n new OptField[Inet4, EmployeeRow](\n _path,\n \"ip_address\",\n _.ipAddress,\n None,\n None,\n (row, value) => row.copy(ipAddress = value),\n MariaTypes.inet4\n )\n }\n\n override def permissions: OptField[MariaSet, EmployeeRow] = {\n new OptField[MariaSet, EmployeeRow](\n _path,\n \"permissions\",\n _.permissions,\n None,\n None,\n (row, value) => row.copy(permissions = value),\n MariaTypes.set\n )\n }\n\n override def columns: java.util.List[FieldLike[?, EmployeeRow]] = java.util.List.of(this.id.underlying, this.departmentId.underlying, this.managerId.underlying, this.email.underlying, this.firstName.underlying, this.lastName.underlying, this.salary.underlying, this.hiredAt.underlying, this.active.underlying, this.createdAt.underlying, this.metadata.underlying, this.photo.underlying, this.ipAddress.underlying, this.permissions.underlying)\n\n override def withPaths(`_path`: java.util.List[Path]): RelationStructure[EmployeeFields, EmployeeRow] = new Impl(`_path`)\n }\n\n def structure: Impl = new Impl(java.util.Collections.emptyList())\n}", - "DepartmentRow": "package showcase.showcase.department\n\nimport dev.typr.foundations.MariaTypes\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport showcase.showcase.company.CompanyId\n\n/** Table: showcase.department\n * Primary key: id\n */\ncase class DepartmentRow(\n id: DepartmentId,\n /** Points to [[showcase.showcase.company.CompanyRow.id]] */\n companyId: CompanyId,\n name: String,\n budget: Option[BigDecimal]\n)\n\nobject DepartmentRow {\n val `_rowParser`: RowParser[DepartmentRow] = RowParsers.of(DepartmentId.pgType, CompanyId.pgType, MariaTypes.varchar, ScalaDbTypes.MariaTypes.numeric.nullable)(DepartmentRow.apply)(row => Array[Any](row.id, row.companyId, row.name, row.budget))\n}", - "DepartmentId": "package showcase.showcase.department\n\nimport dev.typr.foundations.MariaType\nimport dev.typr.foundations.MariaTypes\nimport dev.typr.foundations.scala.Bijection\n\n/** Type for the primary key of table `showcase.department` */\ncase class DepartmentId(value: String) extends scala.AnyVal\n\nobject DepartmentId {\n given bijection: Bijection[DepartmentId, String] = Bijection.apply[DepartmentId, String](_.value)(DepartmentId.apply)\n\n given pgType: MariaType[DepartmentId] = MariaTypes.varchar.bimap(DepartmentId.apply, _.value)\n}", - "DepartmentRepo": "package showcase.showcase.department\n\nimport dev.typr.foundations.scala.DeleteBuilder\nimport dev.typr.foundations.scala.SelectBuilder\nimport dev.typr.foundations.scala.UpdateBuilder\nimport java.sql.Connection\n\ntrait DepartmentRepo {\n def delete: DeleteBuilder[DepartmentFields, DepartmentRow]\n\n def deleteById(id: DepartmentId)(using c: Connection): Boolean\n\n def deleteByIds(ids: Array[DepartmentId])(using c: Connection): Int\n\n def insert(unsaved: DepartmentRow)(using c: Connection): DepartmentRow\n\n def select: SelectBuilder[DepartmentFields, DepartmentRow]\n\n def selectAll(using c: Connection): List[DepartmentRow]\n\n def selectById(id: DepartmentId)(using c: Connection): Option[DepartmentRow]\n\n def selectByIds(ids: Array[DepartmentId])(using c: Connection): List[DepartmentRow]\n\n def selectByIdsTracked(ids: Array[DepartmentId])(using c: Connection): Map[DepartmentId, DepartmentRow]\n\n def update: UpdateBuilder[DepartmentFields, DepartmentRow]\n\n def update(row: DepartmentRow)(using c: Connection): Boolean\n\n def upsert(unsaved: DepartmentRow)(using c: Connection): DepartmentRow\n\n def upsertBatch(unsaved: Iterator[DepartmentRow])(using c: Connection): List[DepartmentRow]\n}", - "DepartmentRepoMock": "package showcase.showcase.department\n\nimport dev.typr.foundations.scala.DeleteBuilder\nimport dev.typr.foundations.scala.DeleteBuilderMock\nimport dev.typr.foundations.scala.DeleteParams\nimport dev.typr.foundations.scala.SelectBuilder\nimport dev.typr.foundations.scala.SelectBuilderMock\nimport dev.typr.foundations.scala.SelectParams\nimport dev.typr.foundations.scala.UpdateBuilder\nimport dev.typr.foundations.scala.UpdateBuilderMock\nimport dev.typr.foundations.scala.UpdateParams\nimport java.lang.RuntimeException\nimport java.sql.Connection\n\ncase class DepartmentRepoMock(map: scala.collection.mutable.Map[DepartmentId, DepartmentRow] = scala.collection.mutable.Map.empty[DepartmentId, DepartmentRow]) extends DepartmentRepo {\n override def delete: DeleteBuilder[DepartmentFields, DepartmentRow] = DeleteBuilderMock(DepartmentFields.structure, () => map.values.toList, DeleteParams.empty(), row => row.id, id => map.remove(id): @scala.annotation.nowarn)\n\n override def deleteById(id: DepartmentId)(using c: Connection): Boolean = map.remove(id).isDefined\n\n override def deleteByIds(ids: Array[DepartmentId])(using c: Connection): Int = {\n var count = 0\n ids.foreach { id => if (map.remove(id).isDefined) {\n count = count + 1\n } }\n return count\n }\n\n override def insert(unsaved: DepartmentRow)(using c: Connection): DepartmentRow = {\n if (map.contains(unsaved.id)) {\n throw new RuntimeException(s\"id ${unsaved.id} already exists\")\n }\n map.put(unsaved.id, unsaved): @scala.annotation.nowarn\n return unsaved\n }\n\n override def select: SelectBuilder[DepartmentFields, DepartmentRow] = SelectBuilderMock(DepartmentFields.structure, () => map.values.toList, SelectParams.empty())\n\n override def selectAll(using c: Connection): List[DepartmentRow] = map.values.toList\n\n override def selectById(id: DepartmentId)(using c: Connection): Option[DepartmentRow] = map.get(id)\n\n override def selectByIds(ids: Array[DepartmentId])(using c: Connection): List[DepartmentRow] = ids.flatMap(map.get(_)).toList\n\n override def selectByIdsTracked(ids: Array[DepartmentId])(using c: Connection): Map[DepartmentId, DepartmentRow] = selectByIds(ids)(using c).map(x => (((row: DepartmentRow) => row.id).apply(x), x)).toMap\n\n override def update: UpdateBuilder[DepartmentFields, DepartmentRow] = UpdateBuilderMock(DepartmentFields.structure, () => map.values.toList, UpdateParams.empty(), row => row)\n\n override def update(row: DepartmentRow)(using c: Connection): Boolean = {\n val shouldUpdate = map.get(row.id).filter(oldRow => (oldRow != row)).isDefined\n if (shouldUpdate) {\n map.put(row.id, row): @scala.annotation.nowarn\n }\n return shouldUpdate\n }\n\n override def upsert(unsaved: DepartmentRow)(using c: Connection): DepartmentRow = {\n map.put(unsaved.id, unsaved): @scala.annotation.nowarn\n return unsaved\n }\n\n override def upsertBatch(unsaved: Iterator[DepartmentRow])(using c: Connection): List[DepartmentRow] = {\n unsaved.map { row =>\n map.put(row.id, row): @scala.annotation.nowarn\n row\n }.toList\n }\n}", - "ProjectAssignmentRow": "package showcase.showcase.project_assignment\n\nimport dev.typr.foundations.MariaTypes\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport java.time.LocalDate\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.employee.EmployeeId\nimport showcase.showcase.project.ProjectId\n\n/** Table: showcase.project_assignment\n * Composite primary key: employee_id, project_id\n */\ncase class ProjectAssignmentRow(\n /** Points to [[showcase.showcase.employee.EmployeeRow.id]] */\n employeeId: EmployeeId,\n /** Points to [[showcase.showcase.project.ProjectRow.id]] */\n projectId: ProjectId,\n role: String,\n /** Default: 0 */\n hoursAllocated: Option[Int],\n startDate: Option[LocalDate],\n endDate: Option[LocalDate]\n) {\n def compositeId: ProjectAssignmentId = new ProjectAssignmentId(employeeId, projectId)\n\n def id: ProjectAssignmentId = this.compositeId\n\n def toUnsavedRow(hoursAllocated: Defaulted[Option[Int]] = Defaulted.Provided(this.hoursAllocated)): ProjectAssignmentRowUnsaved = {\n new ProjectAssignmentRowUnsaved(\n employeeId,\n projectId,\n role,\n startDate,\n endDate,\n hoursAllocated\n )\n }\n}\n\nobject ProjectAssignmentRow {\n val `_rowParser`: RowParser[ProjectAssignmentRow] = RowParsers.of(EmployeeId.pgType, ProjectId.pgType, MariaTypes.varchar, ScalaDbTypes.MariaTypes.int_.nullable, MariaTypes.date.nullable, MariaTypes.date.nullable)(ProjectAssignmentRow.apply)(row => Array[Any](row.employeeId, row.projectId, row.role, row.hoursAllocated, row.startDate, row.endDate))\n\n def apply(\n compositeId: ProjectAssignmentId,\n role: String,\n hoursAllocated: Option[Int],\n startDate: Option[LocalDate],\n endDate: Option[LocalDate]\n ): ProjectAssignmentRow = {\n new ProjectAssignmentRow(\n compositeId.employeeId,\n compositeId.projectId,\n role,\n hoursAllocated,\n startDate,\n endDate\n )\n }\n}", - "ProjectAssignmentRowUnsaved": "package showcase.showcase.project_assignment\n\nimport java.time.LocalDate\nimport showcase.customtypes.Defaulted\nimport showcase.customtypes.Defaulted.UseDefault\nimport showcase.showcase.employee.EmployeeId\nimport showcase.showcase.project.ProjectId\n\n/** This class corresponds to a row in table `showcase.project_assignment` which has not been persisted yet */\ncase class ProjectAssignmentRowUnsaved(\n /** Points to [[showcase.showcase.employee.EmployeeRow.id]] */\n employeeId: EmployeeId,\n /** Points to [[showcase.showcase.project.ProjectRow.id]] */\n projectId: ProjectId,\n role: String,\n startDate: Option[LocalDate] = None,\n endDate: Option[LocalDate] = None,\n /** Default: 0 */\n hoursAllocated: Defaulted[Option[Int]] = new UseDefault()\n) {\n def toRow(hoursAllocatedDefault: => Option[Int]): ProjectAssignmentRow = {\n new ProjectAssignmentRow(\n employeeId = employeeId,\n projectId = projectId,\n role = role,\n hoursAllocated = hoursAllocated.getOrElse(hoursAllocatedDefault),\n startDate = startDate,\n endDate = endDate\n )\n }\n}", - "ProjectAssignmentId": "package showcase.showcase.project_assignment\n\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport showcase.showcase.employee.EmployeeId\nimport showcase.showcase.project.ProjectId\n\n/** Type for the composite primary key of table `showcase.project_assignment` */\ncase class ProjectAssignmentId(\n employeeId: EmployeeId,\n projectId: ProjectId\n)\n\nobject ProjectAssignmentId {\n val `_rowParser`: RowParser[ProjectAssignmentId] = RowParsers.of(EmployeeId.pgType, ProjectId.pgType)(ProjectAssignmentId.apply)(row => Array[Any](row.employeeId, row.projectId))\n}", - "ProjectAssignmentRepo": "package showcase.showcase.project_assignment\n\nimport dev.typr.foundations.scala.DeleteBuilder\nimport dev.typr.foundations.scala.SelectBuilder\nimport dev.typr.foundations.scala.UpdateBuilder\nimport java.sql.Connection\n\ntrait ProjectAssignmentRepo {\n def delete: DeleteBuilder[ProjectAssignmentFields, ProjectAssignmentRow]\n\n def deleteById(compositeId: ProjectAssignmentId)(using c: Connection): Boolean\n\n def deleteByIds(compositeIds: Array[ProjectAssignmentId])(using c: Connection): Int\n\n def insert(unsaved: ProjectAssignmentRow)(using c: Connection): ProjectAssignmentRow\n\n def insert(unsaved: ProjectAssignmentRowUnsaved)(using c: Connection): ProjectAssignmentRow\n\n def select: SelectBuilder[ProjectAssignmentFields, ProjectAssignmentRow]\n\n def selectAll(using c: Connection): List[ProjectAssignmentRow]\n\n def selectById(compositeId: ProjectAssignmentId)(using c: Connection): Option[ProjectAssignmentRow]\n\n def selectByIds(compositeIds: Array[ProjectAssignmentId])(using c: Connection): List[ProjectAssignmentRow]\n\n def selectByIdsTracked(compositeIds: Array[ProjectAssignmentId])(using c: Connection): Map[ProjectAssignmentId, ProjectAssignmentRow]\n\n def update: UpdateBuilder[ProjectAssignmentFields, ProjectAssignmentRow]\n\n def update(row: ProjectAssignmentRow)(using c: Connection): Boolean\n\n def upsert(unsaved: ProjectAssignmentRow)(using c: Connection): ProjectAssignmentRow\n\n def upsertBatch(unsaved: Iterator[ProjectAssignmentRow])(using c: Connection): List[ProjectAssignmentRow]\n}", - "ProjectRow": "package showcase.showcase.project\n\nimport dev.typr.foundations.MariaTypes\nimport dev.typr.foundations.data.Json\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport java.time.LocalDate\nimport java.time.LocalDateTime\nimport showcase.customtypes.Defaulted\n\n/** Table: showcase.project\n * Primary key: id\n */\ncase class ProjectRow(\n id: ProjectId,\n name: String,\n description: Option[String],\n startDate: Option[LocalDate],\n endDate: Option[LocalDate],\n budget: Option[BigDecimal],\n /** Default: 'planning' */\n status: Option[String],\n /** Default: CURRENT_TIMESTAMP */\n createdAt: Option[LocalDateTime],\n metadata: Option[Json],\n descriptionLong: Option[String],\n attachments: Option[Array[Byte]],\n priority: Option[String]\n) {\n def toUnsavedRow(\n status: Defaulted[Option[String]] = Defaulted.Provided(this.status),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.Provided(this.createdAt)\n ): ProjectRowUnsaved = {\n new ProjectRowUnsaved(\n id,\n name,\n description,\n startDate,\n endDate,\n budget,\n metadata,\n descriptionLong,\n attachments,\n priority,\n status,\n createdAt\n )\n }\n}\n\nobject ProjectRow {\n val `_rowParser`: RowParser[ProjectRow] = RowParsers.of(ProjectId.pgType, MariaTypes.varchar, MariaTypes.varchar.nullable, MariaTypes.date.nullable, MariaTypes.date.nullable, ScalaDbTypes.MariaTypes.numeric.nullable, MariaTypes.varchar.nullable, MariaTypes.timestamp.nullable, MariaTypes.json.nullable, MariaTypes.longtext.nullable, MariaTypes.mediumblob.nullable, MariaTypes.text.nullable)(ProjectRow.apply)(row => Array[Any](row.id, row.name, row.description, row.startDate, row.endDate, row.budget, row.status, row.createdAt, row.metadata, row.descriptionLong, row.attachments, row.priority))\n}", - "ProjectId": "package showcase.showcase.project\n\nimport dev.typr.foundations.MariaType\nimport dev.typr.foundations.MariaTypes\nimport dev.typr.foundations.scala.Bijection\n\n/** Type for the primary key of table `showcase.project` */\ncase class ProjectId(value: String) extends scala.AnyVal\n\nobject ProjectId {\n given bijection: Bijection[ProjectId, String] = Bijection.apply[ProjectId, String](_.value)(ProjectId.apply)\n\n given pgType: MariaType[ProjectId] = MariaTypes.varchar.bimap(ProjectId.apply, _.value)\n}", - "EmployeeSummaryViewRow": "package showcase.showcase.employee_summary\n\nimport dev.typr.foundations.MariaTypes\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport java.time.LocalDate\nimport showcase.showcase.company.CompanyId\nimport showcase.showcase.department.DepartmentId\nimport showcase.showcase.employee.EmployeeId\n\n/** View: showcase.employee_summary\n * Summary view of employees with their department and company information\n */\ncase class EmployeeSummaryViewRow(\n /** Points to [[showcase.showcase.employee.EmployeeRow.id]] */\n employeeId: EmployeeId,\n email: String,\n firstName: String,\n lastName: String,\n salary: Option[BigDecimal],\n hiredAt: Option[LocalDate],\n active: Option[Boolean],\n /** Points to [[showcase.showcase.department.DepartmentRow.id]] */\n departmentId: DepartmentId,\n departmentName: String,\n departmentBudget: Option[BigDecimal],\n /** Points to [[showcase.showcase.company.CompanyRow.id]] */\n companyId: CompanyId,\n companyName: String,\n managerId: Option[String],\n managerFirstName: Option[String],\n managerLastName: Option[String]\n)\n\nobject EmployeeSummaryViewRow {\n val `_rowParser`: RowParser[EmployeeSummaryViewRow] = RowParsers.of(EmployeeId.pgType, MariaTypes.varchar, MariaTypes.varchar, MariaTypes.varchar, ScalaDbTypes.MariaTypes.numeric.nullable, MariaTypes.date.nullable, ScalaDbTypes.MariaTypes.bool.nullable, DepartmentId.pgType, MariaTypes.varchar, ScalaDbTypes.MariaTypes.numeric.nullable, CompanyId.pgType, MariaTypes.varchar, MariaTypes.varchar.nullable, MariaTypes.varchar.nullable, MariaTypes.varchar.nullable)(EmployeeSummaryViewRow.apply)(row => Array[Any](row.employeeId, row.email, row.firstName, row.lastName, row.salary, row.hiredAt, row.active, row.departmentId, row.departmentName, row.departmentBudget, row.companyId, row.companyName, row.managerId, row.managerFirstName, row.managerLastName))\n}", - "EmployeeSummaryViewRepo": "package showcase.showcase.employee_summary\n\nimport dev.typr.foundations.scala.SelectBuilder\nimport java.sql.Connection\n\ntrait EmployeeSummaryViewRepo {\n def select: SelectBuilder[EmployeeSummaryViewFields, EmployeeSummaryViewRow]\n\n def selectAll(using c: Connection): List[EmployeeSummaryViewRow]\n}", - "CustomerOrderRow": "package showcase.showcase.customer_order\n\nimport dev.typr.foundations.MariaTypes\nimport dev.typr.foundations.data.Json\nimport dev.typr.foundations.data.maria.Inet4\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport java.time.LocalDateTime\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.address.AddressId\nimport showcase.showcase.customer.CustomerId\n\n/** Table: showcase.customer_order\n * Primary key: id\n */\ncase class CustomerOrderRow(\n id: CustomerOrderId,\n /** Points to [[showcase.showcase.customer.CustomerRow.id]] */\n customerId: CustomerId,\n /** Points to [[showcase.showcase.address.AddressRow.id]] */\n shippingAddressId: Option[AddressId],\n /** Points to [[showcase.showcase.address.AddressRow.id]] */\n billingAddressId: Option[AddressId],\n /** Default: 'pending' */\n status: Option[String],\n subtotal: BigDecimal,\n /** Default: 0 */\n tax: Option[BigDecimal],\n /** Default: 0 */\n shipping: Option[BigDecimal],\n total: BigDecimal,\n notes: Option[String],\n /** Default: CURRENT_TIMESTAMP */\n createdAt: Option[LocalDateTime],\n shippedAt: Option[LocalDateTime],\n deliveredAt: Option[LocalDateTime],\n metadata: Option[Json],\n ipAddress: Option[Inet4],\n paymentMethod: Option[String]\n) {\n def toUnsavedRow(\n status: Defaulted[Option[String]] = Defaulted.Provided(this.status),\n tax: Defaulted[Option[BigDecimal]] = Defaulted.Provided(this.tax),\n shipping: Defaulted[Option[BigDecimal]] = Defaulted.Provided(this.shipping),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.Provided(this.createdAt)\n ): CustomerOrderRowUnsaved = {\n new CustomerOrderRowUnsaved(\n id,\n customerId,\n shippingAddressId,\n billingAddressId,\n subtotal,\n total,\n notes,\n shippedAt,\n deliveredAt,\n metadata,\n ipAddress,\n paymentMethod,\n status,\n tax,\n shipping,\n createdAt\n )\n }\n}\n\nobject CustomerOrderRow {\n val `_rowParser`: RowParser[CustomerOrderRow] = RowParsers.of(CustomerOrderId.pgType, CustomerId.pgType, AddressId.pgType.nullable, AddressId.pgType.nullable, MariaTypes.varchar.nullable, ScalaDbTypes.MariaTypes.numeric, ScalaDbTypes.MariaTypes.numeric.nullable, ScalaDbTypes.MariaTypes.numeric.nullable, ScalaDbTypes.MariaTypes.numeric, MariaTypes.varchar.nullable, MariaTypes.timestamp.nullable, MariaTypes.timestamp.nullable, MariaTypes.timestamp.nullable, MariaTypes.json.nullable, MariaTypes.inet4.nullable, MariaTypes.text.nullable)(CustomerOrderRow.apply)(row => Array[Any](row.id, row.customerId, row.shippingAddressId, row.billingAddressId, row.status, row.subtotal, row.tax, row.shipping, row.total, row.notes, row.createdAt, row.shippedAt, row.deliveredAt, row.metadata, row.ipAddress, row.paymentMethod))\n}", - "CustomerOrderRepo": "package showcase.showcase.customer_order\n\nimport dev.typr.foundations.scala.DeleteBuilder\nimport dev.typr.foundations.scala.SelectBuilder\nimport dev.typr.foundations.scala.UpdateBuilder\nimport java.sql.Connection\n\ntrait CustomerOrderRepo {\n def delete: DeleteBuilder[CustomerOrderFields, CustomerOrderRow]\n\n def deleteById(id: CustomerOrderId)(using c: Connection): Boolean\n\n def deleteByIds(ids: Array[CustomerOrderId])(using c: Connection): Int\n\n def insert(unsaved: CustomerOrderRow)(using c: Connection): CustomerOrderRow\n\n def insert(unsaved: CustomerOrderRowUnsaved)(using c: Connection): CustomerOrderRow\n\n def select: SelectBuilder[CustomerOrderFields, CustomerOrderRow]\n\n def selectAll(using c: Connection): List[CustomerOrderRow]\n\n def selectById(id: CustomerOrderId)(using c: Connection): Option[CustomerOrderRow]\n\n def selectByIds(ids: Array[CustomerOrderId])(using c: Connection): List[CustomerOrderRow]\n\n def selectByIdsTracked(ids: Array[CustomerOrderId])(using c: Connection): Map[CustomerOrderId, CustomerOrderRow]\n\n def update: UpdateBuilder[CustomerOrderFields, CustomerOrderRow]\n\n def update(row: CustomerOrderRow)(using c: Connection): Boolean\n\n def upsert(unsaved: CustomerOrderRow)(using c: Connection): CustomerOrderRow\n\n def upsertBatch(unsaved: Iterator[CustomerOrderRow])(using c: Connection): List[CustomerOrderRow]\n}", - "OrderItemRow": "package showcase.showcase.order_item\n\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.customer_order.CustomerOrderId\nimport showcase.showcase.product.ProductId\n\n/** Table: showcase.order_item\n * Composite primary key: order_id, product_id\n */\ncase class OrderItemRow(\n /** Points to [[showcase.showcase.customer_order.CustomerOrderRow.id]] */\n orderId: CustomerOrderId,\n /** Points to [[showcase.showcase.product.ProductRow.id]] */\n productId: ProductId,\n quantity: Int,\n unitPrice: BigDecimal,\n /** Default: 0 */\n discount: Option[BigDecimal]\n) {\n def compositeId: OrderItemId = new OrderItemId(orderId, productId)\n\n def id: OrderItemId = this.compositeId\n\n def toUnsavedRow(discount: Defaulted[Option[BigDecimal]] = Defaulted.Provided(this.discount)): OrderItemRowUnsaved = {\n new OrderItemRowUnsaved(\n orderId,\n productId,\n quantity,\n unitPrice,\n discount\n )\n }\n}\n\nobject OrderItemRow {\n val `_rowParser`: RowParser[OrderItemRow] = RowParsers.of(CustomerOrderId.pgType, ProductId.pgType, ScalaDbTypes.MariaTypes.int_, ScalaDbTypes.MariaTypes.numeric, ScalaDbTypes.MariaTypes.numeric.nullable)(OrderItemRow.apply)(row => Array[Any](row.orderId, row.productId, row.quantity, row.unitPrice, row.discount))\n\n def apply(\n compositeId: OrderItemId,\n quantity: Int,\n unitPrice: BigDecimal,\n discount: Option[BigDecimal]\n ): OrderItemRow = {\n new OrderItemRow(\n compositeId.orderId,\n compositeId.productId,\n quantity,\n unitPrice,\n discount\n )\n }\n}", - "OrderItemId": "package showcase.showcase.order_item\n\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport showcase.showcase.customer_order.CustomerOrderId\nimport showcase.showcase.product.ProductId\n\n/** Type for the composite primary key of table `showcase.order_item` */\ncase class OrderItemId(\n orderId: CustomerOrderId,\n productId: ProductId\n)\n\nobject OrderItemId {\n val `_rowParser`: RowParser[OrderItemId] = RowParsers.of(CustomerOrderId.pgType, ProductId.pgType)(OrderItemId.apply)(row => Array[Any](row.orderId, row.productId))\n}", - "ProductRow": "package showcase.showcase.product\n\nimport dev.typr.foundations.MariaTypes\nimport dev.typr.foundations.data.Json\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport java.time.LocalDateTime\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.category.CategoryId\n\n/** Table: showcase.product\n * Primary key: id\n */\ncase class ProductRow(\n id: ProductId,\n /** Points to [[showcase.showcase.category.CategoryRow.id]] */\n categoryId: Option[CategoryId],\n name: String,\n sku: String,\n price: BigDecimal,\n cost: Option[BigDecimal],\n /** Default: true */\n inStock: Option[Boolean],\n /** Default: 0 */\n quantity: Option[Int],\n weight: Option[BigDecimal],\n /** Default: CURRENT_TIMESTAMP */\n createdAt: Option[LocalDateTime],\n attributes: Option[Json],\n specifications: Option[Json],\n seoMetadata: Option[Json],\n descriptionLong: Option[String],\n thumbnail: Option[Array[Byte]]\n) {\n def toUnsavedRow(\n inStock: Defaulted[Option[Boolean]] = Defaulted.Provided(this.inStock),\n quantity: Defaulted[Option[Int]] = Defaulted.Provided(this.quantity),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.Provided(this.createdAt)\n ): ProductRowUnsaved = {\n new ProductRowUnsaved(\n id,\n categoryId,\n name,\n sku,\n price,\n cost,\n weight,\n attributes,\n specifications,\n seoMetadata,\n descriptionLong,\n thumbnail,\n inStock,\n quantity,\n createdAt\n )\n }\n}\n\nobject ProductRow {\n val `_rowParser`: RowParser[ProductRow] = RowParsers.of(ProductId.pgType, CategoryId.pgType.nullable, MariaTypes.varchar, MariaTypes.varchar, ScalaDbTypes.MariaTypes.numeric, ScalaDbTypes.MariaTypes.numeric.nullable, ScalaDbTypes.MariaTypes.bool.nullable, ScalaDbTypes.MariaTypes.int_.nullable, ScalaDbTypes.MariaTypes.numeric.nullable, MariaTypes.timestamp.nullable, MariaTypes.json.nullable, MariaTypes.json.nullable, MariaTypes.json.nullable, MariaTypes.longtext.nullable, MariaTypes.mediumblob.nullable)(ProductRow.apply)(row => Array[Any](row.id, row.categoryId, row.name, row.sku, row.price, row.cost, row.inStock, row.quantity, row.weight, row.createdAt, row.attributes, row.specifications, row.seoMetadata, row.descriptionLong, row.thumbnail))\n}", - "ProductId": "package showcase.showcase.product\n\nimport dev.typr.foundations.MariaType\nimport dev.typr.foundations.MariaTypes\nimport dev.typr.foundations.scala.Bijection\n\n/** Type for the primary key of table `showcase.product` */\ncase class ProductId(value: String) extends scala.AnyVal\n\nobject ProductId {\n given bijection: Bijection[ProductId, String] = Bijection.apply[ProductId, String](_.value)(ProductId.apply)\n\n given pgType: MariaType[ProductId] = MariaTypes.varchar.bimap(ProductId.apply, _.value)\n}", - "CategoryRow": "package showcase.showcase.category\n\nimport dev.typr.foundations.MariaTypes\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\n\n/** Table: showcase.category\n * Primary key: id\n */\ncase class CategoryRow(\n id: CategoryId,\n /** Points to [[showcase.showcase.category.CategoryRow.id]] */\n parentId: Option[CategoryId],\n name: String,\n description: Option[String]\n)\n\nobject CategoryRow {\n val `_rowParser`: RowParser[CategoryRow] = RowParsers.of(CategoryId.pgType, CategoryId.pgType.nullable, MariaTypes.varchar, MariaTypes.varchar.nullable)(CategoryRow.apply)(row => Array[Any](row.id, row.parentId, row.name, row.description))\n}", - "CategoryId": "package showcase.showcase.category\n\nimport dev.typr.foundations.MariaType\nimport dev.typr.foundations.MariaTypes\nimport dev.typr.foundations.scala.Bijection\n\n/** Type for the primary key of table `showcase.category` */\ncase class CategoryId(value: String) extends scala.AnyVal\n\nobject CategoryId {\n given bijection: Bijection[CategoryId, String] = Bijection.apply[CategoryId, String](_.value)(CategoryId.apply)\n\n given pgType: MariaType[CategoryId] = MariaTypes.varchar.bimap(CategoryId.apply, _.value)\n}", - "AddressRow": "package showcase.showcase.address\n\nimport dev.typr.foundations.MariaTypes\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport org.mariadb.jdbc.`type`.Point\nimport org.mariadb.jdbc.`type`.Polygon\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.customer.CustomerId\n\n/** Table: showcase.address\n * Primary key: id\n */\ncase class AddressRow(\n id: AddressId,\n /** Points to [[showcase.showcase.customer.CustomerRow.id]] */\n customerId: CustomerId,\n addressType: String,\n street: String,\n city: String,\n state: Option[String],\n postalCode: Option[String],\n country: String,\n /** Default: false */\n isDefault: Option[Boolean],\n location: Option[Point],\n deliveryZone: Option[Polygon]\n) {\n def toUnsavedRow(isDefault: Defaulted[Option[Boolean]] = Defaulted.Provided(this.isDefault)): AddressRowUnsaved = {\n new AddressRowUnsaved(\n id,\n customerId,\n addressType,\n street,\n city,\n state,\n postalCode,\n country,\n location,\n deliveryZone,\n isDefault\n )\n }\n}\n\nobject AddressRow {\n val `_rowParser`: RowParser[AddressRow] = RowParsers.of(AddressId.pgType, CustomerId.pgType, MariaTypes.varchar, MariaTypes.varchar, MariaTypes.varchar, MariaTypes.varchar.nullable, MariaTypes.varchar.nullable, MariaTypes.varchar, ScalaDbTypes.MariaTypes.bool.nullable, MariaTypes.point.nullable, MariaTypes.polygon.nullable)(AddressRow.apply)(row => Array[Any](row.id, row.customerId, row.addressType, row.street, row.city, row.state, row.postalCode, row.country, row.isDefault, row.location, row.deliveryZone))\n}", - "AddressId": "package showcase.showcase.address\n\nimport dev.typr.foundations.MariaType\nimport dev.typr.foundations.MariaTypes\nimport dev.typr.foundations.scala.Bijection\n\n/** Type for the primary key of table `showcase.address` */\ncase class AddressId(value: String) extends scala.AnyVal\n\nobject AddressId {\n given bijection: Bijection[AddressId, String] = Bijection.apply[AddressId, String](_.value)(AddressId.apply)\n\n given pgType: MariaType[AddressId] = MariaTypes.varchar.bimap(AddressId.apply, _.value)\n}", - "Defaulted": "package showcase.customtypes\n\n\n\n/** This signals a value where if you don't provide it, postgres will generate it for you */\nsealed trait Defaulted[T] {\n def fold[U](\n onDefault: => U,\n onProvided: T => U\n ): U\n\n def getOrElse(onDefault: => T): T\n\n def visit(\n onDefault: => Unit,\n onProvided: T => Unit\n ): Unit\n}\n\nobject Defaulted {\n case class Provided[T](value: T) extends Defaulted[T] {\n override def fold[U](\n onDefault: => U,\n onProvided: T => U\n ): U = onProvided(value)\n\n override def getOrElse(onDefault: => T): T = value\n\n override def visit(\n onDefault: => Unit,\n onProvided: T => Unit\n ): Unit = onProvided(value)\n }\n\n case class UseDefault[T]() extends Defaulted[T] {\n override def fold[U](\n onDefault: => U,\n onProvided: T => U\n ): U = onDefault\n\n override def getOrElse(onDefault: => T): T = onDefault\n\n override def visit(\n onDefault: => Unit,\n onProvided: T => Unit\n ): Unit = onDefault\n }\n}", - "TestInsert": "package showcase\n\nimport dev.typr.foundations.data.Json\nimport dev.typr.foundations.data.maria.Inet4\nimport dev.typr.foundations.data.maria.MariaSet\nimport java.sql.Connection\nimport java.time.LocalDate\nimport java.time.LocalDateTime\nimport org.mariadb.jdbc.`type`.Point\nimport org.mariadb.jdbc.`type`.Polygon\nimport scala.util.Random\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.address.AddressId\nimport showcase.showcase.address.AddressRepoImpl\nimport showcase.showcase.address.AddressRow\nimport showcase.showcase.address.AddressRowUnsaved\nimport showcase.showcase.audit_log.AuditLogId\nimport showcase.showcase.audit_log.AuditLogRepoImpl\nimport showcase.showcase.audit_log.AuditLogRow\nimport showcase.showcase.audit_log.AuditLogRowUnsaved\nimport showcase.showcase.category.CategoryId\nimport showcase.showcase.category.CategoryRepoImpl\nimport showcase.showcase.category.CategoryRow\nimport showcase.showcase.company.CompanyId\nimport showcase.showcase.company.CompanyRepoImpl\nimport showcase.showcase.company.CompanyRow\nimport showcase.showcase.company.CompanyRowUnsaved\nimport showcase.showcase.customer.CustomerId\nimport showcase.showcase.customer.CustomerRepoImpl\nimport showcase.showcase.customer.CustomerRow\nimport showcase.showcase.customer.CustomerRowUnsaved\nimport showcase.showcase.customer_order.CustomerOrderId\nimport showcase.showcase.customer_order.CustomerOrderRepoImpl\nimport showcase.showcase.customer_order.CustomerOrderRow\nimport showcase.showcase.customer_order.CustomerOrderRowUnsaved\nimport showcase.showcase.department.DepartmentId\nimport showcase.showcase.department.DepartmentRepoImpl\nimport showcase.showcase.department.DepartmentRow\nimport showcase.showcase.employee.EmployeeId\nimport showcase.showcase.employee.EmployeeRepoImpl\nimport showcase.showcase.employee.EmployeeRow\nimport showcase.showcase.employee.EmployeeRowUnsaved\nimport showcase.showcase.order_item.OrderItemRepoImpl\nimport showcase.showcase.order_item.OrderItemRow\nimport showcase.showcase.order_item.OrderItemRowUnsaved\nimport showcase.showcase.product.ProductId\nimport showcase.showcase.product.ProductRepoImpl\nimport showcase.showcase.product.ProductRow\nimport showcase.showcase.product.ProductRowUnsaved\nimport showcase.showcase.project.ProjectId\nimport showcase.showcase.project.ProjectRepoImpl\nimport showcase.showcase.project.ProjectRow\nimport showcase.showcase.project.ProjectRowUnsaved\nimport showcase.showcase.project_assignment.ProjectAssignmentRepoImpl\nimport showcase.showcase.project_assignment.ProjectAssignmentRow\nimport showcase.showcase.project_assignment.ProjectAssignmentRowUnsaved\n\n/** Methods to generate random data for `Ident(TestInsert)` */\ncase class TestInsert(random: Random) {\n def showcaseAddress(\n customerId: CustomerId,\n id: AddressId = AddressId(random.alphanumeric.take(20).mkString),\n addressType: String = random.alphanumeric.take(20).mkString,\n street: String = random.alphanumeric.take(20).mkString,\n city: String = random.alphanumeric.take(20).mkString,\n state: Option[String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n postalCode: Option[String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n country: String = random.alphanumeric.take(20).mkString,\n location: Option[Point] = None,\n deliveryZone: Option[Polygon] = None,\n isDefault: Defaulted[Option[Boolean]] = Defaulted.UseDefault()\n )(using c: Connection): AddressRow = {\n (new AddressRepoImpl()).insert(new AddressRowUnsaved(\n id = id,\n customerId = customerId,\n addressType = addressType,\n street = street,\n city = city,\n state = state,\n postalCode = postalCode,\n country = country,\n location = location,\n deliveryZone = deliveryZone,\n isDefault = isDefault\n ))(using c)\n }\n\n def showcaseAuditLog(\n id: AuditLogId = AuditLogId(random.alphanumeric.take(20).mkString),\n tableName: String = random.alphanumeric.take(20).mkString,\n recordId: String = random.alphanumeric.take(20).mkString,\n action: String = random.alphanumeric.take(20).mkString,\n oldValues: Option[String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n newValues: Option[String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n changedBy: Option[EmployeeId] = None,\n changedAt: Defaulted[Option[LocalDateTime]] = Defaulted.UseDefault()\n )(using c: Connection): AuditLogRow = {\n (new AuditLogRepoImpl()).insert(new AuditLogRowUnsaved(\n id = id,\n tableName = tableName,\n recordId = recordId,\n action = action,\n oldValues = oldValues,\n newValues = newValues,\n changedBy = changedBy,\n changedAt = changedAt\n ))(using c)\n }\n\n def showcaseCategory(\n id: CategoryId = CategoryId(random.alphanumeric.take(20).mkString),\n parentId: Option[CategoryId] = None,\n name: String = random.alphanumeric.take(20).mkString,\n description: Option[String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString)\n )(using c: Connection): CategoryRow = {\n (new CategoryRepoImpl()).insert(new CategoryRow(\n id = id,\n parentId = parentId,\n name = name,\n description = description\n ))(using c)\n }\n\n def showcaseCompany(\n id: CompanyId = CompanyId(random.alphanumeric.take(20).mkString),\n name: String = random.alphanumeric.take(20).mkString,\n foundedYear: Option[Int] = if (random.nextBoolean()) None else Some(random.nextInt()),\n active: Defaulted[Option[Boolean]] = Defaulted.UseDefault(),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.UseDefault()\n )(using c: Connection): CompanyRow = {\n (new CompanyRepoImpl()).insert(new CompanyRowUnsaved(\n id = id,\n name = name,\n foundedYear = foundedYear,\n active = active,\n createdAt = createdAt\n ))(using c)\n }\n\n def showcaseCustomer(\n id: CustomerId = CustomerId(random.alphanumeric.take(20).mkString),\n email: String = random.alphanumeric.take(20).mkString,\n firstName: String = random.alphanumeric.take(20).mkString,\n lastName: String = random.alphanumeric.take(20).mkString,\n phone: Option[String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n preferences: Option[Json] = None,\n avatar: Option[Array[Byte]] = None,\n customerType: Option[String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n verified: Defaulted[Option[Boolean]] = Defaulted.UseDefault(),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.UseDefault()\n )(using c: Connection): CustomerRow = {\n (new CustomerRepoImpl()).insert(new CustomerRowUnsaved(\n id = id,\n email = email,\n firstName = firstName,\n lastName = lastName,\n phone = phone,\n preferences = preferences,\n avatar = avatar,\n customerType = customerType,\n verified = verified,\n createdAt = createdAt\n ))(using c)\n }\n\n def showcaseCustomerOrder(\n customerId: CustomerId,\n id: CustomerOrderId = CustomerOrderId(random.alphanumeric.take(20).mkString),\n shippingAddressId: Option[AddressId] = None,\n billingAddressId: Option[AddressId] = None,\n subtotal: BigDecimal = BigDecimal.decimal(random.nextDouble()),\n total: BigDecimal = BigDecimal.decimal(random.nextDouble()),\n notes: Option[String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n shippedAt: Option[LocalDateTime] = None,\n deliveredAt: Option[LocalDateTime] = None,\n metadata: Option[Json] = None,\n ipAddress: Option[Inet4] = None,\n paymentMethod: Option[String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n status: Defaulted[Option[String]] = Defaulted.UseDefault(),\n tax: Defaulted[Option[BigDecimal]] = Defaulted.UseDefault(),\n shipping: Defaulted[Option[BigDecimal]] = Defaulted.UseDefault(),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.UseDefault()\n )(using c: Connection): CustomerOrderRow = {\n (new CustomerOrderRepoImpl()).insert(new CustomerOrderRowUnsaved(\n id = id,\n customerId = customerId,\n shippingAddressId = shippingAddressId,\n billingAddressId = billingAddressId,\n subtotal = subtotal,\n total = total,\n notes = notes,\n shippedAt = shippedAt,\n deliveredAt = deliveredAt,\n metadata = metadata,\n ipAddress = ipAddress,\n paymentMethod = paymentMethod,\n status = status,\n tax = tax,\n shipping = shipping,\n createdAt = createdAt\n ))(using c)\n }\n\n def showcaseDepartment(\n companyId: CompanyId,\n id: DepartmentId = DepartmentId(random.alphanumeric.take(20).mkString),\n name: String = random.alphanumeric.take(20).mkString,\n budget: Option[BigDecimal] = if (random.nextBoolean()) None else Some(BigDecimal.decimal(random.nextDouble()))\n )(using c: Connection): DepartmentRow = {\n (new DepartmentRepoImpl()).insert(new DepartmentRow(\n id = id,\n companyId = companyId,\n name = name,\n budget = budget\n ))(using c)\n }\n\n def showcaseEmployee(\n departmentId: DepartmentId,\n id: EmployeeId = EmployeeId(random.alphanumeric.take(20).mkString),\n managerId: Option[EmployeeId] = None,\n email: String = random.alphanumeric.take(20).mkString,\n firstName: String = random.alphanumeric.take(20).mkString,\n lastName: String = random.alphanumeric.take(20).mkString,\n salary: Option[BigDecimal] = if (random.nextBoolean()) None else Some(BigDecimal.decimal(random.nextDouble())),\n hiredAt: Option[LocalDate] = None,\n metadata: Option[Json] = None,\n photo: Option[Array[Byte]] = None,\n ipAddress: Option[Inet4] = None,\n permissions: Option[MariaSet] = None,\n active: Defaulted[Option[Boolean]] = Defaulted.UseDefault(),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.UseDefault()\n )(using c: Connection): EmployeeRow = {\n (new EmployeeRepoImpl()).insert(new EmployeeRowUnsaved(\n id = id,\n departmentId = departmentId,\n managerId = managerId,\n email = email,\n firstName = firstName,\n lastName = lastName,\n salary = salary,\n hiredAt = hiredAt,\n metadata = metadata,\n photo = photo,\n ipAddress = ipAddress,\n permissions = permissions,\n active = active,\n createdAt = createdAt\n ))(using c)\n }\n\n def showcaseOrderItem(\n orderId: CustomerOrderId,\n productId: ProductId,\n quantity: Int = random.nextInt(),\n unitPrice: BigDecimal = BigDecimal.decimal(random.nextDouble()),\n discount: Defaulted[Option[BigDecimal]] = Defaulted.UseDefault()\n )(using c: Connection): OrderItemRow = {\n (new OrderItemRepoImpl()).insert(new OrderItemRowUnsaved(\n orderId = orderId,\n productId = productId,\n quantity = quantity,\n unitPrice = unitPrice,\n discount = discount\n ))(using c)\n }\n\n def showcaseProduct(\n id: ProductId = ProductId(random.alphanumeric.take(20).mkString),\n categoryId: Option[CategoryId] = None,\n name: String = random.alphanumeric.take(20).mkString,\n sku: String = random.alphanumeric.take(20).mkString,\n price: BigDecimal = BigDecimal.decimal(random.nextDouble()),\n cost: Option[BigDecimal] = if (random.nextBoolean()) None else Some(BigDecimal.decimal(random.nextDouble())),\n weight: Option[BigDecimal] = if (random.nextBoolean()) None else Some(BigDecimal.decimal(random.nextDouble())),\n attributes: Option[Json] = None,\n specifications: Option[Json] = None,\n seoMetadata: Option[Json] = None,\n descriptionLong: Option[String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n thumbnail: Option[Array[Byte]] = None,\n inStock: Defaulted[Option[Boolean]] = Defaulted.UseDefault(),\n quantity: Defaulted[Option[Int]] = Defaulted.UseDefault(),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.UseDefault()\n )(using c: Connection): ProductRow = {\n (new ProductRepoImpl()).insert(new ProductRowUnsaved(\n id = id,\n categoryId = categoryId,\n name = name,\n sku = sku,\n price = price,\n cost = cost,\n weight = weight,\n attributes = attributes,\n specifications = specifications,\n seoMetadata = seoMetadata,\n descriptionLong = descriptionLong,\n thumbnail = thumbnail,\n inStock = inStock,\n quantity = quantity,\n createdAt = createdAt\n ))(using c)\n }\n\n def showcaseProject(\n id: ProjectId = ProjectId(random.alphanumeric.take(20).mkString),\n name: String = random.alphanumeric.take(20).mkString,\n description: Option[String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n startDate: Option[LocalDate] = None,\n endDate: Option[LocalDate] = None,\n budget: Option[BigDecimal] = if (random.nextBoolean()) None else Some(BigDecimal.decimal(random.nextDouble())),\n metadata: Option[Json] = None,\n descriptionLong: Option[String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n attachments: Option[Array[Byte]] = None,\n priority: Option[String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n status: Defaulted[Option[String]] = Defaulted.UseDefault(),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.UseDefault()\n )(using c: Connection): ProjectRow = {\n (new ProjectRepoImpl()).insert(new ProjectRowUnsaved(\n id = id,\n name = name,\n description = description,\n startDate = startDate,\n endDate = endDate,\n budget = budget,\n metadata = metadata,\n descriptionLong = descriptionLong,\n attachments = attachments,\n priority = priority,\n status = status,\n createdAt = createdAt\n ))(using c)\n }\n\n def showcaseProjectAssignment(\n employeeId: EmployeeId,\n projectId: ProjectId,\n role: String = random.alphanumeric.take(20).mkString,\n startDate: Option[LocalDate] = None,\n endDate: Option[LocalDate] = None,\n hoursAllocated: Defaulted[Option[Int]] = Defaulted.UseDefault()\n )(using c: Connection): ProjectAssignmentRow = {\n (new ProjectAssignmentRepoImpl()).insert(new ProjectAssignmentRowUnsaved(\n employeeId = employeeId,\n projectId = projectId,\n role = role,\n startDate = startDate,\n endDate = endDate,\n hoursAllocated = hoursAllocated\n ))(using c)\n }\n}" - } - }, - "duckdb": { - "java": { - "CompanyRow": "package showcase.showcase.company;\n\nimport dev.typr.foundations.DuckDbTypes;\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport java.time.LocalDateTime;\nimport java.util.Optional;\nimport showcase.customtypes.Defaulted;\n\n/** Table: showcase.company\n * Primary key: id\n */\npublic record CompanyRow(\n CompanyId id,\n String name,\n Optional foundedYear,\n /** Default: true */\n Optional active,\n /** Default: CURRENT_TIMESTAMP */\n Optional createdAt\n) {\n public CompanyRow withId(CompanyId id) {\n return new CompanyRow(id, name, foundedYear, active, createdAt);\n };\n\n public CompanyRow withName(String name) {\n return new CompanyRow(id, name, foundedYear, active, createdAt);\n };\n\n public CompanyRow withFoundedYear(Optional foundedYear) {\n return new CompanyRow(id, name, foundedYear, active, createdAt);\n };\n\n /** Default: true */\n public CompanyRow withActive(Optional active) {\n return new CompanyRow(id, name, foundedYear, active, createdAt);\n };\n\n /** Default: CURRENT_TIMESTAMP */\n public CompanyRow withCreatedAt(Optional createdAt) {\n return new CompanyRow(id, name, foundedYear, active, createdAt);\n };\n\n public static RowParser _rowParser = RowParsers.of(CompanyId.duckDbType, DuckDbTypes.varchar, DuckDbTypes.integer.opt(), DuckDbTypes.boolean_.opt(), DuckDbTypes.timestamp.opt(), CompanyRow::new, row -> new Object[]{row.id(), row.name(), row.foundedYear(), row.active(), row.createdAt()});;\n\n public CompanyRowUnsaved toUnsavedRow(\n Defaulted> active,\n Defaulted> createdAt\n ) {\n return new CompanyRowUnsaved(id, name, foundedYear, active, createdAt);\n };\n}", - "CompanyRowUnsaved": "package showcase.showcase.company;\n\nimport java.time.LocalDateTime;\nimport java.util.Optional;\nimport showcase.customtypes.Defaulted;\nimport showcase.customtypes.Defaulted.UseDefault;\n\n/** This class corresponds to a row in table `showcase.company` which has not been persisted yet */\npublic record CompanyRowUnsaved(\n CompanyId id,\n String name,\n Optional foundedYear,\n /** Default: true */\n Defaulted> active,\n /** Default: CURRENT_TIMESTAMP */\n Defaulted> createdAt\n) {\n public CompanyRowUnsaved(\n CompanyId id,\n String name\n ) {\n this(id, name, Optional.empty(), new UseDefault<>(), new UseDefault<>());\n };\n\n public CompanyRowUnsaved withId(CompanyId id) {\n return new CompanyRowUnsaved(id, name, foundedYear, active, createdAt);\n };\n\n public CompanyRowUnsaved withName(String name) {\n return new CompanyRowUnsaved(id, name, foundedYear, active, createdAt);\n };\n\n public CompanyRowUnsaved withFoundedYear(Optional foundedYear) {\n return new CompanyRowUnsaved(id, name, foundedYear, active, createdAt);\n };\n\n /** Default: true */\n public CompanyRowUnsaved withActive(Defaulted> active) {\n return new CompanyRowUnsaved(id, name, foundedYear, active, createdAt);\n };\n\n /** Default: CURRENT_TIMESTAMP */\n public CompanyRowUnsaved withCreatedAt(Defaulted> createdAt) {\n return new CompanyRowUnsaved(id, name, foundedYear, active, createdAt);\n };\n\n public CompanyRow toRow(\n java.util.function.Supplier> activeDefault,\n java.util.function.Supplier> createdAtDefault\n ) {\n return new CompanyRow(id, name, foundedYear, active.getOrElse(activeDefault), createdAt.getOrElse(createdAtDefault));\n };\n}", - "CompanyId": "package showcase.showcase.company;\n\nimport dev.typr.foundations.DuckDbType;\nimport dev.typr.foundations.DuckDbTypes;\nimport dev.typr.foundations.dsl.Bijection;\nimport dev.typr.foundations.internal.arrayMap;\n\n/** Type for the primary key of table `showcase.company` */\npublic record CompanyId(String value) {\n public CompanyId withValue(String value) {\n return new CompanyId(value);\n };\n\n @Override\n public java.lang.String toString() {\n return value.toString();\n };\n\n static public Bijection bijection =\n Bijection.of(CompanyId::value, CompanyId::new);\n\n static public DuckDbType duckDbType =\n DuckDbTypes.varchar.bimap(CompanyId::new, CompanyId::value);\n\n static public DuckDbType pgTypeArray =\n DuckDbTypes.varcharArray.bimap(xs -> arrayMap.map(xs, CompanyId::new, CompanyId.class), xs -> arrayMap.map(xs, CompanyId::value, String.class));\n}", - "CompanyRepo": "package showcase.showcase.company;\n\nimport dev.typr.foundations.dsl.DeleteBuilder;\nimport dev.typr.foundations.dsl.SelectBuilder;\nimport dev.typr.foundations.dsl.UpdateBuilder;\nimport java.sql.Connection;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\n\npublic interface CompanyRepo {\n DeleteBuilder delete();\n\n Boolean deleteById(\n CompanyId id,\n Connection c\n );\n\n Integer deleteByIds(\n CompanyId[] ids,\n Connection c\n );\n\n CompanyRow insert(\n CompanyRow unsaved,\n Connection c\n );\n\n CompanyRow insert(\n CompanyRowUnsaved unsaved,\n Connection c\n );\n\n SelectBuilder select();\n\n List selectAll(Connection c);\n\n Optional selectById(\n CompanyId id,\n Connection c\n );\n\n List selectByIds(\n CompanyId[] ids,\n Connection c\n );\n\n Map selectByIdsTracked(\n CompanyId[] ids,\n Connection c\n );\n\n UpdateBuilder update();\n\n Boolean update(\n CompanyRow row,\n Connection c\n );\n\n CompanyRow upsert(\n CompanyRow unsaved,\n Connection c\n );\n\n List upsertBatch(\n Iterator unsaved,\n Connection c\n );\n}", - "CompanyRepoMock": "package showcase.showcase.company;\n\nimport dev.typr.foundations.dsl.DeleteBuilder;\nimport dev.typr.foundations.dsl.DeleteBuilderMock;\nimport dev.typr.foundations.dsl.DeleteParams;\nimport dev.typr.foundations.dsl.SelectBuilder;\nimport dev.typr.foundations.dsl.SelectBuilderMock;\nimport dev.typr.foundations.dsl.SelectParams;\nimport dev.typr.foundations.dsl.UpdateBuilder;\nimport dev.typr.foundations.dsl.UpdateBuilderMock;\nimport dev.typr.foundations.dsl.UpdateParams;\nimport java.lang.RuntimeException;\nimport java.sql.Connection;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\nimport java.util.function.Function;\nimport java.util.stream.Collectors;\n\npublic record CompanyRepoMock(\n java.util.function.Function toRow,\n HashMap map\n) implements CompanyRepo {\n public CompanyRepoMock(java.util.function.Function toRow) {\n this(toRow, new HashMap());\n };\n\n public CompanyRepoMock withToRow(java.util.function.Function toRow) {\n return new CompanyRepoMock(toRow, map);\n };\n\n public CompanyRepoMock withMap(HashMap map) {\n return new CompanyRepoMock(toRow, map);\n };\n\n @Override\n public DeleteBuilder delete() {\n return new DeleteBuilderMock<>(CompanyFields.structure(), () -> new ArrayList<>(map.values()), DeleteParams.empty(), row -> row.id(), id -> map.remove(id));\n };\n\n @Override\n public Boolean deleteById(\n CompanyId id,\n Connection c\n ) {\n return Optional.ofNullable(map.remove(id)).isPresent();\n };\n\n @Override\n public Integer deleteByIds(\n CompanyId[] ids,\n Connection c\n ) {\n var count = 0;\n for (var id : ids) {\n if (Optional.ofNullable(map.remove(id)).isPresent()) {\n count = count + 1;;\n };\n };\n return count;\n };\n\n @Override\n public CompanyRow insert(\n CompanyRow unsaved,\n Connection c\n ) {\n if (map.containsKey(unsaved.id())) {\n throw new RuntimeException(\"id \" + unsaved.id() + \" already exists\");\n };\n map.put(unsaved.id(), unsaved);\n return unsaved;\n };\n\n @Override\n public CompanyRow insert(\n CompanyRowUnsaved unsaved,\n Connection c\n ) {\n return insert(toRow.apply(unsaved), c);\n };\n\n @Override\n public SelectBuilder select() {\n return new SelectBuilderMock<>(CompanyFields.structure(), () -> new ArrayList<>(map.values()), SelectParams.empty());\n };\n\n @Override\n public List selectAll(Connection c) {\n return new ArrayList<>(map.values());\n };\n\n @Override\n public Optional selectById(\n CompanyId id,\n Connection c\n ) {\n return Optional.ofNullable(map.get(id));\n };\n\n @Override\n public List selectByIds(\n CompanyId[] ids,\n Connection c\n ) {\n var result = new ArrayList();\n for (var id : ids) {\n var opt = Optional.ofNullable(map.get(id));\n if (opt.isPresent()) {\n result.add(opt.get());\n };\n };\n return result;\n };\n\n @Override\n public Map selectByIdsTracked(\n CompanyId[] ids,\n Connection c\n ) {\n return selectByIds(ids, c).stream().collect(Collectors.toMap((CompanyRow row) -> row.id(), Function.identity()));\n };\n\n @Override\n public UpdateBuilder update() {\n return new UpdateBuilderMock<>(CompanyFields.structure(), () -> new ArrayList<>(map.values()), UpdateParams.empty(), row -> row);\n };\n\n @Override\n public Boolean update(\n CompanyRow row,\n Connection c\n ) {\n var shouldUpdate = Optional.ofNullable(map.get(row.id())).filter(oldRow -> !oldRow.equals(row)).isPresent();\n if (shouldUpdate) {\n map.put(row.id(), row);;\n };\n return shouldUpdate;\n };\n\n @Override\n public CompanyRow upsert(\n CompanyRow unsaved,\n Connection c\n ) {\n map.put(unsaved.id(), unsaved);\n return unsaved;\n };\n\n @Override\n public List upsertBatch(\n Iterator unsaved,\n Connection c\n ) {\n var result = new ArrayList();\n while (unsaved.hasNext()) {\n var row = unsaved.next();\n map.put(row.id(), row);\n result.add(row);\n };\n return result;\n };\n}", - "EmployeeRow": "package showcase.showcase.employee;\n\nimport dev.typr.foundations.DuckDbTypes;\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport java.math.BigDecimal;\nimport java.time.Duration;\nimport java.time.LocalDate;\nimport java.time.LocalDateTime;\nimport java.util.Optional;\nimport showcase.EmployeeContactInfo;\nimport showcase.customtypes.Defaulted;\nimport showcase.showcase.department.DepartmentId;\n\n/** Table: showcase.employee\n * Primary key: id\n */\npublic record EmployeeRow(\n EmployeeId id,\n /** Points to {@link showcase.showcase.department.DepartmentRow#id()} */\n DepartmentId departmentId,\n /** Points to {@link showcase.showcase.employee.EmployeeRow#id()} */\n Optional managerId,\n String email,\n String firstName,\n String lastName,\n Optional salary,\n Optional hiredAt,\n /** Default: true */\n Optional active,\n /** Default: CURRENT_TIMESTAMP */\n Optional createdAt,\n Optional skills,\n Optional certifications,\n Optional weeklyAvailability,\n Optional contactInfo,\n Optional settings,\n Optional skillsRating,\n Optional probationPeriod\n) {\n public EmployeeRow withId(EmployeeId id) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, skills, certifications, weeklyAvailability, contactInfo, settings, skillsRating, probationPeriod);\n };\n\n /** Points to {@link showcase.showcase.department.DepartmentRow#id()} */\n public EmployeeRow withDepartmentId(DepartmentId departmentId) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, skills, certifications, weeklyAvailability, contactInfo, settings, skillsRating, probationPeriod);\n };\n\n /** Points to {@link showcase.showcase.employee.EmployeeRow#id()} */\n public EmployeeRow withManagerId(Optional managerId) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, skills, certifications, weeklyAvailability, contactInfo, settings, skillsRating, probationPeriod);\n };\n\n public EmployeeRow withEmail(String email) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, skills, certifications, weeklyAvailability, contactInfo, settings, skillsRating, probationPeriod);\n };\n\n public EmployeeRow withFirstName(String firstName) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, skills, certifications, weeklyAvailability, contactInfo, settings, skillsRating, probationPeriod);\n };\n\n public EmployeeRow withLastName(String lastName) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, skills, certifications, weeklyAvailability, contactInfo, settings, skillsRating, probationPeriod);\n };\n\n public EmployeeRow withSalary(Optional salary) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, skills, certifications, weeklyAvailability, contactInfo, settings, skillsRating, probationPeriod);\n };\n\n public EmployeeRow withHiredAt(Optional hiredAt) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, skills, certifications, weeklyAvailability, contactInfo, settings, skillsRating, probationPeriod);\n };\n\n /** Default: true */\n public EmployeeRow withActive(Optional active) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, skills, certifications, weeklyAvailability, contactInfo, settings, skillsRating, probationPeriod);\n };\n\n /** Default: CURRENT_TIMESTAMP */\n public EmployeeRow withCreatedAt(Optional createdAt) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, skills, certifications, weeklyAvailability, contactInfo, settings, skillsRating, probationPeriod);\n };\n\n public EmployeeRow withSkills(Optional skills) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, skills, certifications, weeklyAvailability, contactInfo, settings, skillsRating, probationPeriod);\n };\n\n public EmployeeRow withCertifications(Optional certifications) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, skills, certifications, weeklyAvailability, contactInfo, settings, skillsRating, probationPeriod);\n };\n\n public EmployeeRow withWeeklyAvailability(Optional weeklyAvailability) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, skills, certifications, weeklyAvailability, contactInfo, settings, skillsRating, probationPeriod);\n };\n\n public EmployeeRow withContactInfo(Optional contactInfo) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, skills, certifications, weeklyAvailability, contactInfo, settings, skillsRating, probationPeriod);\n };\n\n public EmployeeRow withSettings(Optional settings) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, skills, certifications, weeklyAvailability, contactInfo, settings, skillsRating, probationPeriod);\n };\n\n public EmployeeRow withSkillsRating(Optional skillsRating) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, skills, certifications, weeklyAvailability, contactInfo, settings, skillsRating, probationPeriod);\n };\n\n public EmployeeRow withProbationPeriod(Optional probationPeriod) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, skills, certifications, weeklyAvailability, contactInfo, settings, skillsRating, probationPeriod);\n };\n\n public static RowParser _rowParser = RowParsers.of(EmployeeId.duckDbType, DepartmentId.duckDbType, EmployeeId.duckDbType.opt(), DuckDbTypes.varchar, DuckDbTypes.varchar, DuckDbTypes.varchar, DuckDbTypes.numeric.opt(), DuckDbTypes.date.opt(), DuckDbTypes.boolean_.opt(), DuckDbTypes.timestamp.opt(), DuckDbTypes.varcharArray.opt(), DuckDbTypes.varcharArray.opt(), DuckDbTypes.booleanArray.opt(), EmployeeContactInfo.duckDbType.opt(), DuckDbTypes.varchar.mapTo(DuckDbTypes.varchar).opt(), DuckDbTypes.varchar.mapTo(DuckDbTypes.integer).opt(), DuckDbTypes.interval.opt(), EmployeeRow::new, row -> new Object[]{row.id(), row.departmentId(), row.managerId(), row.email(), row.firstName(), row.lastName(), row.salary(), row.hiredAt(), row.active(), row.createdAt(), row.skills(), row.certifications(), row.weeklyAvailability(), row.contactInfo(), row.settings(), row.skillsRating(), row.probationPeriod()});;\n\n public EmployeeRowUnsaved toUnsavedRow(\n Defaulted> active,\n Defaulted> createdAt\n ) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, skills, certifications, weeklyAvailability, contactInfo, settings, skillsRating, probationPeriod, active, createdAt);\n };\n}", - "EmployeeRowUnsaved": "package showcase.showcase.employee;\n\nimport java.math.BigDecimal;\nimport java.time.Duration;\nimport java.time.LocalDate;\nimport java.time.LocalDateTime;\nimport java.util.Optional;\nimport showcase.EmployeeContactInfo;\nimport showcase.customtypes.Defaulted;\nimport showcase.customtypes.Defaulted.UseDefault;\nimport showcase.showcase.department.DepartmentId;\n\n/** This class corresponds to a row in table `showcase.employee` which has not been persisted yet */\npublic record EmployeeRowUnsaved(\n EmployeeId id,\n /** Points to {@link showcase.showcase.department.DepartmentRow#id()} */\n DepartmentId departmentId,\n /** Points to {@link showcase.showcase.employee.EmployeeRow#id()} */\n Optional managerId,\n String email,\n String firstName,\n String lastName,\n Optional salary,\n Optional hiredAt,\n Optional skills,\n Optional certifications,\n Optional weeklyAvailability,\n Optional contactInfo,\n Optional settings,\n Optional skillsRating,\n Optional probationPeriod,\n /** Default: true */\n Defaulted> active,\n /** Default: CURRENT_TIMESTAMP */\n Defaulted> createdAt\n) {\n public EmployeeRowUnsaved(\n EmployeeId id,\n /** Points to {@link showcase.showcase.department.DepartmentRow#id()} */\n DepartmentId departmentId,\n String email,\n String firstName,\n String lastName\n ) {\n this(id, departmentId, Optional.empty(), email, firstName, lastName, Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), new UseDefault<>(), new UseDefault<>());\n };\n\n public EmployeeRowUnsaved withId(EmployeeId id) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, skills, certifications, weeklyAvailability, contactInfo, settings, skillsRating, probationPeriod, active, createdAt);\n };\n\n /** Points to {@link showcase.showcase.department.DepartmentRow#id()} */\n public EmployeeRowUnsaved withDepartmentId(DepartmentId departmentId) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, skills, certifications, weeklyAvailability, contactInfo, settings, skillsRating, probationPeriod, active, createdAt);\n };\n\n /** Points to {@link showcase.showcase.employee.EmployeeRow#id()} */\n public EmployeeRowUnsaved withManagerId(Optional managerId) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, skills, certifications, weeklyAvailability, contactInfo, settings, skillsRating, probationPeriod, active, createdAt);\n };\n\n public EmployeeRowUnsaved withEmail(String email) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, skills, certifications, weeklyAvailability, contactInfo, settings, skillsRating, probationPeriod, active, createdAt);\n };\n\n public EmployeeRowUnsaved withFirstName(String firstName) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, skills, certifications, weeklyAvailability, contactInfo, settings, skillsRating, probationPeriod, active, createdAt);\n };\n\n public EmployeeRowUnsaved withLastName(String lastName) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, skills, certifications, weeklyAvailability, contactInfo, settings, skillsRating, probationPeriod, active, createdAt);\n };\n\n public EmployeeRowUnsaved withSalary(Optional salary) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, skills, certifications, weeklyAvailability, contactInfo, settings, skillsRating, probationPeriod, active, createdAt);\n };\n\n public EmployeeRowUnsaved withHiredAt(Optional hiredAt) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, skills, certifications, weeklyAvailability, contactInfo, settings, skillsRating, probationPeriod, active, createdAt);\n };\n\n public EmployeeRowUnsaved withSkills(Optional skills) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, skills, certifications, weeklyAvailability, contactInfo, settings, skillsRating, probationPeriod, active, createdAt);\n };\n\n public EmployeeRowUnsaved withCertifications(Optional certifications) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, skills, certifications, weeklyAvailability, contactInfo, settings, skillsRating, probationPeriod, active, createdAt);\n };\n\n public EmployeeRowUnsaved withWeeklyAvailability(Optional weeklyAvailability) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, skills, certifications, weeklyAvailability, contactInfo, settings, skillsRating, probationPeriod, active, createdAt);\n };\n\n public EmployeeRowUnsaved withContactInfo(Optional contactInfo) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, skills, certifications, weeklyAvailability, contactInfo, settings, skillsRating, probationPeriod, active, createdAt);\n };\n\n public EmployeeRowUnsaved withSettings(Optional settings) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, skills, certifications, weeklyAvailability, contactInfo, settings, skillsRating, probationPeriod, active, createdAt);\n };\n\n public EmployeeRowUnsaved withSkillsRating(Optional skillsRating) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, skills, certifications, weeklyAvailability, contactInfo, settings, skillsRating, probationPeriod, active, createdAt);\n };\n\n public EmployeeRowUnsaved withProbationPeriod(Optional probationPeriod) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, skills, certifications, weeklyAvailability, contactInfo, settings, skillsRating, probationPeriod, active, createdAt);\n };\n\n /** Default: true */\n public EmployeeRowUnsaved withActive(Defaulted> active) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, skills, certifications, weeklyAvailability, contactInfo, settings, skillsRating, probationPeriod, active, createdAt);\n };\n\n /** Default: CURRENT_TIMESTAMP */\n public EmployeeRowUnsaved withCreatedAt(Defaulted> createdAt) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, skills, certifications, weeklyAvailability, contactInfo, settings, skillsRating, probationPeriod, active, createdAt);\n };\n\n public EmployeeRow toRow(\n java.util.function.Supplier> activeDefault,\n java.util.function.Supplier> createdAtDefault\n ) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active.getOrElse(activeDefault), createdAt.getOrElse(createdAtDefault), skills, certifications, weeklyAvailability, contactInfo, settings, skillsRating, probationPeriod);\n };\n}", - "EmployeeId": "package showcase.showcase.employee;\n\nimport dev.typr.foundations.DuckDbType;\nimport dev.typr.foundations.DuckDbTypes;\nimport dev.typr.foundations.dsl.Bijection;\nimport dev.typr.foundations.internal.arrayMap;\n\n/** Type for the primary key of table `showcase.employee` */\npublic record EmployeeId(String value) {\n public EmployeeId withValue(String value) {\n return new EmployeeId(value);\n };\n\n @Override\n public java.lang.String toString() {\n return value.toString();\n };\n\n static public Bijection bijection =\n Bijection.of(EmployeeId::value, EmployeeId::new);\n\n static public DuckDbType duckDbType =\n DuckDbTypes.varchar.bimap(EmployeeId::new, EmployeeId::value);\n\n static public DuckDbType pgTypeArray =\n DuckDbTypes.varcharArray.bimap(xs -> arrayMap.map(xs, EmployeeId::new, EmployeeId.class), xs -> arrayMap.map(xs, EmployeeId::value, String.class));\n}", - "EmployeeRepo": "package showcase.showcase.employee;\n\nimport dev.typr.foundations.dsl.DeleteBuilder;\nimport dev.typr.foundations.dsl.SelectBuilder;\nimport dev.typr.foundations.dsl.UpdateBuilder;\nimport java.sql.Connection;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\n\npublic interface EmployeeRepo {\n DeleteBuilder delete();\n\n Boolean deleteById(\n EmployeeId id,\n Connection c\n );\n\n Integer deleteByIds(\n EmployeeId[] ids,\n Connection c\n );\n\n EmployeeRow insert(\n EmployeeRow unsaved,\n Connection c\n );\n\n EmployeeRow insert(\n EmployeeRowUnsaved unsaved,\n Connection c\n );\n\n SelectBuilder select();\n\n List selectAll(Connection c);\n\n Optional selectById(\n EmployeeId id,\n Connection c\n );\n\n List selectByIds(\n EmployeeId[] ids,\n Connection c\n );\n\n Map selectByIdsTracked(\n EmployeeId[] ids,\n Connection c\n );\n\n Optional selectByUniqueEmail(\n String email,\n Connection c\n );\n\n UpdateBuilder update();\n\n Boolean update(\n EmployeeRow row,\n Connection c\n );\n\n EmployeeRow upsert(\n EmployeeRow unsaved,\n Connection c\n );\n\n List upsertBatch(\n Iterator unsaved,\n Connection c\n );\n}", - "EmployeeRepoImpl": "package showcase.showcase.employee;\n\nimport dev.typr.foundations.DuckDbTypes;\nimport dev.typr.foundations.Fragment;\nimport dev.typr.foundations.dsl.DeleteBuilder;\nimport dev.typr.foundations.dsl.Dialect;\nimport dev.typr.foundations.dsl.SelectBuilder;\nimport dev.typr.foundations.dsl.UpdateBuilder;\nimport java.sql.Connection;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\nimport showcase.EmployeeContactInfo;\nimport showcase.showcase.department.DepartmentId;\nimport static dev.typr.foundations.Fragment.interpolate;\n\npublic class EmployeeRepoImpl implements EmployeeRepo {\n @Override\n public DeleteBuilder delete() {\n return DeleteBuilder.of(\"\\\"showcase\\\".\\\"employee\\\"\", EmployeeFields.structure(), Dialect.DUCKDB);\n };\n\n @Override\n public Boolean deleteById(\n EmployeeId id,\n Connection c\n ) {\n return interpolate(Fragment.lit(\"delete from \\\"showcase\\\".\\\"employee\\\" where \\\"id\\\" = \"), Fragment.encode(EmployeeId.duckDbType, id), Fragment.lit(\"\")).update().runUnchecked(c) > 0;\n };\n\n @Override\n public Integer deleteByIds(\n EmployeeId[] ids,\n Connection c\n ) {\n return interpolate(Fragment.lit(\"delete\\nfrom \\\"showcase\\\".\\\"employee\\\"\\nwhere \\\"id\\\" = ANY(\"), Fragment.encode(EmployeeId.pgTypeArray, ids), Fragment.lit(\")\"))\n .update()\n .runUnchecked(c);\n };\n\n @Override\n public EmployeeRow insert(\n EmployeeRow unsaved,\n Connection c\n ) {\n return interpolate(Fragment.lit(\"insert into \\\"showcase\\\".\\\"employee\\\"(\\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"skills\\\", \\\"certifications\\\", \\\"weekly_availability\\\", \\\"contact_info\\\", \\\"settings\\\", \\\"skills_rating\\\", \\\"probation_period\\\")\\nvalues (\"), Fragment.encode(EmployeeId.duckDbType, unsaved.id()), Fragment.lit(\", \"), Fragment.encode(DepartmentId.duckDbType, unsaved.departmentId()), Fragment.lit(\", \"), Fragment.encode(EmployeeId.duckDbType.opt(), unsaved.managerId()), Fragment.lit(\", \"), Fragment.encode(DuckDbTypes.varchar, unsaved.email()), Fragment.lit(\", \"), Fragment.encode(DuckDbTypes.varchar, unsaved.firstName()), Fragment.lit(\", \"), Fragment.encode(DuckDbTypes.varchar, unsaved.lastName()), Fragment.lit(\", \"), Fragment.encode(DuckDbTypes.numeric.opt(), unsaved.salary()), Fragment.lit(\", \"), Fragment.encode(DuckDbTypes.date.opt(), unsaved.hiredAt()), Fragment.lit(\", \"), Fragment.encode(DuckDbTypes.boolean_.opt(), unsaved.active()), Fragment.lit(\", \"), Fragment.encode(DuckDbTypes.timestamp.opt(), unsaved.createdAt()), Fragment.lit(\", \"), Fragment.encode(DuckDbTypes.varcharArray.opt(), unsaved.skills()), Fragment.lit(\", \"), Fragment.encode(DuckDbTypes.varcharArray.opt(), unsaved.certifications()), Fragment.lit(\", \"), Fragment.encode(DuckDbTypes.booleanArray.opt(), unsaved.weeklyAvailability()), Fragment.lit(\", \"), Fragment.encode(EmployeeContactInfo.duckDbType.opt(), unsaved.contactInfo()), Fragment.lit(\", \"), Fragment.encode(DuckDbTypes.varchar.mapTo(DuckDbTypes.varchar).opt(), unsaved.settings()), Fragment.lit(\", \"), Fragment.encode(DuckDbTypes.varchar.mapTo(DuckDbTypes.integer).opt(), unsaved.skillsRating()), Fragment.lit(\", \"), Fragment.encode(DuckDbTypes.interval.opt(), unsaved.probationPeriod()), Fragment.lit(\")\\nRETURNING \\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"skills\\\", \\\"certifications\\\", \\\"weekly_availability\\\", \\\"contact_info\\\", \\\"settings\\\", \\\"skills_rating\\\", \\\"probation_period\\\"\\n\"))\n .updateReturning(EmployeeRow._rowParser.exactlyOne()).runUnchecked(c);\n };\n\n @Override\n public EmployeeRow insert(\n EmployeeRowUnsaved unsaved,\n Connection c\n ) {\n ArrayList columns = new ArrayList<>();;\n ArrayList values = new ArrayList<>();;\n columns.add(Fragment.lit(\"\\\"id\\\"\"));\n values.add(interpolate(Fragment.encode(EmployeeId.duckDbType, unsaved.id()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"\\\"department_id\\\"\"));\n values.add(interpolate(Fragment.encode(DepartmentId.duckDbType, unsaved.departmentId()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"\\\"manager_id\\\"\"));\n values.add(interpolate(Fragment.encode(EmployeeId.duckDbType.opt(), unsaved.managerId()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"\\\"email\\\"\"));\n values.add(interpolate(Fragment.encode(DuckDbTypes.varchar, unsaved.email()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"\\\"first_name\\\"\"));\n values.add(interpolate(Fragment.encode(DuckDbTypes.varchar, unsaved.firstName()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"\\\"last_name\\\"\"));\n values.add(interpolate(Fragment.encode(DuckDbTypes.varchar, unsaved.lastName()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"\\\"salary\\\"\"));\n values.add(interpolate(Fragment.encode(DuckDbTypes.numeric.opt(), unsaved.salary()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"\\\"hired_at\\\"\"));\n values.add(interpolate(Fragment.encode(DuckDbTypes.date.opt(), unsaved.hiredAt()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"\\\"skills\\\"\"));\n values.add(interpolate(Fragment.encode(DuckDbTypes.varcharArray.opt(), unsaved.skills()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"\\\"certifications\\\"\"));\n values.add(interpolate(Fragment.encode(DuckDbTypes.varcharArray.opt(), unsaved.certifications()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"\\\"weekly_availability\\\"\"));\n values.add(interpolate(Fragment.encode(DuckDbTypes.booleanArray.opt(), unsaved.weeklyAvailability()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"\\\"contact_info\\\"\"));\n values.add(interpolate(Fragment.encode(EmployeeContactInfo.duckDbType.opt(), unsaved.contactInfo()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"\\\"settings\\\"\"));\n values.add(interpolate(Fragment.encode(DuckDbTypes.varchar.mapTo(DuckDbTypes.varchar).opt(), unsaved.settings()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"\\\"skills_rating\\\"\"));\n values.add(interpolate(Fragment.encode(DuckDbTypes.varchar.mapTo(DuckDbTypes.integer).opt(), unsaved.skillsRating()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"\\\"probation_period\\\"\"));\n values.add(interpolate(Fragment.encode(DuckDbTypes.interval.opt(), unsaved.probationPeriod()), Fragment.lit(\"\")));\n unsaved.active().visit(\n () -> {\n \n },\n value -> {\n columns.add(Fragment.lit(\"\\\"active\\\"\"));\n values.add(interpolate(Fragment.encode(DuckDbTypes.boolean_.opt(), value), Fragment.lit(\"\")));\n }\n );;\n unsaved.createdAt().visit(\n () -> {\n \n },\n value -> {\n columns.add(Fragment.lit(\"\\\"created_at\\\"\"));\n values.add(interpolate(Fragment.encode(DuckDbTypes.timestamp.opt(), value), Fragment.lit(\"\")));\n }\n );;\n Fragment q = interpolate(Fragment.lit(\"insert into \\\"showcase\\\".\\\"employee\\\"(\"), Fragment.comma(columns), Fragment.lit(\")\\nvalues (\"), Fragment.comma(values), Fragment.lit(\")\\nRETURNING \\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"skills\\\", \\\"certifications\\\", \\\"weekly_availability\\\", \\\"contact_info\\\", \\\"settings\\\", \\\"skills_rating\\\", \\\"probation_period\\\"\\n\"));;\n return q.updateReturning(EmployeeRow._rowParser.exactlyOne()).runUnchecked(c);\n };\n\n @Override\n public SelectBuilder select() {\n return SelectBuilder.of(\"\\\"showcase\\\".\\\"employee\\\"\", EmployeeFields.structure(), EmployeeRow._rowParser, Dialect.DUCKDB);\n };\n\n @Override\n public List selectAll(Connection c) {\n return interpolate(Fragment.lit(\"select \\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"skills\\\", \\\"certifications\\\", \\\"weekly_availability\\\", \\\"contact_info\\\", \\\"settings\\\", \\\"skills_rating\\\", \\\"probation_period\\\"\\nfrom \\\"showcase\\\".\\\"employee\\\"\\n\")).query(EmployeeRow._rowParser.all()).runUnchecked(c);\n };\n\n @Override\n public Optional selectById(\n EmployeeId id,\n Connection c\n ) {\n return interpolate(Fragment.lit(\"select \\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"skills\\\", \\\"certifications\\\", \\\"weekly_availability\\\", \\\"contact_info\\\", \\\"settings\\\", \\\"skills_rating\\\", \\\"probation_period\\\"\\nfrom \\\"showcase\\\".\\\"employee\\\"\\nwhere \\\"id\\\" = \"), Fragment.encode(EmployeeId.duckDbType, id), Fragment.lit(\"\")).query(EmployeeRow._rowParser.first()).runUnchecked(c);\n };\n\n @Override\n public List selectByIds(\n EmployeeId[] ids,\n Connection c\n ) {\n return interpolate(Fragment.lit(\"select \\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"skills\\\", \\\"certifications\\\", \\\"weekly_availability\\\", \\\"contact_info\\\", \\\"settings\\\", \\\"skills_rating\\\", \\\"probation_period\\\"\\nfrom \\\"showcase\\\".\\\"employee\\\"\\nwhere \\\"id\\\" = ANY(\"), Fragment.encode(EmployeeId.pgTypeArray, ids), Fragment.lit(\")\")).query(EmployeeRow._rowParser.all()).runUnchecked(c);\n };\n\n @Override\n public Map selectByIdsTracked(\n EmployeeId[] ids,\n Connection c\n ) {\n HashMap ret = new HashMap();\n selectByIds(ids, c).forEach(row -> ret.put(row.id(), row));\n return ret;\n };\n\n @Override\n public Optional selectByUniqueEmail(\n String email,\n Connection c\n ) {\n return interpolate(Fragment.lit(\"select \\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"skills\\\", \\\"certifications\\\", \\\"weekly_availability\\\", \\\"contact_info\\\", \\\"settings\\\", \\\"skills_rating\\\", \\\"probation_period\\\"\\nfrom \\\"showcase\\\".\\\"employee\\\"\\nwhere \\\"email\\\" = \"), Fragment.encode(DuckDbTypes.varchar, email), Fragment.lit(\"\\n\")).query(EmployeeRow._rowParser.first()).runUnchecked(c);\n };\n\n @Override\n public UpdateBuilder update() {\n return UpdateBuilder.of(\"\\\"showcase\\\".\\\"employee\\\"\", EmployeeFields.structure(), EmployeeRow._rowParser, Dialect.DUCKDB);\n };\n\n @Override\n public Boolean update(\n EmployeeRow row,\n Connection c\n ) {\n EmployeeId id = row.id();;\n return interpolate(Fragment.lit(\"update \\\"showcase\\\".\\\"employee\\\"\\nset \\\"department_id\\\" = \"), Fragment.encode(DepartmentId.duckDbType, row.departmentId()), Fragment.lit(\",\\n\\\"manager_id\\\" = \"), Fragment.encode(EmployeeId.duckDbType.opt(), row.managerId()), Fragment.lit(\",\\n\\\"email\\\" = \"), Fragment.encode(DuckDbTypes.varchar, row.email()), Fragment.lit(\",\\n\\\"first_name\\\" = \"), Fragment.encode(DuckDbTypes.varchar, row.firstName()), Fragment.lit(\",\\n\\\"last_name\\\" = \"), Fragment.encode(DuckDbTypes.varchar, row.lastName()), Fragment.lit(\",\\n\\\"salary\\\" = \"), Fragment.encode(DuckDbTypes.numeric.opt(), row.salary()), Fragment.lit(\",\\n\\\"hired_at\\\" = \"), Fragment.encode(DuckDbTypes.date.opt(), row.hiredAt()), Fragment.lit(\",\\n\\\"active\\\" = \"), Fragment.encode(DuckDbTypes.boolean_.opt(), row.active()), Fragment.lit(\",\\n\\\"created_at\\\" = \"), Fragment.encode(DuckDbTypes.timestamp.opt(), row.createdAt()), Fragment.lit(\",\\n\\\"skills\\\" = \"), Fragment.encode(DuckDbTypes.varcharArray.opt(), row.skills()), Fragment.lit(\",\\n\\\"certifications\\\" = \"), Fragment.encode(DuckDbTypes.varcharArray.opt(), row.certifications()), Fragment.lit(\",\\n\\\"weekly_availability\\\" = \"), Fragment.encode(DuckDbTypes.booleanArray.opt(), row.weeklyAvailability()), Fragment.lit(\",\\n\\\"contact_info\\\" = \"), Fragment.encode(EmployeeContactInfo.duckDbType.opt(), row.contactInfo()), Fragment.lit(\",\\n\\\"settings\\\" = \"), Fragment.encode(DuckDbTypes.varchar.mapTo(DuckDbTypes.varchar).opt(), row.settings()), Fragment.lit(\",\\n\\\"skills_rating\\\" = \"), Fragment.encode(DuckDbTypes.varchar.mapTo(DuckDbTypes.integer).opt(), row.skillsRating()), Fragment.lit(\",\\n\\\"probation_period\\\" = \"), Fragment.encode(DuckDbTypes.interval.opt(), row.probationPeriod()), Fragment.lit(\"\\nwhere \\\"id\\\" = \"), Fragment.encode(EmployeeId.duckDbType, id), Fragment.lit(\"\")).update().runUnchecked(c) > 0;\n };\n\n @Override\n public EmployeeRow upsert(\n EmployeeRow unsaved,\n Connection c\n ) {\n return interpolate(Fragment.lit(\"INSERT INTO \\\"showcase\\\".\\\"employee\\\"(\\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"skills\\\", \\\"certifications\\\", \\\"weekly_availability\\\", \\\"contact_info\\\", \\\"settings\\\", \\\"skills_rating\\\", \\\"probation_period\\\")\\nVALUES (\"), Fragment.encode(EmployeeId.duckDbType, unsaved.id()), Fragment.lit(\", \"), Fragment.encode(DepartmentId.duckDbType, unsaved.departmentId()), Fragment.lit(\", \"), Fragment.encode(EmployeeId.duckDbType.opt(), unsaved.managerId()), Fragment.lit(\", \"), Fragment.encode(DuckDbTypes.varchar, unsaved.email()), Fragment.lit(\", \"), Fragment.encode(DuckDbTypes.varchar, unsaved.firstName()), Fragment.lit(\", \"), Fragment.encode(DuckDbTypes.varchar, unsaved.lastName()), Fragment.lit(\", \"), Fragment.encode(DuckDbTypes.numeric.opt(), unsaved.salary()), Fragment.lit(\", \"), Fragment.encode(DuckDbTypes.date.opt(), unsaved.hiredAt()), Fragment.lit(\", \"), Fragment.encode(DuckDbTypes.boolean_.opt(), unsaved.active()), Fragment.lit(\", \"), Fragment.encode(DuckDbTypes.timestamp.opt(), unsaved.createdAt()), Fragment.lit(\", \"), Fragment.encode(DuckDbTypes.varcharArray.opt(), unsaved.skills()), Fragment.lit(\", \"), Fragment.encode(DuckDbTypes.varcharArray.opt(), unsaved.certifications()), Fragment.lit(\", \"), Fragment.encode(DuckDbTypes.booleanArray.opt(), unsaved.weeklyAvailability()), Fragment.lit(\", \"), Fragment.encode(EmployeeContactInfo.duckDbType.opt(), unsaved.contactInfo()), Fragment.lit(\", \"), Fragment.encode(DuckDbTypes.varchar.mapTo(DuckDbTypes.varchar).opt(), unsaved.settings()), Fragment.lit(\", \"), Fragment.encode(DuckDbTypes.varchar.mapTo(DuckDbTypes.integer).opt(), unsaved.skillsRating()), Fragment.lit(\", \"), Fragment.encode(DuckDbTypes.interval.opt(), unsaved.probationPeriod()), Fragment.lit(\")\\nON CONFLICT (\\\"id\\\")\\nDO UPDATE SET\\n \\\"department_id\\\" = EXCLUDED.\\\"department_id\\\",\\n\\\"manager_id\\\" = EXCLUDED.\\\"manager_id\\\",\\n\\\"email\\\" = EXCLUDED.\\\"email\\\",\\n\\\"first_name\\\" = EXCLUDED.\\\"first_name\\\",\\n\\\"last_name\\\" = EXCLUDED.\\\"last_name\\\",\\n\\\"salary\\\" = EXCLUDED.\\\"salary\\\",\\n\\\"hired_at\\\" = EXCLUDED.\\\"hired_at\\\",\\n\\\"active\\\" = EXCLUDED.\\\"active\\\",\\n\\\"created_at\\\" = EXCLUDED.\\\"created_at\\\",\\n\\\"skills\\\" = EXCLUDED.\\\"skills\\\",\\n\\\"certifications\\\" = EXCLUDED.\\\"certifications\\\",\\n\\\"weekly_availability\\\" = EXCLUDED.\\\"weekly_availability\\\",\\n\\\"contact_info\\\" = EXCLUDED.\\\"contact_info\\\",\\n\\\"settings\\\" = EXCLUDED.\\\"settings\\\",\\n\\\"skills_rating\\\" = EXCLUDED.\\\"skills_rating\\\",\\n\\\"probation_period\\\" = EXCLUDED.\\\"probation_period\\\"\\nRETURNING \\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"skills\\\", \\\"certifications\\\", \\\"weekly_availability\\\", \\\"contact_info\\\", \\\"settings\\\", \\\"skills_rating\\\", \\\"probation_period\\\"\"))\n .updateReturning(EmployeeRow._rowParser.exactlyOne())\n .runUnchecked(c);\n };\n\n @Override\n public List upsertBatch(\n Iterator unsaved,\n Connection c\n ) {\n return interpolate(Fragment.lit(\"INSERT INTO \\\"showcase\\\".\\\"employee\\\"(\\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"skills\\\", \\\"certifications\\\", \\\"weekly_availability\\\", \\\"contact_info\\\", \\\"settings\\\", \\\"skills_rating\\\", \\\"probation_period\\\")\\nVALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\\nON CONFLICT (\\\"id\\\")\\nDO UPDATE SET\\n \\\"department_id\\\" = EXCLUDED.\\\"department_id\\\",\\n\\\"manager_id\\\" = EXCLUDED.\\\"manager_id\\\",\\n\\\"email\\\" = EXCLUDED.\\\"email\\\",\\n\\\"first_name\\\" = EXCLUDED.\\\"first_name\\\",\\n\\\"last_name\\\" = EXCLUDED.\\\"last_name\\\",\\n\\\"salary\\\" = EXCLUDED.\\\"salary\\\",\\n\\\"hired_at\\\" = EXCLUDED.\\\"hired_at\\\",\\n\\\"active\\\" = EXCLUDED.\\\"active\\\",\\n\\\"created_at\\\" = EXCLUDED.\\\"created_at\\\",\\n\\\"skills\\\" = EXCLUDED.\\\"skills\\\",\\n\\\"certifications\\\" = EXCLUDED.\\\"certifications\\\",\\n\\\"weekly_availability\\\" = EXCLUDED.\\\"weekly_availability\\\",\\n\\\"contact_info\\\" = EXCLUDED.\\\"contact_info\\\",\\n\\\"settings\\\" = EXCLUDED.\\\"settings\\\",\\n\\\"skills_rating\\\" = EXCLUDED.\\\"skills_rating\\\",\\n\\\"probation_period\\\" = EXCLUDED.\\\"probation_period\\\"\\nRETURNING \\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"skills\\\", \\\"certifications\\\", \\\"weekly_availability\\\", \\\"contact_info\\\", \\\"settings\\\", \\\"skills_rating\\\", \\\"probation_period\\\"\"))\n .updateReturningEach(EmployeeRow._rowParser, unsaved)\n .runUnchecked(c);\n };\n}", - "EmployeeRepoMock": "package showcase.showcase.employee;\n\nimport dev.typr.foundations.dsl.DeleteBuilder;\nimport dev.typr.foundations.dsl.DeleteBuilderMock;\nimport dev.typr.foundations.dsl.DeleteParams;\nimport dev.typr.foundations.dsl.SelectBuilder;\nimport dev.typr.foundations.dsl.SelectBuilderMock;\nimport dev.typr.foundations.dsl.SelectParams;\nimport dev.typr.foundations.dsl.UpdateBuilder;\nimport dev.typr.foundations.dsl.UpdateBuilderMock;\nimport dev.typr.foundations.dsl.UpdateParams;\nimport java.lang.RuntimeException;\nimport java.sql.Connection;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\nimport java.util.function.Function;\nimport java.util.stream.Collectors;\n\npublic record EmployeeRepoMock(\n java.util.function.Function toRow,\n HashMap map\n) implements EmployeeRepo {\n public EmployeeRepoMock(java.util.function.Function toRow) {\n this(toRow, new HashMap());\n };\n\n public EmployeeRepoMock withToRow(java.util.function.Function toRow) {\n return new EmployeeRepoMock(toRow, map);\n };\n\n public EmployeeRepoMock withMap(HashMap map) {\n return new EmployeeRepoMock(toRow, map);\n };\n\n @Override\n public DeleteBuilder delete() {\n return new DeleteBuilderMock<>(EmployeeFields.structure(), () -> new ArrayList<>(map.values()), DeleteParams.empty(), row -> row.id(), id -> map.remove(id));\n };\n\n @Override\n public Boolean deleteById(\n EmployeeId id,\n Connection c\n ) {\n return Optional.ofNullable(map.remove(id)).isPresent();\n };\n\n @Override\n public Integer deleteByIds(\n EmployeeId[] ids,\n Connection c\n ) {\n var count = 0;\n for (var id : ids) {\n if (Optional.ofNullable(map.remove(id)).isPresent()) {\n count = count + 1;;\n };\n };\n return count;\n };\n\n @Override\n public EmployeeRow insert(\n EmployeeRow unsaved,\n Connection c\n ) {\n if (map.containsKey(unsaved.id())) {\n throw new RuntimeException(\"id \" + unsaved.id() + \" already exists\");\n };\n map.put(unsaved.id(), unsaved);\n return unsaved;\n };\n\n @Override\n public EmployeeRow insert(\n EmployeeRowUnsaved unsaved,\n Connection c\n ) {\n return insert(toRow.apply(unsaved), c);\n };\n\n @Override\n public SelectBuilder select() {\n return new SelectBuilderMock<>(EmployeeFields.structure(), () -> new ArrayList<>(map.values()), SelectParams.empty());\n };\n\n @Override\n public List selectAll(Connection c) {\n return new ArrayList<>(map.values());\n };\n\n @Override\n public Optional selectById(\n EmployeeId id,\n Connection c\n ) {\n return Optional.ofNullable(map.get(id));\n };\n\n @Override\n public List selectByIds(\n EmployeeId[] ids,\n Connection c\n ) {\n var result = new ArrayList();\n for (var id : ids) {\n var opt = Optional.ofNullable(map.get(id));\n if (opt.isPresent()) {\n result.add(opt.get());\n };\n };\n return result;\n };\n\n @Override\n public Map selectByIdsTracked(\n EmployeeId[] ids,\n Connection c\n ) {\n return selectByIds(ids, c).stream().collect(Collectors.toMap((EmployeeRow row) -> row.id(), Function.identity()));\n };\n\n @Override\n public Optional selectByUniqueEmail(\n String email,\n Connection c\n ) {\n return new ArrayList<>(map.values()).stream().filter(v -> email.equals(v.email())).findFirst();\n };\n\n @Override\n public UpdateBuilder update() {\n return new UpdateBuilderMock<>(EmployeeFields.structure(), () -> new ArrayList<>(map.values()), UpdateParams.empty(), row -> row);\n };\n\n @Override\n public Boolean update(\n EmployeeRow row,\n Connection c\n ) {\n var shouldUpdate = Optional.ofNullable(map.get(row.id())).filter(oldRow -> !oldRow.equals(row)).isPresent();\n if (shouldUpdate) {\n map.put(row.id(), row);;\n };\n return shouldUpdate;\n };\n\n @Override\n public EmployeeRow upsert(\n EmployeeRow unsaved,\n Connection c\n ) {\n map.put(unsaved.id(), unsaved);\n return unsaved;\n };\n\n @Override\n public List upsertBatch(\n Iterator unsaved,\n Connection c\n ) {\n var result = new ArrayList();\n while (unsaved.hasNext()) {\n var row = unsaved.next();\n map.put(row.id(), row);\n result.add(row);\n };\n return result;\n };\n}", - "EmployeeFields": "package showcase.showcase.employee;\n\nimport dev.typr.foundations.DuckDbTypes;\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.dsl.FieldsExpr;\nimport dev.typr.foundations.dsl.ForeignKey;\nimport dev.typr.foundations.dsl.Path;\nimport dev.typr.foundations.dsl.RelationStructure;\nimport dev.typr.foundations.dsl.SqlExpr.Field;\nimport dev.typr.foundations.dsl.SqlExpr.FieldLike;\nimport dev.typr.foundations.dsl.SqlExpr.IdField;\nimport dev.typr.foundations.dsl.SqlExpr.OptField;\nimport java.math.BigDecimal;\nimport java.time.Duration;\nimport java.time.LocalDate;\nimport java.time.LocalDateTime;\nimport java.util.List;\nimport java.util.Optional;\nimport showcase.EmployeeContactInfo;\nimport showcase.showcase.department.DepartmentFields;\nimport showcase.showcase.department.DepartmentId;\nimport showcase.showcase.department.DepartmentRow;\n\npublic interface EmployeeFields extends FieldsExpr {\n record Impl(List _path) implements EmployeeFields, RelationStructure {\n @Override\n public IdField id() {\n return new IdField(_path, \"id\", EmployeeRow::id, Optional.empty(), Optional.empty(), (row, value) -> row.withId(value), EmployeeId.duckDbType);\n };\n\n @Override\n public Field departmentId() {\n return new Field(_path, \"department_id\", EmployeeRow::departmentId, Optional.empty(), Optional.empty(), (row, value) -> row.withDepartmentId(value), DepartmentId.duckDbType);\n };\n\n @Override\n public OptField managerId() {\n return new OptField(_path, \"manager_id\", EmployeeRow::managerId, Optional.empty(), Optional.empty(), (row, value) -> row.withManagerId(value), EmployeeId.duckDbType);\n };\n\n @Override\n public Field email() {\n return new Field(_path, \"email\", EmployeeRow::email, Optional.empty(), Optional.empty(), (row, value) -> row.withEmail(value), DuckDbTypes.varchar);\n };\n\n @Override\n public Field firstName() {\n return new Field(_path, \"first_name\", EmployeeRow::firstName, Optional.empty(), Optional.empty(), (row, value) -> row.withFirstName(value), DuckDbTypes.varchar);\n };\n\n @Override\n public Field lastName() {\n return new Field(_path, \"last_name\", EmployeeRow::lastName, Optional.empty(), Optional.empty(), (row, value) -> row.withLastName(value), DuckDbTypes.varchar);\n };\n\n @Override\n public OptField salary() {\n return new OptField(_path, \"salary\", EmployeeRow::salary, Optional.empty(), Optional.empty(), (row, value) -> row.withSalary(value), DuckDbTypes.numeric);\n };\n\n @Override\n public OptField hiredAt() {\n return new OptField(_path, \"hired_at\", EmployeeRow::hiredAt, Optional.empty(), Optional.empty(), (row, value) -> row.withHiredAt(value), DuckDbTypes.date);\n };\n\n @Override\n public OptField active() {\n return new OptField(_path, \"active\", EmployeeRow::active, Optional.empty(), Optional.empty(), (row, value) -> row.withActive(value), DuckDbTypes.boolean_);\n };\n\n @Override\n public OptField createdAt() {\n return new OptField(_path, \"created_at\", EmployeeRow::createdAt, Optional.empty(), Optional.empty(), (row, value) -> row.withCreatedAt(value), DuckDbTypes.timestamp);\n };\n\n @Override\n public OptField skills() {\n return new OptField(_path, \"skills\", EmployeeRow::skills, Optional.empty(), Optional.empty(), (row, value) -> row.withSkills(value), DuckDbTypes.varcharArray);\n };\n\n @Override\n public OptField certifications() {\n return new OptField(_path, \"certifications\", EmployeeRow::certifications, Optional.empty(), Optional.empty(), (row, value) -> row.withCertifications(value), DuckDbTypes.varcharArray);\n };\n\n @Override\n public OptField weeklyAvailability() {\n return new OptField(_path, \"weekly_availability\", EmployeeRow::weeklyAvailability, Optional.empty(), Optional.empty(), (row, value) -> row.withWeeklyAvailability(value), DuckDbTypes.booleanArray);\n };\n\n @Override\n public OptField contactInfo() {\n return new OptField(_path, \"contact_info\", EmployeeRow::contactInfo, Optional.empty(), Optional.empty(), (row, value) -> row.withContactInfo(value), EmployeeContactInfo.duckDbType);\n };\n\n @Override\n public OptField settings() {\n return new OptField(_path, \"settings\", EmployeeRow::settings, Optional.empty(), Optional.empty(), (row, value) -> row.withSettings(value), DuckDbTypes.varchar.mapTo(DuckDbTypes.varchar));\n };\n\n @Override\n public OptField skillsRating() {\n return new OptField(_path, \"skills_rating\", EmployeeRow::skillsRating, Optional.empty(), Optional.empty(), (row, value) -> row.withSkillsRating(value), DuckDbTypes.varchar.mapTo(DuckDbTypes.integer));\n };\n\n @Override\n public OptField probationPeriod() {\n return new OptField(_path, \"probation_period\", EmployeeRow::probationPeriod, Optional.empty(), Optional.empty(), (row, value) -> row.withProbationPeriod(value), DuckDbTypes.interval);\n };\n\n @Override\n public List> columns() {\n return java.util.List.of(this.id(), this.departmentId(), this.managerId(), this.email(), this.firstName(), this.lastName(), this.salary(), this.hiredAt(), this.active(), this.createdAt(), this.skills(), this.certifications(), this.weeklyAvailability(), this.contactInfo(), this.settings(), this.skillsRating(), this.probationPeriod());\n };\n\n @Override\n public RelationStructure withPaths(List _path) {\n return new Impl(_path);\n };\n };\n\n static Impl structure() {\n return new Impl(java.util.Collections.emptyList());\n };\n\n IdField id();\n\n Field departmentId();\n\n OptField managerId();\n\n Field email();\n\n Field firstName();\n\n Field lastName();\n\n OptField salary();\n\n OptField hiredAt();\n\n OptField active();\n\n OptField createdAt();\n\n OptField skills();\n\n OptField certifications();\n\n OptField weeklyAvailability();\n\n OptField contactInfo();\n\n OptField settings();\n\n OptField skillsRating();\n\n OptField probationPeriod();\n\n default ForeignKey fkDepartment() {\n return ForeignKey.of(\"employee_department_fk\").withColumnPair(departmentId(), DepartmentFields::id);\n };\n\n default ForeignKey fkEmployee() {\n return ForeignKey.of(\"employee_manager_fk\").withColumnPair(managerId(), EmployeeFields::id);\n };\n\n @Override\n List> columns();\n\n @Override\n default RowParser rowParser() {\n return EmployeeRow._rowParser;\n };\n}", - "DepartmentRow": "package showcase.showcase.department;\n\nimport dev.typr.foundations.DuckDbTypes;\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport java.math.BigDecimal;\nimport java.util.Optional;\nimport showcase.showcase.company.CompanyId;\n\n/** Table: showcase.department\n * Primary key: id\n */\npublic record DepartmentRow(\n DepartmentId id,\n /** Points to {@link showcase.showcase.company.CompanyRow#id()} */\n CompanyId companyId,\n String name,\n Optional budget\n) {\n public DepartmentRow withId(DepartmentId id) {\n return new DepartmentRow(id, companyId, name, budget);\n };\n\n /** Points to {@link showcase.showcase.company.CompanyRow#id()} */\n public DepartmentRow withCompanyId(CompanyId companyId) {\n return new DepartmentRow(id, companyId, name, budget);\n };\n\n public DepartmentRow withName(String name) {\n return new DepartmentRow(id, companyId, name, budget);\n };\n\n public DepartmentRow withBudget(Optional budget) {\n return new DepartmentRow(id, companyId, name, budget);\n };\n\n public static RowParser _rowParser = RowParsers.of(DepartmentId.duckDbType, CompanyId.duckDbType, DuckDbTypes.varchar, DuckDbTypes.numeric.opt(), DepartmentRow::new, row -> new Object[]{row.id(), row.companyId(), row.name(), row.budget()});;\n}", - "DepartmentId": "package showcase.showcase.department;\n\nimport dev.typr.foundations.DuckDbType;\nimport dev.typr.foundations.DuckDbTypes;\nimport dev.typr.foundations.dsl.Bijection;\nimport dev.typr.foundations.internal.arrayMap;\n\n/** Type for the primary key of table `showcase.department` */\npublic record DepartmentId(String value) {\n public DepartmentId withValue(String value) {\n return new DepartmentId(value);\n };\n\n @Override\n public java.lang.String toString() {\n return value.toString();\n };\n\n static public Bijection bijection =\n Bijection.of(DepartmentId::value, DepartmentId::new);\n\n static public DuckDbType duckDbType =\n DuckDbTypes.varchar.bimap(DepartmentId::new, DepartmentId::value);\n\n static public DuckDbType pgTypeArray =\n DuckDbTypes.varcharArray.bimap(xs -> arrayMap.map(xs, DepartmentId::new, DepartmentId.class), xs -> arrayMap.map(xs, DepartmentId::value, String.class));\n}", - "DepartmentRepo": "package showcase.showcase.department;\n\nimport dev.typr.foundations.dsl.DeleteBuilder;\nimport dev.typr.foundations.dsl.SelectBuilder;\nimport dev.typr.foundations.dsl.UpdateBuilder;\nimport java.sql.Connection;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\n\npublic interface DepartmentRepo {\n DeleteBuilder delete();\n\n Boolean deleteById(\n DepartmentId id,\n Connection c\n );\n\n Integer deleteByIds(\n DepartmentId[] ids,\n Connection c\n );\n\n DepartmentRow insert(\n DepartmentRow unsaved,\n Connection c\n );\n\n SelectBuilder select();\n\n List selectAll(Connection c);\n\n Optional selectById(\n DepartmentId id,\n Connection c\n );\n\n List selectByIds(\n DepartmentId[] ids,\n Connection c\n );\n\n Map selectByIdsTracked(\n DepartmentId[] ids,\n Connection c\n );\n\n UpdateBuilder update();\n\n Boolean update(\n DepartmentRow row,\n Connection c\n );\n\n DepartmentRow upsert(\n DepartmentRow unsaved,\n Connection c\n );\n\n List upsertBatch(\n Iterator unsaved,\n Connection c\n );\n}", - "DepartmentRepoMock": "package showcase.showcase.department;\n\nimport dev.typr.foundations.dsl.DeleteBuilder;\nimport dev.typr.foundations.dsl.DeleteBuilderMock;\nimport dev.typr.foundations.dsl.DeleteParams;\nimport dev.typr.foundations.dsl.SelectBuilder;\nimport dev.typr.foundations.dsl.SelectBuilderMock;\nimport dev.typr.foundations.dsl.SelectParams;\nimport dev.typr.foundations.dsl.UpdateBuilder;\nimport dev.typr.foundations.dsl.UpdateBuilderMock;\nimport dev.typr.foundations.dsl.UpdateParams;\nimport java.lang.RuntimeException;\nimport java.sql.Connection;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\nimport java.util.function.Function;\nimport java.util.stream.Collectors;\n\npublic record DepartmentRepoMock(HashMap map) implements DepartmentRepo {\n public DepartmentRepoMock() {\n this(new HashMap());\n };\n\n public DepartmentRepoMock withMap(HashMap map) {\n return new DepartmentRepoMock(map);\n };\n\n @Override\n public DeleteBuilder delete() {\n return new DeleteBuilderMock<>(DepartmentFields.structure(), () -> new ArrayList<>(map.values()), DeleteParams.empty(), row -> row.id(), id -> map.remove(id));\n };\n\n @Override\n public Boolean deleteById(\n DepartmentId id,\n Connection c\n ) {\n return Optional.ofNullable(map.remove(id)).isPresent();\n };\n\n @Override\n public Integer deleteByIds(\n DepartmentId[] ids,\n Connection c\n ) {\n var count = 0;\n for (var id : ids) {\n if (Optional.ofNullable(map.remove(id)).isPresent()) {\n count = count + 1;;\n };\n };\n return count;\n };\n\n @Override\n public DepartmentRow insert(\n DepartmentRow unsaved,\n Connection c\n ) {\n if (map.containsKey(unsaved.id())) {\n throw new RuntimeException(\"id \" + unsaved.id() + \" already exists\");\n };\n map.put(unsaved.id(), unsaved);\n return unsaved;\n };\n\n @Override\n public SelectBuilder select() {\n return new SelectBuilderMock<>(DepartmentFields.structure(), () -> new ArrayList<>(map.values()), SelectParams.empty());\n };\n\n @Override\n public List selectAll(Connection c) {\n return new ArrayList<>(map.values());\n };\n\n @Override\n public Optional selectById(\n DepartmentId id,\n Connection c\n ) {\n return Optional.ofNullable(map.get(id));\n };\n\n @Override\n public List selectByIds(\n DepartmentId[] ids,\n Connection c\n ) {\n var result = new ArrayList();\n for (var id : ids) {\n var opt = Optional.ofNullable(map.get(id));\n if (opt.isPresent()) {\n result.add(opt.get());\n };\n };\n return result;\n };\n\n @Override\n public Map selectByIdsTracked(\n DepartmentId[] ids,\n Connection c\n ) {\n return selectByIds(ids, c).stream().collect(Collectors.toMap((DepartmentRow row) -> row.id(), Function.identity()));\n };\n\n @Override\n public UpdateBuilder update() {\n return new UpdateBuilderMock<>(DepartmentFields.structure(), () -> new ArrayList<>(map.values()), UpdateParams.empty(), row -> row);\n };\n\n @Override\n public Boolean update(\n DepartmentRow row,\n Connection c\n ) {\n var shouldUpdate = Optional.ofNullable(map.get(row.id())).filter(oldRow -> !oldRow.equals(row)).isPresent();\n if (shouldUpdate) {\n map.put(row.id(), row);;\n };\n return shouldUpdate;\n };\n\n @Override\n public DepartmentRow upsert(\n DepartmentRow unsaved,\n Connection c\n ) {\n map.put(unsaved.id(), unsaved);\n return unsaved;\n };\n\n @Override\n public List upsertBatch(\n Iterator unsaved,\n Connection c\n ) {\n var result = new ArrayList();\n while (unsaved.hasNext()) {\n var row = unsaved.next();\n map.put(row.id(), row);\n result.add(row);\n };\n return result;\n };\n}", - "ProjectAssignmentRow": "package showcase.showcase.project_assignment;\n\nimport dev.typr.foundations.DuckDbTypes;\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport java.time.LocalDate;\nimport java.util.Optional;\nimport showcase.customtypes.Defaulted;\nimport showcase.showcase.employee.EmployeeId;\nimport showcase.showcase.project.ProjectId;\n\n/** Table: showcase.project_assignment\n * Composite primary key: employee_id, project_id\n */\npublic record ProjectAssignmentRow(\n /** Points to {@link showcase.showcase.employee.EmployeeRow#id()} */\n EmployeeId employeeId,\n /** Points to {@link showcase.showcase.project.ProjectRow#id()} */\n ProjectId projectId,\n String role,\n /** Default: 0 */\n Optional hoursAllocated,\n Optional startDate,\n Optional endDate\n) {\n /** Points to {@link showcase.showcase.employee.EmployeeRow#id()} */\n public ProjectAssignmentRow withEmployeeId(EmployeeId employeeId) {\n return new ProjectAssignmentRow(employeeId, projectId, role, hoursAllocated, startDate, endDate);\n };\n\n /** Points to {@link showcase.showcase.project.ProjectRow#id()} */\n public ProjectAssignmentRow withProjectId(ProjectId projectId) {\n return new ProjectAssignmentRow(employeeId, projectId, role, hoursAllocated, startDate, endDate);\n };\n\n public ProjectAssignmentRow withRole(String role) {\n return new ProjectAssignmentRow(employeeId, projectId, role, hoursAllocated, startDate, endDate);\n };\n\n /** Default: 0 */\n public ProjectAssignmentRow withHoursAllocated(Optional hoursAllocated) {\n return new ProjectAssignmentRow(employeeId, projectId, role, hoursAllocated, startDate, endDate);\n };\n\n public ProjectAssignmentRow withStartDate(Optional startDate) {\n return new ProjectAssignmentRow(employeeId, projectId, role, hoursAllocated, startDate, endDate);\n };\n\n public ProjectAssignmentRow withEndDate(Optional endDate) {\n return new ProjectAssignmentRow(employeeId, projectId, role, hoursAllocated, startDate, endDate);\n };\n\n public static RowParser _rowParser = RowParsers.of(EmployeeId.duckDbType, ProjectId.duckDbType, DuckDbTypes.varchar, DuckDbTypes.integer.opt(), DuckDbTypes.date.opt(), DuckDbTypes.date.opt(), ProjectAssignmentRow::new, row -> new Object[]{row.employeeId(), row.projectId(), row.role(), row.hoursAllocated(), row.startDate(), row.endDate()});;\n\n static public ProjectAssignmentRow apply(\n ProjectAssignmentId compositeId,\n String role,\n Optional hoursAllocated,\n Optional startDate,\n Optional endDate\n ) {\n return new ProjectAssignmentRow(compositeId.employeeId(), compositeId.projectId(), role, hoursAllocated, startDate, endDate);\n };\n\n public ProjectAssignmentId compositeId() {\n return new ProjectAssignmentId(employeeId, projectId);\n };\n\n public ProjectAssignmentId id() {\n return this.compositeId();\n };\n\n public ProjectAssignmentRowUnsaved toUnsavedRow(Defaulted> hoursAllocated) {\n return new ProjectAssignmentRowUnsaved(employeeId, projectId, role, startDate, endDate, hoursAllocated);\n };\n}", - "ProjectAssignmentRowUnsaved": "package showcase.showcase.project_assignment;\n\nimport java.time.LocalDate;\nimport java.util.Optional;\nimport showcase.customtypes.Defaulted;\nimport showcase.customtypes.Defaulted.UseDefault;\nimport showcase.showcase.employee.EmployeeId;\nimport showcase.showcase.project.ProjectId;\n\n/** This class corresponds to a row in table `showcase.project_assignment` which has not been persisted yet */\npublic record ProjectAssignmentRowUnsaved(\n /** Points to {@link showcase.showcase.employee.EmployeeRow#id()} */\n EmployeeId employeeId,\n /** Points to {@link showcase.showcase.project.ProjectRow#id()} */\n ProjectId projectId,\n String role,\n Optional startDate,\n Optional endDate,\n /** Default: 0 */\n Defaulted> hoursAllocated\n) {\n public ProjectAssignmentRowUnsaved(\n /** Points to {@link showcase.showcase.employee.EmployeeRow#id()} */\n EmployeeId employeeId,\n /** Points to {@link showcase.showcase.project.ProjectRow#id()} */\n ProjectId projectId,\n String role\n ) {\n this(employeeId, projectId, role, Optional.empty(), Optional.empty(), new UseDefault<>());\n };\n\n /** Points to {@link showcase.showcase.employee.EmployeeRow#id()} */\n public ProjectAssignmentRowUnsaved withEmployeeId(EmployeeId employeeId) {\n return new ProjectAssignmentRowUnsaved(employeeId, projectId, role, startDate, endDate, hoursAllocated);\n };\n\n /** Points to {@link showcase.showcase.project.ProjectRow#id()} */\n public ProjectAssignmentRowUnsaved withProjectId(ProjectId projectId) {\n return new ProjectAssignmentRowUnsaved(employeeId, projectId, role, startDate, endDate, hoursAllocated);\n };\n\n public ProjectAssignmentRowUnsaved withRole(String role) {\n return new ProjectAssignmentRowUnsaved(employeeId, projectId, role, startDate, endDate, hoursAllocated);\n };\n\n public ProjectAssignmentRowUnsaved withStartDate(Optional startDate) {\n return new ProjectAssignmentRowUnsaved(employeeId, projectId, role, startDate, endDate, hoursAllocated);\n };\n\n public ProjectAssignmentRowUnsaved withEndDate(Optional endDate) {\n return new ProjectAssignmentRowUnsaved(employeeId, projectId, role, startDate, endDate, hoursAllocated);\n };\n\n /** Default: 0 */\n public ProjectAssignmentRowUnsaved withHoursAllocated(Defaulted> hoursAllocated) {\n return new ProjectAssignmentRowUnsaved(employeeId, projectId, role, startDate, endDate, hoursAllocated);\n };\n\n public ProjectAssignmentRow toRow(java.util.function.Supplier> hoursAllocatedDefault) {\n return new ProjectAssignmentRow(employeeId, projectId, role, hoursAllocated.getOrElse(hoursAllocatedDefault), startDate, endDate);\n };\n}", - "ProjectAssignmentId": "package showcase.showcase.project_assignment;\n\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport showcase.showcase.employee.EmployeeId;\nimport showcase.showcase.project.ProjectId;\n\n/** Type for the composite primary key of table `showcase.project_assignment` */\npublic record ProjectAssignmentId(\n EmployeeId employeeId,\n ProjectId projectId\n) {\n public ProjectAssignmentId withEmployeeId(EmployeeId employeeId) {\n return new ProjectAssignmentId(employeeId, projectId);\n };\n\n public ProjectAssignmentId withProjectId(ProjectId projectId) {\n return new ProjectAssignmentId(employeeId, projectId);\n };\n\n public static RowParser _rowParser = RowParsers.of(EmployeeId.duckDbType, ProjectId.duckDbType, ProjectAssignmentId::new, row -> new Object[]{row.employeeId(), row.projectId()});;\n}", - "ProjectAssignmentRepo": "package showcase.showcase.project_assignment;\n\nimport dev.typr.foundations.dsl.DeleteBuilder;\nimport dev.typr.foundations.dsl.SelectBuilder;\nimport dev.typr.foundations.dsl.UpdateBuilder;\nimport java.sql.Connection;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\n\npublic interface ProjectAssignmentRepo {\n DeleteBuilder delete();\n\n Boolean deleteById(\n ProjectAssignmentId compositeId,\n Connection c\n );\n\n Integer deleteByIds(\n ProjectAssignmentId[] compositeIds,\n Connection c\n );\n\n ProjectAssignmentRow insert(\n ProjectAssignmentRow unsaved,\n Connection c\n );\n\n ProjectAssignmentRow insert(\n ProjectAssignmentRowUnsaved unsaved,\n Connection c\n );\n\n SelectBuilder select();\n\n List selectAll(Connection c);\n\n Optional selectById(\n ProjectAssignmentId compositeId,\n Connection c\n );\n\n List selectByIds(\n ProjectAssignmentId[] compositeIds,\n Connection c\n );\n\n Map selectByIdsTracked(\n ProjectAssignmentId[] compositeIds,\n Connection c\n );\n\n UpdateBuilder update();\n\n Boolean update(\n ProjectAssignmentRow row,\n Connection c\n );\n\n ProjectAssignmentRow upsert(\n ProjectAssignmentRow unsaved,\n Connection c\n );\n\n List upsertBatch(\n Iterator unsaved,\n Connection c\n );\n}", - "ProjectRow": "package showcase.showcase.project;\n\nimport dev.typr.foundations.DuckDbTypes;\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport dev.typr.foundations.data.Json;\nimport java.math.BigDecimal;\nimport java.time.Duration;\nimport java.time.LocalDate;\nimport java.time.LocalDateTime;\nimport java.util.Optional;\nimport showcase.ProjectProjectPhases;\nimport showcase.customtypes.Defaulted;\n\n/** Table: showcase.project\n * Primary key: id\n */\npublic record ProjectRow(\n ProjectId id,\n String name,\n Optional description,\n Optional startDate,\n Optional endDate,\n Optional budget,\n /** Default: 'planning' */\n Optional status,\n /** Default: CURRENT_TIMESTAMP */\n Optional createdAt,\n Optional milestones,\n Optional budgetSnapshots,\n Optional teamMembers,\n Optional projectPhases,\n Optional config,\n Optional riskScores,\n Optional estimatedDuration,\n Optional actualDuration,\n Optional metadata\n) {\n public ProjectRow withId(ProjectId id) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, milestones, budgetSnapshots, teamMembers, projectPhases, config, riskScores, estimatedDuration, actualDuration, metadata);\n };\n\n public ProjectRow withName(String name) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, milestones, budgetSnapshots, teamMembers, projectPhases, config, riskScores, estimatedDuration, actualDuration, metadata);\n };\n\n public ProjectRow withDescription(Optional description) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, milestones, budgetSnapshots, teamMembers, projectPhases, config, riskScores, estimatedDuration, actualDuration, metadata);\n };\n\n public ProjectRow withStartDate(Optional startDate) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, milestones, budgetSnapshots, teamMembers, projectPhases, config, riskScores, estimatedDuration, actualDuration, metadata);\n };\n\n public ProjectRow withEndDate(Optional endDate) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, milestones, budgetSnapshots, teamMembers, projectPhases, config, riskScores, estimatedDuration, actualDuration, metadata);\n };\n\n public ProjectRow withBudget(Optional budget) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, milestones, budgetSnapshots, teamMembers, projectPhases, config, riskScores, estimatedDuration, actualDuration, metadata);\n };\n\n /** Default: 'planning' */\n public ProjectRow withStatus(Optional status) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, milestones, budgetSnapshots, teamMembers, projectPhases, config, riskScores, estimatedDuration, actualDuration, metadata);\n };\n\n /** Default: CURRENT_TIMESTAMP */\n public ProjectRow withCreatedAt(Optional createdAt) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, milestones, budgetSnapshots, teamMembers, projectPhases, config, riskScores, estimatedDuration, actualDuration, metadata);\n };\n\n public ProjectRow withMilestones(Optional milestones) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, milestones, budgetSnapshots, teamMembers, projectPhases, config, riskScores, estimatedDuration, actualDuration, metadata);\n };\n\n public ProjectRow withBudgetSnapshots(Optional budgetSnapshots) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, milestones, budgetSnapshots, teamMembers, projectPhases, config, riskScores, estimatedDuration, actualDuration, metadata);\n };\n\n public ProjectRow withTeamMembers(Optional teamMembers) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, milestones, budgetSnapshots, teamMembers, projectPhases, config, riskScores, estimatedDuration, actualDuration, metadata);\n };\n\n public ProjectRow withProjectPhases(Optional projectPhases) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, milestones, budgetSnapshots, teamMembers, projectPhases, config, riskScores, estimatedDuration, actualDuration, metadata);\n };\n\n public ProjectRow withConfig(Optional config) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, milestones, budgetSnapshots, teamMembers, projectPhases, config, riskScores, estimatedDuration, actualDuration, metadata);\n };\n\n public ProjectRow withRiskScores(Optional riskScores) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, milestones, budgetSnapshots, teamMembers, projectPhases, config, riskScores, estimatedDuration, actualDuration, metadata);\n };\n\n public ProjectRow withEstimatedDuration(Optional estimatedDuration) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, milestones, budgetSnapshots, teamMembers, projectPhases, config, riskScores, estimatedDuration, actualDuration, metadata);\n };\n\n public ProjectRow withActualDuration(Optional actualDuration) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, milestones, budgetSnapshots, teamMembers, projectPhases, config, riskScores, estimatedDuration, actualDuration, metadata);\n };\n\n public ProjectRow withMetadata(Optional metadata) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, milestones, budgetSnapshots, teamMembers, projectPhases, config, riskScores, estimatedDuration, actualDuration, metadata);\n };\n\n public static RowParser _rowParser = RowParsers.of(ProjectId.duckDbType, DuckDbTypes.varchar, DuckDbTypes.varchar.opt(), DuckDbTypes.date.opt(), DuckDbTypes.date.opt(), DuckDbTypes.numeric.opt(), DuckDbTypes.varchar.opt(), DuckDbTypes.timestamp.opt(), DuckDbTypes.varcharArray.opt(), DuckDbTypes.decimalArray.opt(), DuckDbTypes.varcharArray.opt(), ProjectProjectPhases.duckDbType.opt(), DuckDbTypes.varchar.mapTo(DuckDbTypes.varchar).opt(), DuckDbTypes.varchar.mapTo(DuckDbTypes.integer).opt(), DuckDbTypes.interval.opt(), DuckDbTypes.interval.opt(), DuckDbTypes.json.opt(), ProjectRow::new, row -> new Object[]{row.id(), row.name(), row.description(), row.startDate(), row.endDate(), row.budget(), row.status(), row.createdAt(), row.milestones(), row.budgetSnapshots(), row.teamMembers(), row.projectPhases(), row.config(), row.riskScores(), row.estimatedDuration(), row.actualDuration(), row.metadata()});;\n\n public ProjectRowUnsaved toUnsavedRow(\n Defaulted> status,\n Defaulted> createdAt\n ) {\n return new ProjectRowUnsaved(id, name, description, startDate, endDate, budget, milestones, budgetSnapshots, teamMembers, projectPhases, config, riskScores, estimatedDuration, actualDuration, metadata, status, createdAt);\n };\n}", - "ProjectId": "package showcase.showcase.project;\n\nimport dev.typr.foundations.DuckDbType;\nimport dev.typr.foundations.DuckDbTypes;\nimport dev.typr.foundations.dsl.Bijection;\nimport dev.typr.foundations.internal.arrayMap;\n\n/** Type for the primary key of table `showcase.project` */\npublic record ProjectId(String value) {\n public ProjectId withValue(String value) {\n return new ProjectId(value);\n };\n\n @Override\n public java.lang.String toString() {\n return value.toString();\n };\n\n static public Bijection bijection =\n Bijection.of(ProjectId::value, ProjectId::new);\n\n static public DuckDbType duckDbType =\n DuckDbTypes.varchar.bimap(ProjectId::new, ProjectId::value);\n\n static public DuckDbType pgTypeArray =\n DuckDbTypes.varcharArray.bimap(xs -> arrayMap.map(xs, ProjectId::new, ProjectId.class), xs -> arrayMap.map(xs, ProjectId::value, String.class));\n}", - "EmployeeSummaryViewRow": "package showcase.showcase.employee_summary;\n\nimport dev.typr.foundations.DuckDbTypes;\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport java.math.BigDecimal;\nimport java.time.LocalDate;\nimport java.util.Optional;\nimport showcase.showcase.company.CompanyId;\nimport showcase.showcase.department.DepartmentId;\nimport showcase.showcase.employee.EmployeeId;\n\n/** View: showcase.employee_summary\n * Summary view of employees with their department and company information\n */\npublic record EmployeeSummaryViewRow(\n /** Points to {@link showcase.showcase.employee.EmployeeRow#id()} */\n EmployeeId employeeId,\n String email,\n String firstName,\n String lastName,\n Optional salary,\n Optional hiredAt,\n Optional active,\n /** Points to {@link showcase.showcase.department.DepartmentRow#id()} */\n DepartmentId departmentId,\n String departmentName,\n Optional departmentBudget,\n /** Points to {@link showcase.showcase.company.CompanyRow#id()} */\n CompanyId companyId,\n String companyName,\n Optional managerId,\n Optional managerFirstName,\n Optional managerLastName\n) {\n /** Points to {@link showcase.showcase.employee.EmployeeRow#id()} */\n public EmployeeSummaryViewRow withEmployeeId(EmployeeId employeeId) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withEmail(String email) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withFirstName(String firstName) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withLastName(String lastName) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withSalary(Optional salary) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withHiredAt(Optional hiredAt) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withActive(Optional active) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n /** Points to {@link showcase.showcase.department.DepartmentRow#id()} */\n public EmployeeSummaryViewRow withDepartmentId(DepartmentId departmentId) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withDepartmentName(String departmentName) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withDepartmentBudget(Optional departmentBudget) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n /** Points to {@link showcase.showcase.company.CompanyRow#id()} */\n public EmployeeSummaryViewRow withCompanyId(CompanyId companyId) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withCompanyName(String companyName) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withManagerId(Optional managerId) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withManagerFirstName(Optional managerFirstName) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withManagerLastName(Optional managerLastName) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public static RowParser _rowParser = RowParsers.of(EmployeeId.duckDbType, DuckDbTypes.varchar, DuckDbTypes.varchar, DuckDbTypes.varchar, DuckDbTypes.numeric.opt(), DuckDbTypes.date.opt(), DuckDbTypes.boolean_.opt(), DepartmentId.duckDbType, DuckDbTypes.varchar, DuckDbTypes.numeric.opt(), CompanyId.duckDbType, DuckDbTypes.varchar, DuckDbTypes.varchar.opt(), DuckDbTypes.varchar.opt(), DuckDbTypes.varchar.opt(), EmployeeSummaryViewRow::new, row -> new Object[]{row.employeeId(), row.email(), row.firstName(), row.lastName(), row.salary(), row.hiredAt(), row.active(), row.departmentId(), row.departmentName(), row.departmentBudget(), row.companyId(), row.companyName(), row.managerId(), row.managerFirstName(), row.managerLastName()});;\n}", - "EmployeeSummaryViewRepo": "package showcase.showcase.employee_summary;\n\nimport dev.typr.foundations.dsl.SelectBuilder;\nimport java.sql.Connection;\nimport java.util.List;\n\npublic interface EmployeeSummaryViewRepo {\n SelectBuilder select();\n\n List selectAll(Connection c);\n}", - "CustomerOrderRow": "package showcase.showcase.customer_order;\n\nimport dev.typr.foundations.DuckDbTypes;\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport java.math.BigDecimal;\nimport java.time.Duration;\nimport java.time.LocalDateTime;\nimport java.time.OffsetDateTime;\nimport java.util.Optional;\nimport showcase.CustomerOrderLineItemsSummary;\nimport showcase.customtypes.Defaulted;\nimport showcase.showcase.address.AddressId;\nimport showcase.showcase.customer.CustomerId;\n\n/** Table: showcase.customer_order\n * Primary key: id\n */\npublic record CustomerOrderRow(\n CustomerOrderId id,\n /** Points to {@link showcase.showcase.customer.CustomerRow#id()} */\n CustomerId customerId,\n /** Points to {@link showcase.showcase.address.AddressRow#id()} */\n Optional shippingAddressId,\n /** Points to {@link showcase.showcase.address.AddressRow#id()} */\n Optional billingAddressId,\n /** Default: 'pending' */\n Optional status,\n BigDecimal subtotal,\n /** Default: 0 */\n Optional tax,\n /** Default: 0 */\n Optional shipping,\n BigDecimal total,\n Optional notes,\n /** Default: CURRENT_TIMESTAMP */\n Optional createdAt,\n Optional shippedAt,\n Optional deliveredAt,\n /** Default: now() */\n Optional orderedAtTz,\n Optional deliveredAtTz,\n Optional tags,\n Optional fulfillmentTimes,\n Optional lineItemsSummary,\n Optional metadata,\n Optional processingTime\n) {\n public CustomerOrderRow withId(CustomerOrderId id) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderedAtTz, deliveredAtTz, tags, fulfillmentTimes, lineItemsSummary, metadata, processingTime);\n };\n\n /** Points to {@link showcase.showcase.customer.CustomerRow#id()} */\n public CustomerOrderRow withCustomerId(CustomerId customerId) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderedAtTz, deliveredAtTz, tags, fulfillmentTimes, lineItemsSummary, metadata, processingTime);\n };\n\n /** Points to {@link showcase.showcase.address.AddressRow#id()} */\n public CustomerOrderRow withShippingAddressId(Optional shippingAddressId) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderedAtTz, deliveredAtTz, tags, fulfillmentTimes, lineItemsSummary, metadata, processingTime);\n };\n\n /** Points to {@link showcase.showcase.address.AddressRow#id()} */\n public CustomerOrderRow withBillingAddressId(Optional billingAddressId) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderedAtTz, deliveredAtTz, tags, fulfillmentTimes, lineItemsSummary, metadata, processingTime);\n };\n\n /** Default: 'pending' */\n public CustomerOrderRow withStatus(Optional status) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderedAtTz, deliveredAtTz, tags, fulfillmentTimes, lineItemsSummary, metadata, processingTime);\n };\n\n public CustomerOrderRow withSubtotal(BigDecimal subtotal) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderedAtTz, deliveredAtTz, tags, fulfillmentTimes, lineItemsSummary, metadata, processingTime);\n };\n\n /** Default: 0 */\n public CustomerOrderRow withTax(Optional tax) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderedAtTz, deliveredAtTz, tags, fulfillmentTimes, lineItemsSummary, metadata, processingTime);\n };\n\n /** Default: 0 */\n public CustomerOrderRow withShipping(Optional shipping) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderedAtTz, deliveredAtTz, tags, fulfillmentTimes, lineItemsSummary, metadata, processingTime);\n };\n\n public CustomerOrderRow withTotal(BigDecimal total) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderedAtTz, deliveredAtTz, tags, fulfillmentTimes, lineItemsSummary, metadata, processingTime);\n };\n\n public CustomerOrderRow withNotes(Optional notes) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderedAtTz, deliveredAtTz, tags, fulfillmentTimes, lineItemsSummary, metadata, processingTime);\n };\n\n /** Default: CURRENT_TIMESTAMP */\n public CustomerOrderRow withCreatedAt(Optional createdAt) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderedAtTz, deliveredAtTz, tags, fulfillmentTimes, lineItemsSummary, metadata, processingTime);\n };\n\n public CustomerOrderRow withShippedAt(Optional shippedAt) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderedAtTz, deliveredAtTz, tags, fulfillmentTimes, lineItemsSummary, metadata, processingTime);\n };\n\n public CustomerOrderRow withDeliveredAt(Optional deliveredAt) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderedAtTz, deliveredAtTz, tags, fulfillmentTimes, lineItemsSummary, metadata, processingTime);\n };\n\n /** Default: now() */\n public CustomerOrderRow withOrderedAtTz(Optional orderedAtTz) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderedAtTz, deliveredAtTz, tags, fulfillmentTimes, lineItemsSummary, metadata, processingTime);\n };\n\n public CustomerOrderRow withDeliveredAtTz(Optional deliveredAtTz) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderedAtTz, deliveredAtTz, tags, fulfillmentTimes, lineItemsSummary, metadata, processingTime);\n };\n\n public CustomerOrderRow withTags(Optional tags) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderedAtTz, deliveredAtTz, tags, fulfillmentTimes, lineItemsSummary, metadata, processingTime);\n };\n\n public CustomerOrderRow withFulfillmentTimes(Optional fulfillmentTimes) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderedAtTz, deliveredAtTz, tags, fulfillmentTimes, lineItemsSummary, metadata, processingTime);\n };\n\n public CustomerOrderRow withLineItemsSummary(Optional lineItemsSummary) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderedAtTz, deliveredAtTz, tags, fulfillmentTimes, lineItemsSummary, metadata, processingTime);\n };\n\n public CustomerOrderRow withMetadata(Optional metadata) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderedAtTz, deliveredAtTz, tags, fulfillmentTimes, lineItemsSummary, metadata, processingTime);\n };\n\n public CustomerOrderRow withProcessingTime(Optional processingTime) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderedAtTz, deliveredAtTz, tags, fulfillmentTimes, lineItemsSummary, metadata, processingTime);\n };\n\n public static RowParser _rowParser = RowParsers.of(CustomerOrderId.duckDbType, CustomerId.duckDbType, AddressId.duckDbType.opt(), AddressId.duckDbType.opt(), DuckDbTypes.varchar.opt(), DuckDbTypes.numeric, DuckDbTypes.numeric.opt(), DuckDbTypes.numeric.opt(), DuckDbTypes.numeric, DuckDbTypes.varchar.opt(), DuckDbTypes.timestamp.opt(), DuckDbTypes.timestamp.opt(), DuckDbTypes.timestamp.opt(), DuckDbTypes.timestamptz.opt(), DuckDbTypes.timestamptz.opt(), DuckDbTypes.varcharArray.opt(), DuckDbTypes.timestampArray.opt(), CustomerOrderLineItemsSummary.duckDbType.opt(), DuckDbTypes.varchar.mapTo(DuckDbTypes.varchar).opt(), DuckDbTypes.interval.opt(), CustomerOrderRow::new, row -> new Object[]{row.id(), row.customerId(), row.shippingAddressId(), row.billingAddressId(), row.status(), row.subtotal(), row.tax(), row.shipping(), row.total(), row.notes(), row.createdAt(), row.shippedAt(), row.deliveredAt(), row.orderedAtTz(), row.deliveredAtTz(), row.tags(), row.fulfillmentTimes(), row.lineItemsSummary(), row.metadata(), row.processingTime()});;\n\n public CustomerOrderRowUnsaved toUnsavedRow(\n Defaulted> status,\n Defaulted> tax,\n Defaulted> shipping,\n Defaulted> createdAt,\n Defaulted> orderedAtTz\n ) {\n return new CustomerOrderRowUnsaved(id, customerId, shippingAddressId, billingAddressId, subtotal, total, notes, shippedAt, deliveredAt, deliveredAtTz, tags, fulfillmentTimes, lineItemsSummary, metadata, processingTime, status, tax, shipping, createdAt, orderedAtTz);\n };\n}", - "CustomerOrderRepo": "package showcase.showcase.customer_order;\n\nimport dev.typr.foundations.dsl.DeleteBuilder;\nimport dev.typr.foundations.dsl.SelectBuilder;\nimport dev.typr.foundations.dsl.UpdateBuilder;\nimport java.sql.Connection;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\n\npublic interface CustomerOrderRepo {\n DeleteBuilder delete();\n\n Boolean deleteById(\n CustomerOrderId id,\n Connection c\n );\n\n Integer deleteByIds(\n CustomerOrderId[] ids,\n Connection c\n );\n\n CustomerOrderRow insert(\n CustomerOrderRow unsaved,\n Connection c\n );\n\n CustomerOrderRow insert(\n CustomerOrderRowUnsaved unsaved,\n Connection c\n );\n\n SelectBuilder select();\n\n List selectAll(Connection c);\n\n Optional selectById(\n CustomerOrderId id,\n Connection c\n );\n\n List selectByIds(\n CustomerOrderId[] ids,\n Connection c\n );\n\n Map selectByIdsTracked(\n CustomerOrderId[] ids,\n Connection c\n );\n\n UpdateBuilder update();\n\n Boolean update(\n CustomerOrderRow row,\n Connection c\n );\n\n CustomerOrderRow upsert(\n CustomerOrderRow unsaved,\n Connection c\n );\n\n List upsertBatch(\n Iterator unsaved,\n Connection c\n );\n}", - "OrderItemRow": "package showcase.showcase.order_item;\n\nimport dev.typr.foundations.DuckDbTypes;\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport java.math.BigDecimal;\nimport java.util.Optional;\nimport showcase.customtypes.Defaulted;\nimport showcase.showcase.customer_order.CustomerOrderId;\nimport showcase.showcase.product.ProductId;\n\n/** Table: showcase.order_item\n * Composite primary key: order_id, product_id\n */\npublic record OrderItemRow(\n /** Points to {@link showcase.showcase.customer_order.CustomerOrderRow#id()} */\n CustomerOrderId orderId,\n /** Points to {@link showcase.showcase.product.ProductRow#id()} */\n ProductId productId,\n Integer quantity,\n BigDecimal unitPrice,\n /** Default: 0 */\n Optional discount\n) {\n /** Points to {@link showcase.showcase.customer_order.CustomerOrderRow#id()} */\n public OrderItemRow withOrderId(CustomerOrderId orderId) {\n return new OrderItemRow(orderId, productId, quantity, unitPrice, discount);\n };\n\n /** Points to {@link showcase.showcase.product.ProductRow#id()} */\n public OrderItemRow withProductId(ProductId productId) {\n return new OrderItemRow(orderId, productId, quantity, unitPrice, discount);\n };\n\n public OrderItemRow withQuantity(Integer quantity) {\n return new OrderItemRow(orderId, productId, quantity, unitPrice, discount);\n };\n\n public OrderItemRow withUnitPrice(BigDecimal unitPrice) {\n return new OrderItemRow(orderId, productId, quantity, unitPrice, discount);\n };\n\n /** Default: 0 */\n public OrderItemRow withDiscount(Optional discount) {\n return new OrderItemRow(orderId, productId, quantity, unitPrice, discount);\n };\n\n public static RowParser _rowParser = RowParsers.of(CustomerOrderId.duckDbType, ProductId.duckDbType, DuckDbTypes.integer, DuckDbTypes.numeric, DuckDbTypes.numeric.opt(), OrderItemRow::new, row -> new Object[]{row.orderId(), row.productId(), row.quantity(), row.unitPrice(), row.discount()});;\n\n static public OrderItemRow apply(\n OrderItemId compositeId,\n Integer quantity,\n BigDecimal unitPrice,\n Optional discount\n ) {\n return new OrderItemRow(compositeId.orderId(), compositeId.productId(), quantity, unitPrice, discount);\n };\n\n public OrderItemId compositeId() {\n return new OrderItemId(orderId, productId);\n };\n\n public OrderItemId id() {\n return this.compositeId();\n };\n\n public OrderItemRowUnsaved toUnsavedRow(Defaulted> discount) {\n return new OrderItemRowUnsaved(orderId, productId, quantity, unitPrice, discount);\n };\n}", - "OrderItemId": "package showcase.showcase.order_item;\n\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport showcase.showcase.customer_order.CustomerOrderId;\nimport showcase.showcase.product.ProductId;\n\n/** Type for the composite primary key of table `showcase.order_item` */\npublic record OrderItemId(\n CustomerOrderId orderId,\n ProductId productId\n) {\n public OrderItemId withOrderId(CustomerOrderId orderId) {\n return new OrderItemId(orderId, productId);\n };\n\n public OrderItemId withProductId(ProductId productId) {\n return new OrderItemId(orderId, productId);\n };\n\n public static RowParser _rowParser = RowParsers.of(CustomerOrderId.duckDbType, ProductId.duckDbType, OrderItemId::new, row -> new Object[]{row.orderId(), row.productId()});;\n}", - "ProductRow": "package showcase.showcase.product;\n\nimport dev.typr.foundations.DuckDbTypes;\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport dev.typr.foundations.data.Json;\nimport java.math.BigDecimal;\nimport java.time.LocalDateTime;\nimport java.util.Optional;\nimport showcase.ProductDimensions;\nimport showcase.customtypes.Defaulted;\nimport showcase.showcase.category.CategoryId;\n\n/** Table: showcase.product\n * Primary key: id\n */\npublic record ProductRow(\n ProductId id,\n /** Points to {@link showcase.showcase.category.CategoryRow#id()} */\n Optional categoryId,\n String name,\n String sku,\n BigDecimal price,\n Optional cost,\n /** Default: true */\n Optional inStock,\n /** Default: 0 */\n Optional quantity,\n Optional weight,\n /** Default: CURRENT_TIMESTAMP */\n Optional createdAt,\n Optional tags,\n Optional images,\n Optional relatedSkus,\n Optional priceHistory,\n Optional categoryIds,\n Optional dimensions,\n Optional attributes,\n Optional specifications,\n Optional pricesByRegion,\n Optional stockByWarehouse,\n Optional seoMetadata\n) {\n public ProductRow withId(ProductId id) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, tags, images, relatedSkus, priceHistory, categoryIds, dimensions, attributes, specifications, pricesByRegion, stockByWarehouse, seoMetadata);\n };\n\n /** Points to {@link showcase.showcase.category.CategoryRow#id()} */\n public ProductRow withCategoryId(Optional categoryId) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, tags, images, relatedSkus, priceHistory, categoryIds, dimensions, attributes, specifications, pricesByRegion, stockByWarehouse, seoMetadata);\n };\n\n public ProductRow withName(String name) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, tags, images, relatedSkus, priceHistory, categoryIds, dimensions, attributes, specifications, pricesByRegion, stockByWarehouse, seoMetadata);\n };\n\n public ProductRow withSku(String sku) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, tags, images, relatedSkus, priceHistory, categoryIds, dimensions, attributes, specifications, pricesByRegion, stockByWarehouse, seoMetadata);\n };\n\n public ProductRow withPrice(BigDecimal price) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, tags, images, relatedSkus, priceHistory, categoryIds, dimensions, attributes, specifications, pricesByRegion, stockByWarehouse, seoMetadata);\n };\n\n public ProductRow withCost(Optional cost) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, tags, images, relatedSkus, priceHistory, categoryIds, dimensions, attributes, specifications, pricesByRegion, stockByWarehouse, seoMetadata);\n };\n\n /** Default: true */\n public ProductRow withInStock(Optional inStock) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, tags, images, relatedSkus, priceHistory, categoryIds, dimensions, attributes, specifications, pricesByRegion, stockByWarehouse, seoMetadata);\n };\n\n /** Default: 0 */\n public ProductRow withQuantity(Optional quantity) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, tags, images, relatedSkus, priceHistory, categoryIds, dimensions, attributes, specifications, pricesByRegion, stockByWarehouse, seoMetadata);\n };\n\n public ProductRow withWeight(Optional weight) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, tags, images, relatedSkus, priceHistory, categoryIds, dimensions, attributes, specifications, pricesByRegion, stockByWarehouse, seoMetadata);\n };\n\n /** Default: CURRENT_TIMESTAMP */\n public ProductRow withCreatedAt(Optional createdAt) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, tags, images, relatedSkus, priceHistory, categoryIds, dimensions, attributes, specifications, pricesByRegion, stockByWarehouse, seoMetadata);\n };\n\n public ProductRow withTags(Optional tags) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, tags, images, relatedSkus, priceHistory, categoryIds, dimensions, attributes, specifications, pricesByRegion, stockByWarehouse, seoMetadata);\n };\n\n public ProductRow withImages(Optional images) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, tags, images, relatedSkus, priceHistory, categoryIds, dimensions, attributes, specifications, pricesByRegion, stockByWarehouse, seoMetadata);\n };\n\n public ProductRow withRelatedSkus(Optional relatedSkus) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, tags, images, relatedSkus, priceHistory, categoryIds, dimensions, attributes, specifications, pricesByRegion, stockByWarehouse, seoMetadata);\n };\n\n public ProductRow withPriceHistory(Optional priceHistory) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, tags, images, relatedSkus, priceHistory, categoryIds, dimensions, attributes, specifications, pricesByRegion, stockByWarehouse, seoMetadata);\n };\n\n public ProductRow withCategoryIds(Optional categoryIds) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, tags, images, relatedSkus, priceHistory, categoryIds, dimensions, attributes, specifications, pricesByRegion, stockByWarehouse, seoMetadata);\n };\n\n public ProductRow withDimensions(Optional dimensions) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, tags, images, relatedSkus, priceHistory, categoryIds, dimensions, attributes, specifications, pricesByRegion, stockByWarehouse, seoMetadata);\n };\n\n public ProductRow withAttributes(Optional attributes) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, tags, images, relatedSkus, priceHistory, categoryIds, dimensions, attributes, specifications, pricesByRegion, stockByWarehouse, seoMetadata);\n };\n\n public ProductRow withSpecifications(Optional specifications) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, tags, images, relatedSkus, priceHistory, categoryIds, dimensions, attributes, specifications, pricesByRegion, stockByWarehouse, seoMetadata);\n };\n\n public ProductRow withPricesByRegion(Optional pricesByRegion) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, tags, images, relatedSkus, priceHistory, categoryIds, dimensions, attributes, specifications, pricesByRegion, stockByWarehouse, seoMetadata);\n };\n\n public ProductRow withStockByWarehouse(Optional stockByWarehouse) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, tags, images, relatedSkus, priceHistory, categoryIds, dimensions, attributes, specifications, pricesByRegion, stockByWarehouse, seoMetadata);\n };\n\n public ProductRow withSeoMetadata(Optional seoMetadata) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, tags, images, relatedSkus, priceHistory, categoryIds, dimensions, attributes, specifications, pricesByRegion, stockByWarehouse, seoMetadata);\n };\n\n public static RowParser _rowParser = RowParsers.of(ProductId.duckDbType, CategoryId.duckDbType.opt(), DuckDbTypes.varchar, DuckDbTypes.varchar, DuckDbTypes.numeric, DuckDbTypes.numeric.opt(), DuckDbTypes.boolean_.opt(), DuckDbTypes.integer.opt(), DuckDbTypes.numeric.opt(), DuckDbTypes.timestamp.opt(), DuckDbTypes.varcharArray.opt(), DuckDbTypes.varcharArray.opt(), DuckDbTypes.varcharArray.opt(), DuckDbTypes.decimalArray.opt(), DuckDbTypes.integerArray.opt(), ProductDimensions.duckDbType.opt(), DuckDbTypes.varchar.mapTo(DuckDbTypes.varchar).opt(), DuckDbTypes.varchar.mapTo(DuckDbTypes.varchar).opt(), DuckDbTypes.varchar.mapTo(DuckDbTypes.numeric).opt(), DuckDbTypes.varchar.mapTo(DuckDbTypes.integer).opt(), DuckDbTypes.json.opt(), ProductRow::new, row -> new Object[]{row.id(), row.categoryId(), row.name(), row.sku(), row.price(), row.cost(), row.inStock(), row.quantity(), row.weight(), row.createdAt(), row.tags(), row.images(), row.relatedSkus(), row.priceHistory(), row.categoryIds(), row.dimensions(), row.attributes(), row.specifications(), row.pricesByRegion(), row.stockByWarehouse(), row.seoMetadata()});;\n\n public ProductRowUnsaved toUnsavedRow(\n Defaulted> inStock,\n Defaulted> quantity,\n Defaulted> createdAt\n ) {\n return new ProductRowUnsaved(id, categoryId, name, sku, price, cost, weight, tags, images, relatedSkus, priceHistory, categoryIds, dimensions, attributes, specifications, pricesByRegion, stockByWarehouse, seoMetadata, inStock, quantity, createdAt);\n };\n}", - "ProductId": "package showcase.showcase.product;\n\nimport dev.typr.foundations.DuckDbType;\nimport dev.typr.foundations.DuckDbTypes;\nimport dev.typr.foundations.dsl.Bijection;\nimport dev.typr.foundations.internal.arrayMap;\n\n/** Type for the primary key of table `showcase.product` */\npublic record ProductId(String value) {\n public ProductId withValue(String value) {\n return new ProductId(value);\n };\n\n @Override\n public java.lang.String toString() {\n return value.toString();\n };\n\n static public Bijection bijection =\n Bijection.of(ProductId::value, ProductId::new);\n\n static public DuckDbType duckDbType =\n DuckDbTypes.varchar.bimap(ProductId::new, ProductId::value);\n\n static public DuckDbType pgTypeArray =\n DuckDbTypes.varcharArray.bimap(xs -> arrayMap.map(xs, ProductId::new, ProductId.class), xs -> arrayMap.map(xs, ProductId::value, String.class));\n}", - "CategoryRow": "package showcase.showcase.category;\n\nimport dev.typr.foundations.DuckDbTypes;\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport java.util.Optional;\n\n/** Table: showcase.category\n * Primary key: id\n */\npublic record CategoryRow(\n CategoryId id,\n /** Points to {@link showcase.showcase.category.CategoryRow#id()} */\n Optional parentId,\n String name,\n Optional description\n) {\n public CategoryRow withId(CategoryId id) {\n return new CategoryRow(id, parentId, name, description);\n };\n\n /** Points to {@link showcase.showcase.category.CategoryRow#id()} */\n public CategoryRow withParentId(Optional parentId) {\n return new CategoryRow(id, parentId, name, description);\n };\n\n public CategoryRow withName(String name) {\n return new CategoryRow(id, parentId, name, description);\n };\n\n public CategoryRow withDescription(Optional description) {\n return new CategoryRow(id, parentId, name, description);\n };\n\n public static RowParser _rowParser = RowParsers.of(CategoryId.duckDbType, CategoryId.duckDbType.opt(), DuckDbTypes.varchar, DuckDbTypes.varchar.opt(), CategoryRow::new, row -> new Object[]{row.id(), row.parentId(), row.name(), row.description()});;\n}", - "CategoryId": "package showcase.showcase.category;\n\nimport dev.typr.foundations.DuckDbType;\nimport dev.typr.foundations.DuckDbTypes;\nimport dev.typr.foundations.dsl.Bijection;\nimport dev.typr.foundations.internal.arrayMap;\n\n/** Type for the primary key of table `showcase.category` */\npublic record CategoryId(String value) {\n public CategoryId withValue(String value) {\n return new CategoryId(value);\n };\n\n @Override\n public java.lang.String toString() {\n return value.toString();\n };\n\n static public Bijection bijection =\n Bijection.of(CategoryId::value, CategoryId::new);\n\n static public DuckDbType duckDbType =\n DuckDbTypes.varchar.bimap(CategoryId::new, CategoryId::value);\n\n static public DuckDbType pgTypeArray =\n DuckDbTypes.varcharArray.bimap(xs -> arrayMap.map(xs, CategoryId::new, CategoryId.class), xs -> arrayMap.map(xs, CategoryId::value, String.class));\n}", - "AddressRow": "package showcase.showcase.address;\n\nimport dev.typr.foundations.DuckDbTypes;\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport java.util.Optional;\nimport showcase.AddressCoordinates;\nimport showcase.customtypes.Defaulted;\nimport showcase.showcase.customer.CustomerId;\n\n/** Table: showcase.address\n * Primary key: id\n */\npublic record AddressRow(\n AddressId id,\n /** Points to {@link showcase.showcase.customer.CustomerRow#id()} */\n CustomerId customerId,\n String addressType,\n String street,\n String city,\n Optional state,\n Optional postalCode,\n String country,\n /** Default: false */\n Optional isDefault,\n Optional coordinates\n) {\n public AddressRow withId(AddressId id) {\n return new AddressRow(id, customerId, addressType, street, city, state, postalCode, country, isDefault, coordinates);\n };\n\n /** Points to {@link showcase.showcase.customer.CustomerRow#id()} */\n public AddressRow withCustomerId(CustomerId customerId) {\n return new AddressRow(id, customerId, addressType, street, city, state, postalCode, country, isDefault, coordinates);\n };\n\n public AddressRow withAddressType(String addressType) {\n return new AddressRow(id, customerId, addressType, street, city, state, postalCode, country, isDefault, coordinates);\n };\n\n public AddressRow withStreet(String street) {\n return new AddressRow(id, customerId, addressType, street, city, state, postalCode, country, isDefault, coordinates);\n };\n\n public AddressRow withCity(String city) {\n return new AddressRow(id, customerId, addressType, street, city, state, postalCode, country, isDefault, coordinates);\n };\n\n public AddressRow withState(Optional state) {\n return new AddressRow(id, customerId, addressType, street, city, state, postalCode, country, isDefault, coordinates);\n };\n\n public AddressRow withPostalCode(Optional postalCode) {\n return new AddressRow(id, customerId, addressType, street, city, state, postalCode, country, isDefault, coordinates);\n };\n\n public AddressRow withCountry(String country) {\n return new AddressRow(id, customerId, addressType, street, city, state, postalCode, country, isDefault, coordinates);\n };\n\n /** Default: false */\n public AddressRow withIsDefault(Optional isDefault) {\n return new AddressRow(id, customerId, addressType, street, city, state, postalCode, country, isDefault, coordinates);\n };\n\n public AddressRow withCoordinates(Optional coordinates) {\n return new AddressRow(id, customerId, addressType, street, city, state, postalCode, country, isDefault, coordinates);\n };\n\n public static RowParser _rowParser = RowParsers.of(AddressId.duckDbType, CustomerId.duckDbType, DuckDbTypes.varchar, DuckDbTypes.varchar, DuckDbTypes.varchar, DuckDbTypes.varchar.opt(), DuckDbTypes.varchar.opt(), DuckDbTypes.varchar, DuckDbTypes.boolean_.opt(), AddressCoordinates.duckDbType.opt(), AddressRow::new, row -> new Object[]{row.id(), row.customerId(), row.addressType(), row.street(), row.city(), row.state(), row.postalCode(), row.country(), row.isDefault(), row.coordinates()});;\n\n public AddressRowUnsaved toUnsavedRow(Defaulted> isDefault) {\n return new AddressRowUnsaved(id, customerId, addressType, street, city, state, postalCode, country, coordinates, isDefault);\n };\n}", - "AddressId": "package showcase.showcase.address;\n\nimport dev.typr.foundations.DuckDbType;\nimport dev.typr.foundations.DuckDbTypes;\nimport dev.typr.foundations.dsl.Bijection;\nimport dev.typr.foundations.internal.arrayMap;\n\n/** Type for the primary key of table `showcase.address` */\npublic record AddressId(String value) {\n public AddressId withValue(String value) {\n return new AddressId(value);\n };\n\n @Override\n public java.lang.String toString() {\n return value.toString();\n };\n\n static public Bijection bijection =\n Bijection.of(AddressId::value, AddressId::new);\n\n static public DuckDbType duckDbType =\n DuckDbTypes.varchar.bimap(AddressId::new, AddressId::value);\n\n static public DuckDbType pgTypeArray =\n DuckDbTypes.varcharArray.bimap(xs -> arrayMap.map(xs, AddressId::new, AddressId.class), xs -> arrayMap.map(xs, AddressId::value, String.class));\n}", - "Defaulted": "package showcase.customtypes;\n\n\n\n/** This signals a value where if you don't provide it, postgres will generate it for you */\npublic sealed interface Defaulted permits Defaulted.Provided, Defaulted.UseDefault {\n record Provided(T value) implements Defaulted {\n public Provided withValue(T value) {\n return new Provided<>(value);\n };\n\n @Override\n public U fold(\n java.util.function.Supplier onDefault,\n java.util.function.Function onProvided\n ) {\n return onProvided.apply(value);\n };\n\n @Override\n public T getOrElse(java.util.function.Supplier onDefault) {\n return value;\n };\n\n @Override\n public void visit(\n java.lang.Runnable onDefault,\n java.util.function.Consumer onProvided\n ) {\n onProvided.accept(value);\n };\n };\n\n record UseDefault() implements Defaulted {\n @Override\n public U fold(\n java.util.function.Supplier onDefault,\n java.util.function.Function onProvided\n ) {\n return onDefault.get();\n };\n\n @Override\n public T getOrElse(java.util.function.Supplier onDefault) {\n return onDefault.get();\n };\n\n @Override\n public void visit(\n java.lang.Runnable onDefault,\n java.util.function.Consumer onProvided\n ) {\n onDefault.run();\n };\n };\n\n U fold(\n java.util.function.Supplier onDefault,\n java.util.function.Function onProvided\n );\n\n T getOrElse(java.util.function.Supplier onDefault);\n\n void visit(\n java.lang.Runnable onDefault,\n java.util.function.Consumer onProvided\n );\n}", - "TestInsert": "package showcase;\n\nimport dev.typr.foundations.data.Json;\nimport dev.typr.foundations.internal.RandomHelper;\nimport java.math.BigDecimal;\nimport java.math.BigInteger;\nimport java.sql.Connection;\nimport java.time.Duration;\nimport java.time.LocalDate;\nimport java.time.LocalDateTime;\nimport java.time.LocalTime;\nimport java.time.OffsetDateTime;\nimport java.util.Optional;\nimport java.util.Random;\nimport java.util.UUID;\nimport showcase.customtypes.Defaulted;\nimport showcase.showcase.address.AddressId;\nimport showcase.showcase.address.AddressRepoImpl;\nimport showcase.showcase.address.AddressRow;\nimport showcase.showcase.address.AddressRowUnsaved;\nimport showcase.showcase.audit_log.AuditLogId;\nimport showcase.showcase.audit_log.AuditLogRepoImpl;\nimport showcase.showcase.audit_log.AuditLogRow;\nimport showcase.showcase.audit_log.AuditLogRowUnsaved;\nimport showcase.showcase.category.CategoryId;\nimport showcase.showcase.category.CategoryRepoImpl;\nimport showcase.showcase.category.CategoryRow;\nimport showcase.showcase.company.CompanyId;\nimport showcase.showcase.company.CompanyRepoImpl;\nimport showcase.showcase.company.CompanyRow;\nimport showcase.showcase.company.CompanyRowUnsaved;\nimport showcase.showcase.customer.CustomerId;\nimport showcase.showcase.customer.CustomerRepoImpl;\nimport showcase.showcase.customer.CustomerRow;\nimport showcase.showcase.customer.CustomerRowUnsaved;\nimport showcase.showcase.customer_order.CustomerOrderId;\nimport showcase.showcase.customer_order.CustomerOrderRepoImpl;\nimport showcase.showcase.customer_order.CustomerOrderRow;\nimport showcase.showcase.customer_order.CustomerOrderRowUnsaved;\nimport showcase.showcase.datetime_demo.DatetimeDemoId;\nimport showcase.showcase.datetime_demo.DatetimeDemoRepoImpl;\nimport showcase.showcase.datetime_demo.DatetimeDemoRow;\nimport showcase.showcase.datetime_demo.DatetimeDemoRowUnsaved;\nimport showcase.showcase.department.DepartmentId;\nimport showcase.showcase.department.DepartmentRepoImpl;\nimport showcase.showcase.department.DepartmentRow;\nimport showcase.showcase.employee.EmployeeId;\nimport showcase.showcase.employee.EmployeeRepoImpl;\nimport showcase.showcase.employee.EmployeeRow;\nimport showcase.showcase.employee.EmployeeRowUnsaved;\nimport showcase.showcase.file_storage.FileStorageId;\nimport showcase.showcase.file_storage.FileStorageRepoImpl;\nimport showcase.showcase.file_storage.FileStorageRow;\nimport showcase.showcase.file_storage.FileStorageRowUnsaved;\nimport showcase.showcase.financial_record.FinancialRecordId;\nimport showcase.showcase.financial_record.FinancialRecordRepoImpl;\nimport showcase.showcase.financial_record.FinancialRecordRow;\nimport showcase.showcase.financial_record.FinancialRecordRowUnsaved;\nimport showcase.showcase.numeric_types_demo.NumericTypesDemoId;\nimport showcase.showcase.numeric_types_demo.NumericTypesDemoRepoImpl;\nimport showcase.showcase.numeric_types_demo.NumericTypesDemoRow;\nimport showcase.showcase.numeric_types_demo.NumericTypesDemoRowUnsaved;\nimport showcase.showcase.order_item.OrderItemRepoImpl;\nimport showcase.showcase.order_item.OrderItemRow;\nimport showcase.showcase.order_item.OrderItemRowUnsaved;\nimport showcase.showcase.product.ProductId;\nimport showcase.showcase.product.ProductRepoImpl;\nimport showcase.showcase.product.ProductRow;\nimport showcase.showcase.product.ProductRowUnsaved;\nimport showcase.showcase.project.ProjectId;\nimport showcase.showcase.project.ProjectRepoImpl;\nimport showcase.showcase.project.ProjectRow;\nimport showcase.showcase.project.ProjectRowUnsaved;\nimport showcase.showcase.project_assignment.ProjectAssignmentRepoImpl;\nimport showcase.showcase.project_assignment.ProjectAssignmentRow;\nimport showcase.showcase.project_assignment.ProjectAssignmentRowUnsaved;\nimport showcase.showcase.scientific_data.ScientificDataId;\nimport showcase.showcase.scientific_data.ScientificDataRepoImpl;\nimport showcase.showcase.scientific_data.ScientificDataRow;\nimport showcase.showcase.scientific_data.ScientificDataRowUnsaved;\nimport showcase.showcase.session.SessionId;\nimport showcase.showcase.session.SessionRepoImpl;\nimport showcase.showcase.session.SessionRow;\nimport showcase.showcase.session.SessionRowUnsaved;\nimport showcase.showcase.subscription.SubscriptionId;\nimport showcase.showcase.subscription.SubscriptionRepoImpl;\nimport showcase.showcase.subscription.SubscriptionRow;\nimport showcase.showcase.subscription.SubscriptionRowUnsaved;\n\n/** Methods to generate random data for `Ident(TestInsert)` */\npublic record TestInsert(Random random) {\n public TestInsert withRandom(Random random) {\n return new TestInsert(random);\n };\n\n public AddressRow showcaseAddress(\n CustomerId customerId,\n AddressId id,\n String addressType,\n String street,\n String city,\n Optional state,\n Optional postalCode,\n String country,\n Optional coordinates,\n Defaulted> isDefault,\n Connection c\n ) {\n return (new AddressRepoImpl()).insert(new AddressRowUnsaved(id, customerId, addressType, street, city, state, postalCode, country, coordinates, isDefault), c);\n };\n\n public AuditLogRow showcaseAuditLog(\n AuditLogId id,\n String tableName,\n String recordId,\n String action,\n Optional oldValues,\n Optional newValues,\n Optional changedBy,\n Defaulted> changedAt,\n Connection c\n ) {\n return (new AuditLogRepoImpl()).insert(new AuditLogRowUnsaved(id, tableName, recordId, action, oldValues, newValues, changedBy, changedAt), c);\n };\n\n public CategoryRow showcaseCategory(\n CategoryId id,\n Optional parentId,\n String name,\n Optional description,\n Connection c\n ) {\n return (new CategoryRepoImpl()).insert(new CategoryRow(id, parentId, name, description), c);\n };\n\n public CompanyRow showcaseCompany(\n CompanyId id,\n String name,\n Optional foundedYear,\n Defaulted> active,\n Defaulted> createdAt,\n Connection c\n ) {\n return (new CompanyRepoImpl()).insert(new CompanyRowUnsaved(id, name, foundedYear, active, createdAt), c);\n };\n\n public CustomerRow showcaseCustomer(\n CustomerId id,\n String email,\n String firstName,\n String lastName,\n Optional phone,\n Optional interests,\n Optional orderCounts,\n Optional preferences,\n Optional metadata,\n Defaulted> verified,\n Defaulted> createdAt,\n Connection c\n ) {\n return (new CustomerRepoImpl()).insert(new CustomerRowUnsaved(id, email, firstName, lastName, phone, interests, orderCounts, preferences, metadata, verified, createdAt), c);\n };\n\n public CustomerOrderRow showcaseCustomerOrder(\n CustomerId customerId,\n CustomerOrderId id,\n Optional shippingAddressId,\n Optional billingAddressId,\n BigDecimal subtotal,\n BigDecimal total,\n Optional notes,\n Optional shippedAt,\n Optional deliveredAt,\n Optional deliveredAtTz,\n Optional tags,\n Optional fulfillmentTimes,\n Optional lineItemsSummary,\n Optional metadata,\n Optional processingTime,\n Defaulted> status,\n Defaulted> tax,\n Defaulted> shipping,\n Defaulted> createdAt,\n Defaulted> orderedAtTz,\n Connection c\n ) {\n return (new CustomerOrderRepoImpl()).insert(new CustomerOrderRowUnsaved(id, customerId, shippingAddressId, billingAddressId, subtotal, total, notes, shippedAt, deliveredAt, deliveredAtTz, tags, fulfillmentTimes, lineItemsSummary, metadata, processingTime, status, tax, shipping, createdAt, orderedAtTz), c);\n };\n\n public DatetimeDemoRow showcaseDatetimeDemo(\n DatetimeDemoId id,\n Optional dateOnly,\n Optional timeOnly,\n Optional timestampVal,\n Optional timestampTz,\n Optional timestampS,\n Optional timestampMs,\n Optional timestampNs,\n Defaulted> createdAt,\n Connection c\n ) {\n return (new DatetimeDemoRepoImpl()).insert(new DatetimeDemoRowUnsaved(id, dateOnly, timeOnly, timestampVal, timestampTz, timestampS, timestampMs, timestampNs, createdAt), c);\n };\n\n public DepartmentRow showcaseDepartment(\n CompanyId companyId,\n DepartmentId id,\n String name,\n Optional budget,\n Connection c\n ) {\n return (new DepartmentRepoImpl()).insert(new DepartmentRow(id, companyId, name, budget), c);\n };\n\n public EmployeeRow showcaseEmployee(\n DepartmentId departmentId,\n EmployeeId id,\n Optional managerId,\n String email,\n String firstName,\n String lastName,\n Optional salary,\n Optional hiredAt,\n Optional skills,\n Optional certifications,\n Optional weeklyAvailability,\n Optional contactInfo,\n Optional settings,\n Optional skillsRating,\n Optional probationPeriod,\n Defaulted> active,\n Defaulted> createdAt,\n Connection c\n ) {\n return (new EmployeeRepoImpl()).insert(new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, skills, certifications, weeklyAvailability, contactInfo, settings, skillsRating, probationPeriod, active, createdAt), c);\n };\n\n public FileStorageRow showcaseFileStorage(\n FileStorageId id,\n String filename,\n Optional mimeType,\n Optional fileData,\n Optional thumbnail,\n Optional checksum,\n Optional fileSize,\n Defaulted> uploadedAt,\n Connection c\n ) {\n return (new FileStorageRepoImpl()).insert(new FileStorageRowUnsaved(id, filename, mimeType, fileData, thumbnail, checksum, fileSize, uploadedAt), c);\n };\n\n public FinancialRecordRow showcaseFinancialRecord(\n FinancialRecordId id,\n String description,\n BigDecimal amount,\n Optional balance,\n Optional exchangeRate,\n Optional percentage,\n Defaulted> createdAt,\n Connection c\n ) {\n return (new FinancialRecordRepoImpl()).insert(new FinancialRecordRowUnsaved(id, description, amount, balance, exchangeRate, percentage, createdAt), c);\n };\n\n public NumericTypesDemoRow showcaseNumericTypesDemo(\n NumericTypesDemoId id,\n Optional tinyVal,\n Optional utinyVal,\n Optional smallVal,\n Optional usmallVal,\n Optional intVal,\n Optional uintVal,\n Optional bigVal,\n Optional ubigVal,\n Optional hugeVal,\n Optional uhugeVal,\n Defaulted> createdAt,\n Connection c\n ) {\n return (new NumericTypesDemoRepoImpl()).insert(new NumericTypesDemoRowUnsaved(id, tinyVal, utinyVal, smallVal, usmallVal, intVal, uintVal, bigVal, ubigVal, hugeVal, uhugeVal, createdAt), c);\n };\n\n public OrderItemRow showcaseOrderItem(\n CustomerOrderId orderId,\n ProductId productId,\n Integer quantity,\n BigDecimal unitPrice,\n Defaulted> discount,\n Connection c\n ) {\n return (new OrderItemRepoImpl()).insert(new OrderItemRowUnsaved(orderId, productId, quantity, unitPrice, discount), c);\n };\n\n public ProductRow showcaseProduct(\n ProductId id,\n Optional categoryId,\n String name,\n String sku,\n BigDecimal price,\n Optional cost,\n Optional weight,\n Optional tags,\n Optional images,\n Optional relatedSkus,\n Optional priceHistory,\n Optional categoryIds,\n Optional dimensions,\n Optional attributes,\n Optional specifications,\n Optional pricesByRegion,\n Optional stockByWarehouse,\n Optional seoMetadata,\n Defaulted> inStock,\n Defaulted> quantity,\n Defaulted> createdAt,\n Connection c\n ) {\n return (new ProductRepoImpl()).insert(new ProductRowUnsaved(id, categoryId, name, sku, price, cost, weight, tags, images, relatedSkus, priceHistory, categoryIds, dimensions, attributes, specifications, pricesByRegion, stockByWarehouse, seoMetadata, inStock, quantity, createdAt), c);\n };\n\n public ProjectRow showcaseProject(\n ProjectId id,\n String name,\n Optional description,\n Optional startDate,\n Optional endDate,\n Optional budget,\n Optional milestones,\n Optional budgetSnapshots,\n Optional teamMembers,\n Optional projectPhases,\n Optional config,\n Optional riskScores,\n Optional estimatedDuration,\n Optional actualDuration,\n Optional metadata,\n Defaulted> status,\n Defaulted> createdAt,\n Connection c\n ) {\n return (new ProjectRepoImpl()).insert(new ProjectRowUnsaved(id, name, description, startDate, endDate, budget, milestones, budgetSnapshots, teamMembers, projectPhases, config, riskScores, estimatedDuration, actualDuration, metadata, status, createdAt), c);\n };\n\n public ProjectAssignmentRow showcaseProjectAssignment(\n EmployeeId employeeId,\n ProjectId projectId,\n String role,\n Optional startDate,\n Optional endDate,\n Defaulted> hoursAllocated,\n Connection c\n ) {\n return (new ProjectAssignmentRepoImpl()).insert(new ProjectAssignmentRowUnsaved(employeeId, projectId, role, startDate, endDate, hoursAllocated), c);\n };\n\n public ScientificDataRow showcaseScientificData(\n ScientificDataId id,\n Optional floatVal,\n Optional doubleVal,\n Defaulted> createdAt,\n Connection c\n ) {\n return (new ScientificDataRepoImpl()).insert(new ScientificDataRowUnsaved(id, floatVal, doubleVal, createdAt), c);\n };\n\n public SessionRow showcaseSession(\n LocalDateTime expiresAt,\n Optional userId,\n Optional refreshToken,\n Optional deviceId,\n Defaulted id,\n Defaulted token,\n Defaulted> createdAt,\n Connection c\n ) {\n return (new SessionRepoImpl()).insert(new SessionRowUnsaved(userId, refreshToken, deviceId, expiresAt, id, token, createdAt), c);\n };\n\n public SubscriptionRow showcaseSubscription(\n Duration billingCycle,\n SubscriptionId id,\n String customerId,\n String planName,\n Optional trialPeriod,\n Defaulted> startedAt,\n Connection c\n ) {\n return (new SubscriptionRepoImpl()).insert(new SubscriptionRowUnsaved(id, customerId, planName, billingCycle, trialPeriod, startedAt), c);\n };\n}" - }, - "kotlin": { - "CompanyRow": "package showcase.showcase.company\n\nimport dev.typr.foundations.DuckDbTypes\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport dev.typr.foundations.kotlin.nullable\nimport java.time.LocalDateTime\nimport showcase.customtypes.Defaulted\n\n/** Table: showcase.company\n * Primary key: id\n */\ndata class CompanyRow(\n val id: CompanyId,\n val name: String,\n val foundedYear: Int?,\n /** Default: true */\n val active: Boolean?,\n /** Default: CURRENT_TIMESTAMP */\n val createdAt: LocalDateTime?\n) {\n fun toUnsavedRow(\n active: Defaulted,\n createdAt: Defaulted\n ): CompanyRowUnsaved = CompanyRowUnsaved(id, name, foundedYear, active, createdAt)\n\n companion object {\n val _rowParser: RowParser = RowParsers.of(CompanyId.duckDbType, DuckDbTypes.varchar, KotlinDbTypes.DuckDbTypes.integer.nullable(), KotlinDbTypes.DuckDbTypes.boolean_.nullable(), DuckDbTypes.timestamp.nullable(), { t0, t1, t2, t3, t4 -> CompanyRow(t0, t1, t2, t3, t4) }, { row -> arrayOf(row.id, row.name, row.foundedYear, row.active, row.createdAt) })\n }\n}", - "CompanyRowUnsaved": "package showcase.showcase.company\n\nimport java.time.LocalDateTime\nimport showcase.customtypes.Defaulted\nimport showcase.customtypes.Defaulted.UseDefault\n\n/** This class corresponds to a row in table `showcase.company` which has not been persisted yet */\ndata class CompanyRowUnsaved(\n val id: CompanyId,\n val name: String,\n val foundedYear: Int? = null,\n /** Default: true */\n val active: Defaulted = UseDefault(),\n /** Default: CURRENT_TIMESTAMP */\n val createdAt: Defaulted = UseDefault()\n) {\n fun toRow(\n activeDefault: () -> Boolean?,\n createdAtDefault: () -> LocalDateTime?\n ): CompanyRow = CompanyRow(id = id, name = name, foundedYear = foundedYear, active = active.getOrElse(activeDefault), createdAt = createdAt.getOrElse(createdAtDefault))\n}", - "CompanyId": "package showcase.showcase.company\n\nimport dev.typr.foundations.DuckDbType\nimport dev.typr.foundations.DuckDbTypes\nimport dev.typr.foundations.internal.arrayMap\nimport dev.typr.foundations.kotlin.Bijection\n\n/** Type for the primary key of table `showcase.company` */\ndata class CompanyId(val value: String) {\n override fun toString(): kotlin.String {\n return value.toString()\n }\n\n companion object {\n val bijection: Bijection =\n Bijection.of(CompanyId::value, ::CompanyId)\n\n val duckDbType: DuckDbType =\n DuckDbTypes.varchar.bimap(::CompanyId, CompanyId::value)\n\n val pgTypeArray: DuckDbType> =\n DuckDbTypes.varcharArray.bimap({ xs -> arrayMap.map(xs, ::CompanyId, CompanyId::class.java) }, { xs -> arrayMap.map(xs, CompanyId::value, String::class.java) })\n }\n}", - "CompanyRepo": "package showcase.showcase.company\n\nimport dev.typr.foundations.kotlin.DeleteBuilder\nimport dev.typr.foundations.kotlin.SelectBuilder\nimport dev.typr.foundations.kotlin.UpdateBuilder\nimport java.sql.Connection\nimport kotlin.collections.Iterator\nimport kotlin.collections.List\nimport kotlin.collections.Map\n\ninterface CompanyRepo {\n abstract fun delete(): DeleteBuilder\n\n abstract fun deleteById(\n id: CompanyId,\n c: Connection\n ): Boolean\n\n abstract fun deleteByIds(\n ids: Array,\n c: Connection\n ): Int\n\n abstract fun insert(\n unsaved: CompanyRow,\n c: Connection\n ): CompanyRow\n\n abstract fun insert(\n unsaved: CompanyRowUnsaved,\n c: Connection\n ): CompanyRow\n\n abstract fun select(): SelectBuilder\n\n abstract fun selectAll(c: Connection): List\n\n abstract fun selectById(\n id: CompanyId,\n c: Connection\n ): CompanyRow?\n\n abstract fun selectByIds(\n ids: Array,\n c: Connection\n ): List\n\n abstract fun selectByIdsTracked(\n ids: Array,\n c: Connection\n ): Map\n\n abstract fun update(): UpdateBuilder\n\n abstract fun update(\n row: CompanyRow,\n c: Connection\n ): Boolean\n\n abstract fun upsert(\n unsaved: CompanyRow,\n c: Connection\n ): CompanyRow\n\n abstract fun upsertBatch(\n unsaved: Iterator,\n c: Connection\n ): List\n}", - "CompanyRepoMock": "package showcase.showcase.company\n\nimport dev.typr.foundations.kotlin.DeleteBuilder\nimport dev.typr.foundations.kotlin.DeleteBuilderMock\nimport dev.typr.foundations.kotlin.DeleteParams\nimport dev.typr.foundations.kotlin.SelectBuilder\nimport dev.typr.foundations.kotlin.SelectBuilderMock\nimport dev.typr.foundations.kotlin.SelectParams\nimport dev.typr.foundations.kotlin.UpdateBuilder\nimport dev.typr.foundations.kotlin.UpdateBuilderMock\nimport dev.typr.foundations.kotlin.UpdateParams\nimport java.lang.RuntimeException\nimport java.sql.Connection\nimport java.util.ArrayList\nimport kotlin.collections.Iterator\nimport kotlin.collections.List\nimport kotlin.collections.Map\nimport kotlin.collections.MutableMap\n\ndata class CompanyRepoMock(\n val toRow: (CompanyRowUnsaved) -> CompanyRow,\n val map: MutableMap = mutableMapOf()\n) : CompanyRepo {\n override fun delete(): DeleteBuilder = DeleteBuilderMock(CompanyFields.structure, { map.values.toList() }, DeleteParams.empty(), { row -> row.id }, { id -> map.remove(id) })\n\n override fun deleteById(\n id: CompanyId,\n c: Connection\n ): Boolean = map.remove(id) != null\n\n override fun deleteByIds(\n ids: Array,\n c: Connection\n ): Int {\n var count = 0\n for (id in ids) {\n if (map.remove(id) != null) {\n count = count + 1\n }\n }\n return count\n }\n\n override fun insert(\n unsaved: CompanyRow,\n c: Connection\n ): CompanyRow {\n if (map.containsKey(unsaved.id)) {\n throw RuntimeException(\"id \" + unsaved.id + \" already exists\")\n }\n map[unsaved.id] = unsaved\n return unsaved\n }\n\n override fun insert(\n unsaved: CompanyRowUnsaved,\n c: Connection\n ): CompanyRow = insert(toRow(unsaved), c)\n\n override fun select(): SelectBuilder = SelectBuilderMock(CompanyFields.structure, { map.values.toList() }, SelectParams.empty())\n\n override fun selectAll(c: Connection): List = map.values.toList()\n\n override fun selectById(\n id: CompanyId,\n c: Connection\n ): CompanyRow? = map[id]\n\n override fun selectByIds(\n ids: Array,\n c: Connection\n ): List {\n val result = ArrayList()\n for (id in ids) {\n val opt = map[id]\n if (opt != null) {\n result.add(opt!!)\n }\n }\n return result\n }\n\n override fun selectByIdsTracked(\n ids: Array,\n c: Connection\n ): Map = selectByIds(ids, c).associateBy({ row: CompanyRow -> row.id })\n\n override fun update(): UpdateBuilder = UpdateBuilderMock(CompanyFields.structure, { map.values.toList() }, UpdateParams.empty(), { row -> row })\n\n override fun update(\n row: CompanyRow,\n c: Connection\n ): Boolean {\n val shouldUpdate = map[row.id]?.takeIf({ oldRow -> (oldRow != row) }) != null\n if (shouldUpdate) {\n map[row.id] = row\n }\n return shouldUpdate\n }\n\n override fun upsert(\n unsaved: CompanyRow,\n c: Connection\n ): CompanyRow {\n map[unsaved.id] = unsaved\n return unsaved\n }\n\n override fun upsertBatch(\n unsaved: Iterator,\n c: Connection\n ): List {\n val result = ArrayList()\n while (unsaved.hasNext()) {\n val row = unsaved.next()\n map[row.id] = row\n result.add(row)\n }\n return result\n }\n}", - "EmployeeRow": "package showcase.showcase.employee\n\nimport dev.typr.foundations.DuckDbTypes\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport dev.typr.foundations.kotlin.nullable\nimport java.math.BigDecimal\nimport java.time.Duration\nimport java.time.LocalDate\nimport java.time.LocalDateTime\nimport showcase.EmployeeContactInfo\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.department.DepartmentId\n\n/** Table: showcase.employee\n * Primary key: id\n */\ndata class EmployeeRow(\n val id: EmployeeId,\n /** Points to [showcase.showcase.department.DepartmentRow.id] */\n val departmentId: DepartmentId,\n /** Points to [showcase.showcase.employee.EmployeeRow.id] */\n val managerId: EmployeeId?,\n val email: String,\n val firstName: String,\n val lastName: String,\n val salary: BigDecimal?,\n val hiredAt: LocalDate?,\n /** Default: true */\n val active: Boolean?,\n /** Default: CURRENT_TIMESTAMP */\n val createdAt: LocalDateTime?,\n val skills: Array?,\n val certifications: Array?,\n val weeklyAvailability: Array?,\n val contactInfo: EmployeeContactInfo?,\n val settings: /* MAP type - mapped to String */ String?,\n val skillsRating: /* MAP type - mapped to String */ String?,\n val probationPeriod: Duration?\n) {\n fun toUnsavedRow(\n active: Defaulted,\n createdAt: Defaulted\n ): EmployeeRowUnsaved = EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, skills, certifications, weeklyAvailability, contactInfo, settings, skillsRating, probationPeriod, active, createdAt)\n\n companion object {\n val _rowParser: RowParser = RowParsers.of(EmployeeId.duckDbType, DepartmentId.duckDbType, EmployeeId.duckDbType.nullable(), DuckDbTypes.varchar, DuckDbTypes.varchar, DuckDbTypes.varchar, DuckDbTypes.numeric.nullable(), DuckDbTypes.date.nullable(), KotlinDbTypes.DuckDbTypes.boolean_.nullable(), DuckDbTypes.timestamp.nullable(), DuckDbTypes.varcharArray.nullable(), DuckDbTypes.varcharArray.nullable(), DuckDbTypes.booleanArray.nullable(), EmployeeContactInfo.duckDbType.nullable(), DuckDbTypes.varchar.mapTo(DuckDbTypes.varchar).nullable(), DuckDbTypes.varchar.mapTo(DuckDbTypes.integer).nullable(), DuckDbTypes.interval.nullable(), { t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16 -> EmployeeRow(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16) }, { row -> arrayOf(row.id, row.departmentId, row.managerId, row.email, row.firstName, row.lastName, row.salary, row.hiredAt, row.active, row.createdAt, row.skills, row.certifications, row.weeklyAvailability, row.contactInfo, row.settings, row.skillsRating, row.probationPeriod) })\n }\n}", - "EmployeeRowUnsaved": "package showcase.showcase.employee\n\nimport java.math.BigDecimal\nimport java.time.Duration\nimport java.time.LocalDate\nimport java.time.LocalDateTime\nimport showcase.EmployeeContactInfo\nimport showcase.customtypes.Defaulted\nimport showcase.customtypes.Defaulted.UseDefault\nimport showcase.showcase.department.DepartmentId\n\n/** This class corresponds to a row in table `showcase.employee` which has not been persisted yet */\ndata class EmployeeRowUnsaved(\n val id: EmployeeId,\n /** Points to [showcase.showcase.department.DepartmentRow.id] */\n val departmentId: DepartmentId,\n /** Points to [showcase.showcase.employee.EmployeeRow.id] */\n val managerId: EmployeeId? = null,\n val email: String,\n val firstName: String,\n val lastName: String,\n val salary: BigDecimal? = null,\n val hiredAt: LocalDate? = null,\n val skills: Array? = null,\n val certifications: Array? = null,\n val weeklyAvailability: Array? = null,\n val contactInfo: EmployeeContactInfo? = null,\n val settings: /* MAP type - mapped to String */ String? = null,\n val skillsRating: /* MAP type - mapped to String */ String? = null,\n val probationPeriod: Duration? = null,\n /** Default: true */\n val active: Defaulted = UseDefault(),\n /** Default: CURRENT_TIMESTAMP */\n val createdAt: Defaulted = UseDefault()\n) {\n fun toRow(\n activeDefault: () -> Boolean?,\n createdAtDefault: () -> LocalDateTime?\n ): EmployeeRow = EmployeeRow(id = id, departmentId = departmentId, managerId = managerId, email = email, firstName = firstName, lastName = lastName, salary = salary, hiredAt = hiredAt, active = active.getOrElse(activeDefault), createdAt = createdAt.getOrElse(createdAtDefault), skills = skills, certifications = certifications, weeklyAvailability = weeklyAvailability, contactInfo = contactInfo, settings = settings, skillsRating = skillsRating, probationPeriod = probationPeriod)\n}", - "EmployeeId": "package showcase.showcase.employee\n\nimport dev.typr.foundations.DuckDbType\nimport dev.typr.foundations.DuckDbTypes\nimport dev.typr.foundations.internal.arrayMap\nimport dev.typr.foundations.kotlin.Bijection\n\n/** Type for the primary key of table `showcase.employee` */\ndata class EmployeeId(val value: String) {\n override fun toString(): kotlin.String {\n return value.toString()\n }\n\n companion object {\n val bijection: Bijection =\n Bijection.of(EmployeeId::value, ::EmployeeId)\n\n val duckDbType: DuckDbType =\n DuckDbTypes.varchar.bimap(::EmployeeId, EmployeeId::value)\n\n val pgTypeArray: DuckDbType> =\n DuckDbTypes.varcharArray.bimap({ xs -> arrayMap.map(xs, ::EmployeeId, EmployeeId::class.java) }, { xs -> arrayMap.map(xs, EmployeeId::value, String::class.java) })\n }\n}", - "EmployeeRepo": "package showcase.showcase.employee\n\nimport dev.typr.foundations.kotlin.DeleteBuilder\nimport dev.typr.foundations.kotlin.SelectBuilder\nimport dev.typr.foundations.kotlin.UpdateBuilder\nimport java.sql.Connection\nimport kotlin.collections.Iterator\nimport kotlin.collections.List\nimport kotlin.collections.Map\n\ninterface EmployeeRepo {\n abstract fun delete(): DeleteBuilder\n\n abstract fun deleteById(\n id: EmployeeId,\n c: Connection\n ): Boolean\n\n abstract fun deleteByIds(\n ids: Array,\n c: Connection\n ): Int\n\n abstract fun insert(\n unsaved: EmployeeRow,\n c: Connection\n ): EmployeeRow\n\n abstract fun insert(\n unsaved: EmployeeRowUnsaved,\n c: Connection\n ): EmployeeRow\n\n abstract fun select(): SelectBuilder\n\n abstract fun selectAll(c: Connection): List\n\n abstract fun selectById(\n id: EmployeeId,\n c: Connection\n ): EmployeeRow?\n\n abstract fun selectByIds(\n ids: Array,\n c: Connection\n ): List\n\n abstract fun selectByIdsTracked(\n ids: Array,\n c: Connection\n ): Map\n\n abstract fun selectByUniqueEmail(\n email: String,\n c: Connection\n ): EmployeeRow?\n\n abstract fun update(): UpdateBuilder\n\n abstract fun update(\n row: EmployeeRow,\n c: Connection\n ): Boolean\n\n abstract fun upsert(\n unsaved: EmployeeRow,\n c: Connection\n ): EmployeeRow\n\n abstract fun upsertBatch(\n unsaved: Iterator,\n c: Connection\n ): List\n}", - "EmployeeRepoImpl": "package showcase.showcase.employee\n\nimport dev.typr.foundations.DuckDbTypes\nimport dev.typr.foundations.kotlin.DeleteBuilder\nimport dev.typr.foundations.kotlin.Dialect\nimport dev.typr.foundations.kotlin.Fragment\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.SelectBuilder\nimport dev.typr.foundations.kotlin.UpdateBuilder\nimport dev.typr.foundations.kotlin.nullable\nimport java.sql.Connection\nimport java.util.ArrayList\nimport kotlin.collections.Iterator\nimport kotlin.collections.List\nimport kotlin.collections.Map\nimport kotlin.collections.MutableMap\nimport showcase.EmployeeContactInfo\nimport showcase.showcase.department.DepartmentId\n\nclass EmployeeRepoImpl() : EmployeeRepo {\n override fun delete(): DeleteBuilder = DeleteBuilder.of(\"\\\"showcase\\\".\\\"employee\\\"\", EmployeeFields.structure, Dialect.DUCKDB)\n\n override fun deleteById(\n id: EmployeeId,\n c: Connection\n ): Boolean = Fragment.interpolate(Fragment.lit(\"delete from \\\"showcase\\\".\\\"employee\\\" where \\\"id\\\" = \"), Fragment.encode(EmployeeId.duckDbType, id), Fragment.lit(\"\")).update().runUnchecked(c) > 0\n\n override fun deleteByIds(\n ids: Array,\n c: Connection\n ): Int = Fragment.interpolate(Fragment.lit(\"delete\\nfrom \\\"showcase\\\".\\\"employee\\\"\\nwhere \\\"id\\\" = ANY(\"), Fragment.encode(EmployeeId.pgTypeArray, ids), Fragment.lit(\")\"))\n .update()\n .runUnchecked(c)\n\n override fun insert(\n unsaved: EmployeeRow,\n c: Connection\n ): EmployeeRow = Fragment.interpolate(Fragment.lit(\"insert into \\\"showcase\\\".\\\"employee\\\"(\\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"skills\\\", \\\"certifications\\\", \\\"weekly_availability\\\", \\\"contact_info\\\", \\\"settings\\\", \\\"skills_rating\\\", \\\"probation_period\\\")\\nvalues (\"), Fragment.encode(EmployeeId.duckDbType, unsaved.id), Fragment.lit(\", \"), Fragment.encode(DepartmentId.duckDbType, unsaved.departmentId), Fragment.lit(\", \"), Fragment.encode(EmployeeId.duckDbType.nullable(), unsaved.managerId), Fragment.lit(\", \"), Fragment.encode(DuckDbTypes.varchar, unsaved.email), Fragment.lit(\", \"), Fragment.encode(DuckDbTypes.varchar, unsaved.firstName), Fragment.lit(\", \"), Fragment.encode(DuckDbTypes.varchar, unsaved.lastName), Fragment.lit(\", \"), Fragment.encode(DuckDbTypes.numeric.nullable(), unsaved.salary), Fragment.lit(\", \"), Fragment.encode(DuckDbTypes.date.nullable(), unsaved.hiredAt), Fragment.lit(\", \"), Fragment.encode(KotlinDbTypes.DuckDbTypes.boolean_.nullable(), unsaved.active), Fragment.lit(\", \"), Fragment.encode(DuckDbTypes.timestamp.nullable(), unsaved.createdAt), Fragment.lit(\", \"), Fragment.encode(DuckDbTypes.varcharArray.nullable(), unsaved.skills), Fragment.lit(\", \"), Fragment.encode(DuckDbTypes.varcharArray.nullable(), unsaved.certifications), Fragment.lit(\", \"), Fragment.encode(DuckDbTypes.booleanArray.nullable(), unsaved.weeklyAvailability), Fragment.lit(\", \"), Fragment.encode(EmployeeContactInfo.duckDbType.nullable(), unsaved.contactInfo), Fragment.lit(\", \"), Fragment.encode(DuckDbTypes.varchar.mapTo(DuckDbTypes.varchar).nullable(), unsaved.settings), Fragment.lit(\", \"), Fragment.encode(DuckDbTypes.varchar.mapTo(DuckDbTypes.integer).nullable(), unsaved.skillsRating), Fragment.lit(\", \"), Fragment.encode(DuckDbTypes.interval.nullable(), unsaved.probationPeriod), Fragment.lit(\")\\nRETURNING \\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"skills\\\", \\\"certifications\\\", \\\"weekly_availability\\\", \\\"contact_info\\\", \\\"settings\\\", \\\"skills_rating\\\", \\\"probation_period\\\"\\n\"))\n .updateReturning(EmployeeRow._rowParser.exactlyOne()).runUnchecked(c)\n\n override fun insert(\n unsaved: EmployeeRowUnsaved,\n c: Connection\n ): EmployeeRow {\n val columns: ArrayList = ArrayList()\n val values: ArrayList = ArrayList()\n columns.add(Fragment.lit(\"\\\"id\\\"\"))\n values.add(Fragment.interpolate(Fragment.encode(EmployeeId.duckDbType, unsaved.id), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"\\\"department_id\\\"\"))\n values.add(Fragment.interpolate(Fragment.encode(DepartmentId.duckDbType, unsaved.departmentId), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"\\\"manager_id\\\"\"))\n values.add(Fragment.interpolate(Fragment.encode(EmployeeId.duckDbType.nullable(), unsaved.managerId), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"\\\"email\\\"\"))\n values.add(Fragment.interpolate(Fragment.encode(DuckDbTypes.varchar, unsaved.email), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"\\\"first_name\\\"\"))\n values.add(Fragment.interpolate(Fragment.encode(DuckDbTypes.varchar, unsaved.firstName), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"\\\"last_name\\\"\"))\n values.add(Fragment.interpolate(Fragment.encode(DuckDbTypes.varchar, unsaved.lastName), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"\\\"salary\\\"\"))\n values.add(Fragment.interpolate(Fragment.encode(DuckDbTypes.numeric.nullable(), unsaved.salary), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"\\\"hired_at\\\"\"))\n values.add(Fragment.interpolate(Fragment.encode(DuckDbTypes.date.nullable(), unsaved.hiredAt), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"\\\"skills\\\"\"))\n values.add(Fragment.interpolate(Fragment.encode(DuckDbTypes.varcharArray.nullable(), unsaved.skills), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"\\\"certifications\\\"\"))\n values.add(Fragment.interpolate(Fragment.encode(DuckDbTypes.varcharArray.nullable(), unsaved.certifications), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"\\\"weekly_availability\\\"\"))\n values.add(Fragment.interpolate(Fragment.encode(DuckDbTypes.booleanArray.nullable(), unsaved.weeklyAvailability), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"\\\"contact_info\\\"\"))\n values.add(Fragment.interpolate(Fragment.encode(EmployeeContactInfo.duckDbType.nullable(), unsaved.contactInfo), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"\\\"settings\\\"\"))\n values.add(Fragment.interpolate(Fragment.encode(DuckDbTypes.varchar.mapTo(DuckDbTypes.varchar).nullable(), unsaved.settings), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"\\\"skills_rating\\\"\"))\n values.add(Fragment.interpolate(Fragment.encode(DuckDbTypes.varchar.mapTo(DuckDbTypes.integer).nullable(), unsaved.skillsRating), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"\\\"probation_period\\\"\"))\n values.add(Fragment.interpolate(Fragment.encode(DuckDbTypes.interval.nullable(), unsaved.probationPeriod), Fragment.lit(\"\")))\n unsaved.active.visit(\n { },\n { value -> columns.add(Fragment.lit(\"\\\"active\\\"\"))\n values.add(Fragment.interpolate(Fragment.encode(KotlinDbTypes.DuckDbTypes.boolean_.nullable(), value), Fragment.lit(\"\"))) }\n );\n unsaved.createdAt.visit(\n { },\n { value -> columns.add(Fragment.lit(\"\\\"created_at\\\"\"))\n values.add(Fragment.interpolate(Fragment.encode(DuckDbTypes.timestamp.nullable(), value), Fragment.lit(\"\"))) }\n );\n val q: Fragment = Fragment.interpolate(Fragment.lit(\"insert into \\\"showcase\\\".\\\"employee\\\"(\"), Fragment.comma(columns.toMutableList()), Fragment.lit(\")\\nvalues (\"), Fragment.comma(values.toMutableList()), Fragment.lit(\")\\nRETURNING \\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"skills\\\", \\\"certifications\\\", \\\"weekly_availability\\\", \\\"contact_info\\\", \\\"settings\\\", \\\"skills_rating\\\", \\\"probation_period\\\"\\n\"))\n return q.updateReturning(EmployeeRow._rowParser.exactlyOne()).runUnchecked(c)\n }\n\n override fun select(): SelectBuilder = SelectBuilder.of(\"\\\"showcase\\\".\\\"employee\\\"\", EmployeeFields.structure, EmployeeRow._rowParser, Dialect.DUCKDB)\n\n override fun selectAll(c: Connection): List = Fragment.interpolate(Fragment.lit(\"select \\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"skills\\\", \\\"certifications\\\", \\\"weekly_availability\\\", \\\"contact_info\\\", \\\"settings\\\", \\\"skills_rating\\\", \\\"probation_period\\\"\\nfrom \\\"showcase\\\".\\\"employee\\\"\\n\")).query(EmployeeRow._rowParser.all()).runUnchecked(c)\n\n override fun selectById(\n id: EmployeeId,\n c: Connection\n ): EmployeeRow? = Fragment.interpolate(Fragment.lit(\"select \\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"skills\\\", \\\"certifications\\\", \\\"weekly_availability\\\", \\\"contact_info\\\", \\\"settings\\\", \\\"skills_rating\\\", \\\"probation_period\\\"\\nfrom \\\"showcase\\\".\\\"employee\\\"\\nwhere \\\"id\\\" = \"), Fragment.encode(EmployeeId.duckDbType, id), Fragment.lit(\"\")).query(EmployeeRow._rowParser.first()).runUnchecked(c)\n\n override fun selectByIds(\n ids: Array,\n c: Connection\n ): List = Fragment.interpolate(Fragment.lit(\"select \\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"skills\\\", \\\"certifications\\\", \\\"weekly_availability\\\", \\\"contact_info\\\", \\\"settings\\\", \\\"skills_rating\\\", \\\"probation_period\\\"\\nfrom \\\"showcase\\\".\\\"employee\\\"\\nwhere \\\"id\\\" = ANY(\"), Fragment.encode(EmployeeId.pgTypeArray, ids), Fragment.lit(\")\")).query(EmployeeRow._rowParser.all()).runUnchecked(c)\n\n override fun selectByIdsTracked(\n ids: Array,\n c: Connection\n ): Map {\n val ret: MutableMap = mutableMapOf()\n selectByIds(ids, c).forEach({ row -> ret.put(row.id, row) })\n return ret.toMap()\n }\n\n override fun selectByUniqueEmail(\n email: String,\n c: Connection\n ): EmployeeRow? = Fragment.interpolate(Fragment.lit(\"select \\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"skills\\\", \\\"certifications\\\", \\\"weekly_availability\\\", \\\"contact_info\\\", \\\"settings\\\", \\\"skills_rating\\\", \\\"probation_period\\\"\\nfrom \\\"showcase\\\".\\\"employee\\\"\\nwhere \\\"email\\\" = \"), Fragment.encode(DuckDbTypes.varchar, email), Fragment.lit(\"\\n\")).query(EmployeeRow._rowParser.first()).runUnchecked(c)\n\n override fun update(): UpdateBuilder = UpdateBuilder.of(\"\\\"showcase\\\".\\\"employee\\\"\", EmployeeFields.structure, EmployeeRow._rowParser, Dialect.DUCKDB)\n\n override fun update(\n row: EmployeeRow,\n c: Connection\n ): Boolean {\n val id: EmployeeId = row.id\n return Fragment.interpolate(Fragment.lit(\"update \\\"showcase\\\".\\\"employee\\\"\\nset \\\"department_id\\\" = \"), Fragment.encode(DepartmentId.duckDbType, row.departmentId), Fragment.lit(\",\\n\\\"manager_id\\\" = \"), Fragment.encode(EmployeeId.duckDbType.nullable(), row.managerId), Fragment.lit(\",\\n\\\"email\\\" = \"), Fragment.encode(DuckDbTypes.varchar, row.email), Fragment.lit(\",\\n\\\"first_name\\\" = \"), Fragment.encode(DuckDbTypes.varchar, row.firstName), Fragment.lit(\",\\n\\\"last_name\\\" = \"), Fragment.encode(DuckDbTypes.varchar, row.lastName), Fragment.lit(\",\\n\\\"salary\\\" = \"), Fragment.encode(DuckDbTypes.numeric.nullable(), row.salary), Fragment.lit(\",\\n\\\"hired_at\\\" = \"), Fragment.encode(DuckDbTypes.date.nullable(), row.hiredAt), Fragment.lit(\",\\n\\\"active\\\" = \"), Fragment.encode(KotlinDbTypes.DuckDbTypes.boolean_.nullable(), row.active), Fragment.lit(\",\\n\\\"created_at\\\" = \"), Fragment.encode(DuckDbTypes.timestamp.nullable(), row.createdAt), Fragment.lit(\",\\n\\\"skills\\\" = \"), Fragment.encode(DuckDbTypes.varcharArray.nullable(), row.skills), Fragment.lit(\",\\n\\\"certifications\\\" = \"), Fragment.encode(DuckDbTypes.varcharArray.nullable(), row.certifications), Fragment.lit(\",\\n\\\"weekly_availability\\\" = \"), Fragment.encode(DuckDbTypes.booleanArray.nullable(), row.weeklyAvailability), Fragment.lit(\",\\n\\\"contact_info\\\" = \"), Fragment.encode(EmployeeContactInfo.duckDbType.nullable(), row.contactInfo), Fragment.lit(\",\\n\\\"settings\\\" = \"), Fragment.encode(DuckDbTypes.varchar.mapTo(DuckDbTypes.varchar).nullable(), row.settings), Fragment.lit(\",\\n\\\"skills_rating\\\" = \"), Fragment.encode(DuckDbTypes.varchar.mapTo(DuckDbTypes.integer).nullable(), row.skillsRating), Fragment.lit(\",\\n\\\"probation_period\\\" = \"), Fragment.encode(DuckDbTypes.interval.nullable(), row.probationPeriod), Fragment.lit(\"\\nwhere \\\"id\\\" = \"), Fragment.encode(EmployeeId.duckDbType, id), Fragment.lit(\"\")).update().runUnchecked(c) > 0\n }\n\n override fun upsert(\n unsaved: EmployeeRow,\n c: Connection\n ): EmployeeRow = Fragment.interpolate(Fragment.lit(\"INSERT INTO \\\"showcase\\\".\\\"employee\\\"(\\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"skills\\\", \\\"certifications\\\", \\\"weekly_availability\\\", \\\"contact_info\\\", \\\"settings\\\", \\\"skills_rating\\\", \\\"probation_period\\\")\\nVALUES (\"), Fragment.encode(EmployeeId.duckDbType, unsaved.id), Fragment.lit(\", \"), Fragment.encode(DepartmentId.duckDbType, unsaved.departmentId), Fragment.lit(\", \"), Fragment.encode(EmployeeId.duckDbType.nullable(), unsaved.managerId), Fragment.lit(\", \"), Fragment.encode(DuckDbTypes.varchar, unsaved.email), Fragment.lit(\", \"), Fragment.encode(DuckDbTypes.varchar, unsaved.firstName), Fragment.lit(\", \"), Fragment.encode(DuckDbTypes.varchar, unsaved.lastName), Fragment.lit(\", \"), Fragment.encode(DuckDbTypes.numeric.nullable(), unsaved.salary), Fragment.lit(\", \"), Fragment.encode(DuckDbTypes.date.nullable(), unsaved.hiredAt), Fragment.lit(\", \"), Fragment.encode(KotlinDbTypes.DuckDbTypes.boolean_.nullable(), unsaved.active), Fragment.lit(\", \"), Fragment.encode(DuckDbTypes.timestamp.nullable(), unsaved.createdAt), Fragment.lit(\", \"), Fragment.encode(DuckDbTypes.varcharArray.nullable(), unsaved.skills), Fragment.lit(\", \"), Fragment.encode(DuckDbTypes.varcharArray.nullable(), unsaved.certifications), Fragment.lit(\", \"), Fragment.encode(DuckDbTypes.booleanArray.nullable(), unsaved.weeklyAvailability), Fragment.lit(\", \"), Fragment.encode(EmployeeContactInfo.duckDbType.nullable(), unsaved.contactInfo), Fragment.lit(\", \"), Fragment.encode(DuckDbTypes.varchar.mapTo(DuckDbTypes.varchar).nullable(), unsaved.settings), Fragment.lit(\", \"), Fragment.encode(DuckDbTypes.varchar.mapTo(DuckDbTypes.integer).nullable(), unsaved.skillsRating), Fragment.lit(\", \"), Fragment.encode(DuckDbTypes.interval.nullable(), unsaved.probationPeriod), Fragment.lit(\")\\nON CONFLICT (\\\"id\\\")\\nDO UPDATE SET\\n \\\"department_id\\\" = EXCLUDED.\\\"department_id\\\",\\n\\\"manager_id\\\" = EXCLUDED.\\\"manager_id\\\",\\n\\\"email\\\" = EXCLUDED.\\\"email\\\",\\n\\\"first_name\\\" = EXCLUDED.\\\"first_name\\\",\\n\\\"last_name\\\" = EXCLUDED.\\\"last_name\\\",\\n\\\"salary\\\" = EXCLUDED.\\\"salary\\\",\\n\\\"hired_at\\\" = EXCLUDED.\\\"hired_at\\\",\\n\\\"active\\\" = EXCLUDED.\\\"active\\\",\\n\\\"created_at\\\" = EXCLUDED.\\\"created_at\\\",\\n\\\"skills\\\" = EXCLUDED.\\\"skills\\\",\\n\\\"certifications\\\" = EXCLUDED.\\\"certifications\\\",\\n\\\"weekly_availability\\\" = EXCLUDED.\\\"weekly_availability\\\",\\n\\\"contact_info\\\" = EXCLUDED.\\\"contact_info\\\",\\n\\\"settings\\\" = EXCLUDED.\\\"settings\\\",\\n\\\"skills_rating\\\" = EXCLUDED.\\\"skills_rating\\\",\\n\\\"probation_period\\\" = EXCLUDED.\\\"probation_period\\\"\\nRETURNING \\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"skills\\\", \\\"certifications\\\", \\\"weekly_availability\\\", \\\"contact_info\\\", \\\"settings\\\", \\\"skills_rating\\\", \\\"probation_period\\\"\"))\n .updateReturning(EmployeeRow._rowParser.exactlyOne())\n .runUnchecked(c)\n\n override fun upsertBatch(\n unsaved: Iterator,\n c: Connection\n ): List = Fragment.interpolate(Fragment.lit(\"INSERT INTO \\\"showcase\\\".\\\"employee\\\"(\\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"skills\\\", \\\"certifications\\\", \\\"weekly_availability\\\", \\\"contact_info\\\", \\\"settings\\\", \\\"skills_rating\\\", \\\"probation_period\\\")\\nVALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\\nON CONFLICT (\\\"id\\\")\\nDO UPDATE SET\\n \\\"department_id\\\" = EXCLUDED.\\\"department_id\\\",\\n\\\"manager_id\\\" = EXCLUDED.\\\"manager_id\\\",\\n\\\"email\\\" = EXCLUDED.\\\"email\\\",\\n\\\"first_name\\\" = EXCLUDED.\\\"first_name\\\",\\n\\\"last_name\\\" = EXCLUDED.\\\"last_name\\\",\\n\\\"salary\\\" = EXCLUDED.\\\"salary\\\",\\n\\\"hired_at\\\" = EXCLUDED.\\\"hired_at\\\",\\n\\\"active\\\" = EXCLUDED.\\\"active\\\",\\n\\\"created_at\\\" = EXCLUDED.\\\"created_at\\\",\\n\\\"skills\\\" = EXCLUDED.\\\"skills\\\",\\n\\\"certifications\\\" = EXCLUDED.\\\"certifications\\\",\\n\\\"weekly_availability\\\" = EXCLUDED.\\\"weekly_availability\\\",\\n\\\"contact_info\\\" = EXCLUDED.\\\"contact_info\\\",\\n\\\"settings\\\" = EXCLUDED.\\\"settings\\\",\\n\\\"skills_rating\\\" = EXCLUDED.\\\"skills_rating\\\",\\n\\\"probation_period\\\" = EXCLUDED.\\\"probation_period\\\"\\nRETURNING \\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"skills\\\", \\\"certifications\\\", \\\"weekly_availability\\\", \\\"contact_info\\\", \\\"settings\\\", \\\"skills_rating\\\", \\\"probation_period\\\"\"))\n .updateReturningEach(EmployeeRow._rowParser, unsaved)\n .runUnchecked(c)\n}", - "EmployeeRepoMock": "package showcase.showcase.employee\n\nimport dev.typr.foundations.kotlin.DeleteBuilder\nimport dev.typr.foundations.kotlin.DeleteBuilderMock\nimport dev.typr.foundations.kotlin.DeleteParams\nimport dev.typr.foundations.kotlin.SelectBuilder\nimport dev.typr.foundations.kotlin.SelectBuilderMock\nimport dev.typr.foundations.kotlin.SelectParams\nimport dev.typr.foundations.kotlin.UpdateBuilder\nimport dev.typr.foundations.kotlin.UpdateBuilderMock\nimport dev.typr.foundations.kotlin.UpdateParams\nimport java.lang.RuntimeException\nimport java.sql.Connection\nimport java.util.ArrayList\nimport kotlin.collections.Iterator\nimport kotlin.collections.List\nimport kotlin.collections.Map\nimport kotlin.collections.MutableMap\n\ndata class EmployeeRepoMock(\n val toRow: (EmployeeRowUnsaved) -> EmployeeRow,\n val map: MutableMap = mutableMapOf()\n) : EmployeeRepo {\n override fun delete(): DeleteBuilder = DeleteBuilderMock(EmployeeFields.structure, { map.values.toList() }, DeleteParams.empty(), { row -> row.id }, { id -> map.remove(id) })\n\n override fun deleteById(\n id: EmployeeId,\n c: Connection\n ): Boolean = map.remove(id) != null\n\n override fun deleteByIds(\n ids: Array,\n c: Connection\n ): Int {\n var count = 0\n for (id in ids) {\n if (map.remove(id) != null) {\n count = count + 1\n }\n }\n return count\n }\n\n override fun insert(\n unsaved: EmployeeRow,\n c: Connection\n ): EmployeeRow {\n if (map.containsKey(unsaved.id)) {\n throw RuntimeException(\"id \" + unsaved.id + \" already exists\")\n }\n map[unsaved.id] = unsaved\n return unsaved\n }\n\n override fun insert(\n unsaved: EmployeeRowUnsaved,\n c: Connection\n ): EmployeeRow = insert(toRow(unsaved), c)\n\n override fun select(): SelectBuilder = SelectBuilderMock(EmployeeFields.structure, { map.values.toList() }, SelectParams.empty())\n\n override fun selectAll(c: Connection): List = map.values.toList()\n\n override fun selectById(\n id: EmployeeId,\n c: Connection\n ): EmployeeRow? = map[id]\n\n override fun selectByIds(\n ids: Array,\n c: Connection\n ): List {\n val result = ArrayList()\n for (id in ids) {\n val opt = map[id]\n if (opt != null) {\n result.add(opt!!)\n }\n }\n return result\n }\n\n override fun selectByIdsTracked(\n ids: Array,\n c: Connection\n ): Map = selectByIds(ids, c).associateBy({ row: EmployeeRow -> row.id })\n\n override fun selectByUniqueEmail(\n email: String,\n c: Connection\n ): EmployeeRow? = map.values.toList().find({ v -> (email == v.email) })\n\n override fun update(): UpdateBuilder = UpdateBuilderMock(EmployeeFields.structure, { map.values.toList() }, UpdateParams.empty(), { row -> row })\n\n override fun update(\n row: EmployeeRow,\n c: Connection\n ): Boolean {\n val shouldUpdate = map[row.id]?.takeIf({ oldRow -> (oldRow != row) }) != null\n if (shouldUpdate) {\n map[row.id] = row\n }\n return shouldUpdate\n }\n\n override fun upsert(\n unsaved: EmployeeRow,\n c: Connection\n ): EmployeeRow {\n map[unsaved.id] = unsaved\n return unsaved\n }\n\n override fun upsertBatch(\n unsaved: Iterator,\n c: Connection\n ): List {\n val result = ArrayList()\n while (unsaved.hasNext()) {\n val row = unsaved.next()\n map[row.id] = row\n result.add(row)\n }\n return result\n }\n}", - "EmployeeFields": "package showcase.showcase.employee\n\nimport dev.typr.foundations.DuckDbTypes\nimport dev.typr.foundations.RowParser\nimport dev.typr.foundations.dsl.FieldsExpr\nimport dev.typr.foundations.dsl.Path\nimport dev.typr.foundations.dsl.SqlExpr.FieldLike\nimport dev.typr.foundations.kotlin.ForeignKey\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.RelationStructure\nimport dev.typr.foundations.kotlin.SqlExpr.Field\nimport dev.typr.foundations.kotlin.SqlExpr.IdField\nimport dev.typr.foundations.kotlin.SqlExpr.OptField\nimport java.math.BigDecimal\nimport java.time.Duration\nimport java.time.LocalDate\nimport java.time.LocalDateTime\nimport kotlin.collections.List\nimport showcase.EmployeeContactInfo\nimport showcase.showcase.department.DepartmentFields\nimport showcase.showcase.department.DepartmentId\nimport showcase.showcase.department.DepartmentRow\n\ninterface EmployeeFields : FieldsExpr {\n abstract fun active(): OptField\n\n abstract fun certifications(): OptField, EmployeeRow>\n\n abstract override fun columns(): List>\n\n abstract fun contactInfo(): OptField\n\n abstract fun createdAt(): OptField\n\n abstract fun departmentId(): Field\n\n abstract fun email(): Field\n\n abstract fun firstName(): Field\n\n fun fkDepartment(): ForeignKey = ForeignKey.of(\"employee_department_fk\").withColumnPair(departmentId(), DepartmentFields::id)\n\n fun fkEmployee(): ForeignKey = ForeignKey.of(\"employee_manager_fk\").withColumnPair(managerId(), EmployeeFields::id)\n\n abstract fun hiredAt(): OptField\n\n abstract fun id(): IdField\n\n abstract fun lastName(): Field\n\n abstract fun managerId(): OptField\n\n abstract fun probationPeriod(): OptField\n\n override fun rowParser(): RowParser = EmployeeRow._rowParser.underlying\n\n abstract fun salary(): OptField\n\n abstract fun settings(): OptField\n\n abstract fun skills(): OptField, EmployeeRow>\n\n abstract fun skillsRating(): OptField\n\n abstract fun weeklyAvailability(): OptField, EmployeeRow>\n\n companion object {\n data class Impl(val _path: List) : EmployeeFields, RelationStructure {\n override fun id(): IdField = IdField(_path, \"id\", EmployeeRow::id, null, null, { row, value -> row.copy(id = value) }, EmployeeId.duckDbType)\n\n override fun departmentId(): Field = Field(_path, \"department_id\", EmployeeRow::departmentId, null, null, { row, value -> row.copy(departmentId = value) }, DepartmentId.duckDbType)\n\n override fun managerId(): OptField = OptField(_path, \"manager_id\", EmployeeRow::managerId, null, null, { row, value -> row.copy(managerId = value) }, EmployeeId.duckDbType)\n\n override fun email(): Field = Field(_path, \"email\", EmployeeRow::email, null, null, { row, value -> row.copy(email = value) }, DuckDbTypes.varchar)\n\n override fun firstName(): Field = Field(_path, \"first_name\", EmployeeRow::firstName, null, null, { row, value -> row.copy(firstName = value) }, DuckDbTypes.varchar)\n\n override fun lastName(): Field = Field(_path, \"last_name\", EmployeeRow::lastName, null, null, { row, value -> row.copy(lastName = value) }, DuckDbTypes.varchar)\n\n override fun salary(): OptField = OptField(_path, \"salary\", EmployeeRow::salary, null, null, { row, value -> row.copy(salary = value) }, DuckDbTypes.numeric)\n\n override fun hiredAt(): OptField = OptField(_path, \"hired_at\", EmployeeRow::hiredAt, null, null, { row, value -> row.copy(hiredAt = value) }, DuckDbTypes.date)\n\n override fun active(): OptField = OptField(_path, \"active\", EmployeeRow::active, null, null, { row, value -> row.copy(active = value) }, KotlinDbTypes.DuckDbTypes.boolean_)\n\n override fun createdAt(): OptField = OptField(_path, \"created_at\", EmployeeRow::createdAt, null, null, { row, value -> row.copy(createdAt = value) }, DuckDbTypes.timestamp)\n\n override fun skills(): OptField, EmployeeRow> = OptField, EmployeeRow>(_path, \"skills\", EmployeeRow::skills, null, null, { row, value -> row.copy(skills = value) }, DuckDbTypes.varcharArray)\n\n override fun certifications(): OptField, EmployeeRow> = OptField, EmployeeRow>(_path, \"certifications\", EmployeeRow::certifications, null, null, { row, value -> row.copy(certifications = value) }, DuckDbTypes.varcharArray)\n\n override fun weeklyAvailability(): OptField, EmployeeRow> = OptField, EmployeeRow>(_path, \"weekly_availability\", EmployeeRow::weeklyAvailability, null, null, { row, value -> row.copy(weeklyAvailability = value) }, DuckDbTypes.booleanArray)\n\n override fun contactInfo(): OptField = OptField(_path, \"contact_info\", EmployeeRow::contactInfo, null, null, { row, value -> row.copy(contactInfo = value) }, EmployeeContactInfo.duckDbType)\n\n override fun settings(): OptField = OptField(_path, \"settings\", EmployeeRow::settings, null, null, { row, value -> row.copy(settings = value) }, DuckDbTypes.varchar.mapTo(DuckDbTypes.varchar))\n\n override fun skillsRating(): OptField = OptField(_path, \"skills_rating\", EmployeeRow::skillsRating, null, null, { row, value -> row.copy(skillsRating = value) }, DuckDbTypes.varchar.mapTo(DuckDbTypes.integer))\n\n override fun probationPeriod(): OptField = OptField(_path, \"probation_period\", EmployeeRow::probationPeriod, null, null, { row, value -> row.copy(probationPeriod = value) }, DuckDbTypes.interval)\n\n override fun _path(): List = _path\n\n override fun columns(): List> = listOf(this.id().underlying, this.departmentId().underlying, this.managerId().underlying, this.email().underlying, this.firstName().underlying, this.lastName().underlying, this.salary().underlying, this.hiredAt().underlying, this.active().underlying, this.createdAt().underlying, this.skills().underlying, this.certifications().underlying, this.weeklyAvailability().underlying, this.contactInfo().underlying, this.settings().underlying, this.skillsRating().underlying, this.probationPeriod().underlying)\n\n override fun withPaths(_path: List): RelationStructure = Impl(_path)\n }\n\n val structure: Impl = Impl(emptyList())\n }\n}", - "DepartmentRow": "package showcase.showcase.department\n\nimport dev.typr.foundations.DuckDbTypes\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport dev.typr.foundations.kotlin.nullable\nimport java.math.BigDecimal\nimport showcase.showcase.company.CompanyId\n\n/** Table: showcase.department\n * Primary key: id\n */\ndata class DepartmentRow(\n val id: DepartmentId,\n /** Points to [showcase.showcase.company.CompanyRow.id] */\n val companyId: CompanyId,\n val name: String,\n val budget: BigDecimal?\n) {\n companion object {\n val _rowParser: RowParser = RowParsers.of(DepartmentId.duckDbType, CompanyId.duckDbType, DuckDbTypes.varchar, DuckDbTypes.numeric.nullable(), { t0, t1, t2, t3 -> DepartmentRow(t0, t1, t2, t3) }, { row -> arrayOf(row.id, row.companyId, row.name, row.budget) })\n }\n}", - "DepartmentId": "package showcase.showcase.department\n\nimport dev.typr.foundations.DuckDbType\nimport dev.typr.foundations.DuckDbTypes\nimport dev.typr.foundations.internal.arrayMap\nimport dev.typr.foundations.kotlin.Bijection\n\n/** Type for the primary key of table `showcase.department` */\ndata class DepartmentId(val value: String) {\n override fun toString(): kotlin.String {\n return value.toString()\n }\n\n companion object {\n val bijection: Bijection =\n Bijection.of(DepartmentId::value, ::DepartmentId)\n\n val duckDbType: DuckDbType =\n DuckDbTypes.varchar.bimap(::DepartmentId, DepartmentId::value)\n\n val pgTypeArray: DuckDbType> =\n DuckDbTypes.varcharArray.bimap({ xs -> arrayMap.map(xs, ::DepartmentId, DepartmentId::class.java) }, { xs -> arrayMap.map(xs, DepartmentId::value, String::class.java) })\n }\n}", - "DepartmentRepo": "package showcase.showcase.department\n\nimport dev.typr.foundations.kotlin.DeleteBuilder\nimport dev.typr.foundations.kotlin.SelectBuilder\nimport dev.typr.foundations.kotlin.UpdateBuilder\nimport java.sql.Connection\nimport kotlin.collections.Iterator\nimport kotlin.collections.List\nimport kotlin.collections.Map\n\ninterface DepartmentRepo {\n abstract fun delete(): DeleteBuilder\n\n abstract fun deleteById(\n id: DepartmentId,\n c: Connection\n ): Boolean\n\n abstract fun deleteByIds(\n ids: Array,\n c: Connection\n ): Int\n\n abstract fun insert(\n unsaved: DepartmentRow,\n c: Connection\n ): DepartmentRow\n\n abstract fun select(): SelectBuilder\n\n abstract fun selectAll(c: Connection): List\n\n abstract fun selectById(\n id: DepartmentId,\n c: Connection\n ): DepartmentRow?\n\n abstract fun selectByIds(\n ids: Array,\n c: Connection\n ): List\n\n abstract fun selectByIdsTracked(\n ids: Array,\n c: Connection\n ): Map\n\n abstract fun update(): UpdateBuilder\n\n abstract fun update(\n row: DepartmentRow,\n c: Connection\n ): Boolean\n\n abstract fun upsert(\n unsaved: DepartmentRow,\n c: Connection\n ): DepartmentRow\n\n abstract fun upsertBatch(\n unsaved: Iterator,\n c: Connection\n ): List\n}", - "DepartmentRepoMock": "package showcase.showcase.department\n\nimport dev.typr.foundations.kotlin.DeleteBuilder\nimport dev.typr.foundations.kotlin.DeleteBuilderMock\nimport dev.typr.foundations.kotlin.DeleteParams\nimport dev.typr.foundations.kotlin.SelectBuilder\nimport dev.typr.foundations.kotlin.SelectBuilderMock\nimport dev.typr.foundations.kotlin.SelectParams\nimport dev.typr.foundations.kotlin.UpdateBuilder\nimport dev.typr.foundations.kotlin.UpdateBuilderMock\nimport dev.typr.foundations.kotlin.UpdateParams\nimport java.lang.RuntimeException\nimport java.sql.Connection\nimport java.util.ArrayList\nimport kotlin.collections.Iterator\nimport kotlin.collections.List\nimport kotlin.collections.Map\nimport kotlin.collections.MutableMap\n\ndata class DepartmentRepoMock(val map: MutableMap = mutableMapOf()) : DepartmentRepo {\n override fun delete(): DeleteBuilder = DeleteBuilderMock(DepartmentFields.structure, { map.values.toList() }, DeleteParams.empty(), { row -> row.id }, { id -> map.remove(id) })\n\n override fun deleteById(\n id: DepartmentId,\n c: Connection\n ): Boolean = map.remove(id) != null\n\n override fun deleteByIds(\n ids: Array,\n c: Connection\n ): Int {\n var count = 0\n for (id in ids) {\n if (map.remove(id) != null) {\n count = count + 1\n }\n }\n return count\n }\n\n override fun insert(\n unsaved: DepartmentRow,\n c: Connection\n ): DepartmentRow {\n if (map.containsKey(unsaved.id)) {\n throw RuntimeException(\"id \" + unsaved.id + \" already exists\")\n }\n map[unsaved.id] = unsaved\n return unsaved\n }\n\n override fun select(): SelectBuilder = SelectBuilderMock(DepartmentFields.structure, { map.values.toList() }, SelectParams.empty())\n\n override fun selectAll(c: Connection): List = map.values.toList()\n\n override fun selectById(\n id: DepartmentId,\n c: Connection\n ): DepartmentRow? = map[id]\n\n override fun selectByIds(\n ids: Array,\n c: Connection\n ): List {\n val result = ArrayList()\n for (id in ids) {\n val opt = map[id]\n if (opt != null) {\n result.add(opt!!)\n }\n }\n return result\n }\n\n override fun selectByIdsTracked(\n ids: Array,\n c: Connection\n ): Map = selectByIds(ids, c).associateBy({ row: DepartmentRow -> row.id })\n\n override fun update(): UpdateBuilder = UpdateBuilderMock(DepartmentFields.structure, { map.values.toList() }, UpdateParams.empty(), { row -> row })\n\n override fun update(\n row: DepartmentRow,\n c: Connection\n ): Boolean {\n val shouldUpdate = map[row.id]?.takeIf({ oldRow -> (oldRow != row) }) != null\n if (shouldUpdate) {\n map[row.id] = row\n }\n return shouldUpdate\n }\n\n override fun upsert(\n unsaved: DepartmentRow,\n c: Connection\n ): DepartmentRow {\n map[unsaved.id] = unsaved\n return unsaved\n }\n\n override fun upsertBatch(\n unsaved: Iterator,\n c: Connection\n ): List {\n val result = ArrayList()\n while (unsaved.hasNext()) {\n val row = unsaved.next()\n map[row.id] = row\n result.add(row)\n }\n return result\n }\n}", - "ProjectAssignmentRow": "package showcase.showcase.project_assignment\n\nimport dev.typr.foundations.DuckDbTypes\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport dev.typr.foundations.kotlin.nullable\nimport java.time.LocalDate\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.employee.EmployeeId\nimport showcase.showcase.project.ProjectId\n\n/** Table: showcase.project_assignment\n * Composite primary key: employee_id, project_id\n */\ndata class ProjectAssignmentRow(\n /** Points to [showcase.showcase.employee.EmployeeRow.id] */\n val employeeId: EmployeeId,\n /** Points to [showcase.showcase.project.ProjectRow.id] */\n val projectId: ProjectId,\n val role: String,\n /** Default: 0 */\n val hoursAllocated: Int?,\n val startDate: LocalDate?,\n val endDate: LocalDate?\n) {\n fun compositeId(): ProjectAssignmentId = ProjectAssignmentId(employeeId, projectId)\n\n fun id(): ProjectAssignmentId = this.compositeId()\n\n fun toUnsavedRow(hoursAllocated: Defaulted): ProjectAssignmentRowUnsaved = ProjectAssignmentRowUnsaved(employeeId, projectId, role, startDate, endDate, hoursAllocated)\n\n companion object {\n val _rowParser: RowParser = RowParsers.of(EmployeeId.duckDbType, ProjectId.duckDbType, DuckDbTypes.varchar, KotlinDbTypes.DuckDbTypes.integer.nullable(), DuckDbTypes.date.nullable(), DuckDbTypes.date.nullable(), { t0, t1, t2, t3, t4, t5 -> ProjectAssignmentRow(t0, t1, t2, t3, t4, t5) }, { row -> arrayOf(row.employeeId, row.projectId, row.role, row.hoursAllocated, row.startDate, row.endDate) })\n\n fun apply(\n compositeId: ProjectAssignmentId,\n role: String,\n hoursAllocated: Int?,\n startDate: LocalDate?,\n endDate: LocalDate?\n ): ProjectAssignmentRow = ProjectAssignmentRow(compositeId.employeeId, compositeId.projectId, role, hoursAllocated, startDate, endDate)\n }\n}", - "ProjectAssignmentRowUnsaved": "package showcase.showcase.project_assignment\n\nimport java.time.LocalDate\nimport showcase.customtypes.Defaulted\nimport showcase.customtypes.Defaulted.UseDefault\nimport showcase.showcase.employee.EmployeeId\nimport showcase.showcase.project.ProjectId\n\n/** This class corresponds to a row in table `showcase.project_assignment` which has not been persisted yet */\ndata class ProjectAssignmentRowUnsaved(\n /** Points to [showcase.showcase.employee.EmployeeRow.id] */\n val employeeId: EmployeeId,\n /** Points to [showcase.showcase.project.ProjectRow.id] */\n val projectId: ProjectId,\n val role: String,\n val startDate: LocalDate? = null,\n val endDate: LocalDate? = null,\n /** Default: 0 */\n val hoursAllocated: Defaulted = UseDefault()\n) {\n fun toRow(hoursAllocatedDefault: () -> Int?): ProjectAssignmentRow = ProjectAssignmentRow(employeeId = employeeId, projectId = projectId, role = role, hoursAllocated = hoursAllocated.getOrElse(hoursAllocatedDefault), startDate = startDate, endDate = endDate)\n}", - "ProjectAssignmentId": "package showcase.showcase.project_assignment\n\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport showcase.showcase.employee.EmployeeId\nimport showcase.showcase.project.ProjectId\n\n/** Type for the composite primary key of table `showcase.project_assignment` */\ndata class ProjectAssignmentId(\n val employeeId: EmployeeId,\n val projectId: ProjectId\n) {\n companion object {\n val _rowParser: RowParser = RowParsers.of(EmployeeId.duckDbType, ProjectId.duckDbType, { t0, t1 -> ProjectAssignmentId(t0, t1) }, { row -> arrayOf(row.employeeId, row.projectId) })\n }\n}", - "ProjectAssignmentRepo": "package showcase.showcase.project_assignment\n\nimport dev.typr.foundations.kotlin.DeleteBuilder\nimport dev.typr.foundations.kotlin.SelectBuilder\nimport dev.typr.foundations.kotlin.UpdateBuilder\nimport java.sql.Connection\nimport kotlin.collections.Iterator\nimport kotlin.collections.List\nimport kotlin.collections.Map\n\ninterface ProjectAssignmentRepo {\n abstract fun delete(): DeleteBuilder\n\n abstract fun deleteById(\n compositeId: ProjectAssignmentId,\n c: Connection\n ): Boolean\n\n abstract fun deleteByIds(\n compositeIds: Array,\n c: Connection\n ): Int\n\n abstract fun insert(\n unsaved: ProjectAssignmentRow,\n c: Connection\n ): ProjectAssignmentRow\n\n abstract fun insert(\n unsaved: ProjectAssignmentRowUnsaved,\n c: Connection\n ): ProjectAssignmentRow\n\n abstract fun select(): SelectBuilder\n\n abstract fun selectAll(c: Connection): List\n\n abstract fun selectById(\n compositeId: ProjectAssignmentId,\n c: Connection\n ): ProjectAssignmentRow?\n\n abstract fun selectByIds(\n compositeIds: Array,\n c: Connection\n ): List\n\n abstract fun selectByIdsTracked(\n compositeIds: Array,\n c: Connection\n ): Map\n\n abstract fun update(): UpdateBuilder\n\n abstract fun update(\n row: ProjectAssignmentRow,\n c: Connection\n ): Boolean\n\n abstract fun upsert(\n unsaved: ProjectAssignmentRow,\n c: Connection\n ): ProjectAssignmentRow\n\n abstract fun upsertBatch(\n unsaved: Iterator,\n c: Connection\n ): List\n}", - "ProjectRow": "package showcase.showcase.project\n\nimport dev.typr.foundations.DuckDbTypes\nimport dev.typr.foundations.data.Json\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport dev.typr.foundations.kotlin.nullable\nimport java.math.BigDecimal\nimport java.time.Duration\nimport java.time.LocalDate\nimport java.time.LocalDateTime\nimport showcase.ProjectProjectPhases\nimport showcase.customtypes.Defaulted\n\n/** Table: showcase.project\n * Primary key: id\n */\ndata class ProjectRow(\n val id: ProjectId,\n val name: String,\n val description: String?,\n val startDate: LocalDate?,\n val endDate: LocalDate?,\n val budget: BigDecimal?,\n /** Default: 'planning' */\n val status: String?,\n /** Default: CURRENT_TIMESTAMP */\n val createdAt: LocalDateTime?,\n val milestones: Array?,\n val budgetSnapshots: Array?,\n val teamMembers: Array?,\n val projectPhases: ProjectProjectPhases?,\n val config: /* MAP type - mapped to String */ String?,\n val riskScores: /* MAP type - mapped to String */ String?,\n val estimatedDuration: Duration?,\n val actualDuration: Duration?,\n val metadata: Json?\n) {\n fun toUnsavedRow(\n status: Defaulted,\n createdAt: Defaulted\n ): ProjectRowUnsaved = ProjectRowUnsaved(id, name, description, startDate, endDate, budget, milestones, budgetSnapshots, teamMembers, projectPhases, config, riskScores, estimatedDuration, actualDuration, metadata, status, createdAt)\n\n companion object {\n val _rowParser: RowParser = RowParsers.of(ProjectId.duckDbType, DuckDbTypes.varchar, DuckDbTypes.varchar.nullable(), DuckDbTypes.date.nullable(), DuckDbTypes.date.nullable(), DuckDbTypes.numeric.nullable(), DuckDbTypes.varchar.nullable(), DuckDbTypes.timestamp.nullable(), DuckDbTypes.varcharArray.nullable(), DuckDbTypes.decimalArray.nullable(), DuckDbTypes.varcharArray.nullable(), ProjectProjectPhases.duckDbType.nullable(), DuckDbTypes.varchar.mapTo(DuckDbTypes.varchar).nullable(), DuckDbTypes.varchar.mapTo(DuckDbTypes.integer).nullable(), DuckDbTypes.interval.nullable(), DuckDbTypes.interval.nullable(), DuckDbTypes.json.nullable(), { t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16 -> ProjectRow(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16) }, { row -> arrayOf(row.id, row.name, row.description, row.startDate, row.endDate, row.budget, row.status, row.createdAt, row.milestones, row.budgetSnapshots, row.teamMembers, row.projectPhases, row.config, row.riskScores, row.estimatedDuration, row.actualDuration, row.metadata) })\n }\n}", - "ProjectId": "package showcase.showcase.project\n\nimport dev.typr.foundations.DuckDbType\nimport dev.typr.foundations.DuckDbTypes\nimport dev.typr.foundations.internal.arrayMap\nimport dev.typr.foundations.kotlin.Bijection\n\n/** Type for the primary key of table `showcase.project` */\ndata class ProjectId(val value: String) {\n override fun toString(): kotlin.String {\n return value.toString()\n }\n\n companion object {\n val bijection: Bijection =\n Bijection.of(ProjectId::value, ::ProjectId)\n\n val duckDbType: DuckDbType =\n DuckDbTypes.varchar.bimap(::ProjectId, ProjectId::value)\n\n val pgTypeArray: DuckDbType> =\n DuckDbTypes.varcharArray.bimap({ xs -> arrayMap.map(xs, ::ProjectId, ProjectId::class.java) }, { xs -> arrayMap.map(xs, ProjectId::value, String::class.java) })\n }\n}", - "EmployeeSummaryViewRow": "package showcase.showcase.employee_summary\n\nimport dev.typr.foundations.DuckDbTypes\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport dev.typr.foundations.kotlin.nullable\nimport java.math.BigDecimal\nimport java.time.LocalDate\nimport showcase.showcase.company.CompanyId\nimport showcase.showcase.department.DepartmentId\nimport showcase.showcase.employee.EmployeeId\n\n/** View: showcase.employee_summary\n * Summary view of employees with their department and company information\n */\ndata class EmployeeSummaryViewRow(\n /** Points to [showcase.showcase.employee.EmployeeRow.id] */\n val employeeId: EmployeeId,\n val email: String,\n val firstName: String,\n val lastName: String,\n val salary: BigDecimal?,\n val hiredAt: LocalDate?,\n val active: Boolean?,\n /** Points to [showcase.showcase.department.DepartmentRow.id] */\n val departmentId: DepartmentId,\n val departmentName: String,\n val departmentBudget: BigDecimal?,\n /** Points to [showcase.showcase.company.CompanyRow.id] */\n val companyId: CompanyId,\n val companyName: String,\n val managerId: String?,\n val managerFirstName: String?,\n val managerLastName: String?\n) {\n companion object {\n val _rowParser: RowParser = RowParsers.of(EmployeeId.duckDbType, DuckDbTypes.varchar, DuckDbTypes.varchar, DuckDbTypes.varchar, DuckDbTypes.numeric.nullable(), DuckDbTypes.date.nullable(), KotlinDbTypes.DuckDbTypes.boolean_.nullable(), DepartmentId.duckDbType, DuckDbTypes.varchar, DuckDbTypes.numeric.nullable(), CompanyId.duckDbType, DuckDbTypes.varchar, DuckDbTypes.varchar.nullable(), DuckDbTypes.varchar.nullable(), DuckDbTypes.varchar.nullable(), { t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14 -> EmployeeSummaryViewRow(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14) }, { row -> arrayOf(row.employeeId, row.email, row.firstName, row.lastName, row.salary, row.hiredAt, row.active, row.departmentId, row.departmentName, row.departmentBudget, row.companyId, row.companyName, row.managerId, row.managerFirstName, row.managerLastName) })\n }\n}", - "EmployeeSummaryViewRepo": "package showcase.showcase.employee_summary\n\nimport dev.typr.foundations.kotlin.SelectBuilder\nimport java.sql.Connection\nimport kotlin.collections.List\n\ninterface EmployeeSummaryViewRepo {\n abstract fun select(): SelectBuilder\n\n abstract fun selectAll(c: Connection): List\n}", - "CustomerOrderRow": "package showcase.showcase.customer_order\n\nimport dev.typr.foundations.DuckDbTypes\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport dev.typr.foundations.kotlin.nullable\nimport java.math.BigDecimal\nimport java.time.Duration\nimport java.time.LocalDateTime\nimport java.time.OffsetDateTime\nimport showcase.CustomerOrderLineItemsSummary\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.address.AddressId\nimport showcase.showcase.customer.CustomerId\n\n/** Table: showcase.customer_order\n * Primary key: id\n */\ndata class CustomerOrderRow(\n val id: CustomerOrderId,\n /** Points to [showcase.showcase.customer.CustomerRow.id] */\n val customerId: CustomerId,\n /** Points to [showcase.showcase.address.AddressRow.id] */\n val shippingAddressId: AddressId?,\n /** Points to [showcase.showcase.address.AddressRow.id] */\n val billingAddressId: AddressId?,\n /** Default: 'pending' */\n val status: String?,\n val subtotal: BigDecimal,\n /** Default: 0 */\n val tax: BigDecimal?,\n /** Default: 0 */\n val shipping: BigDecimal?,\n val total: BigDecimal,\n val notes: String?,\n /** Default: CURRENT_TIMESTAMP */\n val createdAt: LocalDateTime?,\n val shippedAt: LocalDateTime?,\n val deliveredAt: LocalDateTime?,\n /** Default: now() */\n val orderedAtTz: OffsetDateTime?,\n val deliveredAtTz: OffsetDateTime?,\n val tags: Array?,\n val fulfillmentTimes: Array?,\n val lineItemsSummary: CustomerOrderLineItemsSummary?,\n val metadata: /* MAP type - mapped to String */ String?,\n val processingTime: Duration?\n) {\n fun toUnsavedRow(\n status: Defaulted,\n tax: Defaulted,\n shipping: Defaulted,\n createdAt: Defaulted,\n orderedAtTz: Defaulted\n ): CustomerOrderRowUnsaved = CustomerOrderRowUnsaved(id, customerId, shippingAddressId, billingAddressId, subtotal, total, notes, shippedAt, deliveredAt, deliveredAtTz, tags, fulfillmentTimes, lineItemsSummary, metadata, processingTime, status, tax, shipping, createdAt, orderedAtTz)\n\n companion object {\n val _rowParser: RowParser = RowParsers.of(CustomerOrderId.duckDbType, CustomerId.duckDbType, AddressId.duckDbType.nullable(), AddressId.duckDbType.nullable(), DuckDbTypes.varchar.nullable(), DuckDbTypes.numeric, DuckDbTypes.numeric.nullable(), DuckDbTypes.numeric.nullable(), DuckDbTypes.numeric, DuckDbTypes.varchar.nullable(), DuckDbTypes.timestamp.nullable(), DuckDbTypes.timestamp.nullable(), DuckDbTypes.timestamp.nullable(), DuckDbTypes.timestamptz.nullable(), DuckDbTypes.timestamptz.nullable(), DuckDbTypes.varcharArray.nullable(), DuckDbTypes.timestampArray.nullable(), CustomerOrderLineItemsSummary.duckDbType.nullable(), DuckDbTypes.varchar.mapTo(DuckDbTypes.varchar).nullable(), DuckDbTypes.interval.nullable(), { t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17, t18, t19 -> CustomerOrderRow(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17, t18, t19) }, { row -> arrayOf(row.id, row.customerId, row.shippingAddressId, row.billingAddressId, row.status, row.subtotal, row.tax, row.shipping, row.total, row.notes, row.createdAt, row.shippedAt, row.deliveredAt, row.orderedAtTz, row.deliveredAtTz, row.tags, row.fulfillmentTimes, row.lineItemsSummary, row.metadata, row.processingTime) })\n }\n}", - "CustomerOrderRepo": "package showcase.showcase.customer_order\n\nimport dev.typr.foundations.kotlin.DeleteBuilder\nimport dev.typr.foundations.kotlin.SelectBuilder\nimport dev.typr.foundations.kotlin.UpdateBuilder\nimport java.sql.Connection\nimport kotlin.collections.Iterator\nimport kotlin.collections.List\nimport kotlin.collections.Map\n\ninterface CustomerOrderRepo {\n abstract fun delete(): DeleteBuilder\n\n abstract fun deleteById(\n id: CustomerOrderId,\n c: Connection\n ): Boolean\n\n abstract fun deleteByIds(\n ids: Array,\n c: Connection\n ): Int\n\n abstract fun insert(\n unsaved: CustomerOrderRow,\n c: Connection\n ): CustomerOrderRow\n\n abstract fun insert(\n unsaved: CustomerOrderRowUnsaved,\n c: Connection\n ): CustomerOrderRow\n\n abstract fun select(): SelectBuilder\n\n abstract fun selectAll(c: Connection): List\n\n abstract fun selectById(\n id: CustomerOrderId,\n c: Connection\n ): CustomerOrderRow?\n\n abstract fun selectByIds(\n ids: Array,\n c: Connection\n ): List\n\n abstract fun selectByIdsTracked(\n ids: Array,\n c: Connection\n ): Map\n\n abstract fun update(): UpdateBuilder\n\n abstract fun update(\n row: CustomerOrderRow,\n c: Connection\n ): Boolean\n\n abstract fun upsert(\n unsaved: CustomerOrderRow,\n c: Connection\n ): CustomerOrderRow\n\n abstract fun upsertBatch(\n unsaved: Iterator,\n c: Connection\n ): List\n}", - "OrderItemRow": "package showcase.showcase.order_item\n\nimport dev.typr.foundations.DuckDbTypes\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport dev.typr.foundations.kotlin.nullable\nimport java.math.BigDecimal\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.customer_order.CustomerOrderId\nimport showcase.showcase.product.ProductId\n\n/** Table: showcase.order_item\n * Composite primary key: order_id, product_id\n */\ndata class OrderItemRow(\n /** Points to [showcase.showcase.customer_order.CustomerOrderRow.id] */\n val orderId: CustomerOrderId,\n /** Points to [showcase.showcase.product.ProductRow.id] */\n val productId: ProductId,\n val quantity: Int,\n val unitPrice: BigDecimal,\n /** Default: 0 */\n val discount: BigDecimal?\n) {\n fun compositeId(): OrderItemId = OrderItemId(orderId, productId)\n\n fun id(): OrderItemId = this.compositeId()\n\n fun toUnsavedRow(discount: Defaulted): OrderItemRowUnsaved = OrderItemRowUnsaved(orderId, productId, quantity, unitPrice, discount)\n\n companion object {\n val _rowParser: RowParser = RowParsers.of(CustomerOrderId.duckDbType, ProductId.duckDbType, KotlinDbTypes.DuckDbTypes.integer, DuckDbTypes.numeric, DuckDbTypes.numeric.nullable(), { t0, t1, t2, t3, t4 -> OrderItemRow(t0, t1, t2, t3, t4) }, { row -> arrayOf(row.orderId, row.productId, row.quantity, row.unitPrice, row.discount) })\n\n fun apply(\n compositeId: OrderItemId,\n quantity: Int,\n unitPrice: BigDecimal,\n discount: BigDecimal?\n ): OrderItemRow = OrderItemRow(compositeId.orderId, compositeId.productId, quantity, unitPrice, discount)\n }\n}", - "OrderItemId": "package showcase.showcase.order_item\n\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport showcase.showcase.customer_order.CustomerOrderId\nimport showcase.showcase.product.ProductId\n\n/** Type for the composite primary key of table `showcase.order_item` */\ndata class OrderItemId(\n val orderId: CustomerOrderId,\n val productId: ProductId\n) {\n companion object {\n val _rowParser: RowParser = RowParsers.of(CustomerOrderId.duckDbType, ProductId.duckDbType, { t0, t1 -> OrderItemId(t0, t1) }, { row -> arrayOf(row.orderId, row.productId) })\n }\n}", - "ProductRow": "package showcase.showcase.product\n\nimport dev.typr.foundations.DuckDbTypes\nimport dev.typr.foundations.data.Json\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport dev.typr.foundations.kotlin.nullable\nimport java.math.BigDecimal\nimport java.time.LocalDateTime\nimport showcase.ProductDimensions\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.category.CategoryId\n\n/** Table: showcase.product\n * Primary key: id\n */\ndata class ProductRow(\n val id: ProductId,\n /** Points to [showcase.showcase.category.CategoryRow.id] */\n val categoryId: CategoryId?,\n val name: String,\n val sku: String,\n val price: BigDecimal,\n val cost: BigDecimal?,\n /** Default: true */\n val inStock: Boolean?,\n /** Default: 0 */\n val quantity: Int?,\n val weight: BigDecimal?,\n /** Default: CURRENT_TIMESTAMP */\n val createdAt: LocalDateTime?,\n val tags: Array?,\n val images: Array?,\n val relatedSkus: Array?,\n val priceHistory: Array?,\n val categoryIds: Array?,\n val dimensions: ProductDimensions?,\n val attributes: /* MAP type - mapped to String */ String?,\n val specifications: /* MAP type - mapped to String */ String?,\n val pricesByRegion: /* MAP type - mapped to String */ String?,\n val stockByWarehouse: /* MAP type - mapped to String */ String?,\n val seoMetadata: Json?\n) {\n fun toUnsavedRow(\n inStock: Defaulted,\n quantity: Defaulted,\n createdAt: Defaulted\n ): ProductRowUnsaved = ProductRowUnsaved(id, categoryId, name, sku, price, cost, weight, tags, images, relatedSkus, priceHistory, categoryIds, dimensions, attributes, specifications, pricesByRegion, stockByWarehouse, seoMetadata, inStock, quantity, createdAt)\n\n companion object {\n val _rowParser: RowParser = RowParsers.of(ProductId.duckDbType, CategoryId.duckDbType.nullable(), DuckDbTypes.varchar, DuckDbTypes.varchar, DuckDbTypes.numeric, DuckDbTypes.numeric.nullable(), KotlinDbTypes.DuckDbTypes.boolean_.nullable(), KotlinDbTypes.DuckDbTypes.integer.nullable(), DuckDbTypes.numeric.nullable(), DuckDbTypes.timestamp.nullable(), DuckDbTypes.varcharArray.nullable(), DuckDbTypes.varcharArray.nullable(), DuckDbTypes.varcharArray.nullable(), DuckDbTypes.decimalArray.nullable(), DuckDbTypes.integerArray.nullable(), ProductDimensions.duckDbType.nullable(), DuckDbTypes.varchar.mapTo(DuckDbTypes.varchar).nullable(), DuckDbTypes.varchar.mapTo(DuckDbTypes.varchar).nullable(), DuckDbTypes.varchar.mapTo(DuckDbTypes.numeric).nullable(), DuckDbTypes.varchar.mapTo(DuckDbTypes.integer).nullable(), DuckDbTypes.json.nullable(), { t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17, t18, t19, t20 -> ProductRow(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17, t18, t19, t20) }, { row -> arrayOf(row.id, row.categoryId, row.name, row.sku, row.price, row.cost, row.inStock, row.quantity, row.weight, row.createdAt, row.tags, row.images, row.relatedSkus, row.priceHistory, row.categoryIds, row.dimensions, row.attributes, row.specifications, row.pricesByRegion, row.stockByWarehouse, row.seoMetadata) })\n }\n}", - "ProductId": "package showcase.showcase.product\n\nimport dev.typr.foundations.DuckDbType\nimport dev.typr.foundations.DuckDbTypes\nimport dev.typr.foundations.internal.arrayMap\nimport dev.typr.foundations.kotlin.Bijection\n\n/** Type for the primary key of table `showcase.product` */\ndata class ProductId(val value: String) {\n override fun toString(): kotlin.String {\n return value.toString()\n }\n\n companion object {\n val bijection: Bijection =\n Bijection.of(ProductId::value, ::ProductId)\n\n val duckDbType: DuckDbType =\n DuckDbTypes.varchar.bimap(::ProductId, ProductId::value)\n\n val pgTypeArray: DuckDbType> =\n DuckDbTypes.varcharArray.bimap({ xs -> arrayMap.map(xs, ::ProductId, ProductId::class.java) }, { xs -> arrayMap.map(xs, ProductId::value, String::class.java) })\n }\n}", - "CategoryRow": "package showcase.showcase.category\n\nimport dev.typr.foundations.DuckDbTypes\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport dev.typr.foundations.kotlin.nullable\n\n/** Table: showcase.category\n * Primary key: id\n */\ndata class CategoryRow(\n val id: CategoryId,\n /** Points to [showcase.showcase.category.CategoryRow.id] */\n val parentId: CategoryId?,\n val name: String,\n val description: String?\n) {\n companion object {\n val _rowParser: RowParser = RowParsers.of(CategoryId.duckDbType, CategoryId.duckDbType.nullable(), DuckDbTypes.varchar, DuckDbTypes.varchar.nullable(), { t0, t1, t2, t3 -> CategoryRow(t0, t1, t2, t3) }, { row -> arrayOf(row.id, row.parentId, row.name, row.description) })\n }\n}", - "CategoryId": "package showcase.showcase.category\n\nimport dev.typr.foundations.DuckDbType\nimport dev.typr.foundations.DuckDbTypes\nimport dev.typr.foundations.internal.arrayMap\nimport dev.typr.foundations.kotlin.Bijection\n\n/** Type for the primary key of table `showcase.category` */\ndata class CategoryId(val value: String) {\n override fun toString(): kotlin.String {\n return value.toString()\n }\n\n companion object {\n val bijection: Bijection =\n Bijection.of(CategoryId::value, ::CategoryId)\n\n val duckDbType: DuckDbType =\n DuckDbTypes.varchar.bimap(::CategoryId, CategoryId::value)\n\n val pgTypeArray: DuckDbType> =\n DuckDbTypes.varcharArray.bimap({ xs -> arrayMap.map(xs, ::CategoryId, CategoryId::class.java) }, { xs -> arrayMap.map(xs, CategoryId::value, String::class.java) })\n }\n}", - "AddressRow": "package showcase.showcase.address\n\nimport dev.typr.foundations.DuckDbTypes\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport dev.typr.foundations.kotlin.nullable\nimport showcase.AddressCoordinates\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.customer.CustomerId\n\n/** Table: showcase.address\n * Primary key: id\n */\ndata class AddressRow(\n val id: AddressId,\n /** Points to [showcase.showcase.customer.CustomerRow.id] */\n val customerId: CustomerId,\n val addressType: String,\n val street: String,\n val city: String,\n val state: String?,\n val postalCode: String?,\n val country: String,\n /** Default: false */\n val isDefault: Boolean?,\n val coordinates: AddressCoordinates?\n) {\n fun toUnsavedRow(isDefault: Defaulted): AddressRowUnsaved = AddressRowUnsaved(id, customerId, addressType, street, city, state, postalCode, country, coordinates, isDefault)\n\n companion object {\n val _rowParser: RowParser = RowParsers.of(AddressId.duckDbType, CustomerId.duckDbType, DuckDbTypes.varchar, DuckDbTypes.varchar, DuckDbTypes.varchar, DuckDbTypes.varchar.nullable(), DuckDbTypes.varchar.nullable(), DuckDbTypes.varchar, KotlinDbTypes.DuckDbTypes.boolean_.nullable(), AddressCoordinates.duckDbType.nullable(), { t0, t1, t2, t3, t4, t5, t6, t7, t8, t9 -> AddressRow(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9) }, { row -> arrayOf(row.id, row.customerId, row.addressType, row.street, row.city, row.state, row.postalCode, row.country, row.isDefault, row.coordinates) })\n }\n}", - "AddressId": "package showcase.showcase.address\n\nimport dev.typr.foundations.DuckDbType\nimport dev.typr.foundations.DuckDbTypes\nimport dev.typr.foundations.internal.arrayMap\nimport dev.typr.foundations.kotlin.Bijection\n\n/** Type for the primary key of table `showcase.address` */\ndata class AddressId(val value: String) {\n override fun toString(): kotlin.String {\n return value.toString()\n }\n\n companion object {\n val bijection: Bijection =\n Bijection.of(AddressId::value, ::AddressId)\n\n val duckDbType: DuckDbType =\n DuckDbTypes.varchar.bimap(::AddressId, AddressId::value)\n\n val pgTypeArray: DuckDbType> =\n DuckDbTypes.varcharArray.bimap({ xs -> arrayMap.map(xs, ::AddressId, AddressId::class.java) }, { xs -> arrayMap.map(xs, AddressId::value, String::class.java) })\n }\n}", - "Defaulted": "package showcase.customtypes\n\n\n\n/** This signals a value where if you don't provide it, postgres will generate it for you */\nsealed interface Defaulted {\n data class Provided(val value: T) : Defaulted {\n override fun fold(\n onDefault: () -> U,\n onProvided: (T) -> U\n ): U = onProvided(value)\n\n override fun getOrElse(onDefault: () -> T): T = value\n\n override fun visit(\n onDefault: () -> Unit,\n onProvided: (T) -> Unit\n ) {\n onProvided(value)\n }\n }\n\n class UseDefault : Defaulted {\n override fun fold(\n onDefault: () -> U,\n onProvided: (T) -> U\n ): U = onDefault()\n\n override fun getOrElse(onDefault: () -> T): T = onDefault()\n\n override fun visit(\n onDefault: () -> Unit,\n onProvided: (T) -> Unit\n ) {\n onDefault()\n }\n }\n\n abstract fun fold(\n onDefault: () -> U,\n onProvided: (T) -> U\n ): U\n\n abstract fun getOrElse(onDefault: () -> T): T\n\n abstract fun visit(\n onDefault: () -> Unit,\n onProvided: (T) -> Unit\n )\n}", - "TestInsert": "package showcase\n\nimport dev.typr.foundations.data.Json\nimport java.math.BigDecimal\nimport java.math.BigInteger\nimport java.sql.Connection\nimport java.time.Duration\nimport java.time.LocalDate\nimport java.time.LocalDateTime\nimport java.time.LocalTime\nimport java.time.OffsetDateTime\nimport java.util.Random\nimport java.util.UUID\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.address.AddressId\nimport showcase.showcase.address.AddressRepoImpl\nimport showcase.showcase.address.AddressRow\nimport showcase.showcase.address.AddressRowUnsaved\nimport showcase.showcase.audit_log.AuditLogId\nimport showcase.showcase.audit_log.AuditLogRepoImpl\nimport showcase.showcase.audit_log.AuditLogRow\nimport showcase.showcase.audit_log.AuditLogRowUnsaved\nimport showcase.showcase.category.CategoryId\nimport showcase.showcase.category.CategoryRepoImpl\nimport showcase.showcase.category.CategoryRow\nimport showcase.showcase.company.CompanyId\nimport showcase.showcase.company.CompanyRepoImpl\nimport showcase.showcase.company.CompanyRow\nimport showcase.showcase.company.CompanyRowUnsaved\nimport showcase.showcase.customer.CustomerId\nimport showcase.showcase.customer.CustomerRepoImpl\nimport showcase.showcase.customer.CustomerRow\nimport showcase.showcase.customer.CustomerRowUnsaved\nimport showcase.showcase.customer_order.CustomerOrderId\nimport showcase.showcase.customer_order.CustomerOrderRepoImpl\nimport showcase.showcase.customer_order.CustomerOrderRow\nimport showcase.showcase.customer_order.CustomerOrderRowUnsaved\nimport showcase.showcase.datetime_demo.DatetimeDemoId\nimport showcase.showcase.datetime_demo.DatetimeDemoRepoImpl\nimport showcase.showcase.datetime_demo.DatetimeDemoRow\nimport showcase.showcase.datetime_demo.DatetimeDemoRowUnsaved\nimport showcase.showcase.department.DepartmentId\nimport showcase.showcase.department.DepartmentRepoImpl\nimport showcase.showcase.department.DepartmentRow\nimport showcase.showcase.employee.EmployeeId\nimport showcase.showcase.employee.EmployeeRepoImpl\nimport showcase.showcase.employee.EmployeeRow\nimport showcase.showcase.employee.EmployeeRowUnsaved\nimport showcase.showcase.file_storage.FileStorageId\nimport showcase.showcase.file_storage.FileStorageRepoImpl\nimport showcase.showcase.file_storage.FileStorageRow\nimport showcase.showcase.file_storage.FileStorageRowUnsaved\nimport showcase.showcase.financial_record.FinancialRecordId\nimport showcase.showcase.financial_record.FinancialRecordRepoImpl\nimport showcase.showcase.financial_record.FinancialRecordRow\nimport showcase.showcase.financial_record.FinancialRecordRowUnsaved\nimport showcase.showcase.numeric_types_demo.NumericTypesDemoId\nimport showcase.showcase.numeric_types_demo.NumericTypesDemoRepoImpl\nimport showcase.showcase.numeric_types_demo.NumericTypesDemoRow\nimport showcase.showcase.numeric_types_demo.NumericTypesDemoRowUnsaved\nimport showcase.showcase.order_item.OrderItemRepoImpl\nimport showcase.showcase.order_item.OrderItemRow\nimport showcase.showcase.order_item.OrderItemRowUnsaved\nimport showcase.showcase.product.ProductId\nimport showcase.showcase.product.ProductRepoImpl\nimport showcase.showcase.product.ProductRow\nimport showcase.showcase.product.ProductRowUnsaved\nimport showcase.showcase.project.ProjectId\nimport showcase.showcase.project.ProjectRepoImpl\nimport showcase.showcase.project.ProjectRow\nimport showcase.showcase.project.ProjectRowUnsaved\nimport showcase.showcase.project_assignment.ProjectAssignmentRepoImpl\nimport showcase.showcase.project_assignment.ProjectAssignmentRow\nimport showcase.showcase.project_assignment.ProjectAssignmentRowUnsaved\nimport showcase.showcase.scientific_data.ScientificDataId\nimport showcase.showcase.scientific_data.ScientificDataRepoImpl\nimport showcase.showcase.scientific_data.ScientificDataRow\nimport showcase.showcase.scientific_data.ScientificDataRowUnsaved\nimport showcase.showcase.session.SessionId\nimport showcase.showcase.session.SessionRepoImpl\nimport showcase.showcase.session.SessionRow\nimport showcase.showcase.session.SessionRowUnsaved\nimport showcase.showcase.subscription.SubscriptionId\nimport showcase.showcase.subscription.SubscriptionRepoImpl\nimport showcase.showcase.subscription.SubscriptionRow\nimport showcase.showcase.subscription.SubscriptionRowUnsaved\n\n/** Methods to generate random data for `Ident(TestInsert)` */\ndata class TestInsert(val random: Random) {\n fun showcaseAddress(\n id: AddressId,\n customerId: CustomerId,\n addressType: String,\n street: String,\n city: String,\n country: String,\n state: String?,\n postalCode: String?,\n coordinates: AddressCoordinates?,\n isDefault: Defaulted,\n c: Connection\n ): AddressRow = (AddressRepoImpl()).insert(AddressRowUnsaved(id = id, customerId = customerId, addressType = addressType, street = street, city = city, state = state, postalCode = postalCode, country = country, coordinates = coordinates, isDefault = isDefault), c)\n\n fun showcaseAuditLog(\n id: AuditLogId,\n tableName: String,\n recordId: String,\n action: String,\n oldValues: String?,\n newValues: String?,\n changedBy: EmployeeId?,\n changedAt: Defaulted,\n c: Connection\n ): AuditLogRow = (AuditLogRepoImpl()).insert(AuditLogRowUnsaved(id = id, tableName = tableName, recordId = recordId, action = action, oldValues = oldValues, newValues = newValues, changedBy = changedBy, changedAt = changedAt), c)\n\n fun showcaseCategory(\n id: CategoryId,\n name: String,\n parentId: CategoryId?,\n description: String?,\n c: Connection\n ): CategoryRow = (CategoryRepoImpl()).insert(CategoryRow(id = id, parentId = parentId, name = name, description = description), c)\n\n fun showcaseCompany(\n id: CompanyId,\n name: String,\n foundedYear: Int?,\n active: Defaulted,\n createdAt: Defaulted,\n c: Connection\n ): CompanyRow = (CompanyRepoImpl()).insert(CompanyRowUnsaved(id = id, name = name, foundedYear = foundedYear, active = active, createdAt = createdAt), c)\n\n fun showcaseCustomer(\n id: CustomerId,\n email: String,\n firstName: String,\n lastName: String,\n phone: String?,\n interests: Array?,\n orderCounts: Array?,\n preferences: CustomerPreferences?,\n metadata: /* MAP type - mapped to String */ String?,\n verified: Defaulted,\n createdAt: Defaulted,\n c: Connection\n ): CustomerRow = (CustomerRepoImpl()).insert(CustomerRowUnsaved(id = id, email = email, firstName = firstName, lastName = lastName, phone = phone, interests = interests, orderCounts = orderCounts, preferences = preferences, metadata = metadata, verified = verified, createdAt = createdAt), c)\n\n fun showcaseCustomerOrder(\n id: CustomerOrderId,\n customerId: CustomerId,\n shippingAddressId: AddressId?,\n billingAddressId: AddressId?,\n subtotal: BigDecimal,\n total: BigDecimal,\n notes: String?,\n shippedAt: LocalDateTime?,\n deliveredAt: LocalDateTime?,\n deliveredAtTz: OffsetDateTime?,\n tags: Array?,\n fulfillmentTimes: Array?,\n lineItemsSummary: CustomerOrderLineItemsSummary?,\n metadata: /* MAP type - mapped to String */ String?,\n processingTime: Duration?,\n status: Defaulted,\n tax: Defaulted,\n shipping: Defaulted,\n createdAt: Defaulted,\n orderedAtTz: Defaulted,\n c: Connection\n ): CustomerOrderRow = (CustomerOrderRepoImpl()).insert(CustomerOrderRowUnsaved(id = id, customerId = customerId, shippingAddressId = shippingAddressId, billingAddressId = billingAddressId, subtotal = subtotal, total = total, notes = notes, shippedAt = shippedAt, deliveredAt = deliveredAt, deliveredAtTz = deliveredAtTz, tags = tags, fulfillmentTimes = fulfillmentTimes, lineItemsSummary = lineItemsSummary, metadata = metadata, processingTime = processingTime, status = status, tax = tax, shipping = shipping, createdAt = createdAt, orderedAtTz = orderedAtTz), c)\n\n fun showcaseDatetimeDemo(\n id: DatetimeDemoId,\n dateOnly: LocalDate?,\n timeOnly: LocalTime?,\n timestampVal: LocalDateTime?,\n timestampTz: OffsetDateTime?,\n timestampS: LocalDateTime?,\n timestampMs: LocalDateTime?,\n timestampNs: LocalDateTime?,\n createdAt: Defaulted,\n c: Connection\n ): DatetimeDemoRow = (DatetimeDemoRepoImpl()).insert(DatetimeDemoRowUnsaved(id = id, dateOnly = dateOnly, timeOnly = timeOnly, timestampVal = timestampVal, timestampTz = timestampTz, timestampS = timestampS, timestampMs = timestampMs, timestampNs = timestampNs, createdAt = createdAt), c)\n\n fun showcaseDepartment(\n id: DepartmentId,\n companyId: CompanyId,\n name: String,\n budget: BigDecimal?,\n c: Connection\n ): DepartmentRow = (DepartmentRepoImpl()).insert(DepartmentRow(id = id, companyId = companyId, name = name, budget = budget), c)\n\n fun showcaseEmployee(\n id: EmployeeId,\n departmentId: DepartmentId,\n email: String,\n firstName: String,\n lastName: String,\n managerId: EmployeeId?,\n salary: BigDecimal?,\n hiredAt: LocalDate?,\n skills: Array?,\n certifications: Array?,\n weeklyAvailability: Array?,\n contactInfo: EmployeeContactInfo?,\n settings: /* MAP type - mapped to String */ String?,\n skillsRating: /* MAP type - mapped to String */ String?,\n probationPeriod: Duration?,\n active: Defaulted,\n createdAt: Defaulted,\n c: Connection\n ): EmployeeRow = (EmployeeRepoImpl()).insert(EmployeeRowUnsaved(id = id, departmentId = departmentId, managerId = managerId, email = email, firstName = firstName, lastName = lastName, salary = salary, hiredAt = hiredAt, skills = skills, certifications = certifications, weeklyAvailability = weeklyAvailability, contactInfo = contactInfo, settings = settings, skillsRating = skillsRating, probationPeriod = probationPeriod, active = active, createdAt = createdAt), c)\n\n fun showcaseFileStorage(\n id: FileStorageId,\n filename: String,\n mimeType: String?,\n fileData: ByteArray?,\n thumbnail: ByteArray?,\n checksum: ByteArray?,\n fileSize: BigInteger?,\n uploadedAt: Defaulted,\n c: Connection\n ): FileStorageRow = (FileStorageRepoImpl()).insert(FileStorageRowUnsaved(id = id, filename = filename, mimeType = mimeType, fileData = fileData, thumbnail = thumbnail, checksum = checksum, fileSize = fileSize, uploadedAt = uploadedAt), c)\n\n fun showcaseFinancialRecord(\n id: FinancialRecordId,\n description: String,\n amount: BigDecimal,\n balance: BigDecimal?,\n exchangeRate: BigDecimal?,\n percentage: BigDecimal?,\n createdAt: Defaulted,\n c: Connection\n ): FinancialRecordRow = (FinancialRecordRepoImpl()).insert(FinancialRecordRowUnsaved(id = id, description = description, amount = amount, balance = balance, exchangeRate = exchangeRate, percentage = percentage, createdAt = createdAt), c)\n\n fun showcaseNumericTypesDemo(\n id: NumericTypesDemoId,\n tinyVal: Byte?,\n utinyVal: Short?,\n smallVal: Short?,\n usmallVal: Int?,\n intVal: Int?,\n uintVal: Long?,\n bigVal: Long?,\n ubigVal: BigInteger?,\n hugeVal: BigInteger?,\n uhugeVal: BigInteger?,\n createdAt: Defaulted,\n c: Connection\n ): NumericTypesDemoRow = (NumericTypesDemoRepoImpl()).insert(NumericTypesDemoRowUnsaved(id = id, tinyVal = tinyVal, utinyVal = utinyVal, smallVal = smallVal, usmallVal = usmallVal, intVal = intVal, uintVal = uintVal, bigVal = bigVal, ubigVal = ubigVal, hugeVal = hugeVal, uhugeVal = uhugeVal, createdAt = createdAt), c)\n\n fun showcaseOrderItem(\n orderId: CustomerOrderId,\n productId: ProductId,\n quantity: Int,\n unitPrice: BigDecimal,\n discount: Defaulted,\n c: Connection\n ): OrderItemRow = (OrderItemRepoImpl()).insert(OrderItemRowUnsaved(orderId = orderId, productId = productId, quantity = quantity, unitPrice = unitPrice, discount = discount), c)\n\n fun showcaseProduct(\n id: ProductId,\n name: String,\n sku: String,\n categoryId: CategoryId?,\n price: BigDecimal,\n cost: BigDecimal?,\n weight: BigDecimal?,\n tags: Array?,\n images: Array?,\n relatedSkus: Array?,\n priceHistory: Array?,\n categoryIds: Array?,\n dimensions: ProductDimensions?,\n attributes: /* MAP type - mapped to String */ String?,\n specifications: /* MAP type - mapped to String */ String?,\n pricesByRegion: /* MAP type - mapped to String */ String?,\n stockByWarehouse: /* MAP type - mapped to String */ String?,\n seoMetadata: Json?,\n inStock: Defaulted,\n quantity: Defaulted,\n createdAt: Defaulted,\n c: Connection\n ): ProductRow = (ProductRepoImpl()).insert(ProductRowUnsaved(id = id, categoryId = categoryId, name = name, sku = sku, price = price, cost = cost, weight = weight, tags = tags, images = images, relatedSkus = relatedSkus, priceHistory = priceHistory, categoryIds = categoryIds, dimensions = dimensions, attributes = attributes, specifications = specifications, pricesByRegion = pricesByRegion, stockByWarehouse = stockByWarehouse, seoMetadata = seoMetadata, inStock = inStock, quantity = quantity, createdAt = createdAt), c)\n\n fun showcaseProject(\n id: ProjectId,\n name: String,\n description: String?,\n startDate: LocalDate?,\n endDate: LocalDate?,\n budget: BigDecimal?,\n milestones: Array?,\n budgetSnapshots: Array?,\n teamMembers: Array?,\n projectPhases: ProjectProjectPhases?,\n config: /* MAP type - mapped to String */ String?,\n riskScores: /* MAP type - mapped to String */ String?,\n estimatedDuration: Duration?,\n actualDuration: Duration?,\n metadata: Json?,\n status: Defaulted,\n createdAt: Defaulted,\n c: Connection\n ): ProjectRow = (ProjectRepoImpl()).insert(ProjectRowUnsaved(id = id, name = name, description = description, startDate = startDate, endDate = endDate, budget = budget, milestones = milestones, budgetSnapshots = budgetSnapshots, teamMembers = teamMembers, projectPhases = projectPhases, config = config, riskScores = riskScores, estimatedDuration = estimatedDuration, actualDuration = actualDuration, metadata = metadata, status = status, createdAt = createdAt), c)\n\n fun showcaseProjectAssignment(\n employeeId: EmployeeId,\n projectId: ProjectId,\n role: String,\n startDate: LocalDate?,\n endDate: LocalDate?,\n hoursAllocated: Defaulted,\n c: Connection\n ): ProjectAssignmentRow = (ProjectAssignmentRepoImpl()).insert(ProjectAssignmentRowUnsaved(employeeId = employeeId, projectId = projectId, role = role, startDate = startDate, endDate = endDate, hoursAllocated = hoursAllocated), c)\n\n fun showcaseScientificData(\n id: ScientificDataId,\n floatVal: Float?,\n doubleVal: Double?,\n createdAt: Defaulted,\n c: Connection\n ): ScientificDataRow = (ScientificDataRepoImpl()).insert(ScientificDataRowUnsaved(id = id, floatVal = floatVal, doubleVal = doubleVal, createdAt = createdAt), c)\n\n fun showcaseSession(\n expiresAt: LocalDateTime,\n userId: String?,\n refreshToken: UUID?,\n deviceId: UUID?,\n id: Defaulted,\n token: Defaulted,\n createdAt: Defaulted,\n c: Connection\n ): SessionRow = (SessionRepoImpl()).insert(SessionRowUnsaved(userId = userId, refreshToken = refreshToken, deviceId = deviceId, expiresAt = expiresAt, id = id, token = token, createdAt = createdAt), c)\n\n fun showcaseSubscription(\n id: SubscriptionId,\n customerId: String,\n planName: String,\n billingCycle: Duration,\n trialPeriod: Duration?,\n startedAt: Defaulted,\n c: Connection\n ): SubscriptionRow = (SubscriptionRepoImpl()).insert(SubscriptionRowUnsaved(id = id, customerId = customerId, planName = planName, billingCycle = billingCycle, trialPeriod = trialPeriod, startedAt = startedAt), c)\n}" - }, - "scala": { - "CompanyRow": "package showcase.showcase.company\n\nimport dev.typr.foundations.DuckDbTypes\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport java.time.LocalDateTime\nimport showcase.customtypes.Defaulted\n\n/** Table: showcase.company\n * Primary key: id\n */\ncase class CompanyRow(\n id: CompanyId,\n name: String,\n foundedYear: Option[Int],\n /** Default: true */\n active: Option[Boolean],\n /** Default: CURRENT_TIMESTAMP */\n createdAt: Option[LocalDateTime]\n) {\n def toUnsavedRow(\n active: Defaulted[Option[Boolean]] = Defaulted.Provided(this.active),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.Provided(this.createdAt)\n ): CompanyRowUnsaved = {\n new CompanyRowUnsaved(\n id,\n name,\n foundedYear,\n active,\n createdAt\n )\n }\n}\n\nobject CompanyRow {\n val `_rowParser`: RowParser[CompanyRow] = RowParsers.of(CompanyId.duckDbType, DuckDbTypes.varchar, ScalaDbTypes.DuckDbTypes.integer.nullable, ScalaDbTypes.DuckDbTypes.boolean_.nullable, DuckDbTypes.timestamp.nullable)(CompanyRow.apply)(row => Array[Any](row.id, row.name, row.foundedYear, row.active, row.createdAt))\n}", - "CompanyRowUnsaved": "package showcase.showcase.company\n\nimport java.time.LocalDateTime\nimport showcase.customtypes.Defaulted\nimport showcase.customtypes.Defaulted.UseDefault\n\n/** This class corresponds to a row in table `showcase.company` which has not been persisted yet */\ncase class CompanyRowUnsaved(\n id: CompanyId,\n name: String,\n foundedYear: Option[Int] = None,\n /** Default: true */\n active: Defaulted[Option[Boolean]] = new UseDefault(),\n /** Default: CURRENT_TIMESTAMP */\n createdAt: Defaulted[Option[LocalDateTime]] = new UseDefault()\n) {\n def toRow(\n activeDefault: => Option[Boolean],\n createdAtDefault: => Option[LocalDateTime]\n ): CompanyRow = {\n new CompanyRow(\n id = id,\n name = name,\n foundedYear = foundedYear,\n active = active.getOrElse(activeDefault),\n createdAt = createdAt.getOrElse(createdAtDefault)\n )\n }\n}", - "CompanyId": "package showcase.showcase.company\n\nimport dev.typr.foundations.DuckDbType\nimport dev.typr.foundations.DuckDbTypes\nimport dev.typr.foundations.scala.Bijection\n\n/** Type for the primary key of table `showcase.company` */\ncase class CompanyId(value: String) extends scala.AnyVal\n\nobject CompanyId {\n given bijection: Bijection[CompanyId, String] = Bijection.apply[CompanyId, String](_.value)(CompanyId.apply)\n\n given duckDbType: DuckDbType[CompanyId] = DuckDbTypes.varchar.bimap(CompanyId.apply, _.value)\n\n given pgTypeArray: DuckDbType[Array[CompanyId]] = DuckDbTypes.varcharArray.bimap(xs => xs.map(CompanyId.apply), xs => xs.map(_.value))\n}", - "CompanyRepo": "package showcase.showcase.company\n\nimport dev.typr.foundations.scala.DeleteBuilder\nimport dev.typr.foundations.scala.SelectBuilder\nimport dev.typr.foundations.scala.UpdateBuilder\nimport java.sql.Connection\n\ntrait CompanyRepo {\n def delete: DeleteBuilder[CompanyFields, CompanyRow]\n\n def deleteById(id: CompanyId)(using c: Connection): Boolean\n\n def deleteByIds(ids: Array[CompanyId])(using c: Connection): Int\n\n def insert(unsaved: CompanyRow)(using c: Connection): CompanyRow\n\n def insert(unsaved: CompanyRowUnsaved)(using c: Connection): CompanyRow\n\n def select: SelectBuilder[CompanyFields, CompanyRow]\n\n def selectAll(using c: Connection): List[CompanyRow]\n\n def selectById(id: CompanyId)(using c: Connection): Option[CompanyRow]\n\n def selectByIds(ids: Array[CompanyId])(using c: Connection): List[CompanyRow]\n\n def selectByIdsTracked(ids: Array[CompanyId])(using c: Connection): Map[CompanyId, CompanyRow]\n\n def update: UpdateBuilder[CompanyFields, CompanyRow]\n\n def update(row: CompanyRow)(using c: Connection): Boolean\n\n def upsert(unsaved: CompanyRow)(using c: Connection): CompanyRow\n\n def upsertBatch(unsaved: Iterator[CompanyRow])(using c: Connection): List[CompanyRow]\n}", - "CompanyRepoMock": "package showcase.showcase.company\n\nimport dev.typr.foundations.scala.DeleteBuilder\nimport dev.typr.foundations.scala.DeleteBuilderMock\nimport dev.typr.foundations.scala.DeleteParams\nimport dev.typr.foundations.scala.SelectBuilder\nimport dev.typr.foundations.scala.SelectBuilderMock\nimport dev.typr.foundations.scala.SelectParams\nimport dev.typr.foundations.scala.UpdateBuilder\nimport dev.typr.foundations.scala.UpdateBuilderMock\nimport dev.typr.foundations.scala.UpdateParams\nimport java.lang.RuntimeException\nimport java.sql.Connection\n\ncase class CompanyRepoMock(\n toRow: CompanyRowUnsaved => CompanyRow,\n map: scala.collection.mutable.Map[CompanyId, CompanyRow] = scala.collection.mutable.Map.empty[CompanyId, CompanyRow]\n) extends CompanyRepo {\n override def delete: DeleteBuilder[CompanyFields, CompanyRow] = DeleteBuilderMock(CompanyFields.structure, () => map.values.toList, DeleteParams.empty(), row => row.id, id => map.remove(id): @scala.annotation.nowarn)\n\n override def deleteById(id: CompanyId)(using c: Connection): Boolean = map.remove(id).isDefined\n\n override def deleteByIds(ids: Array[CompanyId])(using c: Connection): Int = {\n var count = 0\n ids.foreach { id => if (map.remove(id).isDefined) {\n count = count + 1\n } }\n return count\n }\n\n override def insert(unsaved: CompanyRow)(using c: Connection): CompanyRow = {\n if (map.contains(unsaved.id)) {\n throw new RuntimeException(s\"id ${unsaved.id} already exists\")\n }\n map.put(unsaved.id, unsaved): @scala.annotation.nowarn\n return unsaved\n }\n\n override def insert(unsaved: CompanyRowUnsaved)(using c: Connection): CompanyRow = insert(toRow(unsaved))(using c)\n\n override def select: SelectBuilder[CompanyFields, CompanyRow] = SelectBuilderMock(CompanyFields.structure, () => map.values.toList, SelectParams.empty())\n\n override def selectAll(using c: Connection): List[CompanyRow] = map.values.toList\n\n override def selectById(id: CompanyId)(using c: Connection): Option[CompanyRow] = map.get(id)\n\n override def selectByIds(ids: Array[CompanyId])(using c: Connection): List[CompanyRow] = ids.flatMap(map.get(_)).toList\n\n override def selectByIdsTracked(ids: Array[CompanyId])(using c: Connection): Map[CompanyId, CompanyRow] = selectByIds(ids)(using c).map(x => (((row: CompanyRow) => row.id).apply(x), x)).toMap\n\n override def update: UpdateBuilder[CompanyFields, CompanyRow] = UpdateBuilderMock(CompanyFields.structure, () => map.values.toList, UpdateParams.empty(), row => row)\n\n override def update(row: CompanyRow)(using c: Connection): Boolean = {\n val shouldUpdate = map.get(row.id).filter(oldRow => (oldRow != row)).isDefined\n if (shouldUpdate) {\n map.put(row.id, row): @scala.annotation.nowarn\n }\n return shouldUpdate\n }\n\n override def upsert(unsaved: CompanyRow)(using c: Connection): CompanyRow = {\n map.put(unsaved.id, unsaved): @scala.annotation.nowarn\n return unsaved\n }\n\n override def upsertBatch(unsaved: Iterator[CompanyRow])(using c: Connection): List[CompanyRow] = {\n unsaved.map { row =>\n map.put(row.id, row): @scala.annotation.nowarn\n row\n }.toList\n }\n}", - "EmployeeRow": "package showcase.showcase.employee\n\nimport dev.typr.foundations.DuckDbTypes\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport java.time.Duration\nimport java.time.LocalDate\nimport java.time.LocalDateTime\nimport showcase.EmployeeContactInfo\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.department.DepartmentId\n\n/** Table: showcase.employee\n * Primary key: id\n */\ncase class EmployeeRow(\n id: EmployeeId,\n /** Points to [[showcase.showcase.department.DepartmentRow.id]] */\n departmentId: DepartmentId,\n /** Points to [[showcase.showcase.employee.EmployeeRow.id]] */\n managerId: Option[EmployeeId],\n email: String,\n firstName: String,\n lastName: String,\n salary: Option[BigDecimal],\n hiredAt: Option[LocalDate],\n /** Default: true */\n active: Option[Boolean],\n /** Default: CURRENT_TIMESTAMP */\n createdAt: Option[LocalDateTime],\n skills: Option[Array[String]],\n certifications: Option[Array[String]],\n weeklyAvailability: Option[Array[Boolean]],\n contactInfo: Option[EmployeeContactInfo],\n settings: Option[/* MAP type - mapped to String */ String],\n skillsRating: Option[/* MAP type - mapped to String */ String],\n probationPeriod: Option[Duration]\n) {\n def toUnsavedRow(\n active: Defaulted[Option[Boolean]] = Defaulted.Provided(this.active),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.Provided(this.createdAt)\n ): EmployeeRowUnsaved = {\n new EmployeeRowUnsaved(\n id,\n departmentId,\n managerId,\n email,\n firstName,\n lastName,\n salary,\n hiredAt,\n skills,\n certifications,\n weeklyAvailability,\n contactInfo,\n settings,\n skillsRating,\n probationPeriod,\n active,\n createdAt\n )\n }\n}\n\nobject EmployeeRow {\n val `_rowParser`: RowParser[EmployeeRow] = RowParsers.of(EmployeeId.duckDbType, DepartmentId.duckDbType, EmployeeId.duckDbType.nullable, DuckDbTypes.varchar, DuckDbTypes.varchar, DuckDbTypes.varchar, ScalaDbTypes.DuckDbTypes.numeric.nullable, DuckDbTypes.date.nullable, ScalaDbTypes.DuckDbTypes.boolean_.nullable, DuckDbTypes.timestamp.nullable, DuckDbTypes.varchar.array().nullable, DuckDbTypes.varchar.array().nullable, ScalaDbTypes.DuckDbTypes.booleanArrayUnboxed.nullable, EmployeeContactInfo.duckDbType.nullable, DuckDbTypes.varchar.mapTo(DuckDbTypes.varchar).nullable, DuckDbTypes.varchar.mapTo(DuckDbTypes.integer).nullable, DuckDbTypes.interval.nullable)(EmployeeRow.apply)(row => Array[Any](row.id, row.departmentId, row.managerId, row.email, row.firstName, row.lastName, row.salary, row.hiredAt, row.active, row.createdAt, row.skills, row.certifications, row.weeklyAvailability, row.contactInfo, row.settings, row.skillsRating, row.probationPeriod))\n}", - "EmployeeRowUnsaved": "package showcase.showcase.employee\n\nimport java.time.Duration\nimport java.time.LocalDate\nimport java.time.LocalDateTime\nimport showcase.EmployeeContactInfo\nimport showcase.customtypes.Defaulted\nimport showcase.customtypes.Defaulted.UseDefault\nimport showcase.showcase.department.DepartmentId\n\n/** This class corresponds to a row in table `showcase.employee` which has not been persisted yet */\ncase class EmployeeRowUnsaved(\n id: EmployeeId,\n /** Points to [[showcase.showcase.department.DepartmentRow.id]] */\n departmentId: DepartmentId,\n /** Points to [[showcase.showcase.employee.EmployeeRow.id]] */\n managerId: Option[EmployeeId] = None,\n email: String,\n firstName: String,\n lastName: String,\n salary: Option[BigDecimal] = None,\n hiredAt: Option[LocalDate] = None,\n skills: Option[Array[String]] = None,\n certifications: Option[Array[String]] = None,\n weeklyAvailability: Option[Array[Boolean]] = None,\n contactInfo: Option[EmployeeContactInfo] = None,\n settings: Option[/* MAP type - mapped to String */ String] = None,\n skillsRating: Option[/* MAP type - mapped to String */ String] = None,\n probationPeriod: Option[Duration] = None,\n /** Default: true */\n active: Defaulted[Option[Boolean]] = new UseDefault(),\n /** Default: CURRENT_TIMESTAMP */\n createdAt: Defaulted[Option[LocalDateTime]] = new UseDefault()\n) {\n def toRow(\n activeDefault: => Option[Boolean],\n createdAtDefault: => Option[LocalDateTime]\n ): EmployeeRow = {\n new EmployeeRow(\n id = id,\n departmentId = departmentId,\n managerId = managerId,\n email = email,\n firstName = firstName,\n lastName = lastName,\n salary = salary,\n hiredAt = hiredAt,\n active = active.getOrElse(activeDefault),\n createdAt = createdAt.getOrElse(createdAtDefault),\n skills = skills,\n certifications = certifications,\n weeklyAvailability = weeklyAvailability,\n contactInfo = contactInfo,\n settings = settings,\n skillsRating = skillsRating,\n probationPeriod = probationPeriod\n )\n }\n}", - "EmployeeId": "package showcase.showcase.employee\n\nimport dev.typr.foundations.DuckDbType\nimport dev.typr.foundations.DuckDbTypes\nimport dev.typr.foundations.scala.Bijection\n\n/** Type for the primary key of table `showcase.employee` */\ncase class EmployeeId(value: String) extends scala.AnyVal\n\nobject EmployeeId {\n given bijection: Bijection[EmployeeId, String] = Bijection.apply[EmployeeId, String](_.value)(EmployeeId.apply)\n\n given duckDbType: DuckDbType[EmployeeId] = DuckDbTypes.varchar.bimap(EmployeeId.apply, _.value)\n\n given pgTypeArray: DuckDbType[Array[EmployeeId]] = DuckDbTypes.varcharArray.bimap(xs => xs.map(EmployeeId.apply), xs => xs.map(_.value))\n}", - "EmployeeRepo": "package showcase.showcase.employee\n\nimport dev.typr.foundations.scala.DeleteBuilder\nimport dev.typr.foundations.scala.SelectBuilder\nimport dev.typr.foundations.scala.UpdateBuilder\nimport java.sql.Connection\n\ntrait EmployeeRepo {\n def delete: DeleteBuilder[EmployeeFields, EmployeeRow]\n\n def deleteById(id: EmployeeId)(using c: Connection): Boolean\n\n def deleteByIds(ids: Array[EmployeeId])(using c: Connection): Int\n\n def insert(unsaved: EmployeeRow)(using c: Connection): EmployeeRow\n\n def insert(unsaved: EmployeeRowUnsaved)(using c: Connection): EmployeeRow\n\n def select: SelectBuilder[EmployeeFields, EmployeeRow]\n\n def selectAll(using c: Connection): List[EmployeeRow]\n\n def selectById(id: EmployeeId)(using c: Connection): Option[EmployeeRow]\n\n def selectByIds(ids: Array[EmployeeId])(using c: Connection): List[EmployeeRow]\n\n def selectByIdsTracked(ids: Array[EmployeeId])(using c: Connection): Map[EmployeeId, EmployeeRow]\n\n def selectByUniqueEmail(email: String)(using c: Connection): Option[EmployeeRow]\n\n def update: UpdateBuilder[EmployeeFields, EmployeeRow]\n\n def update(row: EmployeeRow)(using c: Connection): Boolean\n\n def upsert(unsaved: EmployeeRow)(using c: Connection): EmployeeRow\n\n def upsertBatch(unsaved: Iterator[EmployeeRow])(using c: Connection): List[EmployeeRow]\n}", - "EmployeeRepoImpl": "package showcase.showcase.employee\n\nimport dev.typr.foundations.DuckDbTypes\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.DeleteBuilder\nimport dev.typr.foundations.scala.Dialect\nimport dev.typr.foundations.scala.Fragment\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport dev.typr.foundations.scala.SelectBuilder\nimport dev.typr.foundations.scala.UpdateBuilder\nimport java.sql.Connection\nimport scala.collection.mutable.ListBuffer\nimport showcase.EmployeeContactInfo\nimport showcase.showcase.department.DepartmentId\nimport dev.typr.foundations.scala.Fragment.sql\n\nclass EmployeeRepoImpl extends EmployeeRepo {\n override def delete: DeleteBuilder[EmployeeFields, EmployeeRow] = DeleteBuilder.of(\"\"\"\"showcase\".\"employee\"\"\"\", EmployeeFields.structure, Dialect.DUCKDB)\n\n override def deleteById(id: EmployeeId)(using c: Connection): Boolean = sql\"\"\"delete from \"showcase\".\"employee\" where \"id\" = ${Fragment.encode(EmployeeId.duckDbType, id)}\"\"\".update().runUnchecked(c) > 0\n\n override def deleteByIds(ids: Array[EmployeeId])(using c: Connection): Int = {\n sql\"\"\"delete\n from \"showcase\".\"employee\"\n where \"id\" = ANY(${Fragment.encode(EmployeeId.pgTypeArray, ids)})\"\"\"\n .update()\n .runUnchecked(c)\n }\n\n override def insert(unsaved: EmployeeRow)(using c: Connection): EmployeeRow = {\n sql\"\"\"insert into \"showcase\".\"employee\"(\"id\", \"department_id\", \"manager_id\", \"email\", \"first_name\", \"last_name\", \"salary\", \"hired_at\", \"active\", \"created_at\", \"skills\", \"certifications\", \"weekly_availability\", \"contact_info\", \"settings\", \"skills_rating\", \"probation_period\")\n values (${Fragment.encode(EmployeeId.duckDbType, unsaved.id)}, ${Fragment.encode(DepartmentId.duckDbType, unsaved.departmentId)}, ${Fragment.encode(EmployeeId.duckDbType.nullable, unsaved.managerId)}, ${Fragment.encode(DuckDbTypes.varchar, unsaved.email)}, ${Fragment.encode(DuckDbTypes.varchar, unsaved.firstName)}, ${Fragment.encode(DuckDbTypes.varchar, unsaved.lastName)}, ${Fragment.encode(ScalaDbTypes.DuckDbTypes.numeric.nullable, unsaved.salary)}, ${Fragment.encode(DuckDbTypes.date.nullable, unsaved.hiredAt)}, ${Fragment.encode(ScalaDbTypes.DuckDbTypes.boolean_.nullable, unsaved.active)}, ${Fragment.encode(DuckDbTypes.timestamp.nullable, unsaved.createdAt)}, ${Fragment.encode(DuckDbTypes.varchar.array().nullable, unsaved.skills)}, ${Fragment.encode(DuckDbTypes.varchar.array().nullable, unsaved.certifications)}, ${Fragment.encode(ScalaDbTypes.DuckDbTypes.booleanArrayUnboxed.nullable, unsaved.weeklyAvailability)}, ${Fragment.encode(EmployeeContactInfo.duckDbType.nullable, unsaved.contactInfo)}, ${Fragment.encode(DuckDbTypes.varchar.mapTo(DuckDbTypes.varchar).nullable, unsaved.settings)}, ${Fragment.encode(DuckDbTypes.varchar.mapTo(DuckDbTypes.integer).nullable, unsaved.skillsRating)}, ${Fragment.encode(DuckDbTypes.interval.nullable, unsaved.probationPeriod)})\n RETURNING \"id\", \"department_id\", \"manager_id\", \"email\", \"first_name\", \"last_name\", \"salary\", \"hired_at\", \"active\", \"created_at\", \"skills\", \"certifications\", \"weekly_availability\", \"contact_info\", \"settings\", \"skills_rating\", \"probation_period\"\n \"\"\"\n .updateReturning(EmployeeRow.`_rowParser`.exactlyOne()).runUnchecked(c)\n }\n\n override def insert(unsaved: EmployeeRowUnsaved)(using c: Connection): EmployeeRow = {\n val columns: ListBuffer[Fragment] = ListBuffer()\n val values: ListBuffer[Fragment] = ListBuffer()\n columns.addOne(Fragment.lit(\"\"\"\"id\"\"\"\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(EmployeeId.duckDbType, unsaved.id)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"\"\"\"department_id\"\"\"\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(DepartmentId.duckDbType, unsaved.departmentId)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"\"\"\"manager_id\"\"\"\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(EmployeeId.duckDbType.nullable, unsaved.managerId)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"\"\"\"email\"\"\"\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(DuckDbTypes.varchar, unsaved.email)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"\"\"\"first_name\"\"\"\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(DuckDbTypes.varchar, unsaved.firstName)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"\"\"\"last_name\"\"\"\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(DuckDbTypes.varchar, unsaved.lastName)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"\"\"\"salary\"\"\"\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(ScalaDbTypes.DuckDbTypes.numeric.nullable, unsaved.salary)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"\"\"\"hired_at\"\"\"\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(DuckDbTypes.date.nullable, unsaved.hiredAt)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"\"\"\"skills\"\"\"\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(DuckDbTypes.varchar.array().nullable, unsaved.skills)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"\"\"\"certifications\"\"\"\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(DuckDbTypes.varchar.array().nullable, unsaved.certifications)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"\"\"\"weekly_availability\"\"\"\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(ScalaDbTypes.DuckDbTypes.booleanArrayUnboxed.nullable, unsaved.weeklyAvailability)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"\"\"\"contact_info\"\"\"\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(EmployeeContactInfo.duckDbType.nullable, unsaved.contactInfo)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"\"\"\"settings\"\"\"\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(DuckDbTypes.varchar.mapTo(DuckDbTypes.varchar).nullable, unsaved.settings)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"\"\"\"skills_rating\"\"\"\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(DuckDbTypes.varchar.mapTo(DuckDbTypes.integer).nullable, unsaved.skillsRating)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"\"\"\"probation_period\"\"\"\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(DuckDbTypes.interval.nullable, unsaved.probationPeriod)}\"): @scala.annotation.nowarn\n unsaved.active.visit(\n { },\n value => { columns.addOne(Fragment.lit(\"\"\"\"active\"\"\"\")): @scala.annotation.nowarn; values.addOne(sql\"${Fragment.encode(ScalaDbTypes.DuckDbTypes.boolean_.nullable, value)}\"): @scala.annotation.nowarn }\n );\n unsaved.createdAt.visit(\n { },\n value => { columns.addOne(Fragment.lit(\"\"\"\"created_at\"\"\"\")): @scala.annotation.nowarn; values.addOne(sql\"${Fragment.encode(DuckDbTypes.timestamp.nullable, value)}\"): @scala.annotation.nowarn }\n );\n val q: Fragment = {\n sql\"\"\"insert into \"showcase\".\"employee\"(${Fragment.comma(columns)})\n values (${Fragment.comma(values)})\n RETURNING \"id\", \"department_id\", \"manager_id\", \"email\", \"first_name\", \"last_name\", \"salary\", \"hired_at\", \"active\", \"created_at\", \"skills\", \"certifications\", \"weekly_availability\", \"contact_info\", \"settings\", \"skills_rating\", \"probation_period\"\n \"\"\"\n }\n return q.updateReturning(EmployeeRow.`_rowParser`.exactlyOne()).runUnchecked(c)\n }\n\n override def select: SelectBuilder[EmployeeFields, EmployeeRow] = SelectBuilder.of(\"\"\"\"showcase\".\"employee\"\"\"\", EmployeeFields.structure, EmployeeRow.`_rowParser`, Dialect.DUCKDB)\n\n override def selectAll(using c: Connection): List[EmployeeRow] = {\n sql\"\"\"select \"id\", \"department_id\", \"manager_id\", \"email\", \"first_name\", \"last_name\", \"salary\", \"hired_at\", \"active\", \"created_at\", \"skills\", \"certifications\", \"weekly_availability\", \"contact_info\", \"settings\", \"skills_rating\", \"probation_period\"\n from \"showcase\".\"employee\"\n \"\"\".query(EmployeeRow.`_rowParser`.all()).runUnchecked(c)\n }\n\n override def selectById(id: EmployeeId)(using c: Connection): Option[EmployeeRow] = {\n sql\"\"\"select \"id\", \"department_id\", \"manager_id\", \"email\", \"first_name\", \"last_name\", \"salary\", \"hired_at\", \"active\", \"created_at\", \"skills\", \"certifications\", \"weekly_availability\", \"contact_info\", \"settings\", \"skills_rating\", \"probation_period\"\n from \"showcase\".\"employee\"\n where \"id\" = ${Fragment.encode(EmployeeId.duckDbType, id)}\"\"\".query(EmployeeRow.`_rowParser`.first()).runUnchecked(c)\n }\n\n override def selectByIds(ids: Array[EmployeeId])(using c: Connection): List[EmployeeRow] = {\n sql\"\"\"select \"id\", \"department_id\", \"manager_id\", \"email\", \"first_name\", \"last_name\", \"salary\", \"hired_at\", \"active\", \"created_at\", \"skills\", \"certifications\", \"weekly_availability\", \"contact_info\", \"settings\", \"skills_rating\", \"probation_period\"\n from \"showcase\".\"employee\"\n where \"id\" = ANY(${Fragment.encode(EmployeeId.pgTypeArray, ids)})\"\"\".query(EmployeeRow.`_rowParser`.all()).runUnchecked(c)\n }\n\n override def selectByIdsTracked(ids: Array[EmployeeId])(using c: Connection): Map[EmployeeId, EmployeeRow] = {\n val ret: scala.collection.mutable.Map[EmployeeId, EmployeeRow] = scala.collection.mutable.Map.empty[EmployeeId, EmployeeRow]\n selectByIds(ids)(using c).foreach(row => ret.put(row.id, row): @scala.annotation.nowarn)\n return ret.toMap\n }\n\n override def selectByUniqueEmail(email: String)(using c: Connection): Option[EmployeeRow] = {\n sql\"\"\"select \"id\", \"department_id\", \"manager_id\", \"email\", \"first_name\", \"last_name\", \"salary\", \"hired_at\", \"active\", \"created_at\", \"skills\", \"certifications\", \"weekly_availability\", \"contact_info\", \"settings\", \"skills_rating\", \"probation_period\"\n from \"showcase\".\"employee\"\n where \"email\" = ${Fragment.encode(DuckDbTypes.varchar, email)}\n \"\"\".query(EmployeeRow.`_rowParser`.first()).runUnchecked(c)\n }\n\n override def update: UpdateBuilder[EmployeeFields, EmployeeRow] = UpdateBuilder.of(\"\"\"\"showcase\".\"employee\"\"\"\", EmployeeFields.structure, EmployeeRow.`_rowParser`, Dialect.DUCKDB)\n\n override def update(row: EmployeeRow)(using c: Connection): Boolean = {\n val id: EmployeeId = row.id\n return sql\"\"\"update \"showcase\".\"employee\"\n set \"department_id\" = ${Fragment.encode(DepartmentId.duckDbType, row.departmentId)},\n \"manager_id\" = ${Fragment.encode(EmployeeId.duckDbType.nullable, row.managerId)},\n \"email\" = ${Fragment.encode(DuckDbTypes.varchar, row.email)},\n \"first_name\" = ${Fragment.encode(DuckDbTypes.varchar, row.firstName)},\n \"last_name\" = ${Fragment.encode(DuckDbTypes.varchar, row.lastName)},\n \"salary\" = ${Fragment.encode(ScalaDbTypes.DuckDbTypes.numeric.nullable, row.salary)},\n \"hired_at\" = ${Fragment.encode(DuckDbTypes.date.nullable, row.hiredAt)},\n \"active\" = ${Fragment.encode(ScalaDbTypes.DuckDbTypes.boolean_.nullable, row.active)},\n \"created_at\" = ${Fragment.encode(DuckDbTypes.timestamp.nullable, row.createdAt)},\n \"skills\" = ${Fragment.encode(DuckDbTypes.varchar.array().nullable, row.skills)},\n \"certifications\" = ${Fragment.encode(DuckDbTypes.varchar.array().nullable, row.certifications)},\n \"weekly_availability\" = ${Fragment.encode(ScalaDbTypes.DuckDbTypes.booleanArrayUnboxed.nullable, row.weeklyAvailability)},\n \"contact_info\" = ${Fragment.encode(EmployeeContactInfo.duckDbType.nullable, row.contactInfo)},\n \"settings\" = ${Fragment.encode(DuckDbTypes.varchar.mapTo(DuckDbTypes.varchar).nullable, row.settings)},\n \"skills_rating\" = ${Fragment.encode(DuckDbTypes.varchar.mapTo(DuckDbTypes.integer).nullable, row.skillsRating)},\n \"probation_period\" = ${Fragment.encode(DuckDbTypes.interval.nullable, row.probationPeriod)}\n where \"id\" = ${Fragment.encode(EmployeeId.duckDbType, id)}\"\"\".update().runUnchecked(c) > 0\n }\n\n override def upsert(unsaved: EmployeeRow)(using c: Connection): EmployeeRow = {\n sql\"\"\"INSERT INTO \"showcase\".\"employee\"(\"id\", \"department_id\", \"manager_id\", \"email\", \"first_name\", \"last_name\", \"salary\", \"hired_at\", \"active\", \"created_at\", \"skills\", \"certifications\", \"weekly_availability\", \"contact_info\", \"settings\", \"skills_rating\", \"probation_period\")\n VALUES (${Fragment.encode(EmployeeId.duckDbType, unsaved.id)}, ${Fragment.encode(DepartmentId.duckDbType, unsaved.departmentId)}, ${Fragment.encode(EmployeeId.duckDbType.nullable, unsaved.managerId)}, ${Fragment.encode(DuckDbTypes.varchar, unsaved.email)}, ${Fragment.encode(DuckDbTypes.varchar, unsaved.firstName)}, ${Fragment.encode(DuckDbTypes.varchar, unsaved.lastName)}, ${Fragment.encode(ScalaDbTypes.DuckDbTypes.numeric.nullable, unsaved.salary)}, ${Fragment.encode(DuckDbTypes.date.nullable, unsaved.hiredAt)}, ${Fragment.encode(ScalaDbTypes.DuckDbTypes.boolean_.nullable, unsaved.active)}, ${Fragment.encode(DuckDbTypes.timestamp.nullable, unsaved.createdAt)}, ${Fragment.encode(DuckDbTypes.varchar.array().nullable, unsaved.skills)}, ${Fragment.encode(DuckDbTypes.varchar.array().nullable, unsaved.certifications)}, ${Fragment.encode(ScalaDbTypes.DuckDbTypes.booleanArrayUnboxed.nullable, unsaved.weeklyAvailability)}, ${Fragment.encode(EmployeeContactInfo.duckDbType.nullable, unsaved.contactInfo)}, ${Fragment.encode(DuckDbTypes.varchar.mapTo(DuckDbTypes.varchar).nullable, unsaved.settings)}, ${Fragment.encode(DuckDbTypes.varchar.mapTo(DuckDbTypes.integer).nullable, unsaved.skillsRating)}, ${Fragment.encode(DuckDbTypes.interval.nullable, unsaved.probationPeriod)})\n ON CONFLICT (\"id\")\n DO UPDATE SET\n \"department_id\" = EXCLUDED.\"department_id\",\n \"manager_id\" = EXCLUDED.\"manager_id\",\n \"email\" = EXCLUDED.\"email\",\n \"first_name\" = EXCLUDED.\"first_name\",\n \"last_name\" = EXCLUDED.\"last_name\",\n \"salary\" = EXCLUDED.\"salary\",\n \"hired_at\" = EXCLUDED.\"hired_at\",\n \"active\" = EXCLUDED.\"active\",\n \"created_at\" = EXCLUDED.\"created_at\",\n \"skills\" = EXCLUDED.\"skills\",\n \"certifications\" = EXCLUDED.\"certifications\",\n \"weekly_availability\" = EXCLUDED.\"weekly_availability\",\n \"contact_info\" = EXCLUDED.\"contact_info\",\n \"settings\" = EXCLUDED.\"settings\",\n \"skills_rating\" = EXCLUDED.\"skills_rating\",\n \"probation_period\" = EXCLUDED.\"probation_period\"\n RETURNING \"id\", \"department_id\", \"manager_id\", \"email\", \"first_name\", \"last_name\", \"salary\", \"hired_at\", \"active\", \"created_at\", \"skills\", \"certifications\", \"weekly_availability\", \"contact_info\", \"settings\", \"skills_rating\", \"probation_period\"\"\"\"\n .updateReturning(EmployeeRow.`_rowParser`.exactlyOne())\n .runUnchecked(c)\n }\n\n override def upsertBatch(unsaved: Iterator[EmployeeRow])(using c: Connection): List[EmployeeRow] = {\n sql\"\"\"INSERT INTO \"showcase\".\"employee\"(\"id\", \"department_id\", \"manager_id\", \"email\", \"first_name\", \"last_name\", \"salary\", \"hired_at\", \"active\", \"created_at\", \"skills\", \"certifications\", \"weekly_availability\", \"contact_info\", \"settings\", \"skills_rating\", \"probation_period\")\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n ON CONFLICT (\"id\")\n DO UPDATE SET\n \"department_id\" = EXCLUDED.\"department_id\",\n \"manager_id\" = EXCLUDED.\"manager_id\",\n \"email\" = EXCLUDED.\"email\",\n \"first_name\" = EXCLUDED.\"first_name\",\n \"last_name\" = EXCLUDED.\"last_name\",\n \"salary\" = EXCLUDED.\"salary\",\n \"hired_at\" = EXCLUDED.\"hired_at\",\n \"active\" = EXCLUDED.\"active\",\n \"created_at\" = EXCLUDED.\"created_at\",\n \"skills\" = EXCLUDED.\"skills\",\n \"certifications\" = EXCLUDED.\"certifications\",\n \"weekly_availability\" = EXCLUDED.\"weekly_availability\",\n \"contact_info\" = EXCLUDED.\"contact_info\",\n \"settings\" = EXCLUDED.\"settings\",\n \"skills_rating\" = EXCLUDED.\"skills_rating\",\n \"probation_period\" = EXCLUDED.\"probation_period\"\n RETURNING \"id\", \"department_id\", \"manager_id\", \"email\", \"first_name\", \"last_name\", \"salary\", \"hired_at\", \"active\", \"created_at\", \"skills\", \"certifications\", \"weekly_availability\", \"contact_info\", \"settings\", \"skills_rating\", \"probation_period\"\"\"\"\n .updateReturningEach(EmployeeRow.`_rowParser`, unsaved)\n .runUnchecked(c)\n }\n}", - "EmployeeRepoMock": "package showcase.showcase.employee\n\nimport dev.typr.foundations.scala.DeleteBuilder\nimport dev.typr.foundations.scala.DeleteBuilderMock\nimport dev.typr.foundations.scala.DeleteParams\nimport dev.typr.foundations.scala.SelectBuilder\nimport dev.typr.foundations.scala.SelectBuilderMock\nimport dev.typr.foundations.scala.SelectParams\nimport dev.typr.foundations.scala.UpdateBuilder\nimport dev.typr.foundations.scala.UpdateBuilderMock\nimport dev.typr.foundations.scala.UpdateParams\nimport java.lang.RuntimeException\nimport java.sql.Connection\n\ncase class EmployeeRepoMock(\n toRow: EmployeeRowUnsaved => EmployeeRow,\n map: scala.collection.mutable.Map[EmployeeId, EmployeeRow] = scala.collection.mutable.Map.empty[EmployeeId, EmployeeRow]\n) extends EmployeeRepo {\n override def delete: DeleteBuilder[EmployeeFields, EmployeeRow] = DeleteBuilderMock(EmployeeFields.structure, () => map.values.toList, DeleteParams.empty(), row => row.id, id => map.remove(id): @scala.annotation.nowarn)\n\n override def deleteById(id: EmployeeId)(using c: Connection): Boolean = map.remove(id).isDefined\n\n override def deleteByIds(ids: Array[EmployeeId])(using c: Connection): Int = {\n var count = 0\n ids.foreach { id => if (map.remove(id).isDefined) {\n count = count + 1\n } }\n return count\n }\n\n override def insert(unsaved: EmployeeRow)(using c: Connection): EmployeeRow = {\n if (map.contains(unsaved.id)) {\n throw new RuntimeException(s\"id ${unsaved.id} already exists\")\n }\n map.put(unsaved.id, unsaved): @scala.annotation.nowarn\n return unsaved\n }\n\n override def insert(unsaved: EmployeeRowUnsaved)(using c: Connection): EmployeeRow = insert(toRow(unsaved))(using c)\n\n override def select: SelectBuilder[EmployeeFields, EmployeeRow] = SelectBuilderMock(EmployeeFields.structure, () => map.values.toList, SelectParams.empty())\n\n override def selectAll(using c: Connection): List[EmployeeRow] = map.values.toList\n\n override def selectById(id: EmployeeId)(using c: Connection): Option[EmployeeRow] = map.get(id)\n\n override def selectByIds(ids: Array[EmployeeId])(using c: Connection): List[EmployeeRow] = ids.flatMap(map.get(_)).toList\n\n override def selectByIdsTracked(ids: Array[EmployeeId])(using c: Connection): Map[EmployeeId, EmployeeRow] = selectByIds(ids)(using c).map(x => (((row: EmployeeRow) => row.id).apply(x), x)).toMap\n\n override def selectByUniqueEmail(email: String)(using c: Connection): Option[EmployeeRow] = map.values.toList.find(v => (email == v.email))\n\n override def update: UpdateBuilder[EmployeeFields, EmployeeRow] = UpdateBuilderMock(EmployeeFields.structure, () => map.values.toList, UpdateParams.empty(), row => row)\n\n override def update(row: EmployeeRow)(using c: Connection): Boolean = {\n val shouldUpdate = map.get(row.id).filter(oldRow => (oldRow != row)).isDefined\n if (shouldUpdate) {\n map.put(row.id, row): @scala.annotation.nowarn\n }\n return shouldUpdate\n }\n\n override def upsert(unsaved: EmployeeRow)(using c: Connection): EmployeeRow = {\n map.put(unsaved.id, unsaved): @scala.annotation.nowarn\n return unsaved\n }\n\n override def upsertBatch(unsaved: Iterator[EmployeeRow])(using c: Connection): List[EmployeeRow] = {\n unsaved.map { row =>\n map.put(row.id, row): @scala.annotation.nowarn\n row\n }.toList\n }\n}", - "EmployeeFields": "package showcase.showcase.employee\n\nimport dev.typr.foundations.DuckDbTypes\nimport dev.typr.foundations.RowParser\nimport dev.typr.foundations.dsl.FieldsExpr0\nimport dev.typr.foundations.dsl.Path\nimport dev.typr.foundations.dsl.SqlExpr.FieldLike\nimport dev.typr.foundations.scala.ForeignKey\nimport dev.typr.foundations.scala.RelationStructure\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport dev.typr.foundations.scala.SqlExpr.Field\nimport dev.typr.foundations.scala.SqlExpr.IdField\nimport dev.typr.foundations.scala.SqlExpr.OptField\nimport java.time.Duration\nimport java.time.LocalDate\nimport java.time.LocalDateTime\nimport showcase.EmployeeContactInfo\nimport showcase.showcase.department.DepartmentFields\nimport showcase.showcase.department.DepartmentId\nimport showcase.showcase.department.DepartmentRow\n\ntrait EmployeeFields extends FieldsExpr0[EmployeeRow] {\n def id: IdField[EmployeeId, EmployeeRow]\n\n def departmentId: Field[DepartmentId, EmployeeRow]\n\n def managerId: OptField[EmployeeId, EmployeeRow]\n\n def email: Field[String, EmployeeRow]\n\n def firstName: Field[String, EmployeeRow]\n\n def lastName: Field[String, EmployeeRow]\n\n def salary: OptField[BigDecimal, EmployeeRow]\n\n def hiredAt: OptField[LocalDate, EmployeeRow]\n\n def active: OptField[Boolean, EmployeeRow]\n\n def createdAt: OptField[LocalDateTime, EmployeeRow]\n\n def skills: OptField[Array[String], EmployeeRow]\n\n def certifications: OptField[Array[String], EmployeeRow]\n\n def weeklyAvailability: OptField[Array[Boolean], EmployeeRow]\n\n def contactInfo: OptField[EmployeeContactInfo, EmployeeRow]\n\n def settings: OptField[/* MAP type - mapped to String */ String, EmployeeRow]\n\n def skillsRating: OptField[/* MAP type - mapped to String */ String, EmployeeRow]\n\n def probationPeriod: OptField[Duration, EmployeeRow]\n\n def fkDepartment: ForeignKey[DepartmentFields, DepartmentRow] = ForeignKey.of[DepartmentFields, DepartmentRow](\"employee_department_fk\").withColumnPair[DepartmentId](departmentId, _.id)\n\n def fkEmployee: ForeignKey[EmployeeFields, EmployeeRow] = ForeignKey.of[EmployeeFields, EmployeeRow](\"employee_manager_fk\").withColumnPair[EmployeeId](managerId, _.id)\n\n override def columns: java.util.List[FieldLike[?, EmployeeRow]]\n\n override def rowParser: RowParser[EmployeeRow] = EmployeeRow._rowParser.underlying\n}\n\nobject EmployeeFields {\n case class Impl(val `_path`: java.util.List[Path]) extends EmployeeFields with RelationStructure[EmployeeFields, EmployeeRow] {\n\n override def id: IdField[EmployeeId, EmployeeRow] = {\n new IdField[EmployeeId, EmployeeRow](\n _path,\n \"id\",\n _.id,\n None,\n None,\n (row, value) => row.copy(id = value),\n EmployeeId.duckDbType\n )\n }\n\n override def departmentId: Field[DepartmentId, EmployeeRow] = {\n new Field[DepartmentId, EmployeeRow](\n _path,\n \"department_id\",\n _.departmentId,\n None,\n None,\n (row, value) => row.copy(departmentId = value),\n DepartmentId.duckDbType\n )\n }\n\n override def managerId: OptField[EmployeeId, EmployeeRow] = {\n new OptField[EmployeeId, EmployeeRow](\n _path,\n \"manager_id\",\n _.managerId,\n None,\n None,\n (row, value) => row.copy(managerId = value),\n EmployeeId.duckDbType\n )\n }\n\n override def email: Field[String, EmployeeRow] = {\n new Field[String, EmployeeRow](\n _path,\n \"email\",\n _.email,\n None,\n None,\n (row, value) => row.copy(email = value),\n DuckDbTypes.varchar\n )\n }\n\n override def firstName: Field[String, EmployeeRow] = {\n new Field[String, EmployeeRow](\n _path,\n \"first_name\",\n _.firstName,\n None,\n None,\n (row, value) => row.copy(firstName = value),\n DuckDbTypes.varchar\n )\n }\n\n override def lastName: Field[String, EmployeeRow] = {\n new Field[String, EmployeeRow](\n _path,\n \"last_name\",\n _.lastName,\n None,\n None,\n (row, value) => row.copy(lastName = value),\n DuckDbTypes.varchar\n )\n }\n\n override def salary: OptField[BigDecimal, EmployeeRow] = {\n new OptField[BigDecimal, EmployeeRow](\n _path,\n \"salary\",\n _.salary,\n None,\n None,\n (row, value) => row.copy(salary = value),\n ScalaDbTypes.DuckDbTypes.numeric\n )\n }\n\n override def hiredAt: OptField[LocalDate, EmployeeRow] = {\n new OptField[LocalDate, EmployeeRow](\n _path,\n \"hired_at\",\n _.hiredAt,\n None,\n None,\n (row, value) => row.copy(hiredAt = value),\n DuckDbTypes.date\n )\n }\n\n override def active: OptField[Boolean, EmployeeRow] = {\n new OptField[Boolean, EmployeeRow](\n _path,\n \"active\",\n _.active,\n None,\n None,\n (row, value) => row.copy(active = value),\n ScalaDbTypes.DuckDbTypes.boolean_\n )\n }\n\n override def createdAt: OptField[LocalDateTime, EmployeeRow] = {\n new OptField[LocalDateTime, EmployeeRow](\n _path,\n \"created_at\",\n _.createdAt,\n None,\n None,\n (row, value) => row.copy(createdAt = value),\n DuckDbTypes.timestamp\n )\n }\n\n override def skills: OptField[Array[String], EmployeeRow] = {\n new OptField[Array[String], EmployeeRow](\n _path,\n \"skills\",\n _.skills,\n None,\n None,\n (row, value) => row.copy(skills = value),\n DuckDbTypes.varchar.array()\n )\n }\n\n override def certifications: OptField[Array[String], EmployeeRow] = {\n new OptField[Array[String], EmployeeRow](\n _path,\n \"certifications\",\n _.certifications,\n None,\n None,\n (row, value) => row.copy(certifications = value),\n DuckDbTypes.varchar.array()\n )\n }\n\n override def weeklyAvailability: OptField[Array[Boolean], EmployeeRow] = {\n new OptField[Array[Boolean], EmployeeRow](\n _path,\n \"weekly_availability\",\n _.weeklyAvailability,\n None,\n None,\n (row, value) => row.copy(weeklyAvailability = value),\n ScalaDbTypes.DuckDbTypes.booleanArrayUnboxed\n )\n }\n\n override def contactInfo: OptField[EmployeeContactInfo, EmployeeRow] = {\n new OptField[EmployeeContactInfo, EmployeeRow](\n _path,\n \"contact_info\",\n _.contactInfo,\n None,\n None,\n (row, value) => row.copy(contactInfo = value),\n EmployeeContactInfo.duckDbType\n )\n }\n\n override def settings: OptField[String, EmployeeRow] = {\n new OptField[String, EmployeeRow](\n _path,\n \"settings\",\n _.settings,\n None,\n None,\n (row, value) => row.copy(settings = value),\n DuckDbTypes.varchar.mapTo(DuckDbTypes.varchar)\n )\n }\n\n override def skillsRating: OptField[String, EmployeeRow] = {\n new OptField[String, EmployeeRow](\n _path,\n \"skills_rating\",\n _.skillsRating,\n None,\n None,\n (row, value) => row.copy(skillsRating = value),\n DuckDbTypes.varchar.mapTo(DuckDbTypes.integer)\n )\n }\n\n override def probationPeriod: OptField[Duration, EmployeeRow] = {\n new OptField[Duration, EmployeeRow](\n _path,\n \"probation_period\",\n _.probationPeriod,\n None,\n None,\n (row, value) => row.copy(probationPeriod = value),\n DuckDbTypes.interval\n )\n }\n\n override def columns: java.util.List[FieldLike[?, EmployeeRow]] = java.util.List.of(this.id.underlying, this.departmentId.underlying, this.managerId.underlying, this.email.underlying, this.firstName.underlying, this.lastName.underlying, this.salary.underlying, this.hiredAt.underlying, this.active.underlying, this.createdAt.underlying, this.skills.underlying, this.certifications.underlying, this.weeklyAvailability.underlying, this.contactInfo.underlying, this.settings.underlying, this.skillsRating.underlying, this.probationPeriod.underlying)\n\n override def withPaths(`_path`: java.util.List[Path]): RelationStructure[EmployeeFields, EmployeeRow] = new Impl(`_path`)\n }\n\n def structure: Impl = new Impl(java.util.Collections.emptyList())\n}", - "DepartmentRow": "package showcase.showcase.department\n\nimport dev.typr.foundations.DuckDbTypes\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport showcase.showcase.company.CompanyId\n\n/** Table: showcase.department\n * Primary key: id\n */\ncase class DepartmentRow(\n id: DepartmentId,\n /** Points to [[showcase.showcase.company.CompanyRow.id]] */\n companyId: CompanyId,\n name: String,\n budget: Option[BigDecimal]\n)\n\nobject DepartmentRow {\n val `_rowParser`: RowParser[DepartmentRow] = RowParsers.of(DepartmentId.duckDbType, CompanyId.duckDbType, DuckDbTypes.varchar, ScalaDbTypes.DuckDbTypes.numeric.nullable)(DepartmentRow.apply)(row => Array[Any](row.id, row.companyId, row.name, row.budget))\n}", - "DepartmentId": "package showcase.showcase.department\n\nimport dev.typr.foundations.DuckDbType\nimport dev.typr.foundations.DuckDbTypes\nimport dev.typr.foundations.scala.Bijection\n\n/** Type for the primary key of table `showcase.department` */\ncase class DepartmentId(value: String) extends scala.AnyVal\n\nobject DepartmentId {\n given bijection: Bijection[DepartmentId, String] = Bijection.apply[DepartmentId, String](_.value)(DepartmentId.apply)\n\n given duckDbType: DuckDbType[DepartmentId] = DuckDbTypes.varchar.bimap(DepartmentId.apply, _.value)\n\n given pgTypeArray: DuckDbType[Array[DepartmentId]] = DuckDbTypes.varcharArray.bimap(xs => xs.map(DepartmentId.apply), xs => xs.map(_.value))\n}", - "DepartmentRepo": "package showcase.showcase.department\n\nimport dev.typr.foundations.scala.DeleteBuilder\nimport dev.typr.foundations.scala.SelectBuilder\nimport dev.typr.foundations.scala.UpdateBuilder\nimport java.sql.Connection\n\ntrait DepartmentRepo {\n def delete: DeleteBuilder[DepartmentFields, DepartmentRow]\n\n def deleteById(id: DepartmentId)(using c: Connection): Boolean\n\n def deleteByIds(ids: Array[DepartmentId])(using c: Connection): Int\n\n def insert(unsaved: DepartmentRow)(using c: Connection): DepartmentRow\n\n def select: SelectBuilder[DepartmentFields, DepartmentRow]\n\n def selectAll(using c: Connection): List[DepartmentRow]\n\n def selectById(id: DepartmentId)(using c: Connection): Option[DepartmentRow]\n\n def selectByIds(ids: Array[DepartmentId])(using c: Connection): List[DepartmentRow]\n\n def selectByIdsTracked(ids: Array[DepartmentId])(using c: Connection): Map[DepartmentId, DepartmentRow]\n\n def update: UpdateBuilder[DepartmentFields, DepartmentRow]\n\n def update(row: DepartmentRow)(using c: Connection): Boolean\n\n def upsert(unsaved: DepartmentRow)(using c: Connection): DepartmentRow\n\n def upsertBatch(unsaved: Iterator[DepartmentRow])(using c: Connection): List[DepartmentRow]\n}", - "DepartmentRepoMock": "package showcase.showcase.department\n\nimport dev.typr.foundations.scala.DeleteBuilder\nimport dev.typr.foundations.scala.DeleteBuilderMock\nimport dev.typr.foundations.scala.DeleteParams\nimport dev.typr.foundations.scala.SelectBuilder\nimport dev.typr.foundations.scala.SelectBuilderMock\nimport dev.typr.foundations.scala.SelectParams\nimport dev.typr.foundations.scala.UpdateBuilder\nimport dev.typr.foundations.scala.UpdateBuilderMock\nimport dev.typr.foundations.scala.UpdateParams\nimport java.lang.RuntimeException\nimport java.sql.Connection\n\ncase class DepartmentRepoMock(map: scala.collection.mutable.Map[DepartmentId, DepartmentRow] = scala.collection.mutable.Map.empty[DepartmentId, DepartmentRow]) extends DepartmentRepo {\n override def delete: DeleteBuilder[DepartmentFields, DepartmentRow] = DeleteBuilderMock(DepartmentFields.structure, () => map.values.toList, DeleteParams.empty(), row => row.id, id => map.remove(id): @scala.annotation.nowarn)\n\n override def deleteById(id: DepartmentId)(using c: Connection): Boolean = map.remove(id).isDefined\n\n override def deleteByIds(ids: Array[DepartmentId])(using c: Connection): Int = {\n var count = 0\n ids.foreach { id => if (map.remove(id).isDefined) {\n count = count + 1\n } }\n return count\n }\n\n override def insert(unsaved: DepartmentRow)(using c: Connection): DepartmentRow = {\n if (map.contains(unsaved.id)) {\n throw new RuntimeException(s\"id ${unsaved.id} already exists\")\n }\n map.put(unsaved.id, unsaved): @scala.annotation.nowarn\n return unsaved\n }\n\n override def select: SelectBuilder[DepartmentFields, DepartmentRow] = SelectBuilderMock(DepartmentFields.structure, () => map.values.toList, SelectParams.empty())\n\n override def selectAll(using c: Connection): List[DepartmentRow] = map.values.toList\n\n override def selectById(id: DepartmentId)(using c: Connection): Option[DepartmentRow] = map.get(id)\n\n override def selectByIds(ids: Array[DepartmentId])(using c: Connection): List[DepartmentRow] = ids.flatMap(map.get(_)).toList\n\n override def selectByIdsTracked(ids: Array[DepartmentId])(using c: Connection): Map[DepartmentId, DepartmentRow] = selectByIds(ids)(using c).map(x => (((row: DepartmentRow) => row.id).apply(x), x)).toMap\n\n override def update: UpdateBuilder[DepartmentFields, DepartmentRow] = UpdateBuilderMock(DepartmentFields.structure, () => map.values.toList, UpdateParams.empty(), row => row)\n\n override def update(row: DepartmentRow)(using c: Connection): Boolean = {\n val shouldUpdate = map.get(row.id).filter(oldRow => (oldRow != row)).isDefined\n if (shouldUpdate) {\n map.put(row.id, row): @scala.annotation.nowarn\n }\n return shouldUpdate\n }\n\n override def upsert(unsaved: DepartmentRow)(using c: Connection): DepartmentRow = {\n map.put(unsaved.id, unsaved): @scala.annotation.nowarn\n return unsaved\n }\n\n override def upsertBatch(unsaved: Iterator[DepartmentRow])(using c: Connection): List[DepartmentRow] = {\n unsaved.map { row =>\n map.put(row.id, row): @scala.annotation.nowarn\n row\n }.toList\n }\n}", - "ProjectAssignmentRow": "package showcase.showcase.project_assignment\n\nimport dev.typr.foundations.DuckDbTypes\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport java.time.LocalDate\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.employee.EmployeeId\nimport showcase.showcase.project.ProjectId\n\n/** Table: showcase.project_assignment\n * Composite primary key: employee_id, project_id\n */\ncase class ProjectAssignmentRow(\n /** Points to [[showcase.showcase.employee.EmployeeRow.id]] */\n employeeId: EmployeeId,\n /** Points to [[showcase.showcase.project.ProjectRow.id]] */\n projectId: ProjectId,\n role: String,\n /** Default: 0 */\n hoursAllocated: Option[Int],\n startDate: Option[LocalDate],\n endDate: Option[LocalDate]\n) {\n def compositeId: ProjectAssignmentId = new ProjectAssignmentId(employeeId, projectId)\n\n def id: ProjectAssignmentId = this.compositeId\n\n def toUnsavedRow(hoursAllocated: Defaulted[Option[Int]] = Defaulted.Provided(this.hoursAllocated)): ProjectAssignmentRowUnsaved = {\n new ProjectAssignmentRowUnsaved(\n employeeId,\n projectId,\n role,\n startDate,\n endDate,\n hoursAllocated\n )\n }\n}\n\nobject ProjectAssignmentRow {\n val `_rowParser`: RowParser[ProjectAssignmentRow] = RowParsers.of(EmployeeId.duckDbType, ProjectId.duckDbType, DuckDbTypes.varchar, ScalaDbTypes.DuckDbTypes.integer.nullable, DuckDbTypes.date.nullable, DuckDbTypes.date.nullable)(ProjectAssignmentRow.apply)(row => Array[Any](row.employeeId, row.projectId, row.role, row.hoursAllocated, row.startDate, row.endDate))\n\n def apply(\n compositeId: ProjectAssignmentId,\n role: String,\n hoursAllocated: Option[Int],\n startDate: Option[LocalDate],\n endDate: Option[LocalDate]\n ): ProjectAssignmentRow = {\n new ProjectAssignmentRow(\n compositeId.employeeId,\n compositeId.projectId,\n role,\n hoursAllocated,\n startDate,\n endDate\n )\n }\n}", - "ProjectAssignmentRowUnsaved": "package showcase.showcase.project_assignment\n\nimport java.time.LocalDate\nimport showcase.customtypes.Defaulted\nimport showcase.customtypes.Defaulted.UseDefault\nimport showcase.showcase.employee.EmployeeId\nimport showcase.showcase.project.ProjectId\n\n/** This class corresponds to a row in table `showcase.project_assignment` which has not been persisted yet */\ncase class ProjectAssignmentRowUnsaved(\n /** Points to [[showcase.showcase.employee.EmployeeRow.id]] */\n employeeId: EmployeeId,\n /** Points to [[showcase.showcase.project.ProjectRow.id]] */\n projectId: ProjectId,\n role: String,\n startDate: Option[LocalDate] = None,\n endDate: Option[LocalDate] = None,\n /** Default: 0 */\n hoursAllocated: Defaulted[Option[Int]] = new UseDefault()\n) {\n def toRow(hoursAllocatedDefault: => Option[Int]): ProjectAssignmentRow = {\n new ProjectAssignmentRow(\n employeeId = employeeId,\n projectId = projectId,\n role = role,\n hoursAllocated = hoursAllocated.getOrElse(hoursAllocatedDefault),\n startDate = startDate,\n endDate = endDate\n )\n }\n}", - "ProjectAssignmentId": "package showcase.showcase.project_assignment\n\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport showcase.showcase.employee.EmployeeId\nimport showcase.showcase.project.ProjectId\n\n/** Type for the composite primary key of table `showcase.project_assignment` */\ncase class ProjectAssignmentId(\n employeeId: EmployeeId,\n projectId: ProjectId\n)\n\nobject ProjectAssignmentId {\n val `_rowParser`: RowParser[ProjectAssignmentId] = RowParsers.of(EmployeeId.duckDbType, ProjectId.duckDbType)(ProjectAssignmentId.apply)(row => Array[Any](row.employeeId, row.projectId))\n}", - "ProjectAssignmentRepo": "package showcase.showcase.project_assignment\n\nimport dev.typr.foundations.scala.DeleteBuilder\nimport dev.typr.foundations.scala.SelectBuilder\nimport dev.typr.foundations.scala.UpdateBuilder\nimport java.sql.Connection\n\ntrait ProjectAssignmentRepo {\n def delete: DeleteBuilder[ProjectAssignmentFields, ProjectAssignmentRow]\n\n def deleteById(compositeId: ProjectAssignmentId)(using c: Connection): Boolean\n\n def deleteByIds(compositeIds: Array[ProjectAssignmentId])(using c: Connection): Int\n\n def insert(unsaved: ProjectAssignmentRow)(using c: Connection): ProjectAssignmentRow\n\n def insert(unsaved: ProjectAssignmentRowUnsaved)(using c: Connection): ProjectAssignmentRow\n\n def select: SelectBuilder[ProjectAssignmentFields, ProjectAssignmentRow]\n\n def selectAll(using c: Connection): List[ProjectAssignmentRow]\n\n def selectById(compositeId: ProjectAssignmentId)(using c: Connection): Option[ProjectAssignmentRow]\n\n def selectByIds(compositeIds: Array[ProjectAssignmentId])(using c: Connection): List[ProjectAssignmentRow]\n\n def selectByIdsTracked(compositeIds: Array[ProjectAssignmentId])(using c: Connection): Map[ProjectAssignmentId, ProjectAssignmentRow]\n\n def update: UpdateBuilder[ProjectAssignmentFields, ProjectAssignmentRow]\n\n def update(row: ProjectAssignmentRow)(using c: Connection): Boolean\n\n def upsert(unsaved: ProjectAssignmentRow)(using c: Connection): ProjectAssignmentRow\n\n def upsertBatch(unsaved: Iterator[ProjectAssignmentRow])(using c: Connection): List[ProjectAssignmentRow]\n}", - "ProjectRow": "package showcase.showcase.project\n\nimport dev.typr.foundations.DuckDbTypes\nimport dev.typr.foundations.data.Json\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport java.time.Duration\nimport java.time.LocalDate\nimport java.time.LocalDateTime\nimport showcase.ProjectProjectPhases\nimport showcase.customtypes.Defaulted\n\n/** Table: showcase.project\n * Primary key: id\n */\ncase class ProjectRow(\n id: ProjectId,\n name: String,\n description: Option[String],\n startDate: Option[LocalDate],\n endDate: Option[LocalDate],\n budget: Option[BigDecimal],\n /** Default: 'planning' */\n status: Option[String],\n /** Default: CURRENT_TIMESTAMP */\n createdAt: Option[LocalDateTime],\n milestones: Option[Array[String]],\n budgetSnapshots: Option[Array[BigDecimal]],\n teamMembers: Option[Array[String]],\n projectPhases: Option[ProjectProjectPhases],\n config: Option[/* MAP type - mapped to String */ String],\n riskScores: Option[/* MAP type - mapped to String */ String],\n estimatedDuration: Option[Duration],\n actualDuration: Option[Duration],\n metadata: Option[Json]\n) {\n def toUnsavedRow(\n status: Defaulted[Option[String]] = Defaulted.Provided(this.status),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.Provided(this.createdAt)\n ): ProjectRowUnsaved = {\n new ProjectRowUnsaved(\n id,\n name,\n description,\n startDate,\n endDate,\n budget,\n milestones,\n budgetSnapshots,\n teamMembers,\n projectPhases,\n config,\n riskScores,\n estimatedDuration,\n actualDuration,\n metadata,\n status,\n createdAt\n )\n }\n}\n\nobject ProjectRow {\n val `_rowParser`: RowParser[ProjectRow] = RowParsers.of(ProjectId.duckDbType, DuckDbTypes.varchar, DuckDbTypes.varchar.nullable, DuckDbTypes.date.nullable, DuckDbTypes.date.nullable, ScalaDbTypes.DuckDbTypes.numeric.nullable, DuckDbTypes.varchar.nullable, DuckDbTypes.timestamp.nullable, DuckDbTypes.varchar.array().nullable, DuckDbTypes.numeric.array().nullable, DuckDbTypes.varchar.array().nullable, ProjectProjectPhases.duckDbType.nullable, DuckDbTypes.varchar.mapTo(DuckDbTypes.varchar).nullable, DuckDbTypes.varchar.mapTo(DuckDbTypes.integer).nullable, DuckDbTypes.interval.nullable, DuckDbTypes.interval.nullable, DuckDbTypes.json.nullable)(ProjectRow.apply)(row => Array[Any](row.id, row.name, row.description, row.startDate, row.endDate, row.budget, row.status, row.createdAt, row.milestones, row.budgetSnapshots, row.teamMembers, row.projectPhases, row.config, row.riskScores, row.estimatedDuration, row.actualDuration, row.metadata))\n}", - "ProjectId": "package showcase.showcase.project\n\nimport dev.typr.foundations.DuckDbType\nimport dev.typr.foundations.DuckDbTypes\nimport dev.typr.foundations.scala.Bijection\n\n/** Type for the primary key of table `showcase.project` */\ncase class ProjectId(value: String) extends scala.AnyVal\n\nobject ProjectId {\n given bijection: Bijection[ProjectId, String] = Bijection.apply[ProjectId, String](_.value)(ProjectId.apply)\n\n given duckDbType: DuckDbType[ProjectId] = DuckDbTypes.varchar.bimap(ProjectId.apply, _.value)\n\n given pgTypeArray: DuckDbType[Array[ProjectId]] = DuckDbTypes.varcharArray.bimap(xs => xs.map(ProjectId.apply), xs => xs.map(_.value))\n}", - "EmployeeSummaryViewRow": "package showcase.showcase.employee_summary\n\nimport dev.typr.foundations.DuckDbTypes\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport java.time.LocalDate\nimport showcase.showcase.company.CompanyId\nimport showcase.showcase.department.DepartmentId\nimport showcase.showcase.employee.EmployeeId\n\n/** View: showcase.employee_summary\n * Summary view of employees with their department and company information\n */\ncase class EmployeeSummaryViewRow(\n /** Points to [[showcase.showcase.employee.EmployeeRow.id]] */\n employeeId: EmployeeId,\n email: String,\n firstName: String,\n lastName: String,\n salary: Option[BigDecimal],\n hiredAt: Option[LocalDate],\n active: Option[Boolean],\n /** Points to [[showcase.showcase.department.DepartmentRow.id]] */\n departmentId: DepartmentId,\n departmentName: String,\n departmentBudget: Option[BigDecimal],\n /** Points to [[showcase.showcase.company.CompanyRow.id]] */\n companyId: CompanyId,\n companyName: String,\n managerId: Option[String],\n managerFirstName: Option[String],\n managerLastName: Option[String]\n)\n\nobject EmployeeSummaryViewRow {\n val `_rowParser`: RowParser[EmployeeSummaryViewRow] = RowParsers.of(EmployeeId.duckDbType, DuckDbTypes.varchar, DuckDbTypes.varchar, DuckDbTypes.varchar, ScalaDbTypes.DuckDbTypes.numeric.nullable, DuckDbTypes.date.nullable, ScalaDbTypes.DuckDbTypes.boolean_.nullable, DepartmentId.duckDbType, DuckDbTypes.varchar, ScalaDbTypes.DuckDbTypes.numeric.nullable, CompanyId.duckDbType, DuckDbTypes.varchar, DuckDbTypes.varchar.nullable, DuckDbTypes.varchar.nullable, DuckDbTypes.varchar.nullable)(EmployeeSummaryViewRow.apply)(row => Array[Any](row.employeeId, row.email, row.firstName, row.lastName, row.salary, row.hiredAt, row.active, row.departmentId, row.departmentName, row.departmentBudget, row.companyId, row.companyName, row.managerId, row.managerFirstName, row.managerLastName))\n}", - "EmployeeSummaryViewRepo": "package showcase.showcase.employee_summary\n\nimport dev.typr.foundations.scala.SelectBuilder\nimport java.sql.Connection\n\ntrait EmployeeSummaryViewRepo {\n def select: SelectBuilder[EmployeeSummaryViewFields, EmployeeSummaryViewRow]\n\n def selectAll(using c: Connection): List[EmployeeSummaryViewRow]\n}", - "CustomerOrderRow": "package showcase.showcase.customer_order\n\nimport dev.typr.foundations.DuckDbTypes\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport java.time.Duration\nimport java.time.LocalDateTime\nimport java.time.OffsetDateTime\nimport showcase.CustomerOrderLineItemsSummary\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.address.AddressId\nimport showcase.showcase.customer.CustomerId\n\n/** Table: showcase.customer_order\n * Primary key: id\n */\ncase class CustomerOrderRow(\n id: CustomerOrderId,\n /** Points to [[showcase.showcase.customer.CustomerRow.id]] */\n customerId: CustomerId,\n /** Points to [[showcase.showcase.address.AddressRow.id]] */\n shippingAddressId: Option[AddressId],\n /** Points to [[showcase.showcase.address.AddressRow.id]] */\n billingAddressId: Option[AddressId],\n /** Default: 'pending' */\n status: Option[String],\n subtotal: BigDecimal,\n /** Default: 0 */\n tax: Option[BigDecimal],\n /** Default: 0 */\n shipping: Option[BigDecimal],\n total: BigDecimal,\n notes: Option[String],\n /** Default: CURRENT_TIMESTAMP */\n createdAt: Option[LocalDateTime],\n shippedAt: Option[LocalDateTime],\n deliveredAt: Option[LocalDateTime],\n /** Default: now() */\n orderedAtTz: Option[OffsetDateTime],\n deliveredAtTz: Option[OffsetDateTime],\n tags: Option[Array[String]],\n fulfillmentTimes: Option[Array[LocalDateTime]],\n lineItemsSummary: Option[CustomerOrderLineItemsSummary],\n metadata: Option[/* MAP type - mapped to String */ String],\n processingTime: Option[Duration]\n) {\n def toUnsavedRow(\n status: Defaulted[Option[String]] = Defaulted.Provided(this.status),\n tax: Defaulted[Option[BigDecimal]] = Defaulted.Provided(this.tax),\n shipping: Defaulted[Option[BigDecimal]] = Defaulted.Provided(this.shipping),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.Provided(this.createdAt),\n orderedAtTz: Defaulted[Option[OffsetDateTime]] = Defaulted.Provided(this.orderedAtTz)\n ): CustomerOrderRowUnsaved = {\n new CustomerOrderRowUnsaved(\n id,\n customerId,\n shippingAddressId,\n billingAddressId,\n subtotal,\n total,\n notes,\n shippedAt,\n deliveredAt,\n deliveredAtTz,\n tags,\n fulfillmentTimes,\n lineItemsSummary,\n metadata,\n processingTime,\n status,\n tax,\n shipping,\n createdAt,\n orderedAtTz\n )\n }\n}\n\nobject CustomerOrderRow {\n val `_rowParser`: RowParser[CustomerOrderRow] = RowParsers.of(CustomerOrderId.duckDbType, CustomerId.duckDbType, AddressId.duckDbType.nullable, AddressId.duckDbType.nullable, DuckDbTypes.varchar.nullable, ScalaDbTypes.DuckDbTypes.numeric, ScalaDbTypes.DuckDbTypes.numeric.nullable, ScalaDbTypes.DuckDbTypes.numeric.nullable, ScalaDbTypes.DuckDbTypes.numeric, DuckDbTypes.varchar.nullable, DuckDbTypes.timestamp.nullable, DuckDbTypes.timestamp.nullable, DuckDbTypes.timestamp.nullable, DuckDbTypes.timestamptz.nullable, DuckDbTypes.timestamptz.nullable, DuckDbTypes.varchar.array().nullable, DuckDbTypes.timestamp.array().nullable, CustomerOrderLineItemsSummary.duckDbType.nullable, DuckDbTypes.varchar.mapTo(DuckDbTypes.varchar).nullable, DuckDbTypes.interval.nullable)(CustomerOrderRow.apply)(row => Array[Any](row.id, row.customerId, row.shippingAddressId, row.billingAddressId, row.status, row.subtotal, row.tax, row.shipping, row.total, row.notes, row.createdAt, row.shippedAt, row.deliveredAt, row.orderedAtTz, row.deliveredAtTz, row.tags, row.fulfillmentTimes, row.lineItemsSummary, row.metadata, row.processingTime))\n}", - "CustomerOrderRepo": "package showcase.showcase.customer_order\n\nimport dev.typr.foundations.scala.DeleteBuilder\nimport dev.typr.foundations.scala.SelectBuilder\nimport dev.typr.foundations.scala.UpdateBuilder\nimport java.sql.Connection\n\ntrait CustomerOrderRepo {\n def delete: DeleteBuilder[CustomerOrderFields, CustomerOrderRow]\n\n def deleteById(id: CustomerOrderId)(using c: Connection): Boolean\n\n def deleteByIds(ids: Array[CustomerOrderId])(using c: Connection): Int\n\n def insert(unsaved: CustomerOrderRow)(using c: Connection): CustomerOrderRow\n\n def insert(unsaved: CustomerOrderRowUnsaved)(using c: Connection): CustomerOrderRow\n\n def select: SelectBuilder[CustomerOrderFields, CustomerOrderRow]\n\n def selectAll(using c: Connection): List[CustomerOrderRow]\n\n def selectById(id: CustomerOrderId)(using c: Connection): Option[CustomerOrderRow]\n\n def selectByIds(ids: Array[CustomerOrderId])(using c: Connection): List[CustomerOrderRow]\n\n def selectByIdsTracked(ids: Array[CustomerOrderId])(using c: Connection): Map[CustomerOrderId, CustomerOrderRow]\n\n def update: UpdateBuilder[CustomerOrderFields, CustomerOrderRow]\n\n def update(row: CustomerOrderRow)(using c: Connection): Boolean\n\n def upsert(unsaved: CustomerOrderRow)(using c: Connection): CustomerOrderRow\n\n def upsertBatch(unsaved: Iterator[CustomerOrderRow])(using c: Connection): List[CustomerOrderRow]\n}", - "OrderItemRow": "package showcase.showcase.order_item\n\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.customer_order.CustomerOrderId\nimport showcase.showcase.product.ProductId\n\n/** Table: showcase.order_item\n * Composite primary key: order_id, product_id\n */\ncase class OrderItemRow(\n /** Points to [[showcase.showcase.customer_order.CustomerOrderRow.id]] */\n orderId: CustomerOrderId,\n /** Points to [[showcase.showcase.product.ProductRow.id]] */\n productId: ProductId,\n quantity: Int,\n unitPrice: BigDecimal,\n /** Default: 0 */\n discount: Option[BigDecimal]\n) {\n def compositeId: OrderItemId = new OrderItemId(orderId, productId)\n\n def id: OrderItemId = this.compositeId\n\n def toUnsavedRow(discount: Defaulted[Option[BigDecimal]] = Defaulted.Provided(this.discount)): OrderItemRowUnsaved = {\n new OrderItemRowUnsaved(\n orderId,\n productId,\n quantity,\n unitPrice,\n discount\n )\n }\n}\n\nobject OrderItemRow {\n val `_rowParser`: RowParser[OrderItemRow] = RowParsers.of(CustomerOrderId.duckDbType, ProductId.duckDbType, ScalaDbTypes.DuckDbTypes.integer, ScalaDbTypes.DuckDbTypes.numeric, ScalaDbTypes.DuckDbTypes.numeric.nullable)(OrderItemRow.apply)(row => Array[Any](row.orderId, row.productId, row.quantity, row.unitPrice, row.discount))\n\n def apply(\n compositeId: OrderItemId,\n quantity: Int,\n unitPrice: BigDecimal,\n discount: Option[BigDecimal]\n ): OrderItemRow = {\n new OrderItemRow(\n compositeId.orderId,\n compositeId.productId,\n quantity,\n unitPrice,\n discount\n )\n }\n}", - "OrderItemId": "package showcase.showcase.order_item\n\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport showcase.showcase.customer_order.CustomerOrderId\nimport showcase.showcase.product.ProductId\n\n/** Type for the composite primary key of table `showcase.order_item` */\ncase class OrderItemId(\n orderId: CustomerOrderId,\n productId: ProductId\n)\n\nobject OrderItemId {\n val `_rowParser`: RowParser[OrderItemId] = RowParsers.of(CustomerOrderId.duckDbType, ProductId.duckDbType)(OrderItemId.apply)(row => Array[Any](row.orderId, row.productId))\n}", - "ProductRow": "package showcase.showcase.product\n\nimport dev.typr.foundations.DuckDbTypes\nimport dev.typr.foundations.data.Json\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport java.time.LocalDateTime\nimport showcase.ProductDimensions\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.category.CategoryId\n\n/** Table: showcase.product\n * Primary key: id\n */\ncase class ProductRow(\n id: ProductId,\n /** Points to [[showcase.showcase.category.CategoryRow.id]] */\n categoryId: Option[CategoryId],\n name: String,\n sku: String,\n price: BigDecimal,\n cost: Option[BigDecimal],\n /** Default: true */\n inStock: Option[Boolean],\n /** Default: 0 */\n quantity: Option[Int],\n weight: Option[BigDecimal],\n /** Default: CURRENT_TIMESTAMP */\n createdAt: Option[LocalDateTime],\n tags: Option[Array[String]],\n images: Option[Array[String]],\n relatedSkus: Option[Array[String]],\n priceHistory: Option[Array[BigDecimal]],\n categoryIds: Option[Array[Int]],\n dimensions: Option[ProductDimensions],\n attributes: Option[/* MAP type - mapped to String */ String],\n specifications: Option[/* MAP type - mapped to String */ String],\n pricesByRegion: Option[/* MAP type - mapped to String */ String],\n stockByWarehouse: Option[/* MAP type - mapped to String */ String],\n seoMetadata: Option[Json]\n) {\n def toUnsavedRow(\n inStock: Defaulted[Option[Boolean]] = Defaulted.Provided(this.inStock),\n quantity: Defaulted[Option[Int]] = Defaulted.Provided(this.quantity),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.Provided(this.createdAt)\n ): ProductRowUnsaved = {\n new ProductRowUnsaved(\n id,\n categoryId,\n name,\n sku,\n price,\n cost,\n weight,\n tags,\n images,\n relatedSkus,\n priceHistory,\n categoryIds,\n dimensions,\n attributes,\n specifications,\n pricesByRegion,\n stockByWarehouse,\n seoMetadata,\n inStock,\n quantity,\n createdAt\n )\n }\n}\n\nobject ProductRow {\n val `_rowParser`: RowParser[ProductRow] = RowParsers.of(ProductId.duckDbType, CategoryId.duckDbType.nullable, DuckDbTypes.varchar, DuckDbTypes.varchar, ScalaDbTypes.DuckDbTypes.numeric, ScalaDbTypes.DuckDbTypes.numeric.nullable, ScalaDbTypes.DuckDbTypes.boolean_.nullable, ScalaDbTypes.DuckDbTypes.integer.nullable, ScalaDbTypes.DuckDbTypes.numeric.nullable, DuckDbTypes.timestamp.nullable, DuckDbTypes.varchar.array().nullable, DuckDbTypes.varchar.array().nullable, DuckDbTypes.varchar.array().nullable, DuckDbTypes.numeric.array().nullable, ScalaDbTypes.DuckDbTypes.integerArrayUnboxed.nullable, ProductDimensions.duckDbType.nullable, DuckDbTypes.varchar.mapTo(DuckDbTypes.varchar).nullable, DuckDbTypes.varchar.mapTo(DuckDbTypes.varchar).nullable, DuckDbTypes.varchar.mapTo(DuckDbTypes.numeric).nullable, DuckDbTypes.varchar.mapTo(DuckDbTypes.integer).nullable, DuckDbTypes.json.nullable)(ProductRow.apply)(row => Array[Any](row.id, row.categoryId, row.name, row.sku, row.price, row.cost, row.inStock, row.quantity, row.weight, row.createdAt, row.tags, row.images, row.relatedSkus, row.priceHistory, row.categoryIds, row.dimensions, row.attributes, row.specifications, row.pricesByRegion, row.stockByWarehouse, row.seoMetadata))\n}", - "ProductId": "package showcase.showcase.product\n\nimport dev.typr.foundations.DuckDbType\nimport dev.typr.foundations.DuckDbTypes\nimport dev.typr.foundations.scala.Bijection\n\n/** Type for the primary key of table `showcase.product` */\ncase class ProductId(value: String) extends scala.AnyVal\n\nobject ProductId {\n given bijection: Bijection[ProductId, String] = Bijection.apply[ProductId, String](_.value)(ProductId.apply)\n\n given duckDbType: DuckDbType[ProductId] = DuckDbTypes.varchar.bimap(ProductId.apply, _.value)\n\n given pgTypeArray: DuckDbType[Array[ProductId]] = DuckDbTypes.varcharArray.bimap(xs => xs.map(ProductId.apply), xs => xs.map(_.value))\n}", - "CategoryRow": "package showcase.showcase.category\n\nimport dev.typr.foundations.DuckDbTypes\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\n\n/** Table: showcase.category\n * Primary key: id\n */\ncase class CategoryRow(\n id: CategoryId,\n /** Points to [[showcase.showcase.category.CategoryRow.id]] */\n parentId: Option[CategoryId],\n name: String,\n description: Option[String]\n)\n\nobject CategoryRow {\n val `_rowParser`: RowParser[CategoryRow] = RowParsers.of(CategoryId.duckDbType, CategoryId.duckDbType.nullable, DuckDbTypes.varchar, DuckDbTypes.varchar.nullable)(CategoryRow.apply)(row => Array[Any](row.id, row.parentId, row.name, row.description))\n}", - "CategoryId": "package showcase.showcase.category\n\nimport dev.typr.foundations.DuckDbType\nimport dev.typr.foundations.DuckDbTypes\nimport dev.typr.foundations.scala.Bijection\n\n/** Type for the primary key of table `showcase.category` */\ncase class CategoryId(value: String) extends scala.AnyVal\n\nobject CategoryId {\n given bijection: Bijection[CategoryId, String] = Bijection.apply[CategoryId, String](_.value)(CategoryId.apply)\n\n given duckDbType: DuckDbType[CategoryId] = DuckDbTypes.varchar.bimap(CategoryId.apply, _.value)\n\n given pgTypeArray: DuckDbType[Array[CategoryId]] = DuckDbTypes.varcharArray.bimap(xs => xs.map(CategoryId.apply), xs => xs.map(_.value))\n}", - "AddressRow": "package showcase.showcase.address\n\nimport dev.typr.foundations.DuckDbTypes\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport showcase.AddressCoordinates\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.customer.CustomerId\n\n/** Table: showcase.address\n * Primary key: id\n */\ncase class AddressRow(\n id: AddressId,\n /** Points to [[showcase.showcase.customer.CustomerRow.id]] */\n customerId: CustomerId,\n addressType: String,\n street: String,\n city: String,\n state: Option[String],\n postalCode: Option[String],\n country: String,\n /** Default: false */\n isDefault: Option[Boolean],\n coordinates: Option[AddressCoordinates]\n) {\n def toUnsavedRow(isDefault: Defaulted[Option[Boolean]] = Defaulted.Provided(this.isDefault)): AddressRowUnsaved = {\n new AddressRowUnsaved(\n id,\n customerId,\n addressType,\n street,\n city,\n state,\n postalCode,\n country,\n coordinates,\n isDefault\n )\n }\n}\n\nobject AddressRow {\n val `_rowParser`: RowParser[AddressRow] = RowParsers.of(AddressId.duckDbType, CustomerId.duckDbType, DuckDbTypes.varchar, DuckDbTypes.varchar, DuckDbTypes.varchar, DuckDbTypes.varchar.nullable, DuckDbTypes.varchar.nullable, DuckDbTypes.varchar, ScalaDbTypes.DuckDbTypes.boolean_.nullable, AddressCoordinates.duckDbType.nullable)(AddressRow.apply)(row => Array[Any](row.id, row.customerId, row.addressType, row.street, row.city, row.state, row.postalCode, row.country, row.isDefault, row.coordinates))\n}", - "AddressId": "package showcase.showcase.address\n\nimport dev.typr.foundations.DuckDbType\nimport dev.typr.foundations.DuckDbTypes\nimport dev.typr.foundations.scala.Bijection\n\n/** Type for the primary key of table `showcase.address` */\ncase class AddressId(value: String) extends scala.AnyVal\n\nobject AddressId {\n given bijection: Bijection[AddressId, String] = Bijection.apply[AddressId, String](_.value)(AddressId.apply)\n\n given duckDbType: DuckDbType[AddressId] = DuckDbTypes.varchar.bimap(AddressId.apply, _.value)\n\n given pgTypeArray: DuckDbType[Array[AddressId]] = DuckDbTypes.varcharArray.bimap(xs => xs.map(AddressId.apply), xs => xs.map(_.value))\n}", - "Defaulted": "package showcase.customtypes\n\n\n\n/** This signals a value where if you don't provide it, postgres will generate it for you */\nsealed trait Defaulted[T] {\n def fold[U](\n onDefault: => U,\n onProvided: T => U\n ): U\n\n def getOrElse(onDefault: => T): T\n\n def visit(\n onDefault: => Unit,\n onProvided: T => Unit\n ): Unit\n}\n\nobject Defaulted {\n case class Provided[T](value: T) extends Defaulted[T] {\n override def fold[U](\n onDefault: => U,\n onProvided: T => U\n ): U = onProvided(value)\n\n override def getOrElse(onDefault: => T): T = value\n\n override def visit(\n onDefault: => Unit,\n onProvided: T => Unit\n ): Unit = onProvided(value)\n }\n\n case class UseDefault[T]() extends Defaulted[T] {\n override def fold[U](\n onDefault: => U,\n onProvided: T => U\n ): U = onDefault\n\n override def getOrElse(onDefault: => T): T = onDefault\n\n override def visit(\n onDefault: => Unit,\n onProvided: T => Unit\n ): Unit = onDefault\n }\n}", - "TestInsert": "package showcase\n\nimport dev.typr.foundations.data.Json\nimport java.math.BigInteger\nimport java.sql.Connection\nimport java.time.Duration\nimport java.time.LocalDate\nimport java.time.LocalDateTime\nimport java.time.LocalTime\nimport java.time.OffsetDateTime\nimport java.util.UUID\nimport scala.util.Random\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.address.AddressId\nimport showcase.showcase.address.AddressRepoImpl\nimport showcase.showcase.address.AddressRow\nimport showcase.showcase.address.AddressRowUnsaved\nimport showcase.showcase.audit_log.AuditLogId\nimport showcase.showcase.audit_log.AuditLogRepoImpl\nimport showcase.showcase.audit_log.AuditLogRow\nimport showcase.showcase.audit_log.AuditLogRowUnsaved\nimport showcase.showcase.category.CategoryId\nimport showcase.showcase.category.CategoryRepoImpl\nimport showcase.showcase.category.CategoryRow\nimport showcase.showcase.company.CompanyId\nimport showcase.showcase.company.CompanyRepoImpl\nimport showcase.showcase.company.CompanyRow\nimport showcase.showcase.company.CompanyRowUnsaved\nimport showcase.showcase.customer.CustomerId\nimport showcase.showcase.customer.CustomerRepoImpl\nimport showcase.showcase.customer.CustomerRow\nimport showcase.showcase.customer.CustomerRowUnsaved\nimport showcase.showcase.customer_order.CustomerOrderId\nimport showcase.showcase.customer_order.CustomerOrderRepoImpl\nimport showcase.showcase.customer_order.CustomerOrderRow\nimport showcase.showcase.customer_order.CustomerOrderRowUnsaved\nimport showcase.showcase.datetime_demo.DatetimeDemoId\nimport showcase.showcase.datetime_demo.DatetimeDemoRepoImpl\nimport showcase.showcase.datetime_demo.DatetimeDemoRow\nimport showcase.showcase.datetime_demo.DatetimeDemoRowUnsaved\nimport showcase.showcase.department.DepartmentId\nimport showcase.showcase.department.DepartmentRepoImpl\nimport showcase.showcase.department.DepartmentRow\nimport showcase.showcase.employee.EmployeeId\nimport showcase.showcase.employee.EmployeeRepoImpl\nimport showcase.showcase.employee.EmployeeRow\nimport showcase.showcase.employee.EmployeeRowUnsaved\nimport showcase.showcase.file_storage.FileStorageId\nimport showcase.showcase.file_storage.FileStorageRepoImpl\nimport showcase.showcase.file_storage.FileStorageRow\nimport showcase.showcase.file_storage.FileStorageRowUnsaved\nimport showcase.showcase.financial_record.FinancialRecordId\nimport showcase.showcase.financial_record.FinancialRecordRepoImpl\nimport showcase.showcase.financial_record.FinancialRecordRow\nimport showcase.showcase.financial_record.FinancialRecordRowUnsaved\nimport showcase.showcase.numeric_types_demo.NumericTypesDemoId\nimport showcase.showcase.numeric_types_demo.NumericTypesDemoRepoImpl\nimport showcase.showcase.numeric_types_demo.NumericTypesDemoRow\nimport showcase.showcase.numeric_types_demo.NumericTypesDemoRowUnsaved\nimport showcase.showcase.order_item.OrderItemRepoImpl\nimport showcase.showcase.order_item.OrderItemRow\nimport showcase.showcase.order_item.OrderItemRowUnsaved\nimport showcase.showcase.product.ProductId\nimport showcase.showcase.product.ProductRepoImpl\nimport showcase.showcase.product.ProductRow\nimport showcase.showcase.product.ProductRowUnsaved\nimport showcase.showcase.project.ProjectId\nimport showcase.showcase.project.ProjectRepoImpl\nimport showcase.showcase.project.ProjectRow\nimport showcase.showcase.project.ProjectRowUnsaved\nimport showcase.showcase.project_assignment.ProjectAssignmentRepoImpl\nimport showcase.showcase.project_assignment.ProjectAssignmentRow\nimport showcase.showcase.project_assignment.ProjectAssignmentRowUnsaved\nimport showcase.showcase.scientific_data.ScientificDataId\nimport showcase.showcase.scientific_data.ScientificDataRepoImpl\nimport showcase.showcase.scientific_data.ScientificDataRow\nimport showcase.showcase.scientific_data.ScientificDataRowUnsaved\nimport showcase.showcase.session.SessionId\nimport showcase.showcase.session.SessionRepoImpl\nimport showcase.showcase.session.SessionRow\nimport showcase.showcase.session.SessionRowUnsaved\nimport showcase.showcase.subscription.SubscriptionId\nimport showcase.showcase.subscription.SubscriptionRepoImpl\nimport showcase.showcase.subscription.SubscriptionRow\nimport showcase.showcase.subscription.SubscriptionRowUnsaved\n\n/** Methods to generate random data for `Ident(TestInsert)` */\ncase class TestInsert(random: Random) {\n def showcaseAddress(\n customerId: CustomerId,\n id: AddressId = AddressId(random.alphanumeric.take(20).mkString),\n addressType: String = random.alphanumeric.take(20).mkString,\n street: String = random.alphanumeric.take(20).mkString,\n city: String = random.alphanumeric.take(20).mkString,\n state: Option[String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n postalCode: Option[String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n country: String = random.alphanumeric.take(20).mkString,\n coordinates: Option[AddressCoordinates] = None,\n isDefault: Defaulted[Option[Boolean]] = Defaulted.UseDefault()\n )(using c: Connection): AddressRow = {\n (new AddressRepoImpl()).insert(new AddressRowUnsaved(\n id = id,\n customerId = customerId,\n addressType = addressType,\n street = street,\n city = city,\n state = state,\n postalCode = postalCode,\n country = country,\n coordinates = coordinates,\n isDefault = isDefault\n ))(using c)\n }\n\n def showcaseAuditLog(\n id: AuditLogId = AuditLogId(random.alphanumeric.take(20).mkString),\n tableName: String = random.alphanumeric.take(20).mkString,\n recordId: String = random.alphanumeric.take(20).mkString,\n action: String = random.alphanumeric.take(20).mkString,\n oldValues: Option[String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n newValues: Option[String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n changedBy: Option[EmployeeId] = None,\n changedAt: Defaulted[Option[LocalDateTime]] = Defaulted.UseDefault()\n )(using c: Connection): AuditLogRow = {\n (new AuditLogRepoImpl()).insert(new AuditLogRowUnsaved(\n id = id,\n tableName = tableName,\n recordId = recordId,\n action = action,\n oldValues = oldValues,\n newValues = newValues,\n changedBy = changedBy,\n changedAt = changedAt\n ))(using c)\n }\n\n def showcaseCategory(\n id: CategoryId = CategoryId(random.alphanumeric.take(20).mkString),\n parentId: Option[CategoryId] = None,\n name: String = random.alphanumeric.take(20).mkString,\n description: Option[String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString)\n )(using c: Connection): CategoryRow = {\n (new CategoryRepoImpl()).insert(new CategoryRow(\n id = id,\n parentId = parentId,\n name = name,\n description = description\n ))(using c)\n }\n\n def showcaseCompany(\n id: CompanyId = CompanyId(random.alphanumeric.take(20).mkString),\n name: String = random.alphanumeric.take(20).mkString,\n foundedYear: Option[Int] = if (random.nextBoolean()) None else Some(random.nextInt()),\n active: Defaulted[Option[Boolean]] = Defaulted.UseDefault(),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.UseDefault()\n )(using c: Connection): CompanyRow = {\n (new CompanyRepoImpl()).insert(new CompanyRowUnsaved(\n id = id,\n name = name,\n foundedYear = foundedYear,\n active = active,\n createdAt = createdAt\n ))(using c)\n }\n\n def showcaseCustomer(\n id: CustomerId = CustomerId(random.alphanumeric.take(20).mkString),\n email: String = random.alphanumeric.take(20).mkString,\n firstName: String = random.alphanumeric.take(20).mkString,\n lastName: String = random.alphanumeric.take(20).mkString,\n phone: Option[String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n interests: Option[Array[String]] = None,\n orderCounts: Option[Array[Int]] = None,\n preferences: Option[CustomerPreferences] = None,\n metadata: Option[/* MAP type - mapped to String */ String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n verified: Defaulted[Option[Boolean]] = Defaulted.UseDefault(),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.UseDefault()\n )(using c: Connection): CustomerRow = {\n (new CustomerRepoImpl()).insert(new CustomerRowUnsaved(\n id = id,\n email = email,\n firstName = firstName,\n lastName = lastName,\n phone = phone,\n interests = interests,\n orderCounts = orderCounts,\n preferences = preferences,\n metadata = metadata,\n verified = verified,\n createdAt = createdAt\n ))(using c)\n }\n\n def showcaseCustomerOrder(\n customerId: CustomerId,\n id: CustomerOrderId = CustomerOrderId(random.alphanumeric.take(20).mkString),\n shippingAddressId: Option[AddressId] = None,\n billingAddressId: Option[AddressId] = None,\n subtotal: BigDecimal = BigDecimal.decimal(random.nextDouble()),\n total: BigDecimal = BigDecimal.decimal(random.nextDouble()),\n notes: Option[String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n shippedAt: Option[LocalDateTime] = None,\n deliveredAt: Option[LocalDateTime] = None,\n deliveredAtTz: Option[OffsetDateTime] = None,\n tags: Option[Array[String]] = None,\n fulfillmentTimes: Option[Array[LocalDateTime]] = None,\n lineItemsSummary: Option[CustomerOrderLineItemsSummary] = None,\n metadata: Option[/* MAP type - mapped to String */ String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n processingTime: Option[Duration] = None,\n status: Defaulted[Option[String]] = Defaulted.UseDefault(),\n tax: Defaulted[Option[BigDecimal]] = Defaulted.UseDefault(),\n shipping: Defaulted[Option[BigDecimal]] = Defaulted.UseDefault(),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.UseDefault(),\n orderedAtTz: Defaulted[Option[OffsetDateTime]] = Defaulted.UseDefault()\n )(using c: Connection): CustomerOrderRow = {\n (new CustomerOrderRepoImpl()).insert(new CustomerOrderRowUnsaved(\n id = id,\n customerId = customerId,\n shippingAddressId = shippingAddressId,\n billingAddressId = billingAddressId,\n subtotal = subtotal,\n total = total,\n notes = notes,\n shippedAt = shippedAt,\n deliveredAt = deliveredAt,\n deliveredAtTz = deliveredAtTz,\n tags = tags,\n fulfillmentTimes = fulfillmentTimes,\n lineItemsSummary = lineItemsSummary,\n metadata = metadata,\n processingTime = processingTime,\n status = status,\n tax = tax,\n shipping = shipping,\n createdAt = createdAt,\n orderedAtTz = orderedAtTz\n ))(using c)\n }\n\n def showcaseDatetimeDemo(\n id: DatetimeDemoId = DatetimeDemoId(random.alphanumeric.take(20).mkString),\n dateOnly: Option[LocalDate] = None,\n timeOnly: Option[LocalTime] = None,\n timestampVal: Option[LocalDateTime] = None,\n timestampTz: Option[OffsetDateTime] = None,\n timestampS: Option[LocalDateTime] = None,\n timestampMs: Option[LocalDateTime] = None,\n timestampNs: Option[LocalDateTime] = None,\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.UseDefault()\n )(using c: Connection): DatetimeDemoRow = {\n (new DatetimeDemoRepoImpl()).insert(new DatetimeDemoRowUnsaved(\n id = id,\n dateOnly = dateOnly,\n timeOnly = timeOnly,\n timestampVal = timestampVal,\n timestampTz = timestampTz,\n timestampS = timestampS,\n timestampMs = timestampMs,\n timestampNs = timestampNs,\n createdAt = createdAt\n ))(using c)\n }\n\n def showcaseDepartment(\n companyId: CompanyId,\n id: DepartmentId = DepartmentId(random.alphanumeric.take(20).mkString),\n name: String = random.alphanumeric.take(20).mkString,\n budget: Option[BigDecimal] = if (random.nextBoolean()) None else Some(BigDecimal.decimal(random.nextDouble()))\n )(using c: Connection): DepartmentRow = {\n (new DepartmentRepoImpl()).insert(new DepartmentRow(\n id = id,\n companyId = companyId,\n name = name,\n budget = budget\n ))(using c)\n }\n\n def showcaseEmployee(\n departmentId: DepartmentId,\n id: EmployeeId = EmployeeId(random.alphanumeric.take(20).mkString),\n managerId: Option[EmployeeId] = None,\n email: String = random.alphanumeric.take(20).mkString,\n firstName: String = random.alphanumeric.take(20).mkString,\n lastName: String = random.alphanumeric.take(20).mkString,\n salary: Option[BigDecimal] = if (random.nextBoolean()) None else Some(BigDecimal.decimal(random.nextDouble())),\n hiredAt: Option[LocalDate] = None,\n skills: Option[Array[String]] = None,\n certifications: Option[Array[String]] = None,\n weeklyAvailability: Option[Array[Boolean]] = None,\n contactInfo: Option[EmployeeContactInfo] = None,\n settings: Option[/* MAP type - mapped to String */ String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n skillsRating: Option[/* MAP type - mapped to String */ String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n probationPeriod: Option[Duration] = None,\n active: Defaulted[Option[Boolean]] = Defaulted.UseDefault(),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.UseDefault()\n )(using c: Connection): EmployeeRow = {\n (new EmployeeRepoImpl()).insert(new EmployeeRowUnsaved(\n id = id,\n departmentId = departmentId,\n managerId = managerId,\n email = email,\n firstName = firstName,\n lastName = lastName,\n salary = salary,\n hiredAt = hiredAt,\n skills = skills,\n certifications = certifications,\n weeklyAvailability = weeklyAvailability,\n contactInfo = contactInfo,\n settings = settings,\n skillsRating = skillsRating,\n probationPeriod = probationPeriod,\n active = active,\n createdAt = createdAt\n ))(using c)\n }\n\n def showcaseFileStorage(\n id: FileStorageId = FileStorageId(random.alphanumeric.take(20).mkString),\n filename: String = random.alphanumeric.take(20).mkString,\n mimeType: Option[String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n fileData: Option[Array[Byte]] = None,\n thumbnail: Option[Array[Byte]] = None,\n checksum: Option[Array[Byte]] = None,\n fileSize: Option[BigInteger] = None,\n uploadedAt: Defaulted[Option[LocalDateTime]] = Defaulted.UseDefault()\n )(using c: Connection): FileStorageRow = {\n (new FileStorageRepoImpl()).insert(new FileStorageRowUnsaved(\n id = id,\n filename = filename,\n mimeType = mimeType,\n fileData = fileData,\n thumbnail = thumbnail,\n checksum = checksum,\n fileSize = fileSize,\n uploadedAt = uploadedAt\n ))(using c)\n }\n\n def showcaseFinancialRecord(\n id: FinancialRecordId = FinancialRecordId(random.alphanumeric.take(20).mkString),\n description: String = random.alphanumeric.take(20).mkString,\n amount: BigDecimal = BigDecimal.decimal(random.nextDouble()),\n balance: Option[BigDecimal] = if (random.nextBoolean()) None else Some(BigDecimal.decimal(random.nextDouble())),\n exchangeRate: Option[BigDecimal] = if (random.nextBoolean()) None else Some(BigDecimal.decimal(random.nextDouble())),\n percentage: Option[BigDecimal] = if (random.nextBoolean()) None else Some(BigDecimal.decimal(random.nextDouble())),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.UseDefault()\n )(using c: Connection): FinancialRecordRow = {\n (new FinancialRecordRepoImpl()).insert(new FinancialRecordRowUnsaved(\n id = id,\n description = description,\n amount = amount,\n balance = balance,\n exchangeRate = exchangeRate,\n percentage = percentage,\n createdAt = createdAt\n ))(using c)\n }\n\n def showcaseNumericTypesDemo(\n id: NumericTypesDemoId = NumericTypesDemoId(random.alphanumeric.take(20).mkString),\n tinyVal: Option[Byte] = if (random.nextBoolean()) None else Some(random.nextInt(Byte.MaxValue).toByte),\n utinyVal: Option[Short] = if (random.nextBoolean()) None else Some(random.nextInt(Short.MaxValue).toShort),\n smallVal: Option[Short] = if (random.nextBoolean()) None else Some(random.nextInt(Short.MaxValue).toShort),\n usmallVal: Option[Int] = if (random.nextBoolean()) None else Some(random.nextInt()),\n intVal: Option[Int] = if (random.nextBoolean()) None else Some(random.nextInt()),\n uintVal: Option[Long] = if (random.nextBoolean()) None else Some(random.nextLong()),\n bigVal: Option[Long] = if (random.nextBoolean()) None else Some(random.nextLong()),\n ubigVal: Option[BigInteger] = None,\n hugeVal: Option[BigInteger] = None,\n uhugeVal: Option[BigInteger] = None,\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.UseDefault()\n )(using c: Connection): NumericTypesDemoRow = {\n (new NumericTypesDemoRepoImpl()).insert(new NumericTypesDemoRowUnsaved(\n id = id,\n tinyVal = tinyVal,\n utinyVal = utinyVal,\n smallVal = smallVal,\n usmallVal = usmallVal,\n intVal = intVal,\n uintVal = uintVal,\n bigVal = bigVal,\n ubigVal = ubigVal,\n hugeVal = hugeVal,\n uhugeVal = uhugeVal,\n createdAt = createdAt\n ))(using c)\n }\n\n def showcaseOrderItem(\n orderId: CustomerOrderId,\n productId: ProductId,\n quantity: Int = random.nextInt(),\n unitPrice: BigDecimal = BigDecimal.decimal(random.nextDouble()),\n discount: Defaulted[Option[BigDecimal]] = Defaulted.UseDefault()\n )(using c: Connection): OrderItemRow = {\n (new OrderItemRepoImpl()).insert(new OrderItemRowUnsaved(\n orderId = orderId,\n productId = productId,\n quantity = quantity,\n unitPrice = unitPrice,\n discount = discount\n ))(using c)\n }\n\n def showcaseProduct(\n id: ProductId = ProductId(random.alphanumeric.take(20).mkString),\n categoryId: Option[CategoryId] = None,\n name: String = random.alphanumeric.take(20).mkString,\n sku: String = random.alphanumeric.take(20).mkString,\n price: BigDecimal = BigDecimal.decimal(random.nextDouble()),\n cost: Option[BigDecimal] = if (random.nextBoolean()) None else Some(BigDecimal.decimal(random.nextDouble())),\n weight: Option[BigDecimal] = if (random.nextBoolean()) None else Some(BigDecimal.decimal(random.nextDouble())),\n tags: Option[Array[String]] = None,\n images: Option[Array[String]] = None,\n relatedSkus: Option[Array[String]] = None,\n priceHistory: Option[Array[BigDecimal]] = None,\n categoryIds: Option[Array[Int]] = None,\n dimensions: Option[ProductDimensions] = None,\n attributes: Option[/* MAP type - mapped to String */ String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n specifications: Option[/* MAP type - mapped to String */ String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n pricesByRegion: Option[/* MAP type - mapped to String */ String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n stockByWarehouse: Option[/* MAP type - mapped to String */ String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n seoMetadata: Option[Json] = None,\n inStock: Defaulted[Option[Boolean]] = Defaulted.UseDefault(),\n quantity: Defaulted[Option[Int]] = Defaulted.UseDefault(),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.UseDefault()\n )(using c: Connection): ProductRow = {\n (new ProductRepoImpl()).insert(new ProductRowUnsaved(\n id = id,\n categoryId = categoryId,\n name = name,\n sku = sku,\n price = price,\n cost = cost,\n weight = weight,\n tags = tags,\n images = images,\n relatedSkus = relatedSkus,\n priceHistory = priceHistory,\n categoryIds = categoryIds,\n dimensions = dimensions,\n attributes = attributes,\n specifications = specifications,\n pricesByRegion = pricesByRegion,\n stockByWarehouse = stockByWarehouse,\n seoMetadata = seoMetadata,\n inStock = inStock,\n quantity = quantity,\n createdAt = createdAt\n ))(using c)\n }\n\n def showcaseProject(\n id: ProjectId = ProjectId(random.alphanumeric.take(20).mkString),\n name: String = random.alphanumeric.take(20).mkString,\n description: Option[String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n startDate: Option[LocalDate] = None,\n endDate: Option[LocalDate] = None,\n budget: Option[BigDecimal] = if (random.nextBoolean()) None else Some(BigDecimal.decimal(random.nextDouble())),\n milestones: Option[Array[String]] = None,\n budgetSnapshots: Option[Array[BigDecimal]] = None,\n teamMembers: Option[Array[String]] = None,\n projectPhases: Option[ProjectProjectPhases] = None,\n config: Option[/* MAP type - mapped to String */ String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n riskScores: Option[/* MAP type - mapped to String */ String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n estimatedDuration: Option[Duration] = None,\n actualDuration: Option[Duration] = None,\n metadata: Option[Json] = None,\n status: Defaulted[Option[String]] = Defaulted.UseDefault(),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.UseDefault()\n )(using c: Connection): ProjectRow = {\n (new ProjectRepoImpl()).insert(new ProjectRowUnsaved(\n id = id,\n name = name,\n description = description,\n startDate = startDate,\n endDate = endDate,\n budget = budget,\n milestones = milestones,\n budgetSnapshots = budgetSnapshots,\n teamMembers = teamMembers,\n projectPhases = projectPhases,\n config = config,\n riskScores = riskScores,\n estimatedDuration = estimatedDuration,\n actualDuration = actualDuration,\n metadata = metadata,\n status = status,\n createdAt = createdAt\n ))(using c)\n }\n\n def showcaseProjectAssignment(\n employeeId: EmployeeId,\n projectId: ProjectId,\n role: String = random.alphanumeric.take(20).mkString,\n startDate: Option[LocalDate] = None,\n endDate: Option[LocalDate] = None,\n hoursAllocated: Defaulted[Option[Int]] = Defaulted.UseDefault()\n )(using c: Connection): ProjectAssignmentRow = {\n (new ProjectAssignmentRepoImpl()).insert(new ProjectAssignmentRowUnsaved(\n employeeId = employeeId,\n projectId = projectId,\n role = role,\n startDate = startDate,\n endDate = endDate,\n hoursAllocated = hoursAllocated\n ))(using c)\n }\n\n def showcaseScientificData(\n id: ScientificDataId = ScientificDataId(random.alphanumeric.take(20).mkString),\n floatVal: Option[Float] = if (random.nextBoolean()) None else Some(random.nextFloat()),\n doubleVal: Option[Double] = if (random.nextBoolean()) None else Some(random.nextDouble()),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.UseDefault()\n )(using c: Connection): ScientificDataRow = {\n (new ScientificDataRepoImpl()).insert(new ScientificDataRowUnsaved(\n id = id,\n floatVal = floatVal,\n doubleVal = doubleVal,\n createdAt = createdAt\n ))(using c)\n }\n\n def showcaseSession(\n expiresAt: LocalDateTime,\n userId: Option[String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n refreshToken: Option[UUID] = if (random.nextBoolean()) None else Some(UUID.nameUUIDFromBytes{val bs = Array.ofDim[Byte](16); random.nextBytes(bs); bs}),\n deviceId: Option[UUID] = if (random.nextBoolean()) None else Some(UUID.nameUUIDFromBytes{val bs = Array.ofDim[Byte](16); random.nextBytes(bs); bs}),\n id: Defaulted[SessionId] = Defaulted.UseDefault(),\n token: Defaulted[UUID] = Defaulted.UseDefault(),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.UseDefault()\n )(using c: Connection): SessionRow = {\n (new SessionRepoImpl()).insert(new SessionRowUnsaved(\n userId = userId,\n refreshToken = refreshToken,\n deviceId = deviceId,\n expiresAt = expiresAt,\n id = id,\n token = token,\n createdAt = createdAt\n ))(using c)\n }\n\n def showcaseSubscription(\n billingCycle: Duration,\n id: SubscriptionId = SubscriptionId(random.alphanumeric.take(20).mkString),\n customerId: String = random.alphanumeric.take(20).mkString,\n planName: String = random.alphanumeric.take(20).mkString,\n trialPeriod: Option[Duration] = None,\n startedAt: Defaulted[Option[LocalDateTime]] = Defaulted.UseDefault()\n )(using c: Connection): SubscriptionRow = {\n (new SubscriptionRepoImpl()).insert(new SubscriptionRowUnsaved(\n id = id,\n customerId = customerId,\n planName = planName,\n billingCycle = billingCycle,\n trialPeriod = trialPeriod,\n startedAt = startedAt\n ))(using c)\n }\n}" - } - }, - "oracle": { - "java": { - "CompanyRow": "package showcase.showcase.company;\n\nimport dev.typr.foundations.OracleTypes;\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport java.math.BigDecimal;\nimport java.time.LocalDateTime;\nimport java.util.Optional;\nimport showcase.customtypes.Defaulted;\n\n/** Table: showcase.company\n * Primary key: id\n */\npublic record CompanyRow(\n CompanyId id,\n String name,\n Optional foundedYear,\n /** Default: true */\n Optional active,\n /** Default: CURRENT_TIMESTAMP */\n Optional createdAt\n) {\n public CompanyRow withId(CompanyId id) {\n return new CompanyRow(id, name, foundedYear, active, createdAt);\n };\n\n public CompanyRow withName(String name) {\n return new CompanyRow(id, name, foundedYear, active, createdAt);\n };\n\n public CompanyRow withFoundedYear(Optional foundedYear) {\n return new CompanyRow(id, name, foundedYear, active, createdAt);\n };\n\n /** Default: true */\n public CompanyRow withActive(Optional active) {\n return new CompanyRow(id, name, foundedYear, active, createdAt);\n };\n\n /** Default: CURRENT_TIMESTAMP */\n public CompanyRow withCreatedAt(Optional createdAt) {\n return new CompanyRow(id, name, foundedYear, active, createdAt);\n };\n\n public static RowParser _rowParser = RowParsers.of(CompanyId.oracleType, OracleTypes.varchar2, OracleTypes.number.opt(), OracleTypes.number.opt(), OracleTypes.timestamp.opt(), CompanyRow::new, row -> new Object[]{row.id(), row.name(), row.foundedYear(), row.active(), row.createdAt()});;\n\n public CompanyRowUnsaved toUnsavedRow(\n Defaulted> active,\n Defaulted> createdAt\n ) {\n return new CompanyRowUnsaved(id, name, foundedYear, active, createdAt);\n };\n}", - "CompanyRowUnsaved": "package showcase.showcase.company;\n\nimport java.math.BigDecimal;\nimport java.time.LocalDateTime;\nimport java.util.Optional;\nimport showcase.customtypes.Defaulted;\nimport showcase.customtypes.Defaulted.UseDefault;\n\n/** This class corresponds to a row in table `showcase.company` which has not been persisted yet */\npublic record CompanyRowUnsaved(\n CompanyId id,\n String name,\n Optional foundedYear,\n /** Default: true */\n Defaulted> active,\n /** Default: CURRENT_TIMESTAMP */\n Defaulted> createdAt\n) {\n public CompanyRowUnsaved(\n CompanyId id,\n String name\n ) {\n this(id, name, Optional.empty(), new UseDefault<>(), new UseDefault<>());\n };\n\n public CompanyRowUnsaved withId(CompanyId id) {\n return new CompanyRowUnsaved(id, name, foundedYear, active, createdAt);\n };\n\n public CompanyRowUnsaved withName(String name) {\n return new CompanyRowUnsaved(id, name, foundedYear, active, createdAt);\n };\n\n public CompanyRowUnsaved withFoundedYear(Optional foundedYear) {\n return new CompanyRowUnsaved(id, name, foundedYear, active, createdAt);\n };\n\n /** Default: true */\n public CompanyRowUnsaved withActive(Defaulted> active) {\n return new CompanyRowUnsaved(id, name, foundedYear, active, createdAt);\n };\n\n /** Default: CURRENT_TIMESTAMP */\n public CompanyRowUnsaved withCreatedAt(Defaulted> createdAt) {\n return new CompanyRowUnsaved(id, name, foundedYear, active, createdAt);\n };\n\n public CompanyRow toRow(\n java.util.function.Supplier> activeDefault,\n java.util.function.Supplier> createdAtDefault\n ) {\n return new CompanyRow(id, name, foundedYear, active.getOrElse(activeDefault), createdAt.getOrElse(createdAtDefault));\n };\n}", - "CompanyId": "package showcase.showcase.company;\n\nimport dev.typr.foundations.OracleType;\nimport dev.typr.foundations.OracleTypes;\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport dev.typr.foundations.dsl.Bijection;\n\n/** Type for the primary key of table `showcase.company` */\npublic record CompanyId(String value) {\n public CompanyId withValue(String value) {\n return new CompanyId(value);\n };\n\n @Override\n public java.lang.String toString() {\n return value.toString();\n };\n\n static public RowParser _rowParser =\n RowParsers.of(OracleTypes.varchar2.bimap(CompanyId::new, CompanyId::value), x -> x, id -> new Object[]{id});\n\n static public Bijection bijection =\n Bijection.of(CompanyId::value, CompanyId::new);\n\n static public OracleType oracleType =\n OracleTypes.varchar2.bimap(CompanyId::new, CompanyId::value);\n}", - "CompanyRepo": "package showcase.showcase.company;\n\nimport dev.typr.foundations.dsl.DeleteBuilder;\nimport dev.typr.foundations.dsl.SelectBuilder;\nimport dev.typr.foundations.dsl.UpdateBuilder;\nimport java.sql.Connection;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\n\npublic interface CompanyRepo {\n DeleteBuilder delete();\n\n Boolean deleteById(\n CompanyId id,\n Connection c\n );\n\n Integer deleteByIds(\n CompanyId[] ids,\n Connection c\n );\n\n CompanyRow insert(\n CompanyRow unsaved,\n Connection c\n );\n\n CompanyRow insert(\n CompanyRowUnsaved unsaved,\n Connection c\n );\n\n SelectBuilder select();\n\n List selectAll(Connection c);\n\n Optional selectById(\n CompanyId id,\n Connection c\n );\n\n List selectByIds(\n CompanyId[] ids,\n Connection c\n );\n\n Map selectByIdsTracked(\n CompanyId[] ids,\n Connection c\n );\n\n UpdateBuilder update();\n\n Boolean update(\n CompanyRow row,\n Connection c\n );\n\n CompanyRow upsert(\n CompanyRow unsaved,\n Connection c\n );\n\n List upsertBatch(\n Iterator unsaved,\n Connection c\n );\n}", - "CompanyRepoMock": "package showcase.showcase.company;\n\nimport dev.typr.foundations.dsl.DeleteBuilder;\nimport dev.typr.foundations.dsl.DeleteBuilderMock;\nimport dev.typr.foundations.dsl.DeleteParams;\nimport dev.typr.foundations.dsl.SelectBuilder;\nimport dev.typr.foundations.dsl.SelectBuilderMock;\nimport dev.typr.foundations.dsl.SelectParams;\nimport dev.typr.foundations.dsl.UpdateBuilder;\nimport dev.typr.foundations.dsl.UpdateBuilderMock;\nimport dev.typr.foundations.dsl.UpdateParams;\nimport java.lang.RuntimeException;\nimport java.sql.Connection;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\nimport java.util.function.Function;\nimport java.util.stream.Collectors;\n\npublic record CompanyRepoMock(\n java.util.function.Function toRow,\n HashMap map\n) implements CompanyRepo {\n public CompanyRepoMock(java.util.function.Function toRow) {\n this(toRow, new HashMap());\n };\n\n public CompanyRepoMock withToRow(java.util.function.Function toRow) {\n return new CompanyRepoMock(toRow, map);\n };\n\n public CompanyRepoMock withMap(HashMap map) {\n return new CompanyRepoMock(toRow, map);\n };\n\n @Override\n public DeleteBuilder delete() {\n return new DeleteBuilderMock<>(CompanyFields.structure(), () -> new ArrayList<>(map.values()), DeleteParams.empty(), row -> row.id(), id -> map.remove(id));\n };\n\n @Override\n public Boolean deleteById(\n CompanyId id,\n Connection c\n ) {\n return Optional.ofNullable(map.remove(id)).isPresent();\n };\n\n @Override\n public Integer deleteByIds(\n CompanyId[] ids,\n Connection c\n ) {\n var count = 0;\n for (var id : ids) {\n if (Optional.ofNullable(map.remove(id)).isPresent()) {\n count = count + 1;;\n };\n };\n return count;\n };\n\n @Override\n public CompanyRow insert(\n CompanyRow unsaved,\n Connection c\n ) {\n if (map.containsKey(unsaved.id())) {\n throw new RuntimeException(\"id \" + unsaved.id() + \" already exists\");\n };\n map.put(unsaved.id(), unsaved);\n return unsaved;\n };\n\n @Override\n public CompanyRow insert(\n CompanyRowUnsaved unsaved,\n Connection c\n ) {\n return insert(toRow.apply(unsaved), c);\n };\n\n @Override\n public SelectBuilder select() {\n return new SelectBuilderMock<>(CompanyFields.structure(), () -> new ArrayList<>(map.values()), SelectParams.empty());\n };\n\n @Override\n public List selectAll(Connection c) {\n return new ArrayList<>(map.values());\n };\n\n @Override\n public Optional selectById(\n CompanyId id,\n Connection c\n ) {\n return Optional.ofNullable(map.get(id));\n };\n\n @Override\n public List selectByIds(\n CompanyId[] ids,\n Connection c\n ) {\n var result = new ArrayList();\n for (var id : ids) {\n var opt = Optional.ofNullable(map.get(id));\n if (opt.isPresent()) {\n result.add(opt.get());\n };\n };\n return result;\n };\n\n @Override\n public Map selectByIdsTracked(\n CompanyId[] ids,\n Connection c\n ) {\n return selectByIds(ids, c).stream().collect(Collectors.toMap((CompanyRow row) -> row.id(), Function.identity()));\n };\n\n @Override\n public UpdateBuilder update() {\n return new UpdateBuilderMock<>(CompanyFields.structure(), () -> new ArrayList<>(map.values()), UpdateParams.empty(), row -> row);\n };\n\n @Override\n public Boolean update(\n CompanyRow row,\n Connection c\n ) {\n var shouldUpdate = Optional.ofNullable(map.get(row.id())).filter(oldRow -> !oldRow.equals(row)).isPresent();\n if (shouldUpdate) {\n map.put(row.id(), row);;\n };\n return shouldUpdate;\n };\n\n @Override\n public CompanyRow upsert(\n CompanyRow unsaved,\n Connection c\n ) {\n map.put(unsaved.id(), unsaved);\n return unsaved;\n };\n\n @Override\n public List upsertBatch(\n Iterator unsaved,\n Connection c\n ) {\n var result = new ArrayList();\n while (unsaved.hasNext()) {\n var row = unsaved.next();\n map.put(row.id(), row);\n result.add(row);\n };\n return result;\n };\n}", - "EmployeeRow": "package showcase.showcase.employee;\n\nimport dev.typr.foundations.OracleTypes;\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport dev.typr.foundations.data.Json;\nimport dev.typr.foundations.data.OracleIntervalDS;\nimport dev.typr.foundations.data.OracleIntervalYM;\nimport java.math.BigDecimal;\nimport java.time.LocalDateTime;\nimport java.util.Optional;\nimport showcase.customtypes.Defaulted;\nimport showcase.showcase.department.DepartmentId;\n\n/** Table: showcase.employee\n * Primary key: id\n */\npublic record EmployeeRow(\n EmployeeId id,\n /** Points to {@link showcase.showcase.department.DepartmentRow#id()} */\n DepartmentId departmentId,\n /** Points to {@link showcase.showcase.employee.EmployeeRow#id()} */\n Optional managerId,\n String email,\n String firstName,\n String lastName,\n Optional salary,\n Optional hiredAt,\n /** Default: true */\n Optional active,\n /** Default: CURRENT_TIMESTAMP */\n Optional createdAt,\n Optional metadata,\n Optional resume,\n Optional photo,\n Optional probationPeriod,\n Optional shiftDuration\n) {\n public EmployeeRow withId(EmployeeId id) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, metadata, resume, photo, probationPeriod, shiftDuration);\n };\n\n /** Points to {@link showcase.showcase.department.DepartmentRow#id()} */\n public EmployeeRow withDepartmentId(DepartmentId departmentId) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, metadata, resume, photo, probationPeriod, shiftDuration);\n };\n\n /** Points to {@link showcase.showcase.employee.EmployeeRow#id()} */\n public EmployeeRow withManagerId(Optional managerId) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, metadata, resume, photo, probationPeriod, shiftDuration);\n };\n\n public EmployeeRow withEmail(String email) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, metadata, resume, photo, probationPeriod, shiftDuration);\n };\n\n public EmployeeRow withFirstName(String firstName) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, metadata, resume, photo, probationPeriod, shiftDuration);\n };\n\n public EmployeeRow withLastName(String lastName) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, metadata, resume, photo, probationPeriod, shiftDuration);\n };\n\n public EmployeeRow withSalary(Optional salary) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, metadata, resume, photo, probationPeriod, shiftDuration);\n };\n\n public EmployeeRow withHiredAt(Optional hiredAt) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, metadata, resume, photo, probationPeriod, shiftDuration);\n };\n\n /** Default: true */\n public EmployeeRow withActive(Optional active) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, metadata, resume, photo, probationPeriod, shiftDuration);\n };\n\n /** Default: CURRENT_TIMESTAMP */\n public EmployeeRow withCreatedAt(Optional createdAt) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, metadata, resume, photo, probationPeriod, shiftDuration);\n };\n\n public EmployeeRow withMetadata(Optional metadata) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, metadata, resume, photo, probationPeriod, shiftDuration);\n };\n\n public EmployeeRow withResume(Optional resume) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, metadata, resume, photo, probationPeriod, shiftDuration);\n };\n\n public EmployeeRow withPhoto(Optional photo) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, metadata, resume, photo, probationPeriod, shiftDuration);\n };\n\n public EmployeeRow withProbationPeriod(Optional probationPeriod) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, metadata, resume, photo, probationPeriod, shiftDuration);\n };\n\n public EmployeeRow withShiftDuration(Optional shiftDuration) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, metadata, resume, photo, probationPeriod, shiftDuration);\n };\n\n public static RowParser _rowParser = RowParsers.of(EmployeeId.oracleType, DepartmentId.oracleType, EmployeeId.oracleType.opt(), OracleTypes.varchar2, OracleTypes.varchar2, OracleTypes.varchar2, OracleTypes.number.opt(), OracleTypes.date.opt(), OracleTypes.number.opt(), OracleTypes.timestamp.opt(), OracleTypes.json.opt(), OracleTypes.clob.opt(), OracleTypes.blob.opt(), OracleTypes.intervalYearToMonth.opt(), OracleTypes.intervalDayToSecond.opt(), EmployeeRow::new, row -> new Object[]{row.id(), row.departmentId(), row.managerId(), row.email(), row.firstName(), row.lastName(), row.salary(), row.hiredAt(), row.active(), row.createdAt(), row.metadata(), row.resume(), row.photo(), row.probationPeriod(), row.shiftDuration()});;\n\n public EmployeeRowUnsaved toUnsavedRow(\n Defaulted> active,\n Defaulted> createdAt\n ) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, metadata, resume, photo, probationPeriod, shiftDuration, active, createdAt);\n };\n}", - "EmployeeRowUnsaved": "package showcase.showcase.employee;\n\nimport dev.typr.foundations.data.Json;\nimport dev.typr.foundations.data.OracleIntervalDS;\nimport dev.typr.foundations.data.OracleIntervalYM;\nimport java.math.BigDecimal;\nimport java.time.LocalDateTime;\nimport java.util.Optional;\nimport showcase.customtypes.Defaulted;\nimport showcase.customtypes.Defaulted.UseDefault;\nimport showcase.showcase.department.DepartmentId;\n\n/** This class corresponds to a row in table `showcase.employee` which has not been persisted yet */\npublic record EmployeeRowUnsaved(\n EmployeeId id,\n /** Points to {@link showcase.showcase.department.DepartmentRow#id()} */\n DepartmentId departmentId,\n /** Points to {@link showcase.showcase.employee.EmployeeRow#id()} */\n Optional managerId,\n String email,\n String firstName,\n String lastName,\n Optional salary,\n Optional hiredAt,\n Optional metadata,\n Optional resume,\n Optional photo,\n Optional probationPeriod,\n Optional shiftDuration,\n /** Default: true */\n Defaulted> active,\n /** Default: CURRENT_TIMESTAMP */\n Defaulted> createdAt\n) {\n public EmployeeRowUnsaved(\n EmployeeId id,\n /** Points to {@link showcase.showcase.department.DepartmentRow#id()} */\n DepartmentId departmentId,\n String email,\n String firstName,\n String lastName\n ) {\n this(id, departmentId, Optional.empty(), email, firstName, lastName, Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), new UseDefault<>(), new UseDefault<>());\n };\n\n public EmployeeRowUnsaved withId(EmployeeId id) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, metadata, resume, photo, probationPeriod, shiftDuration, active, createdAt);\n };\n\n /** Points to {@link showcase.showcase.department.DepartmentRow#id()} */\n public EmployeeRowUnsaved withDepartmentId(DepartmentId departmentId) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, metadata, resume, photo, probationPeriod, shiftDuration, active, createdAt);\n };\n\n /** Points to {@link showcase.showcase.employee.EmployeeRow#id()} */\n public EmployeeRowUnsaved withManagerId(Optional managerId) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, metadata, resume, photo, probationPeriod, shiftDuration, active, createdAt);\n };\n\n public EmployeeRowUnsaved withEmail(String email) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, metadata, resume, photo, probationPeriod, shiftDuration, active, createdAt);\n };\n\n public EmployeeRowUnsaved withFirstName(String firstName) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, metadata, resume, photo, probationPeriod, shiftDuration, active, createdAt);\n };\n\n public EmployeeRowUnsaved withLastName(String lastName) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, metadata, resume, photo, probationPeriod, shiftDuration, active, createdAt);\n };\n\n public EmployeeRowUnsaved withSalary(Optional salary) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, metadata, resume, photo, probationPeriod, shiftDuration, active, createdAt);\n };\n\n public EmployeeRowUnsaved withHiredAt(Optional hiredAt) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, metadata, resume, photo, probationPeriod, shiftDuration, active, createdAt);\n };\n\n public EmployeeRowUnsaved withMetadata(Optional metadata) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, metadata, resume, photo, probationPeriod, shiftDuration, active, createdAt);\n };\n\n public EmployeeRowUnsaved withResume(Optional resume) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, metadata, resume, photo, probationPeriod, shiftDuration, active, createdAt);\n };\n\n public EmployeeRowUnsaved withPhoto(Optional photo) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, metadata, resume, photo, probationPeriod, shiftDuration, active, createdAt);\n };\n\n public EmployeeRowUnsaved withProbationPeriod(Optional probationPeriod) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, metadata, resume, photo, probationPeriod, shiftDuration, active, createdAt);\n };\n\n public EmployeeRowUnsaved withShiftDuration(Optional shiftDuration) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, metadata, resume, photo, probationPeriod, shiftDuration, active, createdAt);\n };\n\n /** Default: true */\n public EmployeeRowUnsaved withActive(Defaulted> active) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, metadata, resume, photo, probationPeriod, shiftDuration, active, createdAt);\n };\n\n /** Default: CURRENT_TIMESTAMP */\n public EmployeeRowUnsaved withCreatedAt(Defaulted> createdAt) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, metadata, resume, photo, probationPeriod, shiftDuration, active, createdAt);\n };\n\n public EmployeeRow toRow(\n java.util.function.Supplier> activeDefault,\n java.util.function.Supplier> createdAtDefault\n ) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active.getOrElse(activeDefault), createdAt.getOrElse(createdAtDefault), metadata, resume, photo, probationPeriod, shiftDuration);\n };\n}", - "EmployeeId": "package showcase.showcase.employee;\n\nimport dev.typr.foundations.OracleType;\nimport dev.typr.foundations.OracleTypes;\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport dev.typr.foundations.dsl.Bijection;\n\n/** Type for the primary key of table `showcase.employee` */\npublic record EmployeeId(String value) {\n public EmployeeId withValue(String value) {\n return new EmployeeId(value);\n };\n\n @Override\n public java.lang.String toString() {\n return value.toString();\n };\n\n static public RowParser _rowParser =\n RowParsers.of(OracleTypes.varchar2.bimap(EmployeeId::new, EmployeeId::value), x -> x, id -> new Object[]{id});\n\n static public Bijection bijection =\n Bijection.of(EmployeeId::value, EmployeeId::new);\n\n static public OracleType oracleType =\n OracleTypes.varchar2.bimap(EmployeeId::new, EmployeeId::value);\n}", - "EmployeeRepo": "package showcase.showcase.employee;\n\nimport dev.typr.foundations.dsl.DeleteBuilder;\nimport dev.typr.foundations.dsl.SelectBuilder;\nimport dev.typr.foundations.dsl.UpdateBuilder;\nimport java.sql.Connection;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\n\npublic interface EmployeeRepo {\n DeleteBuilder delete();\n\n Boolean deleteById(\n EmployeeId id,\n Connection c\n );\n\n Integer deleteByIds(\n EmployeeId[] ids,\n Connection c\n );\n\n EmployeeRow insert(\n EmployeeRow unsaved,\n Connection c\n );\n\n EmployeeRow insert(\n EmployeeRowUnsaved unsaved,\n Connection c\n );\n\n SelectBuilder select();\n\n List selectAll(Connection c);\n\n Optional selectById(\n EmployeeId id,\n Connection c\n );\n\n List selectByIds(\n EmployeeId[] ids,\n Connection c\n );\n\n Map selectByIdsTracked(\n EmployeeId[] ids,\n Connection c\n );\n\n Optional selectByUniqueEmail(\n String email,\n Connection c\n );\n\n UpdateBuilder update();\n\n Boolean update(\n EmployeeRow row,\n Connection c\n );\n\n EmployeeRow upsert(\n EmployeeRow unsaved,\n Connection c\n );\n\n List upsertBatch(\n Iterator unsaved,\n Connection c\n );\n}", - "EmployeeRepoImpl": "package showcase.showcase.employee;\n\nimport dev.typr.foundations.Fragment;\nimport dev.typr.foundations.OracleTypes;\nimport dev.typr.foundations.dsl.DeleteBuilder;\nimport dev.typr.foundations.dsl.Dialect;\nimport dev.typr.foundations.dsl.SelectBuilder;\nimport dev.typr.foundations.dsl.UpdateBuilder;\nimport java.sql.Connection;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\nimport showcase.showcase.department.DepartmentId;\nimport static dev.typr.foundations.Fragment.interpolate;\n\npublic class EmployeeRepoImpl implements EmployeeRepo {\n @Override\n public DeleteBuilder delete() {\n return DeleteBuilder.of(\"\\\"showcase\\\".\\\"employee\\\"\", EmployeeFields.structure(), Dialect.ORACLE);\n };\n\n @Override\n public Boolean deleteById(\n EmployeeId id,\n Connection c\n ) {\n return interpolate(Fragment.lit(\"delete from \\\"showcase\\\".\\\"employee\\\" where \\\"id\\\" = \"), Fragment.encode(EmployeeId.oracleType, id), Fragment.lit(\"\")).update().runUnchecked(c) > 0;\n };\n\n @Override\n public Integer deleteByIds(\n EmployeeId[] ids,\n Connection c\n ) {\n ArrayList fragments = new ArrayList<>();\n for (var id : ids) { fragments.add(Fragment.encode(EmployeeId.oracleType, id)); };\n return Fragment.interpolate(Fragment.lit(\"delete from \\\"showcase\\\".\\\"employee\\\" where \\\"id\\\" in (\"), Fragment.comma(fragments), Fragment.lit(\")\")).update().runUnchecked(c);\n };\n\n @Override\n public EmployeeRow insert(\n EmployeeRow unsaved,\n Connection c\n ) {\n return interpolate(Fragment.lit(\"insert into \\\"showcase\\\".\\\"employee\\\"(\\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"metadata\\\", \\\"resume\\\", \\\"photo\\\", \\\"probation_period\\\", \\\"shift_duration\\\")\\nvalues (\"), Fragment.encode(EmployeeId.oracleType, unsaved.id()), Fragment.lit(\", \"), Fragment.encode(DepartmentId.oracleType, unsaved.departmentId()), Fragment.lit(\", \"), Fragment.encode(EmployeeId.oracleType.opt(), unsaved.managerId()), Fragment.lit(\", \"), Fragment.encode(OracleTypes.varchar2, unsaved.email()), Fragment.lit(\", \"), Fragment.encode(OracleTypes.varchar2, unsaved.firstName()), Fragment.lit(\", \"), Fragment.encode(OracleTypes.varchar2, unsaved.lastName()), Fragment.lit(\", \"), Fragment.encode(OracleTypes.number.opt(), unsaved.salary()), Fragment.lit(\", \"), Fragment.encode(OracleTypes.date.opt(), unsaved.hiredAt()), Fragment.lit(\", \"), Fragment.encode(OracleTypes.number.opt(), unsaved.active()), Fragment.lit(\", \"), Fragment.encode(OracleTypes.timestamp.opt(), unsaved.createdAt()), Fragment.lit(\", \"), Fragment.encode(OracleTypes.json.opt(), unsaved.metadata()), Fragment.lit(\", \"), Fragment.encode(OracleTypes.clob.opt(), unsaved.resume()), Fragment.lit(\", \"), Fragment.encode(OracleTypes.blob.opt(), unsaved.photo()), Fragment.lit(\", \"), Fragment.encode(OracleTypes.intervalYearToMonth.opt(), unsaved.probationPeriod()), Fragment.lit(\", \"), Fragment.encode(OracleTypes.intervalDayToSecond.opt(), unsaved.shiftDuration()), Fragment.lit(\")\\n\"))\n .updateReturningGeneratedKeys(new String[]{\"id\", \"department_id\", \"manager_id\", \"email\", \"first_name\", \"last_name\", \"salary\", \"hired_at\", \"active\", \"created_at\", \"metadata\", \"resume\", \"photo\", \"probation_period\", \"shift_duration\"}, EmployeeRow._rowParser.exactlyOne()).runUnchecked(c);\n };\n\n @Override\n public EmployeeRow insert(\n EmployeeRowUnsaved unsaved,\n Connection c\n ) {\n ArrayList columns = new ArrayList<>();;\n ArrayList values = new ArrayList<>();;\n columns.add(Fragment.lit(\"\\\"id\\\"\"));\n values.add(interpolate(Fragment.encode(EmployeeId.oracleType, unsaved.id()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"\\\"department_id\\\"\"));\n values.add(interpolate(Fragment.encode(DepartmentId.oracleType, unsaved.departmentId()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"\\\"manager_id\\\"\"));\n values.add(interpolate(Fragment.encode(EmployeeId.oracleType.opt(), unsaved.managerId()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"\\\"email\\\"\"));\n values.add(interpolate(Fragment.encode(OracleTypes.varchar2, unsaved.email()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"\\\"first_name\\\"\"));\n values.add(interpolate(Fragment.encode(OracleTypes.varchar2, unsaved.firstName()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"\\\"last_name\\\"\"));\n values.add(interpolate(Fragment.encode(OracleTypes.varchar2, unsaved.lastName()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"\\\"salary\\\"\"));\n values.add(interpolate(Fragment.encode(OracleTypes.number.opt(), unsaved.salary()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"\\\"hired_at\\\"\"));\n values.add(interpolate(Fragment.encode(OracleTypes.date.opt(), unsaved.hiredAt()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"\\\"metadata\\\"\"));\n values.add(interpolate(Fragment.encode(OracleTypes.json.opt(), unsaved.metadata()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"\\\"resume\\\"\"));\n values.add(interpolate(Fragment.encode(OracleTypes.clob.opt(), unsaved.resume()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"\\\"photo\\\"\"));\n values.add(interpolate(Fragment.encode(OracleTypes.blob.opt(), unsaved.photo()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"\\\"probation_period\\\"\"));\n values.add(interpolate(Fragment.encode(OracleTypes.intervalYearToMonth.opt(), unsaved.probationPeriod()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"\\\"shift_duration\\\"\"));\n values.add(interpolate(Fragment.encode(OracleTypes.intervalDayToSecond.opt(), unsaved.shiftDuration()), Fragment.lit(\"\")));\n unsaved.active().visit(\n () -> {\n \n },\n value -> {\n columns.add(Fragment.lit(\"\\\"active\\\"\"));\n values.add(interpolate(Fragment.encode(OracleTypes.number.opt(), value), Fragment.lit(\"\")));\n }\n );;\n unsaved.createdAt().visit(\n () -> {\n \n },\n value -> {\n columns.add(Fragment.lit(\"\\\"created_at\\\"\"));\n values.add(interpolate(Fragment.encode(OracleTypes.timestamp.opt(), value), Fragment.lit(\"\")));\n }\n );;\n Fragment q = interpolate(Fragment.lit(\"insert into \\\"showcase\\\".\\\"employee\\\"(\"), Fragment.comma(columns), Fragment.lit(\")\\nvalues (\"), Fragment.comma(values), Fragment.lit(\")\\n\"));;\n return q.updateReturningGeneratedKeys(new String[]{\"id\", \"department_id\", \"manager_id\", \"email\", \"first_name\", \"last_name\", \"salary\", \"hired_at\", \"active\", \"created_at\", \"metadata\", \"resume\", \"photo\", \"probation_period\", \"shift_duration\"}, EmployeeRow._rowParser.exactlyOne()).runUnchecked(c);\n };\n\n @Override\n public SelectBuilder select() {\n return SelectBuilder.of(\"\\\"showcase\\\".\\\"employee\\\"\", EmployeeFields.structure(), EmployeeRow._rowParser, Dialect.ORACLE);\n };\n\n @Override\n public List selectAll(Connection c) {\n return interpolate(Fragment.lit(\"select \\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"metadata\\\", \\\"resume\\\", \\\"photo\\\", \\\"probation_period\\\", \\\"shift_duration\\\"\\nfrom \\\"showcase\\\".\\\"employee\\\"\\n\")).query(EmployeeRow._rowParser.all()).runUnchecked(c);\n };\n\n @Override\n public Optional selectById(\n EmployeeId id,\n Connection c\n ) {\n return interpolate(Fragment.lit(\"select \\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"metadata\\\", \\\"resume\\\", \\\"photo\\\", \\\"probation_period\\\", \\\"shift_duration\\\"\\nfrom \\\"showcase\\\".\\\"employee\\\"\\nwhere \\\"id\\\" = \"), Fragment.encode(EmployeeId.oracleType, id), Fragment.lit(\"\")).query(EmployeeRow._rowParser.first()).runUnchecked(c);\n };\n\n @Override\n public List selectByIds(\n EmployeeId[] ids,\n Connection c\n ) {\n ArrayList fragments = new ArrayList<>();\n for (var id : ids) { fragments.add(Fragment.encode(EmployeeId.oracleType, id)); };\n return Fragment.interpolate(Fragment.lit(\"select \\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"metadata\\\", \\\"resume\\\", \\\"photo\\\", \\\"probation_period\\\", \\\"shift_duration\\\" from \\\"showcase\\\".\\\"employee\\\" where \\\"id\\\" in (\"), Fragment.comma(fragments), Fragment.lit(\")\")).query(EmployeeRow._rowParser.all()).runUnchecked(c);\n };\n\n @Override\n public Map selectByIdsTracked(\n EmployeeId[] ids,\n Connection c\n ) {\n HashMap ret = new HashMap();\n selectByIds(ids, c).forEach(row -> ret.put(row.id(), row));\n return ret;\n };\n\n @Override\n public Optional selectByUniqueEmail(\n String email,\n Connection c\n ) {\n return interpolate(Fragment.lit(\"select \\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"metadata\\\", \\\"resume\\\", \\\"photo\\\", \\\"probation_period\\\", \\\"shift_duration\\\"\\nfrom \\\"showcase\\\".\\\"employee\\\"\\nwhere \\\"email\\\" = \"), Fragment.encode(OracleTypes.varchar2, email), Fragment.lit(\"\\n\")).query(EmployeeRow._rowParser.first()).runUnchecked(c);\n };\n\n @Override\n public UpdateBuilder update() {\n return UpdateBuilder.of(\"\\\"showcase\\\".\\\"employee\\\"\", EmployeeFields.structure(), EmployeeRow._rowParser, Dialect.ORACLE);\n };\n\n @Override\n public Boolean update(\n EmployeeRow row,\n Connection c\n ) {\n EmployeeId id = row.id();;\n return interpolate(Fragment.lit(\"update \\\"showcase\\\".\\\"employee\\\"\\nset \\\"department_id\\\" = \"), Fragment.encode(DepartmentId.oracleType, row.departmentId()), Fragment.lit(\",\\n\\\"manager_id\\\" = \"), Fragment.encode(EmployeeId.oracleType.opt(), row.managerId()), Fragment.lit(\",\\n\\\"email\\\" = \"), Fragment.encode(OracleTypes.varchar2, row.email()), Fragment.lit(\",\\n\\\"first_name\\\" = \"), Fragment.encode(OracleTypes.varchar2, row.firstName()), Fragment.lit(\",\\n\\\"last_name\\\" = \"), Fragment.encode(OracleTypes.varchar2, row.lastName()), Fragment.lit(\",\\n\\\"salary\\\" = \"), Fragment.encode(OracleTypes.number.opt(), row.salary()), Fragment.lit(\",\\n\\\"hired_at\\\" = \"), Fragment.encode(OracleTypes.date.opt(), row.hiredAt()), Fragment.lit(\",\\n\\\"active\\\" = \"), Fragment.encode(OracleTypes.number.opt(), row.active()), Fragment.lit(\",\\n\\\"created_at\\\" = \"), Fragment.encode(OracleTypes.timestamp.opt(), row.createdAt()), Fragment.lit(\",\\n\\\"metadata\\\" = \"), Fragment.encode(OracleTypes.json.opt(), row.metadata()), Fragment.lit(\",\\n\\\"resume\\\" = \"), Fragment.encode(OracleTypes.clob.opt(), row.resume()), Fragment.lit(\",\\n\\\"photo\\\" = \"), Fragment.encode(OracleTypes.blob.opt(), row.photo()), Fragment.lit(\",\\n\\\"probation_period\\\" = \"), Fragment.encode(OracleTypes.intervalYearToMonth.opt(), row.probationPeriod()), Fragment.lit(\",\\n\\\"shift_duration\\\" = \"), Fragment.encode(OracleTypes.intervalDayToSecond.opt(), row.shiftDuration()), Fragment.lit(\"\\nwhere \\\"id\\\" = \"), Fragment.encode(EmployeeId.oracleType, id), Fragment.lit(\"\")).update().runUnchecked(c) > 0;\n };\n\n @Override\n public EmployeeRow upsert(\n EmployeeRow unsaved,\n Connection c\n ) {\n return interpolate(Fragment.lit(\"MERGE INTO \\\"showcase\\\".\\\"employee\\\" t\\nUSING (SELECT \"), Fragment.encode(EmployeeId.oracleType, unsaved.id()), Fragment.lit(\", \"), Fragment.encode(DepartmentId.oracleType, unsaved.departmentId()), Fragment.lit(\", \"), Fragment.encode(EmployeeId.oracleType.opt(), unsaved.managerId()), Fragment.lit(\", \"), Fragment.encode(OracleTypes.varchar2, unsaved.email()), Fragment.lit(\", \"), Fragment.encode(OracleTypes.varchar2, unsaved.firstName()), Fragment.lit(\", \"), Fragment.encode(OracleTypes.varchar2, unsaved.lastName()), Fragment.lit(\", \"), Fragment.encode(OracleTypes.number.opt(), unsaved.salary()), Fragment.lit(\", \"), Fragment.encode(OracleTypes.date.opt(), unsaved.hiredAt()), Fragment.lit(\", \"), Fragment.encode(OracleTypes.number.opt(), unsaved.active()), Fragment.lit(\", \"), Fragment.encode(OracleTypes.timestamp.opt(), unsaved.createdAt()), Fragment.lit(\", \"), Fragment.encode(OracleTypes.json.opt(), unsaved.metadata()), Fragment.lit(\", \"), Fragment.encode(OracleTypes.clob.opt(), unsaved.resume()), Fragment.lit(\", \"), Fragment.encode(OracleTypes.blob.opt(), unsaved.photo()), Fragment.lit(\", \"), Fragment.encode(OracleTypes.intervalYearToMonth.opt(), unsaved.probationPeriod()), Fragment.lit(\", \"), Fragment.encode(OracleTypes.intervalDayToSecond.opt(), unsaved.shiftDuration()), Fragment.lit(\" FROM DUAL) s\\nON (\\\"id\\\")\\nWHEN MATCHED THEN UPDATE SET t.\\\"department_id\\\" = s.\\\"department_id\\\",\\nt.\\\"manager_id\\\" = s.\\\"manager_id\\\",\\nt.\\\"email\\\" = s.\\\"email\\\",\\nt.\\\"first_name\\\" = s.\\\"first_name\\\",\\nt.\\\"last_name\\\" = s.\\\"last_name\\\",\\nt.\\\"salary\\\" = s.\\\"salary\\\",\\nt.\\\"hired_at\\\" = s.\\\"hired_at\\\",\\nt.\\\"active\\\" = s.\\\"active\\\",\\nt.\\\"created_at\\\" = s.\\\"created_at\\\",\\nt.\\\"metadata\\\" = s.\\\"metadata\\\",\\nt.\\\"resume\\\" = s.\\\"resume\\\",\\nt.\\\"photo\\\" = s.\\\"photo\\\",\\nt.\\\"probation_period\\\" = s.\\\"probation_period\\\",\\nt.\\\"shift_duration\\\" = s.\\\"shift_duration\\\"\\nWHEN NOT MATCHED THEN INSERT (\\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"metadata\\\", \\\"resume\\\", \\\"photo\\\", \\\"probation_period\\\", \\\"shift_duration\\\") VALUES (\"), Fragment.encode(EmployeeId.oracleType, unsaved.id()), Fragment.lit(\", \"), Fragment.encode(DepartmentId.oracleType, unsaved.departmentId()), Fragment.lit(\", \"), Fragment.encode(EmployeeId.oracleType.opt(), unsaved.managerId()), Fragment.lit(\", \"), Fragment.encode(OracleTypes.varchar2, unsaved.email()), Fragment.lit(\", \"), Fragment.encode(OracleTypes.varchar2, unsaved.firstName()), Fragment.lit(\", \"), Fragment.encode(OracleTypes.varchar2, unsaved.lastName()), Fragment.lit(\", \"), Fragment.encode(OracleTypes.number.opt(), unsaved.salary()), Fragment.lit(\", \"), Fragment.encode(OracleTypes.date.opt(), unsaved.hiredAt()), Fragment.lit(\", \"), Fragment.encode(OracleTypes.number.opt(), unsaved.active()), Fragment.lit(\", \"), Fragment.encode(OracleTypes.timestamp.opt(), unsaved.createdAt()), Fragment.lit(\", \"), Fragment.encode(OracleTypes.json.opt(), unsaved.metadata()), Fragment.lit(\", \"), Fragment.encode(OracleTypes.clob.opt(), unsaved.resume()), Fragment.lit(\", \"), Fragment.encode(OracleTypes.blob.opt(), unsaved.photo()), Fragment.lit(\", \"), Fragment.encode(OracleTypes.intervalYearToMonth.opt(), unsaved.probationPeriod()), Fragment.lit(\", \"), Fragment.encode(OracleTypes.intervalDayToSecond.opt(), unsaved.shiftDuration()), Fragment.lit(\")\"))\n .updateReturning(EmployeeRow._rowParser.exactlyOne())\n .runUnchecked(c);\n };\n\n @Override\n public List upsertBatch(\n Iterator unsaved,\n Connection c\n ) {\n return interpolate(Fragment.lit(\"MERGE INTO \\\"showcase\\\".\\\"employee\\\" t\\nUSING (SELECT ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? FROM DUAL) s\\nON (\\\"id\\\")\\nWHEN MATCHED THEN UPDATE SET t.\\\"department_id\\\" = s.\\\"department_id\\\",\\nt.\\\"manager_id\\\" = s.\\\"manager_id\\\",\\nt.\\\"email\\\" = s.\\\"email\\\",\\nt.\\\"first_name\\\" = s.\\\"first_name\\\",\\nt.\\\"last_name\\\" = s.\\\"last_name\\\",\\nt.\\\"salary\\\" = s.\\\"salary\\\",\\nt.\\\"hired_at\\\" = s.\\\"hired_at\\\",\\nt.\\\"active\\\" = s.\\\"active\\\",\\nt.\\\"created_at\\\" = s.\\\"created_at\\\",\\nt.\\\"metadata\\\" = s.\\\"metadata\\\",\\nt.\\\"resume\\\" = s.\\\"resume\\\",\\nt.\\\"photo\\\" = s.\\\"photo\\\",\\nt.\\\"probation_period\\\" = s.\\\"probation_period\\\",\\nt.\\\"shift_duration\\\" = s.\\\"shift_duration\\\"\\nWHEN NOT MATCHED THEN INSERT (\\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"metadata\\\", \\\"resume\\\", \\\"photo\\\", \\\"probation_period\\\", \\\"shift_duration\\\") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\"))\n .updateReturningEach(EmployeeRow._rowParser, unsaved)\n .runUnchecked(c);\n };\n}", - "EmployeeRepoMock": "package showcase.showcase.employee;\n\nimport dev.typr.foundations.dsl.DeleteBuilder;\nimport dev.typr.foundations.dsl.DeleteBuilderMock;\nimport dev.typr.foundations.dsl.DeleteParams;\nimport dev.typr.foundations.dsl.SelectBuilder;\nimport dev.typr.foundations.dsl.SelectBuilderMock;\nimport dev.typr.foundations.dsl.SelectParams;\nimport dev.typr.foundations.dsl.UpdateBuilder;\nimport dev.typr.foundations.dsl.UpdateBuilderMock;\nimport dev.typr.foundations.dsl.UpdateParams;\nimport java.lang.RuntimeException;\nimport java.sql.Connection;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\nimport java.util.function.Function;\nimport java.util.stream.Collectors;\n\npublic record EmployeeRepoMock(\n java.util.function.Function toRow,\n HashMap map\n) implements EmployeeRepo {\n public EmployeeRepoMock(java.util.function.Function toRow) {\n this(toRow, new HashMap());\n };\n\n public EmployeeRepoMock withToRow(java.util.function.Function toRow) {\n return new EmployeeRepoMock(toRow, map);\n };\n\n public EmployeeRepoMock withMap(HashMap map) {\n return new EmployeeRepoMock(toRow, map);\n };\n\n @Override\n public DeleteBuilder delete() {\n return new DeleteBuilderMock<>(EmployeeFields.structure(), () -> new ArrayList<>(map.values()), DeleteParams.empty(), row -> row.id(), id -> map.remove(id));\n };\n\n @Override\n public Boolean deleteById(\n EmployeeId id,\n Connection c\n ) {\n return Optional.ofNullable(map.remove(id)).isPresent();\n };\n\n @Override\n public Integer deleteByIds(\n EmployeeId[] ids,\n Connection c\n ) {\n var count = 0;\n for (var id : ids) {\n if (Optional.ofNullable(map.remove(id)).isPresent()) {\n count = count + 1;;\n };\n };\n return count;\n };\n\n @Override\n public EmployeeRow insert(\n EmployeeRow unsaved,\n Connection c\n ) {\n if (map.containsKey(unsaved.id())) {\n throw new RuntimeException(\"id \" + unsaved.id() + \" already exists\");\n };\n map.put(unsaved.id(), unsaved);\n return unsaved;\n };\n\n @Override\n public EmployeeRow insert(\n EmployeeRowUnsaved unsaved,\n Connection c\n ) {\n return insert(toRow.apply(unsaved), c);\n };\n\n @Override\n public SelectBuilder select() {\n return new SelectBuilderMock<>(EmployeeFields.structure(), () -> new ArrayList<>(map.values()), SelectParams.empty());\n };\n\n @Override\n public List selectAll(Connection c) {\n return new ArrayList<>(map.values());\n };\n\n @Override\n public Optional selectById(\n EmployeeId id,\n Connection c\n ) {\n return Optional.ofNullable(map.get(id));\n };\n\n @Override\n public List selectByIds(\n EmployeeId[] ids,\n Connection c\n ) {\n var result = new ArrayList();\n for (var id : ids) {\n var opt = Optional.ofNullable(map.get(id));\n if (opt.isPresent()) {\n result.add(opt.get());\n };\n };\n return result;\n };\n\n @Override\n public Map selectByIdsTracked(\n EmployeeId[] ids,\n Connection c\n ) {\n return selectByIds(ids, c).stream().collect(Collectors.toMap((EmployeeRow row) -> row.id(), Function.identity()));\n };\n\n @Override\n public Optional selectByUniqueEmail(\n String email,\n Connection c\n ) {\n return new ArrayList<>(map.values()).stream().filter(v -> email.equals(v.email())).findFirst();\n };\n\n @Override\n public UpdateBuilder update() {\n return new UpdateBuilderMock<>(EmployeeFields.structure(), () -> new ArrayList<>(map.values()), UpdateParams.empty(), row -> row);\n };\n\n @Override\n public Boolean update(\n EmployeeRow row,\n Connection c\n ) {\n var shouldUpdate = Optional.ofNullable(map.get(row.id())).filter(oldRow -> !oldRow.equals(row)).isPresent();\n if (shouldUpdate) {\n map.put(row.id(), row);;\n };\n return shouldUpdate;\n };\n\n @Override\n public EmployeeRow upsert(\n EmployeeRow unsaved,\n Connection c\n ) {\n map.put(unsaved.id(), unsaved);\n return unsaved;\n };\n\n @Override\n public List upsertBatch(\n Iterator unsaved,\n Connection c\n ) {\n var result = new ArrayList();\n while (unsaved.hasNext()) {\n var row = unsaved.next();\n map.put(row.id(), row);\n result.add(row);\n };\n return result;\n };\n}", - "EmployeeFields": "package showcase.showcase.employee;\n\nimport dev.typr.foundations.OracleTypes;\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.data.Json;\nimport dev.typr.foundations.data.OracleIntervalDS;\nimport dev.typr.foundations.data.OracleIntervalYM;\nimport dev.typr.foundations.dsl.FieldsExpr;\nimport dev.typr.foundations.dsl.ForeignKey;\nimport dev.typr.foundations.dsl.Path;\nimport dev.typr.foundations.dsl.RelationStructure;\nimport dev.typr.foundations.dsl.SqlExpr.Field;\nimport dev.typr.foundations.dsl.SqlExpr.FieldLike;\nimport dev.typr.foundations.dsl.SqlExpr.IdField;\nimport dev.typr.foundations.dsl.SqlExpr.OptField;\nimport java.math.BigDecimal;\nimport java.time.LocalDateTime;\nimport java.util.List;\nimport java.util.Optional;\nimport showcase.showcase.department.DepartmentFields;\nimport showcase.showcase.department.DepartmentId;\nimport showcase.showcase.department.DepartmentRow;\n\npublic interface EmployeeFields extends FieldsExpr {\n record Impl(List _path) implements EmployeeFields, RelationStructure {\n @Override\n public IdField id() {\n return new IdField(_path, \"id\", EmployeeRow::id, Optional.empty(), Optional.empty(), (row, value) -> row.withId(value), EmployeeId.oracleType);\n };\n\n @Override\n public Field departmentId() {\n return new Field(_path, \"department_id\", EmployeeRow::departmentId, Optional.empty(), Optional.empty(), (row, value) -> row.withDepartmentId(value), DepartmentId.oracleType);\n };\n\n @Override\n public OptField managerId() {\n return new OptField(_path, \"manager_id\", EmployeeRow::managerId, Optional.empty(), Optional.empty(), (row, value) -> row.withManagerId(value), EmployeeId.oracleType);\n };\n\n @Override\n public Field email() {\n return new Field(_path, \"email\", EmployeeRow::email, Optional.empty(), Optional.empty(), (row, value) -> row.withEmail(value), OracleTypes.varchar2);\n };\n\n @Override\n public Field firstName() {\n return new Field(_path, \"first_name\", EmployeeRow::firstName, Optional.empty(), Optional.empty(), (row, value) -> row.withFirstName(value), OracleTypes.varchar2);\n };\n\n @Override\n public Field lastName() {\n return new Field(_path, \"last_name\", EmployeeRow::lastName, Optional.empty(), Optional.empty(), (row, value) -> row.withLastName(value), OracleTypes.varchar2);\n };\n\n @Override\n public OptField salary() {\n return new OptField(_path, \"salary\", EmployeeRow::salary, Optional.empty(), Optional.empty(), (row, value) -> row.withSalary(value), OracleTypes.number);\n };\n\n @Override\n public OptField hiredAt() {\n return new OptField(_path, \"hired_at\", EmployeeRow::hiredAt, Optional.empty(), Optional.empty(), (row, value) -> row.withHiredAt(value), OracleTypes.date);\n };\n\n @Override\n public OptField active() {\n return new OptField(_path, \"active\", EmployeeRow::active, Optional.empty(), Optional.empty(), (row, value) -> row.withActive(value), OracleTypes.number);\n };\n\n @Override\n public OptField createdAt() {\n return new OptField(_path, \"created_at\", EmployeeRow::createdAt, Optional.empty(), Optional.empty(), (row, value) -> row.withCreatedAt(value), OracleTypes.timestamp);\n };\n\n @Override\n public OptField metadata() {\n return new OptField(_path, \"metadata\", EmployeeRow::metadata, Optional.empty(), Optional.empty(), (row, value) -> row.withMetadata(value), OracleTypes.json);\n };\n\n @Override\n public OptField resume() {\n return new OptField(_path, \"resume\", EmployeeRow::resume, Optional.empty(), Optional.empty(), (row, value) -> row.withResume(value), OracleTypes.clob);\n };\n\n @Override\n public OptField photo() {\n return new OptField(_path, \"photo\", EmployeeRow::photo, Optional.empty(), Optional.empty(), (row, value) -> row.withPhoto(value), OracleTypes.blob);\n };\n\n @Override\n public OptField probationPeriod() {\n return new OptField(_path, \"probation_period\", EmployeeRow::probationPeriod, Optional.empty(), Optional.empty(), (row, value) -> row.withProbationPeriod(value), OracleTypes.intervalYearToMonth);\n };\n\n @Override\n public OptField shiftDuration() {\n return new OptField(_path, \"shift_duration\", EmployeeRow::shiftDuration, Optional.empty(), Optional.empty(), (row, value) -> row.withShiftDuration(value), OracleTypes.intervalDayToSecond);\n };\n\n @Override\n public List> columns() {\n return java.util.List.of(this.id(), this.departmentId(), this.managerId(), this.email(), this.firstName(), this.lastName(), this.salary(), this.hiredAt(), this.active(), this.createdAt(), this.metadata(), this.resume(), this.photo(), this.probationPeriod(), this.shiftDuration());\n };\n\n @Override\n public RelationStructure withPaths(List _path) {\n return new Impl(_path);\n };\n };\n\n static Impl structure() {\n return new Impl(java.util.Collections.emptyList());\n };\n\n IdField id();\n\n Field departmentId();\n\n OptField managerId();\n\n Field email();\n\n Field firstName();\n\n Field lastName();\n\n OptField salary();\n\n OptField hiredAt();\n\n OptField active();\n\n OptField createdAt();\n\n OptField metadata();\n\n OptField resume();\n\n OptField photo();\n\n OptField probationPeriod();\n\n OptField shiftDuration();\n\n default ForeignKey fkDepartment() {\n return ForeignKey.of(\"employee_department_fk\").withColumnPair(departmentId(), DepartmentFields::id);\n };\n\n default ForeignKey fkEmployee() {\n return ForeignKey.of(\"employee_manager_fk\").withColumnPair(managerId(), EmployeeFields::id);\n };\n\n @Override\n List> columns();\n\n @Override\n default RowParser rowParser() {\n return EmployeeRow._rowParser;\n };\n}", - "DepartmentRow": "package showcase.showcase.department;\n\nimport dev.typr.foundations.OracleTypes;\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport java.math.BigDecimal;\nimport java.util.Optional;\nimport showcase.showcase.company.CompanyId;\n\n/** Table: showcase.department\n * Primary key: id\n */\npublic record DepartmentRow(\n DepartmentId id,\n /** Points to {@link showcase.showcase.company.CompanyRow#id()} */\n CompanyId companyId,\n String name,\n Optional budget\n) {\n public DepartmentRow withId(DepartmentId id) {\n return new DepartmentRow(id, companyId, name, budget);\n };\n\n /** Points to {@link showcase.showcase.company.CompanyRow#id()} */\n public DepartmentRow withCompanyId(CompanyId companyId) {\n return new DepartmentRow(id, companyId, name, budget);\n };\n\n public DepartmentRow withName(String name) {\n return new DepartmentRow(id, companyId, name, budget);\n };\n\n public DepartmentRow withBudget(Optional budget) {\n return new DepartmentRow(id, companyId, name, budget);\n };\n\n public static RowParser _rowParser = RowParsers.of(DepartmentId.oracleType, CompanyId.oracleType, OracleTypes.varchar2, OracleTypes.number.opt(), DepartmentRow::new, row -> new Object[]{row.id(), row.companyId(), row.name(), row.budget()});;\n}", - "DepartmentId": "package showcase.showcase.department;\n\nimport dev.typr.foundations.OracleType;\nimport dev.typr.foundations.OracleTypes;\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport dev.typr.foundations.dsl.Bijection;\n\n/** Type for the primary key of table `showcase.department` */\npublic record DepartmentId(String value) {\n public DepartmentId withValue(String value) {\n return new DepartmentId(value);\n };\n\n @Override\n public java.lang.String toString() {\n return value.toString();\n };\n\n static public RowParser _rowParser =\n RowParsers.of(OracleTypes.varchar2.bimap(DepartmentId::new, DepartmentId::value), x -> x, id -> new Object[]{id});\n\n static public Bijection bijection =\n Bijection.of(DepartmentId::value, DepartmentId::new);\n\n static public OracleType oracleType =\n OracleTypes.varchar2.bimap(DepartmentId::new, DepartmentId::value);\n}", - "DepartmentRepo": "package showcase.showcase.department;\n\nimport dev.typr.foundations.dsl.DeleteBuilder;\nimport dev.typr.foundations.dsl.SelectBuilder;\nimport dev.typr.foundations.dsl.UpdateBuilder;\nimport java.sql.Connection;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\n\npublic interface DepartmentRepo {\n DeleteBuilder delete();\n\n Boolean deleteById(\n DepartmentId id,\n Connection c\n );\n\n Integer deleteByIds(\n DepartmentId[] ids,\n Connection c\n );\n\n DepartmentRow insert(\n DepartmentRow unsaved,\n Connection c\n );\n\n SelectBuilder select();\n\n List selectAll(Connection c);\n\n Optional selectById(\n DepartmentId id,\n Connection c\n );\n\n List selectByIds(\n DepartmentId[] ids,\n Connection c\n );\n\n Map selectByIdsTracked(\n DepartmentId[] ids,\n Connection c\n );\n\n UpdateBuilder update();\n\n Boolean update(\n DepartmentRow row,\n Connection c\n );\n\n DepartmentRow upsert(\n DepartmentRow unsaved,\n Connection c\n );\n\n List upsertBatch(\n Iterator unsaved,\n Connection c\n );\n}", - "DepartmentRepoMock": "package showcase.showcase.department;\n\nimport dev.typr.foundations.dsl.DeleteBuilder;\nimport dev.typr.foundations.dsl.DeleteBuilderMock;\nimport dev.typr.foundations.dsl.DeleteParams;\nimport dev.typr.foundations.dsl.SelectBuilder;\nimport dev.typr.foundations.dsl.SelectBuilderMock;\nimport dev.typr.foundations.dsl.SelectParams;\nimport dev.typr.foundations.dsl.UpdateBuilder;\nimport dev.typr.foundations.dsl.UpdateBuilderMock;\nimport dev.typr.foundations.dsl.UpdateParams;\nimport java.lang.RuntimeException;\nimport java.sql.Connection;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\nimport java.util.function.Function;\nimport java.util.stream.Collectors;\n\npublic record DepartmentRepoMock(HashMap map) implements DepartmentRepo {\n public DepartmentRepoMock() {\n this(new HashMap());\n };\n\n public DepartmentRepoMock withMap(HashMap map) {\n return new DepartmentRepoMock(map);\n };\n\n @Override\n public DeleteBuilder delete() {\n return new DeleteBuilderMock<>(DepartmentFields.structure(), () -> new ArrayList<>(map.values()), DeleteParams.empty(), row -> row.id(), id -> map.remove(id));\n };\n\n @Override\n public Boolean deleteById(\n DepartmentId id,\n Connection c\n ) {\n return Optional.ofNullable(map.remove(id)).isPresent();\n };\n\n @Override\n public Integer deleteByIds(\n DepartmentId[] ids,\n Connection c\n ) {\n var count = 0;\n for (var id : ids) {\n if (Optional.ofNullable(map.remove(id)).isPresent()) {\n count = count + 1;;\n };\n };\n return count;\n };\n\n @Override\n public DepartmentRow insert(\n DepartmentRow unsaved,\n Connection c\n ) {\n if (map.containsKey(unsaved.id())) {\n throw new RuntimeException(\"id \" + unsaved.id() + \" already exists\");\n };\n map.put(unsaved.id(), unsaved);\n return unsaved;\n };\n\n @Override\n public SelectBuilder select() {\n return new SelectBuilderMock<>(DepartmentFields.structure(), () -> new ArrayList<>(map.values()), SelectParams.empty());\n };\n\n @Override\n public List selectAll(Connection c) {\n return new ArrayList<>(map.values());\n };\n\n @Override\n public Optional selectById(\n DepartmentId id,\n Connection c\n ) {\n return Optional.ofNullable(map.get(id));\n };\n\n @Override\n public List selectByIds(\n DepartmentId[] ids,\n Connection c\n ) {\n var result = new ArrayList();\n for (var id : ids) {\n var opt = Optional.ofNullable(map.get(id));\n if (opt.isPresent()) {\n result.add(opt.get());\n };\n };\n return result;\n };\n\n @Override\n public Map selectByIdsTracked(\n DepartmentId[] ids,\n Connection c\n ) {\n return selectByIds(ids, c).stream().collect(Collectors.toMap((DepartmentRow row) -> row.id(), Function.identity()));\n };\n\n @Override\n public UpdateBuilder update() {\n return new UpdateBuilderMock<>(DepartmentFields.structure(), () -> new ArrayList<>(map.values()), UpdateParams.empty(), row -> row);\n };\n\n @Override\n public Boolean update(\n DepartmentRow row,\n Connection c\n ) {\n var shouldUpdate = Optional.ofNullable(map.get(row.id())).filter(oldRow -> !oldRow.equals(row)).isPresent();\n if (shouldUpdate) {\n map.put(row.id(), row);;\n };\n return shouldUpdate;\n };\n\n @Override\n public DepartmentRow upsert(\n DepartmentRow unsaved,\n Connection c\n ) {\n map.put(unsaved.id(), unsaved);\n return unsaved;\n };\n\n @Override\n public List upsertBatch(\n Iterator unsaved,\n Connection c\n ) {\n var result = new ArrayList();\n while (unsaved.hasNext()) {\n var row = unsaved.next();\n map.put(row.id(), row);\n result.add(row);\n };\n return result;\n };\n}", - "ProjectAssignmentRow": "package showcase.showcase.project_assignment;\n\nimport dev.typr.foundations.OracleTypes;\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport java.math.BigDecimal;\nimport java.time.LocalDateTime;\nimport java.util.Optional;\nimport showcase.customtypes.Defaulted;\nimport showcase.showcase.employee.EmployeeId;\nimport showcase.showcase.project.ProjectId;\n\n/** Table: showcase.project_assignment\n * Composite primary key: employee_id, project_id\n */\npublic record ProjectAssignmentRow(\n /** Points to {@link showcase.showcase.employee.EmployeeRow#id()} */\n EmployeeId employeeId,\n /** Points to {@link showcase.showcase.project.ProjectRow#id()} */\n ProjectId projectId,\n String role,\n /** Default: 0 */\n Optional hoursAllocated,\n Optional startDate,\n Optional endDate\n) {\n /** Points to {@link showcase.showcase.employee.EmployeeRow#id()} */\n public ProjectAssignmentRow withEmployeeId(EmployeeId employeeId) {\n return new ProjectAssignmentRow(employeeId, projectId, role, hoursAllocated, startDate, endDate);\n };\n\n /** Points to {@link showcase.showcase.project.ProjectRow#id()} */\n public ProjectAssignmentRow withProjectId(ProjectId projectId) {\n return new ProjectAssignmentRow(employeeId, projectId, role, hoursAllocated, startDate, endDate);\n };\n\n public ProjectAssignmentRow withRole(String role) {\n return new ProjectAssignmentRow(employeeId, projectId, role, hoursAllocated, startDate, endDate);\n };\n\n /** Default: 0 */\n public ProjectAssignmentRow withHoursAllocated(Optional hoursAllocated) {\n return new ProjectAssignmentRow(employeeId, projectId, role, hoursAllocated, startDate, endDate);\n };\n\n public ProjectAssignmentRow withStartDate(Optional startDate) {\n return new ProjectAssignmentRow(employeeId, projectId, role, hoursAllocated, startDate, endDate);\n };\n\n public ProjectAssignmentRow withEndDate(Optional endDate) {\n return new ProjectAssignmentRow(employeeId, projectId, role, hoursAllocated, startDate, endDate);\n };\n\n public static RowParser _rowParser = RowParsers.of(EmployeeId.oracleType, ProjectId.oracleType, OracleTypes.varchar2, OracleTypes.number.opt(), OracleTypes.date.opt(), OracleTypes.date.opt(), ProjectAssignmentRow::new, row -> new Object[]{row.employeeId(), row.projectId(), row.role(), row.hoursAllocated(), row.startDate(), row.endDate()});;\n\n static public ProjectAssignmentRow apply(\n ProjectAssignmentId compositeId,\n String role,\n Optional hoursAllocated,\n Optional startDate,\n Optional endDate\n ) {\n return new ProjectAssignmentRow(compositeId.employeeId(), compositeId.projectId(), role, hoursAllocated, startDate, endDate);\n };\n\n public ProjectAssignmentId compositeId() {\n return new ProjectAssignmentId(employeeId, projectId);\n };\n\n public ProjectAssignmentId id() {\n return this.compositeId();\n };\n\n public ProjectAssignmentRowUnsaved toUnsavedRow(Defaulted> hoursAllocated) {\n return new ProjectAssignmentRowUnsaved(employeeId, projectId, role, startDate, endDate, hoursAllocated);\n };\n}", - "ProjectAssignmentRowUnsaved": "package showcase.showcase.project_assignment;\n\nimport java.math.BigDecimal;\nimport java.time.LocalDateTime;\nimport java.util.Optional;\nimport showcase.customtypes.Defaulted;\nimport showcase.customtypes.Defaulted.UseDefault;\nimport showcase.showcase.employee.EmployeeId;\nimport showcase.showcase.project.ProjectId;\n\n/** This class corresponds to a row in table `showcase.project_assignment` which has not been persisted yet */\npublic record ProjectAssignmentRowUnsaved(\n /** Points to {@link showcase.showcase.employee.EmployeeRow#id()} */\n EmployeeId employeeId,\n /** Points to {@link showcase.showcase.project.ProjectRow#id()} */\n ProjectId projectId,\n String role,\n Optional startDate,\n Optional endDate,\n /** Default: 0 */\n Defaulted> hoursAllocated\n) {\n public ProjectAssignmentRowUnsaved(\n /** Points to {@link showcase.showcase.employee.EmployeeRow#id()} */\n EmployeeId employeeId,\n /** Points to {@link showcase.showcase.project.ProjectRow#id()} */\n ProjectId projectId,\n String role\n ) {\n this(employeeId, projectId, role, Optional.empty(), Optional.empty(), new UseDefault<>());\n };\n\n /** Points to {@link showcase.showcase.employee.EmployeeRow#id()} */\n public ProjectAssignmentRowUnsaved withEmployeeId(EmployeeId employeeId) {\n return new ProjectAssignmentRowUnsaved(employeeId, projectId, role, startDate, endDate, hoursAllocated);\n };\n\n /** Points to {@link showcase.showcase.project.ProjectRow#id()} */\n public ProjectAssignmentRowUnsaved withProjectId(ProjectId projectId) {\n return new ProjectAssignmentRowUnsaved(employeeId, projectId, role, startDate, endDate, hoursAllocated);\n };\n\n public ProjectAssignmentRowUnsaved withRole(String role) {\n return new ProjectAssignmentRowUnsaved(employeeId, projectId, role, startDate, endDate, hoursAllocated);\n };\n\n public ProjectAssignmentRowUnsaved withStartDate(Optional startDate) {\n return new ProjectAssignmentRowUnsaved(employeeId, projectId, role, startDate, endDate, hoursAllocated);\n };\n\n public ProjectAssignmentRowUnsaved withEndDate(Optional endDate) {\n return new ProjectAssignmentRowUnsaved(employeeId, projectId, role, startDate, endDate, hoursAllocated);\n };\n\n /** Default: 0 */\n public ProjectAssignmentRowUnsaved withHoursAllocated(Defaulted> hoursAllocated) {\n return new ProjectAssignmentRowUnsaved(employeeId, projectId, role, startDate, endDate, hoursAllocated);\n };\n\n public ProjectAssignmentRow toRow(java.util.function.Supplier> hoursAllocatedDefault) {\n return new ProjectAssignmentRow(employeeId, projectId, role, hoursAllocated.getOrElse(hoursAllocatedDefault), startDate, endDate);\n };\n}", - "ProjectAssignmentId": "package showcase.showcase.project_assignment;\n\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport showcase.showcase.employee.EmployeeId;\nimport showcase.showcase.project.ProjectId;\n\n/** Type for the composite primary key of table `showcase.project_assignment` */\npublic record ProjectAssignmentId(\n EmployeeId employeeId,\n ProjectId projectId\n) {\n public ProjectAssignmentId withEmployeeId(EmployeeId employeeId) {\n return new ProjectAssignmentId(employeeId, projectId);\n };\n\n public ProjectAssignmentId withProjectId(ProjectId projectId) {\n return new ProjectAssignmentId(employeeId, projectId);\n };\n\n public static RowParser _rowParser = RowParsers.of(EmployeeId.oracleType, ProjectId.oracleType, ProjectAssignmentId::new, row -> new Object[]{row.employeeId(), row.projectId()});;\n}", - "ProjectAssignmentRepo": "package showcase.showcase.project_assignment;\n\nimport dev.typr.foundations.dsl.DeleteBuilder;\nimport dev.typr.foundations.dsl.SelectBuilder;\nimport dev.typr.foundations.dsl.UpdateBuilder;\nimport java.sql.Connection;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\n\npublic interface ProjectAssignmentRepo {\n DeleteBuilder delete();\n\n Boolean deleteById(\n ProjectAssignmentId compositeId,\n Connection c\n );\n\n Integer deleteByIds(\n ProjectAssignmentId[] compositeIds,\n Connection c\n );\n\n ProjectAssignmentRow insert(\n ProjectAssignmentRow unsaved,\n Connection c\n );\n\n ProjectAssignmentRow insert(\n ProjectAssignmentRowUnsaved unsaved,\n Connection c\n );\n\n SelectBuilder select();\n\n List selectAll(Connection c);\n\n Optional selectById(\n ProjectAssignmentId compositeId,\n Connection c\n );\n\n List selectByIds(\n ProjectAssignmentId[] compositeIds,\n Connection c\n );\n\n Map selectByIdsTracked(\n ProjectAssignmentId[] compositeIds,\n Connection c\n );\n\n UpdateBuilder update();\n\n Boolean update(\n ProjectAssignmentRow row,\n Connection c\n );\n\n ProjectAssignmentRow upsert(\n ProjectAssignmentRow unsaved,\n Connection c\n );\n\n List upsertBatch(\n Iterator unsaved,\n Connection c\n );\n}", - "ProjectRow": "package showcase.showcase.project;\n\nimport dev.typr.foundations.OracleTypes;\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport dev.typr.foundations.data.Json;\nimport dev.typr.foundations.data.OracleIntervalDS;\nimport dev.typr.foundations.data.OracleIntervalYM;\nimport java.math.BigDecimal;\nimport java.time.LocalDateTime;\nimport java.util.Optional;\nimport showcase.customtypes.Defaulted;\n\n/** Table: showcase.project\n * Primary key: id\n */\npublic record ProjectRow(\n ProjectId id,\n String name,\n Optional description,\n Optional startDate,\n Optional endDate,\n Optional budget,\n /** Default: 'planning' */\n Optional status,\n /** Default: CURRENT_TIMESTAMP */\n Optional createdAt,\n Optional metadata,\n Optional descriptionLong,\n Optional attachments,\n Optional estimatedDuration,\n Optional actualDuration,\n Optional xmlPlan\n) {\n public ProjectRow withId(ProjectId id) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, metadata, descriptionLong, attachments, estimatedDuration, actualDuration, xmlPlan);\n };\n\n public ProjectRow withName(String name) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, metadata, descriptionLong, attachments, estimatedDuration, actualDuration, xmlPlan);\n };\n\n public ProjectRow withDescription(Optional description) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, metadata, descriptionLong, attachments, estimatedDuration, actualDuration, xmlPlan);\n };\n\n public ProjectRow withStartDate(Optional startDate) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, metadata, descriptionLong, attachments, estimatedDuration, actualDuration, xmlPlan);\n };\n\n public ProjectRow withEndDate(Optional endDate) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, metadata, descriptionLong, attachments, estimatedDuration, actualDuration, xmlPlan);\n };\n\n public ProjectRow withBudget(Optional budget) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, metadata, descriptionLong, attachments, estimatedDuration, actualDuration, xmlPlan);\n };\n\n /** Default: 'planning' */\n public ProjectRow withStatus(Optional status) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, metadata, descriptionLong, attachments, estimatedDuration, actualDuration, xmlPlan);\n };\n\n /** Default: CURRENT_TIMESTAMP */\n public ProjectRow withCreatedAt(Optional createdAt) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, metadata, descriptionLong, attachments, estimatedDuration, actualDuration, xmlPlan);\n };\n\n public ProjectRow withMetadata(Optional metadata) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, metadata, descriptionLong, attachments, estimatedDuration, actualDuration, xmlPlan);\n };\n\n public ProjectRow withDescriptionLong(Optional descriptionLong) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, metadata, descriptionLong, attachments, estimatedDuration, actualDuration, xmlPlan);\n };\n\n public ProjectRow withAttachments(Optional attachments) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, metadata, descriptionLong, attachments, estimatedDuration, actualDuration, xmlPlan);\n };\n\n public ProjectRow withEstimatedDuration(Optional estimatedDuration) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, metadata, descriptionLong, attachments, estimatedDuration, actualDuration, xmlPlan);\n };\n\n public ProjectRow withActualDuration(Optional actualDuration) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, metadata, descriptionLong, attachments, estimatedDuration, actualDuration, xmlPlan);\n };\n\n public ProjectRow withXmlPlan(Optional xmlPlan) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, metadata, descriptionLong, attachments, estimatedDuration, actualDuration, xmlPlan);\n };\n\n public static RowParser _rowParser = RowParsers.of(ProjectId.oracleType, OracleTypes.varchar2, OracleTypes.varchar2.opt(), OracleTypes.date.opt(), OracleTypes.date.opt(), OracleTypes.number.opt(), OracleTypes.varchar2.opt(), OracleTypes.timestamp.opt(), OracleTypes.json.opt(), OracleTypes.clob.opt(), OracleTypes.blob.opt(), OracleTypes.intervalYearToMonth.opt(), OracleTypes.intervalDayToSecond.opt(), OracleTypes.xmlType.opt(), ProjectRow::new, row -> new Object[]{row.id(), row.name(), row.description(), row.startDate(), row.endDate(), row.budget(), row.status(), row.createdAt(), row.metadata(), row.descriptionLong(), row.attachments(), row.estimatedDuration(), row.actualDuration(), row.xmlPlan()});;\n\n public ProjectRowUnsaved toUnsavedRow(\n Defaulted> status,\n Defaulted> createdAt\n ) {\n return new ProjectRowUnsaved(id, name, description, startDate, endDate, budget, metadata, descriptionLong, attachments, estimatedDuration, actualDuration, xmlPlan, status, createdAt);\n };\n}", - "ProjectId": "package showcase.showcase.project;\n\nimport dev.typr.foundations.OracleType;\nimport dev.typr.foundations.OracleTypes;\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport dev.typr.foundations.dsl.Bijection;\n\n/** Type for the primary key of table `showcase.project` */\npublic record ProjectId(String value) {\n public ProjectId withValue(String value) {\n return new ProjectId(value);\n };\n\n @Override\n public java.lang.String toString() {\n return value.toString();\n };\n\n static public RowParser _rowParser =\n RowParsers.of(OracleTypes.varchar2.bimap(ProjectId::new, ProjectId::value), x -> x, id -> new Object[]{id});\n\n static public Bijection bijection =\n Bijection.of(ProjectId::value, ProjectId::new);\n\n static public OracleType oracleType =\n OracleTypes.varchar2.bimap(ProjectId::new, ProjectId::value);\n}", - "EmployeeSummaryViewRow": "package showcase.showcase.employee_summary;\n\nimport dev.typr.foundations.OracleTypes;\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport java.math.BigDecimal;\nimport java.time.LocalDateTime;\nimport java.util.Optional;\nimport showcase.showcase.company.CompanyId;\nimport showcase.showcase.department.DepartmentId;\nimport showcase.showcase.employee.EmployeeId;\n\n/** View: showcase.employee_summary\n * Summary view of employees with their department and company information\n */\npublic record EmployeeSummaryViewRow(\n /** Points to {@link showcase.showcase.employee.EmployeeRow#id()} */\n EmployeeId employeeId,\n String email,\n String firstName,\n String lastName,\n Optional salary,\n Optional hiredAt,\n Optional active,\n /** Points to {@link showcase.showcase.department.DepartmentRow#id()} */\n DepartmentId departmentId,\n String departmentName,\n Optional departmentBudget,\n /** Points to {@link showcase.showcase.company.CompanyRow#id()} */\n CompanyId companyId,\n String companyName,\n Optional managerId,\n Optional managerFirstName,\n Optional managerLastName\n) {\n /** Points to {@link showcase.showcase.employee.EmployeeRow#id()} */\n public EmployeeSummaryViewRow withEmployeeId(EmployeeId employeeId) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withEmail(String email) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withFirstName(String firstName) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withLastName(String lastName) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withSalary(Optional salary) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withHiredAt(Optional hiredAt) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withActive(Optional active) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n /** Points to {@link showcase.showcase.department.DepartmentRow#id()} */\n public EmployeeSummaryViewRow withDepartmentId(DepartmentId departmentId) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withDepartmentName(String departmentName) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withDepartmentBudget(Optional departmentBudget) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n /** Points to {@link showcase.showcase.company.CompanyRow#id()} */\n public EmployeeSummaryViewRow withCompanyId(CompanyId companyId) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withCompanyName(String companyName) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withManagerId(Optional managerId) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withManagerFirstName(Optional managerFirstName) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withManagerLastName(Optional managerLastName) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public static RowParser _rowParser = RowParsers.of(EmployeeId.oracleType, OracleTypes.varchar2, OracleTypes.varchar2, OracleTypes.varchar2, OracleTypes.number.opt(), OracleTypes.date.opt(), OracleTypes.number.opt(), DepartmentId.oracleType, OracleTypes.varchar2, OracleTypes.number.opt(), CompanyId.oracleType, OracleTypes.varchar2, OracleTypes.varchar2.opt(), OracleTypes.varchar2.opt(), OracleTypes.varchar2.opt(), EmployeeSummaryViewRow::new, row -> new Object[]{row.employeeId(), row.email(), row.firstName(), row.lastName(), row.salary(), row.hiredAt(), row.active(), row.departmentId(), row.departmentName(), row.departmentBudget(), row.companyId(), row.companyName(), row.managerId(), row.managerFirstName(), row.managerLastName()});;\n}", - "EmployeeSummaryViewRepo": "package showcase.showcase.employee_summary;\n\nimport dev.typr.foundations.dsl.SelectBuilder;\nimport java.sql.Connection;\nimport java.util.List;\n\npublic interface EmployeeSummaryViewRepo {\n SelectBuilder select();\n\n List selectAll(Connection c);\n}", - "CustomerOrderRow": "package showcase.showcase.customer_order;\n\nimport dev.typr.foundations.OracleTypes;\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport dev.typr.foundations.data.Json;\nimport dev.typr.foundations.data.OracleIntervalDS;\nimport java.math.BigDecimal;\nimport java.time.LocalDateTime;\nimport java.util.Optional;\nimport showcase.customtypes.Defaulted;\nimport showcase.showcase.address.AddressId;\nimport showcase.showcase.customer.CustomerId;\n\n/** Table: showcase.customer_order\n * Primary key: id\n */\npublic record CustomerOrderRow(\n CustomerOrderId id,\n /** Points to {@link showcase.showcase.customer.CustomerRow#id()} */\n CustomerId customerId,\n /** Points to {@link showcase.showcase.address.AddressRow#id()} */\n Optional shippingAddressId,\n /** Points to {@link showcase.showcase.address.AddressRow#id()} */\n Optional billingAddressId,\n /** Default: 'pending' */\n Optional status,\n BigDecimal subtotal,\n /** Default: 0 */\n Optional tax,\n /** Default: 0 */\n Optional shipping,\n BigDecimal total,\n Optional notes,\n /** Default: CURRENT_TIMESTAMP */\n Optional createdAt,\n Optional shippedAt,\n Optional deliveredAt,\n Optional metadata,\n Optional notesExtended,\n Optional receiptData,\n Optional processingTime,\n Optional xmlInvoice\n) {\n public CustomerOrderRow withId(CustomerOrderId id) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, metadata, notesExtended, receiptData, processingTime, xmlInvoice);\n };\n\n /** Points to {@link showcase.showcase.customer.CustomerRow#id()} */\n public CustomerOrderRow withCustomerId(CustomerId customerId) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, metadata, notesExtended, receiptData, processingTime, xmlInvoice);\n };\n\n /** Points to {@link showcase.showcase.address.AddressRow#id()} */\n public CustomerOrderRow withShippingAddressId(Optional shippingAddressId) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, metadata, notesExtended, receiptData, processingTime, xmlInvoice);\n };\n\n /** Points to {@link showcase.showcase.address.AddressRow#id()} */\n public CustomerOrderRow withBillingAddressId(Optional billingAddressId) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, metadata, notesExtended, receiptData, processingTime, xmlInvoice);\n };\n\n /** Default: 'pending' */\n public CustomerOrderRow withStatus(Optional status) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, metadata, notesExtended, receiptData, processingTime, xmlInvoice);\n };\n\n public CustomerOrderRow withSubtotal(BigDecimal subtotal) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, metadata, notesExtended, receiptData, processingTime, xmlInvoice);\n };\n\n /** Default: 0 */\n public CustomerOrderRow withTax(Optional tax) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, metadata, notesExtended, receiptData, processingTime, xmlInvoice);\n };\n\n /** Default: 0 */\n public CustomerOrderRow withShipping(Optional shipping) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, metadata, notesExtended, receiptData, processingTime, xmlInvoice);\n };\n\n public CustomerOrderRow withTotal(BigDecimal total) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, metadata, notesExtended, receiptData, processingTime, xmlInvoice);\n };\n\n public CustomerOrderRow withNotes(Optional notes) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, metadata, notesExtended, receiptData, processingTime, xmlInvoice);\n };\n\n /** Default: CURRENT_TIMESTAMP */\n public CustomerOrderRow withCreatedAt(Optional createdAt) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, metadata, notesExtended, receiptData, processingTime, xmlInvoice);\n };\n\n public CustomerOrderRow withShippedAt(Optional shippedAt) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, metadata, notesExtended, receiptData, processingTime, xmlInvoice);\n };\n\n public CustomerOrderRow withDeliveredAt(Optional deliveredAt) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, metadata, notesExtended, receiptData, processingTime, xmlInvoice);\n };\n\n public CustomerOrderRow withMetadata(Optional metadata) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, metadata, notesExtended, receiptData, processingTime, xmlInvoice);\n };\n\n public CustomerOrderRow withNotesExtended(Optional notesExtended) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, metadata, notesExtended, receiptData, processingTime, xmlInvoice);\n };\n\n public CustomerOrderRow withReceiptData(Optional receiptData) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, metadata, notesExtended, receiptData, processingTime, xmlInvoice);\n };\n\n public CustomerOrderRow withProcessingTime(Optional processingTime) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, metadata, notesExtended, receiptData, processingTime, xmlInvoice);\n };\n\n public CustomerOrderRow withXmlInvoice(Optional xmlInvoice) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, metadata, notesExtended, receiptData, processingTime, xmlInvoice);\n };\n\n public static RowParser _rowParser = RowParsers.of(CustomerOrderId.oracleType, CustomerId.oracleType, AddressId.oracleType.opt(), AddressId.oracleType.opt(), OracleTypes.varchar2.opt(), OracleTypes.number, OracleTypes.number.opt(), OracleTypes.number.opt(), OracleTypes.number, OracleTypes.varchar2.opt(), OracleTypes.timestamp.opt(), OracleTypes.timestamp.opt(), OracleTypes.timestamp.opt(), OracleTypes.json.opt(), OracleTypes.clob.opt(), OracleTypes.blob.opt(), OracleTypes.intervalDayToSecond.opt(), OracleTypes.xmlType.opt(), CustomerOrderRow::new, row -> new Object[]{row.id(), row.customerId(), row.shippingAddressId(), row.billingAddressId(), row.status(), row.subtotal(), row.tax(), row.shipping(), row.total(), row.notes(), row.createdAt(), row.shippedAt(), row.deliveredAt(), row.metadata(), row.notesExtended(), row.receiptData(), row.processingTime(), row.xmlInvoice()});;\n\n public CustomerOrderRowUnsaved toUnsavedRow(\n Defaulted> status,\n Defaulted> tax,\n Defaulted> shipping,\n Defaulted> createdAt\n ) {\n return new CustomerOrderRowUnsaved(id, customerId, shippingAddressId, billingAddressId, subtotal, total, notes, shippedAt, deliveredAt, metadata, notesExtended, receiptData, processingTime, xmlInvoice, status, tax, shipping, createdAt);\n };\n}", - "CustomerOrderRepo": "package showcase.showcase.customer_order;\n\nimport dev.typr.foundations.dsl.DeleteBuilder;\nimport dev.typr.foundations.dsl.SelectBuilder;\nimport dev.typr.foundations.dsl.UpdateBuilder;\nimport java.sql.Connection;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\n\npublic interface CustomerOrderRepo {\n DeleteBuilder delete();\n\n Boolean deleteById(\n CustomerOrderId id,\n Connection c\n );\n\n Integer deleteByIds(\n CustomerOrderId[] ids,\n Connection c\n );\n\n CustomerOrderRow insert(\n CustomerOrderRow unsaved,\n Connection c\n );\n\n CustomerOrderRow insert(\n CustomerOrderRowUnsaved unsaved,\n Connection c\n );\n\n SelectBuilder select();\n\n List selectAll(Connection c);\n\n Optional selectById(\n CustomerOrderId id,\n Connection c\n );\n\n List selectByIds(\n CustomerOrderId[] ids,\n Connection c\n );\n\n Map selectByIdsTracked(\n CustomerOrderId[] ids,\n Connection c\n );\n\n UpdateBuilder update();\n\n Boolean update(\n CustomerOrderRow row,\n Connection c\n );\n\n CustomerOrderRow upsert(\n CustomerOrderRow unsaved,\n Connection c\n );\n\n List upsertBatch(\n Iterator unsaved,\n Connection c\n );\n}", - "OrderItemRow": "package showcase.showcase.order_item;\n\nimport dev.typr.foundations.OracleTypes;\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport java.math.BigDecimal;\nimport java.util.Optional;\nimport showcase.customtypes.Defaulted;\nimport showcase.showcase.customer_order.CustomerOrderId;\nimport showcase.showcase.product.ProductId;\n\n/** Table: showcase.order_item\n * Composite primary key: order_id, product_id\n */\npublic record OrderItemRow(\n /** Points to {@link showcase.showcase.customer_order.CustomerOrderRow#id()} */\n CustomerOrderId orderId,\n /** Points to {@link showcase.showcase.product.ProductRow#id()} */\n ProductId productId,\n BigDecimal quantity,\n BigDecimal unitPrice,\n /** Default: 0 */\n Optional discount\n) {\n /** Points to {@link showcase.showcase.customer_order.CustomerOrderRow#id()} */\n public OrderItemRow withOrderId(CustomerOrderId orderId) {\n return new OrderItemRow(orderId, productId, quantity, unitPrice, discount);\n };\n\n /** Points to {@link showcase.showcase.product.ProductRow#id()} */\n public OrderItemRow withProductId(ProductId productId) {\n return new OrderItemRow(orderId, productId, quantity, unitPrice, discount);\n };\n\n public OrderItemRow withQuantity(BigDecimal quantity) {\n return new OrderItemRow(orderId, productId, quantity, unitPrice, discount);\n };\n\n public OrderItemRow withUnitPrice(BigDecimal unitPrice) {\n return new OrderItemRow(orderId, productId, quantity, unitPrice, discount);\n };\n\n /** Default: 0 */\n public OrderItemRow withDiscount(Optional discount) {\n return new OrderItemRow(orderId, productId, quantity, unitPrice, discount);\n };\n\n public static RowParser _rowParser = RowParsers.of(CustomerOrderId.oracleType, ProductId.oracleType, OracleTypes.number, OracleTypes.number, OracleTypes.number.opt(), OrderItemRow::new, row -> new Object[]{row.orderId(), row.productId(), row.quantity(), row.unitPrice(), row.discount()});;\n\n static public OrderItemRow apply(\n OrderItemId compositeId,\n BigDecimal quantity,\n BigDecimal unitPrice,\n Optional discount\n ) {\n return new OrderItemRow(compositeId.orderId(), compositeId.productId(), quantity, unitPrice, discount);\n };\n\n public OrderItemId compositeId() {\n return new OrderItemId(orderId, productId);\n };\n\n public OrderItemId id() {\n return this.compositeId();\n };\n\n public OrderItemRowUnsaved toUnsavedRow(Defaulted> discount) {\n return new OrderItemRowUnsaved(orderId, productId, quantity, unitPrice, discount);\n };\n}", - "OrderItemId": "package showcase.showcase.order_item;\n\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport showcase.showcase.customer_order.CustomerOrderId;\nimport showcase.showcase.product.ProductId;\n\n/** Type for the composite primary key of table `showcase.order_item` */\npublic record OrderItemId(\n CustomerOrderId orderId,\n ProductId productId\n) {\n public OrderItemId withOrderId(CustomerOrderId orderId) {\n return new OrderItemId(orderId, productId);\n };\n\n public OrderItemId withProductId(ProductId productId) {\n return new OrderItemId(orderId, productId);\n };\n\n public static RowParser _rowParser = RowParsers.of(CustomerOrderId.oracleType, ProductId.oracleType, OrderItemId::new, row -> new Object[]{row.orderId(), row.productId()});;\n}", - "ProductRow": "package showcase.showcase.product;\n\nimport dev.typr.foundations.OracleTypes;\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport dev.typr.foundations.data.Json;\nimport java.math.BigDecimal;\nimport java.time.LocalDateTime;\nimport java.util.Optional;\nimport showcase.customtypes.Defaulted;\nimport showcase.showcase.category.CategoryId;\n\n/** Table: showcase.product\n * Primary key: id\n */\npublic record ProductRow(\n ProductId id,\n /** Points to {@link showcase.showcase.category.CategoryRow#id()} */\n Optional categoryId,\n String name,\n String sku,\n BigDecimal price,\n Optional cost,\n /** Default: true */\n Optional inStock,\n /** Default: 0 */\n Optional quantity,\n Optional weight,\n /** Default: CURRENT_TIMESTAMP */\n Optional createdAt,\n Optional attributes,\n Optional specifications,\n Optional descriptionLong,\n Optional thumbnail,\n Optional xmlData\n) {\n public ProductRow withId(ProductId id) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, attributes, specifications, descriptionLong, thumbnail, xmlData);\n };\n\n /** Points to {@link showcase.showcase.category.CategoryRow#id()} */\n public ProductRow withCategoryId(Optional categoryId) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, attributes, specifications, descriptionLong, thumbnail, xmlData);\n };\n\n public ProductRow withName(String name) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, attributes, specifications, descriptionLong, thumbnail, xmlData);\n };\n\n public ProductRow withSku(String sku) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, attributes, specifications, descriptionLong, thumbnail, xmlData);\n };\n\n public ProductRow withPrice(BigDecimal price) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, attributes, specifications, descriptionLong, thumbnail, xmlData);\n };\n\n public ProductRow withCost(Optional cost) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, attributes, specifications, descriptionLong, thumbnail, xmlData);\n };\n\n /** Default: true */\n public ProductRow withInStock(Optional inStock) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, attributes, specifications, descriptionLong, thumbnail, xmlData);\n };\n\n /** Default: 0 */\n public ProductRow withQuantity(Optional quantity) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, attributes, specifications, descriptionLong, thumbnail, xmlData);\n };\n\n public ProductRow withWeight(Optional weight) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, attributes, specifications, descriptionLong, thumbnail, xmlData);\n };\n\n /** Default: CURRENT_TIMESTAMP */\n public ProductRow withCreatedAt(Optional createdAt) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, attributes, specifications, descriptionLong, thumbnail, xmlData);\n };\n\n public ProductRow withAttributes(Optional attributes) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, attributes, specifications, descriptionLong, thumbnail, xmlData);\n };\n\n public ProductRow withSpecifications(Optional specifications) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, attributes, specifications, descriptionLong, thumbnail, xmlData);\n };\n\n public ProductRow withDescriptionLong(Optional descriptionLong) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, attributes, specifications, descriptionLong, thumbnail, xmlData);\n };\n\n public ProductRow withThumbnail(Optional thumbnail) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, attributes, specifications, descriptionLong, thumbnail, xmlData);\n };\n\n public ProductRow withXmlData(Optional xmlData) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, attributes, specifications, descriptionLong, thumbnail, xmlData);\n };\n\n public static RowParser _rowParser = RowParsers.of(ProductId.oracleType, CategoryId.oracleType.opt(), OracleTypes.varchar2, OracleTypes.varchar2, OracleTypes.number, OracleTypes.number.opt(), OracleTypes.number.opt(), OracleTypes.number.opt(), OracleTypes.number.opt(), OracleTypes.timestamp.opt(), OracleTypes.json.opt(), OracleTypes.clob.opt(), OracleTypes.clob.opt(), OracleTypes.blob.opt(), OracleTypes.xmlType.opt(), ProductRow::new, row -> new Object[]{row.id(), row.categoryId(), row.name(), row.sku(), row.price(), row.cost(), row.inStock(), row.quantity(), row.weight(), row.createdAt(), row.attributes(), row.specifications(), row.descriptionLong(), row.thumbnail(), row.xmlData()});;\n\n public ProductRowUnsaved toUnsavedRow(\n Defaulted> inStock,\n Defaulted> quantity,\n Defaulted> createdAt\n ) {\n return new ProductRowUnsaved(id, categoryId, name, sku, price, cost, weight, attributes, specifications, descriptionLong, thumbnail, xmlData, inStock, quantity, createdAt);\n };\n}", - "ProductId": "package showcase.showcase.product;\n\nimport dev.typr.foundations.OracleType;\nimport dev.typr.foundations.OracleTypes;\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport dev.typr.foundations.dsl.Bijection;\n\n/** Type for the primary key of table `showcase.product` */\npublic record ProductId(String value) {\n public ProductId withValue(String value) {\n return new ProductId(value);\n };\n\n @Override\n public java.lang.String toString() {\n return value.toString();\n };\n\n static public RowParser _rowParser =\n RowParsers.of(OracleTypes.varchar2.bimap(ProductId::new, ProductId::value), x -> x, id -> new Object[]{id});\n\n static public Bijection bijection =\n Bijection.of(ProductId::value, ProductId::new);\n\n static public OracleType oracleType =\n OracleTypes.varchar2.bimap(ProductId::new, ProductId::value);\n}", - "CategoryRow": "package showcase.showcase.category;\n\nimport dev.typr.foundations.OracleTypes;\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport java.util.Optional;\n\n/** Table: showcase.category\n * Primary key: id\n */\npublic record CategoryRow(\n CategoryId id,\n /** Points to {@link showcase.showcase.category.CategoryRow#id()} */\n Optional parentId,\n String name,\n Optional description\n) {\n public CategoryRow withId(CategoryId id) {\n return new CategoryRow(id, parentId, name, description);\n };\n\n /** Points to {@link showcase.showcase.category.CategoryRow#id()} */\n public CategoryRow withParentId(Optional parentId) {\n return new CategoryRow(id, parentId, name, description);\n };\n\n public CategoryRow withName(String name) {\n return new CategoryRow(id, parentId, name, description);\n };\n\n public CategoryRow withDescription(Optional description) {\n return new CategoryRow(id, parentId, name, description);\n };\n\n public static RowParser _rowParser = RowParsers.of(CategoryId.oracleType, CategoryId.oracleType.opt(), OracleTypes.varchar2, OracleTypes.varchar2.opt(), CategoryRow::new, row -> new Object[]{row.id(), row.parentId(), row.name(), row.description()});;\n}", - "CategoryId": "package showcase.showcase.category;\n\nimport dev.typr.foundations.OracleType;\nimport dev.typr.foundations.OracleTypes;\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport dev.typr.foundations.dsl.Bijection;\n\n/** Type for the primary key of table `showcase.category` */\npublic record CategoryId(String value) {\n public CategoryId withValue(String value) {\n return new CategoryId(value);\n };\n\n @Override\n public java.lang.String toString() {\n return value.toString();\n };\n\n static public RowParser _rowParser =\n RowParsers.of(OracleTypes.varchar2.bimap(CategoryId::new, CategoryId::value), x -> x, id -> new Object[]{id});\n\n static public Bijection bijection =\n Bijection.of(CategoryId::value, CategoryId::new);\n\n static public OracleType oracleType =\n OracleTypes.varchar2.bimap(CategoryId::new, CategoryId::value);\n}", - "AddressRow": "package showcase.showcase.address;\n\nimport dev.typr.foundations.OracleTypes;\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport java.math.BigDecimal;\nimport java.util.Optional;\nimport showcase.customtypes.Defaulted;\nimport showcase.showcase.customer.CustomerId;\n\n/** Table: showcase.address\n * Primary key: id\n */\npublic record AddressRow(\n AddressId id,\n /** Points to {@link showcase.showcase.customer.CustomerRow#id()} */\n CustomerId customerId,\n String addressType,\n String street,\n String city,\n Optional state,\n Optional postalCode,\n String country,\n /** Default: false */\n Optional isDefault,\n Optional location,\n Optional notes\n) {\n public AddressRow withId(AddressId id) {\n return new AddressRow(id, customerId, addressType, street, city, state, postalCode, country, isDefault, location, notes);\n };\n\n /** Points to {@link showcase.showcase.customer.CustomerRow#id()} */\n public AddressRow withCustomerId(CustomerId customerId) {\n return new AddressRow(id, customerId, addressType, street, city, state, postalCode, country, isDefault, location, notes);\n };\n\n public AddressRow withAddressType(String addressType) {\n return new AddressRow(id, customerId, addressType, street, city, state, postalCode, country, isDefault, location, notes);\n };\n\n public AddressRow withStreet(String street) {\n return new AddressRow(id, customerId, addressType, street, city, state, postalCode, country, isDefault, location, notes);\n };\n\n public AddressRow withCity(String city) {\n return new AddressRow(id, customerId, addressType, street, city, state, postalCode, country, isDefault, location, notes);\n };\n\n public AddressRow withState(Optional state) {\n return new AddressRow(id, customerId, addressType, street, city, state, postalCode, country, isDefault, location, notes);\n };\n\n public AddressRow withPostalCode(Optional postalCode) {\n return new AddressRow(id, customerId, addressType, street, city, state, postalCode, country, isDefault, location, notes);\n };\n\n public AddressRow withCountry(String country) {\n return new AddressRow(id, customerId, addressType, street, city, state, postalCode, country, isDefault, location, notes);\n };\n\n /** Default: false */\n public AddressRow withIsDefault(Optional isDefault) {\n return new AddressRow(id, customerId, addressType, street, city, state, postalCode, country, isDefault, location, notes);\n };\n\n public AddressRow withLocation(Optional location) {\n return new AddressRow(id, customerId, addressType, street, city, state, postalCode, country, isDefault, location, notes);\n };\n\n public AddressRow withNotes(Optional notes) {\n return new AddressRow(id, customerId, addressType, street, city, state, postalCode, country, isDefault, location, notes);\n };\n\n public static RowParser _rowParser = RowParsers.of(AddressId.oracleType, CustomerId.oracleType, OracleTypes.varchar2, OracleTypes.varchar2, OracleTypes.varchar2, OracleTypes.varchar2.opt(), OracleTypes.varchar2.opt(), OracleTypes.varchar2, OracleTypes.number.opt(), OracleTypes.varchar2.opt(), OracleTypes.clob.opt(), AddressRow::new, row -> new Object[]{row.id(), row.customerId(), row.addressType(), row.street(), row.city(), row.state(), row.postalCode(), row.country(), row.isDefault(), row.location(), row.notes()});;\n\n public AddressRowUnsaved toUnsavedRow(Defaulted> isDefault) {\n return new AddressRowUnsaved(id, customerId, addressType, street, city, state, postalCode, country, location, notes, isDefault);\n };\n}", - "AddressId": "package showcase.showcase.address;\n\nimport dev.typr.foundations.OracleType;\nimport dev.typr.foundations.OracleTypes;\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport dev.typr.foundations.dsl.Bijection;\n\n/** Type for the primary key of table `showcase.address` */\npublic record AddressId(String value) {\n public AddressId withValue(String value) {\n return new AddressId(value);\n };\n\n @Override\n public java.lang.String toString() {\n return value.toString();\n };\n\n static public RowParser _rowParser =\n RowParsers.of(OracleTypes.varchar2.bimap(AddressId::new, AddressId::value), x -> x, id -> new Object[]{id});\n\n static public Bijection bijection =\n Bijection.of(AddressId::value, AddressId::new);\n\n static public OracleType oracleType =\n OracleTypes.varchar2.bimap(AddressId::new, AddressId::value);\n}", - "Defaulted": "package showcase.customtypes;\n\n\n\n/** This signals a value where if you don't provide it, postgres will generate it for you */\npublic sealed interface Defaulted permits Defaulted.Provided, Defaulted.UseDefault {\n record Provided(T value) implements Defaulted {\n public Provided withValue(T value) {\n return new Provided<>(value);\n };\n\n @Override\n public U fold(\n java.util.function.Supplier onDefault,\n java.util.function.Function onProvided\n ) {\n return onProvided.apply(value);\n };\n\n @Override\n public T getOrElse(java.util.function.Supplier onDefault) {\n return value;\n };\n\n @Override\n public void visit(\n java.lang.Runnable onDefault,\n java.util.function.Consumer onProvided\n ) {\n onProvided.accept(value);\n };\n };\n\n record UseDefault() implements Defaulted {\n @Override\n public U fold(\n java.util.function.Supplier onDefault,\n java.util.function.Function onProvided\n ) {\n return onDefault.get();\n };\n\n @Override\n public T getOrElse(java.util.function.Supplier onDefault) {\n return onDefault.get();\n };\n\n @Override\n public void visit(\n java.lang.Runnable onDefault,\n java.util.function.Consumer onProvided\n ) {\n onDefault.run();\n };\n };\n\n U fold(\n java.util.function.Supplier onDefault,\n java.util.function.Function onProvided\n );\n\n T getOrElse(java.util.function.Supplier onDefault);\n\n void visit(\n java.lang.Runnable onDefault,\n java.util.function.Consumer onProvided\n );\n}", - "TestInsert": "package showcase;\n\nimport dev.typr.foundations.data.Json;\nimport dev.typr.foundations.data.OracleIntervalDS;\nimport dev.typr.foundations.data.OracleIntervalYM;\nimport dev.typr.foundations.internal.RandomHelper;\nimport java.math.BigDecimal;\nimport java.sql.Connection;\nimport java.time.LocalDateTime;\nimport java.util.Optional;\nimport java.util.Random;\nimport showcase.customtypes.Defaulted;\nimport showcase.showcase.address.AddressId;\nimport showcase.showcase.address.AddressRepoImpl;\nimport showcase.showcase.address.AddressRow;\nimport showcase.showcase.address.AddressRowUnsaved;\nimport showcase.showcase.audit_log.AuditLogId;\nimport showcase.showcase.audit_log.AuditLogRepoImpl;\nimport showcase.showcase.audit_log.AuditLogRow;\nimport showcase.showcase.audit_log.AuditLogRowUnsaved;\nimport showcase.showcase.category.CategoryId;\nimport showcase.showcase.category.CategoryRepoImpl;\nimport showcase.showcase.category.CategoryRow;\nimport showcase.showcase.company.CompanyId;\nimport showcase.showcase.company.CompanyRepoImpl;\nimport showcase.showcase.company.CompanyRow;\nimport showcase.showcase.company.CompanyRowUnsaved;\nimport showcase.showcase.customer.CustomerId;\nimport showcase.showcase.customer.CustomerRepoImpl;\nimport showcase.showcase.customer.CustomerRow;\nimport showcase.showcase.customer.CustomerRowUnsaved;\nimport showcase.showcase.customer_order.CustomerOrderId;\nimport showcase.showcase.customer_order.CustomerOrderRepoImpl;\nimport showcase.showcase.customer_order.CustomerOrderRow;\nimport showcase.showcase.customer_order.CustomerOrderRowUnsaved;\nimport showcase.showcase.department.DepartmentId;\nimport showcase.showcase.department.DepartmentRepoImpl;\nimport showcase.showcase.department.DepartmentRow;\nimport showcase.showcase.employee.EmployeeId;\nimport showcase.showcase.employee.EmployeeRepoImpl;\nimport showcase.showcase.employee.EmployeeRow;\nimport showcase.showcase.employee.EmployeeRowUnsaved;\nimport showcase.showcase.order_item.OrderItemRepoImpl;\nimport showcase.showcase.order_item.OrderItemRow;\nimport showcase.showcase.order_item.OrderItemRowUnsaved;\nimport showcase.showcase.product.ProductId;\nimport showcase.showcase.product.ProductRepoImpl;\nimport showcase.showcase.product.ProductRow;\nimport showcase.showcase.product.ProductRowUnsaved;\nimport showcase.showcase.project.ProjectId;\nimport showcase.showcase.project.ProjectRepoImpl;\nimport showcase.showcase.project.ProjectRow;\nimport showcase.showcase.project.ProjectRowUnsaved;\nimport showcase.showcase.project_assignment.ProjectAssignmentRepoImpl;\nimport showcase.showcase.project_assignment.ProjectAssignmentRow;\nimport showcase.showcase.project_assignment.ProjectAssignmentRowUnsaved;\n\n/** Methods to generate random data for `Ident(TestInsert)` */\npublic record TestInsert(Random random) {\n public TestInsert withRandom(Random random) {\n return new TestInsert(random);\n };\n\n public AddressRow showcaseAddress(\n CustomerId customerId,\n AddressId id,\n String addressType,\n String street,\n String city,\n Optional state,\n Optional postalCode,\n String country,\n Optional location,\n Optional notes,\n Defaulted> isDefault,\n Connection c\n ) {\n return (new AddressRepoImpl()).insert(new AddressRowUnsaved(id, customerId, addressType, street, city, state, postalCode, country, location, notes, isDefault), c);\n };\n\n public AuditLogRow showcaseAuditLog(\n AuditLogId id,\n String tableName,\n String recordId,\n String action,\n Optional oldValues,\n Optional newValues,\n Optional changedBy,\n Defaulted> changedAt,\n Connection c\n ) {\n return (new AuditLogRepoImpl()).insert(new AuditLogRowUnsaved(id, tableName, recordId, action, oldValues, newValues, changedBy, changedAt), c);\n };\n\n public CategoryRow showcaseCategory(\n CategoryId id,\n Optional parentId,\n String name,\n Optional description,\n Connection c\n ) {\n return (new CategoryRepoImpl()).insert(new CategoryRow(id, parentId, name, description), c);\n };\n\n public CompanyRow showcaseCompany(\n CompanyId id,\n String name,\n Optional foundedYear,\n Defaulted> active,\n Defaulted> createdAt,\n Connection c\n ) {\n return (new CompanyRepoImpl()).insert(new CompanyRowUnsaved(id, name, foundedYear, active, createdAt), c);\n };\n\n public CustomerRow showcaseCustomer(\n CustomerId id,\n String email,\n String firstName,\n String lastName,\n Optional phone,\n Optional preferences,\n Optional avatar,\n Optional notes,\n Defaulted> verified,\n Defaulted> createdAt,\n Connection c\n ) {\n return (new CustomerRepoImpl()).insert(new CustomerRowUnsaved(id, email, firstName, lastName, phone, preferences, avatar, notes, verified, createdAt), c);\n };\n\n public CustomerOrderRow showcaseCustomerOrder(\n CustomerId customerId,\n CustomerOrderId id,\n Optional shippingAddressId,\n Optional billingAddressId,\n BigDecimal subtotal,\n BigDecimal total,\n Optional notes,\n Optional shippedAt,\n Optional deliveredAt,\n Optional metadata,\n Optional notesExtended,\n Optional receiptData,\n Optional processingTime,\n Optional xmlInvoice,\n Defaulted> status,\n Defaulted> tax,\n Defaulted> shipping,\n Defaulted> createdAt,\n Connection c\n ) {\n return (new CustomerOrderRepoImpl()).insert(new CustomerOrderRowUnsaved(id, customerId, shippingAddressId, billingAddressId, subtotal, total, notes, shippedAt, deliveredAt, metadata, notesExtended, receiptData, processingTime, xmlInvoice, status, tax, shipping, createdAt), c);\n };\n\n public DepartmentRow showcaseDepartment(\n CompanyId companyId,\n DepartmentId id,\n String name,\n Optional budget,\n Connection c\n ) {\n return (new DepartmentRepoImpl()).insert(new DepartmentRow(id, companyId, name, budget), c);\n };\n\n public EmployeeRow showcaseEmployee(\n DepartmentId departmentId,\n EmployeeId id,\n Optional managerId,\n String email,\n String firstName,\n String lastName,\n Optional salary,\n Optional hiredAt,\n Optional metadata,\n Optional resume,\n Optional photo,\n Optional probationPeriod,\n Optional shiftDuration,\n Defaulted> active,\n Defaulted> createdAt,\n Connection c\n ) {\n return (new EmployeeRepoImpl()).insert(new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, metadata, resume, photo, probationPeriod, shiftDuration, active, createdAt), c);\n };\n\n public OrderItemRow showcaseOrderItem(\n CustomerOrderId orderId,\n ProductId productId,\n BigDecimal quantity,\n BigDecimal unitPrice,\n Defaulted> discount,\n Connection c\n ) {\n return (new OrderItemRepoImpl()).insert(new OrderItemRowUnsaved(orderId, productId, quantity, unitPrice, discount), c);\n };\n\n public ProductRow showcaseProduct(\n ProductId id,\n Optional categoryId,\n String name,\n String sku,\n BigDecimal price,\n Optional cost,\n Optional weight,\n Optional attributes,\n Optional specifications,\n Optional descriptionLong,\n Optional thumbnail,\n Optional xmlData,\n Defaulted> inStock,\n Defaulted> quantity,\n Defaulted> createdAt,\n Connection c\n ) {\n return (new ProductRepoImpl()).insert(new ProductRowUnsaved(id, categoryId, name, sku, price, cost, weight, attributes, specifications, descriptionLong, thumbnail, xmlData, inStock, quantity, createdAt), c);\n };\n\n public ProjectRow showcaseProject(\n ProjectId id,\n String name,\n Optional description,\n Optional startDate,\n Optional endDate,\n Optional budget,\n Optional metadata,\n Optional descriptionLong,\n Optional attachments,\n Optional estimatedDuration,\n Optional actualDuration,\n Optional xmlPlan,\n Defaulted> status,\n Defaulted> createdAt,\n Connection c\n ) {\n return (new ProjectRepoImpl()).insert(new ProjectRowUnsaved(id, name, description, startDate, endDate, budget, metadata, descriptionLong, attachments, estimatedDuration, actualDuration, xmlPlan, status, createdAt), c);\n };\n\n public ProjectAssignmentRow showcaseProjectAssignment(\n EmployeeId employeeId,\n ProjectId projectId,\n String role,\n Optional startDate,\n Optional endDate,\n Defaulted> hoursAllocated,\n Connection c\n ) {\n return (new ProjectAssignmentRepoImpl()).insert(new ProjectAssignmentRowUnsaved(employeeId, projectId, role, startDate, endDate, hoursAllocated), c);\n };\n}" - }, - "kotlin": { - "CompanyRow": "package showcase.showcase.company\n\nimport dev.typr.foundations.OracleTypes\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport dev.typr.foundations.kotlin.nullable\nimport java.math.BigDecimal\nimport java.time.LocalDateTime\nimport showcase.customtypes.Defaulted\n\n/** Table: showcase.company\n * Primary key: id\n */\ndata class CompanyRow(\n val id: CompanyId,\n val name: String,\n val foundedYear: BigDecimal?,\n /** Default: true */\n val active: BigDecimal?,\n /** Default: CURRENT_TIMESTAMP */\n val createdAt: LocalDateTime?\n) {\n fun toUnsavedRow(\n active: Defaulted,\n createdAt: Defaulted\n ): CompanyRowUnsaved = CompanyRowUnsaved(id, name, foundedYear, active, createdAt)\n\n companion object {\n val _rowParser: RowParser = RowParsers.of(CompanyId.oracleType, OracleTypes.varchar2, KotlinDbTypes.OracleTypes.number.nullable(), KotlinDbTypes.OracleTypes.number.nullable(), OracleTypes.timestamp.nullable(), { t0, t1, t2, t3, t4 -> CompanyRow(t0, t1, t2, t3, t4) }, { row -> arrayOf(row.id, row.name, row.foundedYear, row.active, row.createdAt) })\n }\n}", - "CompanyRowUnsaved": "package showcase.showcase.company\n\nimport java.math.BigDecimal\nimport java.time.LocalDateTime\nimport showcase.customtypes.Defaulted\nimport showcase.customtypes.Defaulted.UseDefault\n\n/** This class corresponds to a row in table `showcase.company` which has not been persisted yet */\ndata class CompanyRowUnsaved(\n val id: CompanyId,\n val name: String,\n val foundedYear: BigDecimal? = null,\n /** Default: true */\n val active: Defaulted = UseDefault(),\n /** Default: CURRENT_TIMESTAMP */\n val createdAt: Defaulted = UseDefault()\n) {\n fun toRow(\n activeDefault: () -> BigDecimal?,\n createdAtDefault: () -> LocalDateTime?\n ): CompanyRow = CompanyRow(id = id, name = name, foundedYear = foundedYear, active = active.getOrElse(activeDefault), createdAt = createdAt.getOrElse(createdAtDefault))\n}", - "CompanyId": "package showcase.showcase.company\n\nimport dev.typr.foundations.OracleType\nimport dev.typr.foundations.OracleTypes\nimport dev.typr.foundations.kotlin.Bijection\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\n\n/** Type for the primary key of table `showcase.company` */\ndata class CompanyId(val value: String) {\n override fun toString(): kotlin.String {\n return value.toString()\n }\n\n companion object {\n val _rowParser: RowParser =\n RowParsers.of(OracleTypes.varchar2.bimap(::CompanyId, CompanyId::value), { x -> x }, { id -> arrayOf(id) })\n\n val bijection: Bijection =\n Bijection.of(CompanyId::value, ::CompanyId)\n\n val oracleType: OracleType =\n OracleTypes.varchar2.bimap(::CompanyId, CompanyId::value)\n }\n}", - "CompanyRepo": "package showcase.showcase.company\n\nimport dev.typr.foundations.kotlin.DeleteBuilder\nimport dev.typr.foundations.kotlin.SelectBuilder\nimport dev.typr.foundations.kotlin.UpdateBuilder\nimport java.sql.Connection\nimport kotlin.collections.Iterator\nimport kotlin.collections.List\nimport kotlin.collections.Map\n\ninterface CompanyRepo {\n abstract fun delete(): DeleteBuilder\n\n abstract fun deleteById(\n id: CompanyId,\n c: Connection\n ): Boolean\n\n abstract fun deleteByIds(\n ids: Array,\n c: Connection\n ): Int\n\n abstract fun insert(\n unsaved: CompanyRow,\n c: Connection\n ): CompanyRow\n\n abstract fun insert(\n unsaved: CompanyRowUnsaved,\n c: Connection\n ): CompanyRow\n\n abstract fun select(): SelectBuilder\n\n abstract fun selectAll(c: Connection): List\n\n abstract fun selectById(\n id: CompanyId,\n c: Connection\n ): CompanyRow?\n\n abstract fun selectByIds(\n ids: Array,\n c: Connection\n ): List\n\n abstract fun selectByIdsTracked(\n ids: Array,\n c: Connection\n ): Map\n\n abstract fun update(): UpdateBuilder\n\n abstract fun update(\n row: CompanyRow,\n c: Connection\n ): Boolean\n\n abstract fun upsert(\n unsaved: CompanyRow,\n c: Connection\n ): CompanyRow\n\n abstract fun upsertBatch(\n unsaved: Iterator,\n c: Connection\n ): List\n}", - "CompanyRepoMock": "package showcase.showcase.company\n\nimport dev.typr.foundations.kotlin.DeleteBuilder\nimport dev.typr.foundations.kotlin.DeleteBuilderMock\nimport dev.typr.foundations.kotlin.DeleteParams\nimport dev.typr.foundations.kotlin.SelectBuilder\nimport dev.typr.foundations.kotlin.SelectBuilderMock\nimport dev.typr.foundations.kotlin.SelectParams\nimport dev.typr.foundations.kotlin.UpdateBuilder\nimport dev.typr.foundations.kotlin.UpdateBuilderMock\nimport dev.typr.foundations.kotlin.UpdateParams\nimport java.lang.RuntimeException\nimport java.sql.Connection\nimport java.util.ArrayList\nimport kotlin.collections.Iterator\nimport kotlin.collections.List\nimport kotlin.collections.Map\nimport kotlin.collections.MutableMap\n\ndata class CompanyRepoMock(\n val toRow: (CompanyRowUnsaved) -> CompanyRow,\n val map: MutableMap = mutableMapOf()\n) : CompanyRepo {\n override fun delete(): DeleteBuilder = DeleteBuilderMock(CompanyFields.structure, { map.values.toList() }, DeleteParams.empty(), { row -> row.id }, { id -> map.remove(id) })\n\n override fun deleteById(\n id: CompanyId,\n c: Connection\n ): Boolean = map.remove(id) != null\n\n override fun deleteByIds(\n ids: Array,\n c: Connection\n ): Int {\n var count = 0\n for (id in ids) {\n if (map.remove(id) != null) {\n count = count + 1\n }\n }\n return count\n }\n\n override fun insert(\n unsaved: CompanyRow,\n c: Connection\n ): CompanyRow {\n if (map.containsKey(unsaved.id)) {\n throw RuntimeException(\"id \" + unsaved.id + \" already exists\")\n }\n map[unsaved.id] = unsaved\n return unsaved\n }\n\n override fun insert(\n unsaved: CompanyRowUnsaved,\n c: Connection\n ): CompanyRow = insert(toRow(unsaved), c)\n\n override fun select(): SelectBuilder = SelectBuilderMock(CompanyFields.structure, { map.values.toList() }, SelectParams.empty())\n\n override fun selectAll(c: Connection): List = map.values.toList()\n\n override fun selectById(\n id: CompanyId,\n c: Connection\n ): CompanyRow? = map[id]\n\n override fun selectByIds(\n ids: Array,\n c: Connection\n ): List {\n val result = ArrayList()\n for (id in ids) {\n val opt = map[id]\n if (opt != null) {\n result.add(opt!!)\n }\n }\n return result\n }\n\n override fun selectByIdsTracked(\n ids: Array,\n c: Connection\n ): Map = selectByIds(ids, c).associateBy({ row: CompanyRow -> row.id })\n\n override fun update(): UpdateBuilder = UpdateBuilderMock(CompanyFields.structure, { map.values.toList() }, UpdateParams.empty(), { row -> row })\n\n override fun update(\n row: CompanyRow,\n c: Connection\n ): Boolean {\n val shouldUpdate = map[row.id]?.takeIf({ oldRow -> (oldRow != row) }) != null\n if (shouldUpdate) {\n map[row.id] = row\n }\n return shouldUpdate\n }\n\n override fun upsert(\n unsaved: CompanyRow,\n c: Connection\n ): CompanyRow {\n map[unsaved.id] = unsaved\n return unsaved\n }\n\n override fun upsertBatch(\n unsaved: Iterator,\n c: Connection\n ): List {\n val result = ArrayList()\n while (unsaved.hasNext()) {\n val row = unsaved.next()\n map[row.id] = row\n result.add(row)\n }\n return result\n }\n}", - "EmployeeRow": "package showcase.showcase.employee\n\nimport dev.typr.foundations.OracleTypes\nimport dev.typr.foundations.data.Json\nimport dev.typr.foundations.data.OracleIntervalDS\nimport dev.typr.foundations.data.OracleIntervalYM\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport dev.typr.foundations.kotlin.nullable\nimport java.math.BigDecimal\nimport java.time.LocalDateTime\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.department.DepartmentId\n\n/** Table: showcase.employee\n * Primary key: id\n */\ndata class EmployeeRow(\n val id: EmployeeId,\n /** Points to [showcase.showcase.department.DepartmentRow.id] */\n val departmentId: DepartmentId,\n /** Points to [showcase.showcase.employee.EmployeeRow.id] */\n val managerId: EmployeeId?,\n val email: String,\n val firstName: String,\n val lastName: String,\n val salary: BigDecimal?,\n val hiredAt: LocalDateTime?,\n /** Default: true */\n val active: BigDecimal?,\n /** Default: CURRENT_TIMESTAMP */\n val createdAt: LocalDateTime?,\n val metadata: Json?,\n val resume: String?,\n val photo: ByteArray?,\n val probationPeriod: OracleIntervalYM?,\n val shiftDuration: OracleIntervalDS?\n) {\n fun toUnsavedRow(\n active: Defaulted,\n createdAt: Defaulted\n ): EmployeeRowUnsaved = EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, metadata, resume, photo, probationPeriod, shiftDuration, active, createdAt)\n\n companion object {\n val _rowParser: RowParser = RowParsers.of(EmployeeId.oracleType, DepartmentId.oracleType, EmployeeId.oracleType.nullable(), OracleTypes.varchar2, OracleTypes.varchar2, OracleTypes.varchar2, KotlinDbTypes.OracleTypes.number.nullable(), OracleTypes.date.nullable(), KotlinDbTypes.OracleTypes.number.nullable(), OracleTypes.timestamp.nullable(), OracleTypes.json.nullable(), OracleTypes.clob.nullable(), OracleTypes.blob.nullable(), OracleTypes.intervalYearToMonth.nullable(), OracleTypes.intervalDayToSecond.nullable(), { t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14 -> EmployeeRow(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14) }, { row -> arrayOf(row.id, row.departmentId, row.managerId, row.email, row.firstName, row.lastName, row.salary, row.hiredAt, row.active, row.createdAt, row.metadata, row.resume, row.photo, row.probationPeriod, row.shiftDuration) })\n }\n}", - "EmployeeRowUnsaved": "package showcase.showcase.employee\n\nimport dev.typr.foundations.data.Json\nimport dev.typr.foundations.data.OracleIntervalDS\nimport dev.typr.foundations.data.OracleIntervalYM\nimport java.math.BigDecimal\nimport java.time.LocalDateTime\nimport showcase.customtypes.Defaulted\nimport showcase.customtypes.Defaulted.UseDefault\nimport showcase.showcase.department.DepartmentId\n\n/** This class corresponds to a row in table `showcase.employee` which has not been persisted yet */\ndata class EmployeeRowUnsaved(\n val id: EmployeeId,\n /** Points to [showcase.showcase.department.DepartmentRow.id] */\n val departmentId: DepartmentId,\n /** Points to [showcase.showcase.employee.EmployeeRow.id] */\n val managerId: EmployeeId? = null,\n val email: String,\n val firstName: String,\n val lastName: String,\n val salary: BigDecimal? = null,\n val hiredAt: LocalDateTime? = null,\n val metadata: Json? = null,\n val resume: String? = null,\n val photo: ByteArray? = null,\n val probationPeriod: OracleIntervalYM? = null,\n val shiftDuration: OracleIntervalDS? = null,\n /** Default: true */\n val active: Defaulted = UseDefault(),\n /** Default: CURRENT_TIMESTAMP */\n val createdAt: Defaulted = UseDefault()\n) {\n fun toRow(\n activeDefault: () -> BigDecimal?,\n createdAtDefault: () -> LocalDateTime?\n ): EmployeeRow = EmployeeRow(id = id, departmentId = departmentId, managerId = managerId, email = email, firstName = firstName, lastName = lastName, salary = salary, hiredAt = hiredAt, active = active.getOrElse(activeDefault), createdAt = createdAt.getOrElse(createdAtDefault), metadata = metadata, resume = resume, photo = photo, probationPeriod = probationPeriod, shiftDuration = shiftDuration)\n}", - "EmployeeId": "package showcase.showcase.employee\n\nimport dev.typr.foundations.OracleType\nimport dev.typr.foundations.OracleTypes\nimport dev.typr.foundations.kotlin.Bijection\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\n\n/** Type for the primary key of table `showcase.employee` */\ndata class EmployeeId(val value: String) {\n override fun toString(): kotlin.String {\n return value.toString()\n }\n\n companion object {\n val _rowParser: RowParser =\n RowParsers.of(OracleTypes.varchar2.bimap(::EmployeeId, EmployeeId::value), { x -> x }, { id -> arrayOf(id) })\n\n val bijection: Bijection =\n Bijection.of(EmployeeId::value, ::EmployeeId)\n\n val oracleType: OracleType =\n OracleTypes.varchar2.bimap(::EmployeeId, EmployeeId::value)\n }\n}", - "EmployeeRepo": "package showcase.showcase.employee\n\nimport dev.typr.foundations.kotlin.DeleteBuilder\nimport dev.typr.foundations.kotlin.SelectBuilder\nimport dev.typr.foundations.kotlin.UpdateBuilder\nimport java.sql.Connection\nimport kotlin.collections.Iterator\nimport kotlin.collections.List\nimport kotlin.collections.Map\n\ninterface EmployeeRepo {\n abstract fun delete(): DeleteBuilder\n\n abstract fun deleteById(\n id: EmployeeId,\n c: Connection\n ): Boolean\n\n abstract fun deleteByIds(\n ids: Array,\n c: Connection\n ): Int\n\n abstract fun insert(\n unsaved: EmployeeRow,\n c: Connection\n ): EmployeeRow\n\n abstract fun insert(\n unsaved: EmployeeRowUnsaved,\n c: Connection\n ): EmployeeRow\n\n abstract fun select(): SelectBuilder\n\n abstract fun selectAll(c: Connection): List\n\n abstract fun selectById(\n id: EmployeeId,\n c: Connection\n ): EmployeeRow?\n\n abstract fun selectByIds(\n ids: Array,\n c: Connection\n ): List\n\n abstract fun selectByIdsTracked(\n ids: Array,\n c: Connection\n ): Map\n\n abstract fun selectByUniqueEmail(\n email: String,\n c: Connection\n ): EmployeeRow?\n\n abstract fun update(): UpdateBuilder\n\n abstract fun update(\n row: EmployeeRow,\n c: Connection\n ): Boolean\n\n abstract fun upsert(\n unsaved: EmployeeRow,\n c: Connection\n ): EmployeeRow\n\n abstract fun upsertBatch(\n unsaved: Iterator,\n c: Connection\n ): List\n}", - "EmployeeRepoImpl": "package showcase.showcase.employee\n\nimport dev.typr.foundations.OracleTypes\nimport dev.typr.foundations.kotlin.DeleteBuilder\nimport dev.typr.foundations.kotlin.Dialect\nimport dev.typr.foundations.kotlin.Fragment\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.SelectBuilder\nimport dev.typr.foundations.kotlin.UpdateBuilder\nimport dev.typr.foundations.kotlin.nullable\nimport java.sql.Connection\nimport java.util.ArrayList\nimport kotlin.collections.Iterator\nimport kotlin.collections.List\nimport kotlin.collections.Map\nimport kotlin.collections.MutableMap\nimport showcase.showcase.department.DepartmentId\n\nclass EmployeeRepoImpl() : EmployeeRepo {\n override fun delete(): DeleteBuilder = DeleteBuilder.of(\"\\\"showcase\\\".\\\"employee\\\"\", EmployeeFields.structure, Dialect.ORACLE)\n\n override fun deleteById(\n id: EmployeeId,\n c: Connection\n ): Boolean = Fragment.interpolate(Fragment.lit(\"delete from \\\"showcase\\\".\\\"employee\\\" where \\\"id\\\" = \"), Fragment.encode(EmployeeId.oracleType, id), Fragment.lit(\"\")).update().runUnchecked(c) > 0\n\n override fun deleteByIds(\n ids: Array,\n c: Connection\n ): Int {\n val fragments: ArrayList = ArrayList()\n for (id in ids) { fragments.add(Fragment.encode(EmployeeId.oracleType, id)) }\n return Fragment.interpolate(Fragment.lit(\"delete from \\\"showcase\\\".\\\"employee\\\" where \\\"id\\\" in (\"), Fragment.comma(fragments.toMutableList()), Fragment.lit(\")\")).update().runUnchecked(c)\n }\n\n override fun insert(\n unsaved: EmployeeRow,\n c: Connection\n ): EmployeeRow = Fragment.interpolate(Fragment.lit(\"insert into \\\"showcase\\\".\\\"employee\\\"(\\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"metadata\\\", \\\"resume\\\", \\\"photo\\\", \\\"probation_period\\\", \\\"shift_duration\\\")\\nvalues (\"), Fragment.encode(EmployeeId.oracleType, unsaved.id), Fragment.lit(\", \"), Fragment.encode(DepartmentId.oracleType, unsaved.departmentId), Fragment.lit(\", \"), Fragment.encode(EmployeeId.oracleType.nullable(), unsaved.managerId), Fragment.lit(\", \"), Fragment.encode(OracleTypes.varchar2, unsaved.email), Fragment.lit(\", \"), Fragment.encode(OracleTypes.varchar2, unsaved.firstName), Fragment.lit(\", \"), Fragment.encode(OracleTypes.varchar2, unsaved.lastName), Fragment.lit(\", \"), Fragment.encode(KotlinDbTypes.OracleTypes.number.nullable(), unsaved.salary), Fragment.lit(\", \"), Fragment.encode(OracleTypes.date.nullable(), unsaved.hiredAt), Fragment.lit(\", \"), Fragment.encode(KotlinDbTypes.OracleTypes.number.nullable(), unsaved.active), Fragment.lit(\", \"), Fragment.encode(OracleTypes.timestamp.nullable(), unsaved.createdAt), Fragment.lit(\", \"), Fragment.encode(OracleTypes.json.nullable(), unsaved.metadata), Fragment.lit(\", \"), Fragment.encode(OracleTypes.clob.nullable(), unsaved.resume), Fragment.lit(\", \"), Fragment.encode(OracleTypes.blob.nullable(), unsaved.photo), Fragment.lit(\", \"), Fragment.encode(OracleTypes.intervalYearToMonth.nullable(), unsaved.probationPeriod), Fragment.lit(\", \"), Fragment.encode(OracleTypes.intervalDayToSecond.nullable(), unsaved.shiftDuration), Fragment.lit(\")\\n\"))\n .updateReturningGeneratedKeys(arrayOf(\"id\", \"department_id\", \"manager_id\", \"email\", \"first_name\", \"last_name\", \"salary\", \"hired_at\", \"active\", \"created_at\", \"metadata\", \"resume\", \"photo\", \"probation_period\", \"shift_duration\"), EmployeeRow._rowParser.exactlyOne()).runUnchecked(c)\n\n override fun insert(\n unsaved: EmployeeRowUnsaved,\n c: Connection\n ): EmployeeRow {\n val columns: ArrayList = ArrayList()\n val values: ArrayList = ArrayList()\n columns.add(Fragment.lit(\"\\\"id\\\"\"))\n values.add(Fragment.interpolate(Fragment.encode(EmployeeId.oracleType, unsaved.id), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"\\\"department_id\\\"\"))\n values.add(Fragment.interpolate(Fragment.encode(DepartmentId.oracleType, unsaved.departmentId), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"\\\"manager_id\\\"\"))\n values.add(Fragment.interpolate(Fragment.encode(EmployeeId.oracleType.nullable(), unsaved.managerId), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"\\\"email\\\"\"))\n values.add(Fragment.interpolate(Fragment.encode(OracleTypes.varchar2, unsaved.email), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"\\\"first_name\\\"\"))\n values.add(Fragment.interpolate(Fragment.encode(OracleTypes.varchar2, unsaved.firstName), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"\\\"last_name\\\"\"))\n values.add(Fragment.interpolate(Fragment.encode(OracleTypes.varchar2, unsaved.lastName), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"\\\"salary\\\"\"))\n values.add(Fragment.interpolate(Fragment.encode(KotlinDbTypes.OracleTypes.number.nullable(), unsaved.salary), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"\\\"hired_at\\\"\"))\n values.add(Fragment.interpolate(Fragment.encode(OracleTypes.date.nullable(), unsaved.hiredAt), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"\\\"metadata\\\"\"))\n values.add(Fragment.interpolate(Fragment.encode(OracleTypes.json.nullable(), unsaved.metadata), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"\\\"resume\\\"\"))\n values.add(Fragment.interpolate(Fragment.encode(OracleTypes.clob.nullable(), unsaved.resume), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"\\\"photo\\\"\"))\n values.add(Fragment.interpolate(Fragment.encode(OracleTypes.blob.nullable(), unsaved.photo), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"\\\"probation_period\\\"\"))\n values.add(Fragment.interpolate(Fragment.encode(OracleTypes.intervalYearToMonth.nullable(), unsaved.probationPeriod), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"\\\"shift_duration\\\"\"))\n values.add(Fragment.interpolate(Fragment.encode(OracleTypes.intervalDayToSecond.nullable(), unsaved.shiftDuration), Fragment.lit(\"\")))\n unsaved.active.visit(\n { },\n { value -> columns.add(Fragment.lit(\"\\\"active\\\"\"))\n values.add(Fragment.interpolate(Fragment.encode(KotlinDbTypes.OracleTypes.number.nullable(), value), Fragment.lit(\"\"))) }\n );\n unsaved.createdAt.visit(\n { },\n { value -> columns.add(Fragment.lit(\"\\\"created_at\\\"\"))\n values.add(Fragment.interpolate(Fragment.encode(OracleTypes.timestamp.nullable(), value), Fragment.lit(\"\"))) }\n );\n val q: Fragment = Fragment.interpolate(Fragment.lit(\"insert into \\\"showcase\\\".\\\"employee\\\"(\"), Fragment.comma(columns.toMutableList()), Fragment.lit(\")\\nvalues (\"), Fragment.comma(values.toMutableList()), Fragment.lit(\")\\n\"))\n return q.updateReturningGeneratedKeys(arrayOf(\"id\", \"department_id\", \"manager_id\", \"email\", \"first_name\", \"last_name\", \"salary\", \"hired_at\", \"active\", \"created_at\", \"metadata\", \"resume\", \"photo\", \"probation_period\", \"shift_duration\"), EmployeeRow._rowParser.exactlyOne()).runUnchecked(c)\n }\n\n override fun select(): SelectBuilder = SelectBuilder.of(\"\\\"showcase\\\".\\\"employee\\\"\", EmployeeFields.structure, EmployeeRow._rowParser, Dialect.ORACLE)\n\n override fun selectAll(c: Connection): List = Fragment.interpolate(Fragment.lit(\"select \\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"metadata\\\", \\\"resume\\\", \\\"photo\\\", \\\"probation_period\\\", \\\"shift_duration\\\"\\nfrom \\\"showcase\\\".\\\"employee\\\"\\n\")).query(EmployeeRow._rowParser.all()).runUnchecked(c)\n\n override fun selectById(\n id: EmployeeId,\n c: Connection\n ): EmployeeRow? = Fragment.interpolate(Fragment.lit(\"select \\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"metadata\\\", \\\"resume\\\", \\\"photo\\\", \\\"probation_period\\\", \\\"shift_duration\\\"\\nfrom \\\"showcase\\\".\\\"employee\\\"\\nwhere \\\"id\\\" = \"), Fragment.encode(EmployeeId.oracleType, id), Fragment.lit(\"\")).query(EmployeeRow._rowParser.first()).runUnchecked(c)\n\n override fun selectByIds(\n ids: Array,\n c: Connection\n ): List {\n val fragments: ArrayList = ArrayList()\n for (id in ids) { fragments.add(Fragment.encode(EmployeeId.oracleType, id)) }\n return Fragment.interpolate(Fragment.lit(\"select \\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"metadata\\\", \\\"resume\\\", \\\"photo\\\", \\\"probation_period\\\", \\\"shift_duration\\\" from \\\"showcase\\\".\\\"employee\\\" where \\\"id\\\" in (\"), Fragment.comma(fragments.toMutableList()), Fragment.lit(\")\")).query(EmployeeRow._rowParser.all()).runUnchecked(c)\n }\n\n override fun selectByIdsTracked(\n ids: Array,\n c: Connection\n ): Map {\n val ret: MutableMap = mutableMapOf()\n selectByIds(ids, c).forEach({ row -> ret.put(row.id, row) })\n return ret.toMap()\n }\n\n override fun selectByUniqueEmail(\n email: String,\n c: Connection\n ): EmployeeRow? = Fragment.interpolate(Fragment.lit(\"select \\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"metadata\\\", \\\"resume\\\", \\\"photo\\\", \\\"probation_period\\\", \\\"shift_duration\\\"\\nfrom \\\"showcase\\\".\\\"employee\\\"\\nwhere \\\"email\\\" = \"), Fragment.encode(OracleTypes.varchar2, email), Fragment.lit(\"\\n\")).query(EmployeeRow._rowParser.first()).runUnchecked(c)\n\n override fun update(): UpdateBuilder = UpdateBuilder.of(\"\\\"showcase\\\".\\\"employee\\\"\", EmployeeFields.structure, EmployeeRow._rowParser, Dialect.ORACLE)\n\n override fun update(\n row: EmployeeRow,\n c: Connection\n ): Boolean {\n val id: EmployeeId = row.id\n return Fragment.interpolate(Fragment.lit(\"update \\\"showcase\\\".\\\"employee\\\"\\nset \\\"department_id\\\" = \"), Fragment.encode(DepartmentId.oracleType, row.departmentId), Fragment.lit(\",\\n\\\"manager_id\\\" = \"), Fragment.encode(EmployeeId.oracleType.nullable(), row.managerId), Fragment.lit(\",\\n\\\"email\\\" = \"), Fragment.encode(OracleTypes.varchar2, row.email), Fragment.lit(\",\\n\\\"first_name\\\" = \"), Fragment.encode(OracleTypes.varchar2, row.firstName), Fragment.lit(\",\\n\\\"last_name\\\" = \"), Fragment.encode(OracleTypes.varchar2, row.lastName), Fragment.lit(\",\\n\\\"salary\\\" = \"), Fragment.encode(KotlinDbTypes.OracleTypes.number.nullable(), row.salary), Fragment.lit(\",\\n\\\"hired_at\\\" = \"), Fragment.encode(OracleTypes.date.nullable(), row.hiredAt), Fragment.lit(\",\\n\\\"active\\\" = \"), Fragment.encode(KotlinDbTypes.OracleTypes.number.nullable(), row.active), Fragment.lit(\",\\n\\\"created_at\\\" = \"), Fragment.encode(OracleTypes.timestamp.nullable(), row.createdAt), Fragment.lit(\",\\n\\\"metadata\\\" = \"), Fragment.encode(OracleTypes.json.nullable(), row.metadata), Fragment.lit(\",\\n\\\"resume\\\" = \"), Fragment.encode(OracleTypes.clob.nullable(), row.resume), Fragment.lit(\",\\n\\\"photo\\\" = \"), Fragment.encode(OracleTypes.blob.nullable(), row.photo), Fragment.lit(\",\\n\\\"probation_period\\\" = \"), Fragment.encode(OracleTypes.intervalYearToMonth.nullable(), row.probationPeriod), Fragment.lit(\",\\n\\\"shift_duration\\\" = \"), Fragment.encode(OracleTypes.intervalDayToSecond.nullable(), row.shiftDuration), Fragment.lit(\"\\nwhere \\\"id\\\" = \"), Fragment.encode(EmployeeId.oracleType, id), Fragment.lit(\"\")).update().runUnchecked(c) > 0\n }\n\n override fun upsert(\n unsaved: EmployeeRow,\n c: Connection\n ): EmployeeRow = Fragment.interpolate(Fragment.lit(\"MERGE INTO \\\"showcase\\\".\\\"employee\\\" t\\nUSING (SELECT \"), Fragment.encode(EmployeeId.oracleType, unsaved.id), Fragment.lit(\", \"), Fragment.encode(DepartmentId.oracleType, unsaved.departmentId), Fragment.lit(\", \"), Fragment.encode(EmployeeId.oracleType.nullable(), unsaved.managerId), Fragment.lit(\", \"), Fragment.encode(OracleTypes.varchar2, unsaved.email), Fragment.lit(\", \"), Fragment.encode(OracleTypes.varchar2, unsaved.firstName), Fragment.lit(\", \"), Fragment.encode(OracleTypes.varchar2, unsaved.lastName), Fragment.lit(\", \"), Fragment.encode(KotlinDbTypes.OracleTypes.number.nullable(), unsaved.salary), Fragment.lit(\", \"), Fragment.encode(OracleTypes.date.nullable(), unsaved.hiredAt), Fragment.lit(\", \"), Fragment.encode(KotlinDbTypes.OracleTypes.number.nullable(), unsaved.active), Fragment.lit(\", \"), Fragment.encode(OracleTypes.timestamp.nullable(), unsaved.createdAt), Fragment.lit(\", \"), Fragment.encode(OracleTypes.json.nullable(), unsaved.metadata), Fragment.lit(\", \"), Fragment.encode(OracleTypes.clob.nullable(), unsaved.resume), Fragment.lit(\", \"), Fragment.encode(OracleTypes.blob.nullable(), unsaved.photo), Fragment.lit(\", \"), Fragment.encode(OracleTypes.intervalYearToMonth.nullable(), unsaved.probationPeriod), Fragment.lit(\", \"), Fragment.encode(OracleTypes.intervalDayToSecond.nullable(), unsaved.shiftDuration), Fragment.lit(\" FROM DUAL) s\\nON (\\\"id\\\")\\nWHEN MATCHED THEN UPDATE SET t.\\\"department_id\\\" = s.\\\"department_id\\\",\\nt.\\\"manager_id\\\" = s.\\\"manager_id\\\",\\nt.\\\"email\\\" = s.\\\"email\\\",\\nt.\\\"first_name\\\" = s.\\\"first_name\\\",\\nt.\\\"last_name\\\" = s.\\\"last_name\\\",\\nt.\\\"salary\\\" = s.\\\"salary\\\",\\nt.\\\"hired_at\\\" = s.\\\"hired_at\\\",\\nt.\\\"active\\\" = s.\\\"active\\\",\\nt.\\\"created_at\\\" = s.\\\"created_at\\\",\\nt.\\\"metadata\\\" = s.\\\"metadata\\\",\\nt.\\\"resume\\\" = s.\\\"resume\\\",\\nt.\\\"photo\\\" = s.\\\"photo\\\",\\nt.\\\"probation_period\\\" = s.\\\"probation_period\\\",\\nt.\\\"shift_duration\\\" = s.\\\"shift_duration\\\"\\nWHEN NOT MATCHED THEN INSERT (\\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"metadata\\\", \\\"resume\\\", \\\"photo\\\", \\\"probation_period\\\", \\\"shift_duration\\\") VALUES (\"), Fragment.encode(EmployeeId.oracleType, unsaved.id), Fragment.lit(\", \"), Fragment.encode(DepartmentId.oracleType, unsaved.departmentId), Fragment.lit(\", \"), Fragment.encode(EmployeeId.oracleType.nullable(), unsaved.managerId), Fragment.lit(\", \"), Fragment.encode(OracleTypes.varchar2, unsaved.email), Fragment.lit(\", \"), Fragment.encode(OracleTypes.varchar2, unsaved.firstName), Fragment.lit(\", \"), Fragment.encode(OracleTypes.varchar2, unsaved.lastName), Fragment.lit(\", \"), Fragment.encode(KotlinDbTypes.OracleTypes.number.nullable(), unsaved.salary), Fragment.lit(\", \"), Fragment.encode(OracleTypes.date.nullable(), unsaved.hiredAt), Fragment.lit(\", \"), Fragment.encode(KotlinDbTypes.OracleTypes.number.nullable(), unsaved.active), Fragment.lit(\", \"), Fragment.encode(OracleTypes.timestamp.nullable(), unsaved.createdAt), Fragment.lit(\", \"), Fragment.encode(OracleTypes.json.nullable(), unsaved.metadata), Fragment.lit(\", \"), Fragment.encode(OracleTypes.clob.nullable(), unsaved.resume), Fragment.lit(\", \"), Fragment.encode(OracleTypes.blob.nullable(), unsaved.photo), Fragment.lit(\", \"), Fragment.encode(OracleTypes.intervalYearToMonth.nullable(), unsaved.probationPeriod), Fragment.lit(\", \"), Fragment.encode(OracleTypes.intervalDayToSecond.nullable(), unsaved.shiftDuration), Fragment.lit(\")\"))\n .updateReturning(EmployeeRow._rowParser.exactlyOne())\n .runUnchecked(c)\n\n override fun upsertBatch(\n unsaved: Iterator,\n c: Connection\n ): List = Fragment.interpolate(Fragment.lit(\"MERGE INTO \\\"showcase\\\".\\\"employee\\\" t\\nUSING (SELECT ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? FROM DUAL) s\\nON (\\\"id\\\")\\nWHEN MATCHED THEN UPDATE SET t.\\\"department_id\\\" = s.\\\"department_id\\\",\\nt.\\\"manager_id\\\" = s.\\\"manager_id\\\",\\nt.\\\"email\\\" = s.\\\"email\\\",\\nt.\\\"first_name\\\" = s.\\\"first_name\\\",\\nt.\\\"last_name\\\" = s.\\\"last_name\\\",\\nt.\\\"salary\\\" = s.\\\"salary\\\",\\nt.\\\"hired_at\\\" = s.\\\"hired_at\\\",\\nt.\\\"active\\\" = s.\\\"active\\\",\\nt.\\\"created_at\\\" = s.\\\"created_at\\\",\\nt.\\\"metadata\\\" = s.\\\"metadata\\\",\\nt.\\\"resume\\\" = s.\\\"resume\\\",\\nt.\\\"photo\\\" = s.\\\"photo\\\",\\nt.\\\"probation_period\\\" = s.\\\"probation_period\\\",\\nt.\\\"shift_duration\\\" = s.\\\"shift_duration\\\"\\nWHEN NOT MATCHED THEN INSERT (\\\"id\\\", \\\"department_id\\\", \\\"manager_id\\\", \\\"email\\\", \\\"first_name\\\", \\\"last_name\\\", \\\"salary\\\", \\\"hired_at\\\", \\\"active\\\", \\\"created_at\\\", \\\"metadata\\\", \\\"resume\\\", \\\"photo\\\", \\\"probation_period\\\", \\\"shift_duration\\\") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\"))\n .updateReturningEach(EmployeeRow._rowParser, unsaved)\n .runUnchecked(c)\n}", - "EmployeeRepoMock": "package showcase.showcase.employee\n\nimport dev.typr.foundations.kotlin.DeleteBuilder\nimport dev.typr.foundations.kotlin.DeleteBuilderMock\nimport dev.typr.foundations.kotlin.DeleteParams\nimport dev.typr.foundations.kotlin.SelectBuilder\nimport dev.typr.foundations.kotlin.SelectBuilderMock\nimport dev.typr.foundations.kotlin.SelectParams\nimport dev.typr.foundations.kotlin.UpdateBuilder\nimport dev.typr.foundations.kotlin.UpdateBuilderMock\nimport dev.typr.foundations.kotlin.UpdateParams\nimport java.lang.RuntimeException\nimport java.sql.Connection\nimport java.util.ArrayList\nimport kotlin.collections.Iterator\nimport kotlin.collections.List\nimport kotlin.collections.Map\nimport kotlin.collections.MutableMap\n\ndata class EmployeeRepoMock(\n val toRow: (EmployeeRowUnsaved) -> EmployeeRow,\n val map: MutableMap = mutableMapOf()\n) : EmployeeRepo {\n override fun delete(): DeleteBuilder = DeleteBuilderMock(EmployeeFields.structure, { map.values.toList() }, DeleteParams.empty(), { row -> row.id }, { id -> map.remove(id) })\n\n override fun deleteById(\n id: EmployeeId,\n c: Connection\n ): Boolean = map.remove(id) != null\n\n override fun deleteByIds(\n ids: Array,\n c: Connection\n ): Int {\n var count = 0\n for (id in ids) {\n if (map.remove(id) != null) {\n count = count + 1\n }\n }\n return count\n }\n\n override fun insert(\n unsaved: EmployeeRow,\n c: Connection\n ): EmployeeRow {\n if (map.containsKey(unsaved.id)) {\n throw RuntimeException(\"id \" + unsaved.id + \" already exists\")\n }\n map[unsaved.id] = unsaved\n return unsaved\n }\n\n override fun insert(\n unsaved: EmployeeRowUnsaved,\n c: Connection\n ): EmployeeRow = insert(toRow(unsaved), c)\n\n override fun select(): SelectBuilder = SelectBuilderMock(EmployeeFields.structure, { map.values.toList() }, SelectParams.empty())\n\n override fun selectAll(c: Connection): List = map.values.toList()\n\n override fun selectById(\n id: EmployeeId,\n c: Connection\n ): EmployeeRow? = map[id]\n\n override fun selectByIds(\n ids: Array,\n c: Connection\n ): List {\n val result = ArrayList()\n for (id in ids) {\n val opt = map[id]\n if (opt != null) {\n result.add(opt!!)\n }\n }\n return result\n }\n\n override fun selectByIdsTracked(\n ids: Array,\n c: Connection\n ): Map = selectByIds(ids, c).associateBy({ row: EmployeeRow -> row.id })\n\n override fun selectByUniqueEmail(\n email: String,\n c: Connection\n ): EmployeeRow? = map.values.toList().find({ v -> (email == v.email) })\n\n override fun update(): UpdateBuilder = UpdateBuilderMock(EmployeeFields.structure, { map.values.toList() }, UpdateParams.empty(), { row -> row })\n\n override fun update(\n row: EmployeeRow,\n c: Connection\n ): Boolean {\n val shouldUpdate = map[row.id]?.takeIf({ oldRow -> (oldRow != row) }) != null\n if (shouldUpdate) {\n map[row.id] = row\n }\n return shouldUpdate\n }\n\n override fun upsert(\n unsaved: EmployeeRow,\n c: Connection\n ): EmployeeRow {\n map[unsaved.id] = unsaved\n return unsaved\n }\n\n override fun upsertBatch(\n unsaved: Iterator,\n c: Connection\n ): List {\n val result = ArrayList()\n while (unsaved.hasNext()) {\n val row = unsaved.next()\n map[row.id] = row\n result.add(row)\n }\n return result\n }\n}", - "EmployeeFields": "package showcase.showcase.employee\n\nimport dev.typr.foundations.OracleTypes\nimport dev.typr.foundations.RowParser\nimport dev.typr.foundations.data.Json\nimport dev.typr.foundations.data.OracleIntervalDS\nimport dev.typr.foundations.data.OracleIntervalYM\nimport dev.typr.foundations.dsl.FieldsExpr\nimport dev.typr.foundations.dsl.Path\nimport dev.typr.foundations.dsl.SqlExpr.FieldLike\nimport dev.typr.foundations.kotlin.ForeignKey\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.RelationStructure\nimport dev.typr.foundations.kotlin.SqlExpr.Field\nimport dev.typr.foundations.kotlin.SqlExpr.IdField\nimport dev.typr.foundations.kotlin.SqlExpr.OptField\nimport java.math.BigDecimal\nimport java.time.LocalDateTime\nimport kotlin.collections.List\nimport showcase.showcase.department.DepartmentFields\nimport showcase.showcase.department.DepartmentId\nimport showcase.showcase.department.DepartmentRow\n\ninterface EmployeeFields : FieldsExpr {\n abstract fun active(): OptField\n\n abstract override fun columns(): List>\n\n abstract fun createdAt(): OptField\n\n abstract fun departmentId(): Field\n\n abstract fun email(): Field\n\n abstract fun firstName(): Field\n\n fun fkDepartment(): ForeignKey = ForeignKey.of(\"employee_department_fk\").withColumnPair(departmentId(), DepartmentFields::id)\n\n fun fkEmployee(): ForeignKey = ForeignKey.of(\"employee_manager_fk\").withColumnPair(managerId(), EmployeeFields::id)\n\n abstract fun hiredAt(): OptField\n\n abstract fun id(): IdField\n\n abstract fun lastName(): Field\n\n abstract fun managerId(): OptField\n\n abstract fun metadata(): OptField\n\n abstract fun photo(): OptField\n\n abstract fun probationPeriod(): OptField\n\n abstract fun resume(): OptField\n\n override fun rowParser(): RowParser = EmployeeRow._rowParser.underlying\n\n abstract fun salary(): OptField\n\n abstract fun shiftDuration(): OptField\n\n companion object {\n data class Impl(val _path: List) : EmployeeFields, RelationStructure {\n override fun id(): IdField = IdField(_path, \"id\", EmployeeRow::id, null, null, { row, value -> row.copy(id = value) }, EmployeeId.oracleType)\n\n override fun departmentId(): Field = Field(_path, \"department_id\", EmployeeRow::departmentId, null, null, { row, value -> row.copy(departmentId = value) }, DepartmentId.oracleType)\n\n override fun managerId(): OptField = OptField(_path, \"manager_id\", EmployeeRow::managerId, null, null, { row, value -> row.copy(managerId = value) }, EmployeeId.oracleType)\n\n override fun email(): Field = Field(_path, \"email\", EmployeeRow::email, null, null, { row, value -> row.copy(email = value) }, OracleTypes.varchar2)\n\n override fun firstName(): Field = Field(_path, \"first_name\", EmployeeRow::firstName, null, null, { row, value -> row.copy(firstName = value) }, OracleTypes.varchar2)\n\n override fun lastName(): Field = Field(_path, \"last_name\", EmployeeRow::lastName, null, null, { row, value -> row.copy(lastName = value) }, OracleTypes.varchar2)\n\n override fun salary(): OptField = OptField(_path, \"salary\", EmployeeRow::salary, null, null, { row, value -> row.copy(salary = value) }, KotlinDbTypes.OracleTypes.number)\n\n override fun hiredAt(): OptField = OptField(_path, \"hired_at\", EmployeeRow::hiredAt, null, null, { row, value -> row.copy(hiredAt = value) }, OracleTypes.date)\n\n override fun active(): OptField = OptField(_path, \"active\", EmployeeRow::active, null, null, { row, value -> row.copy(active = value) }, KotlinDbTypes.OracleTypes.number)\n\n override fun createdAt(): OptField = OptField(_path, \"created_at\", EmployeeRow::createdAt, null, null, { row, value -> row.copy(createdAt = value) }, OracleTypes.timestamp)\n\n override fun metadata(): OptField = OptField(_path, \"metadata\", EmployeeRow::metadata, null, null, { row, value -> row.copy(metadata = value) }, OracleTypes.json)\n\n override fun resume(): OptField = OptField(_path, \"resume\", EmployeeRow::resume, null, null, { row, value -> row.copy(resume = value) }, OracleTypes.clob)\n\n override fun photo(): OptField = OptField(_path, \"photo\", EmployeeRow::photo, null, null, { row, value -> row.copy(photo = value) }, OracleTypes.blob)\n\n override fun probationPeriod(): OptField = OptField(_path, \"probation_period\", EmployeeRow::probationPeriod, null, null, { row, value -> row.copy(probationPeriod = value) }, OracleTypes.intervalYearToMonth)\n\n override fun shiftDuration(): OptField = OptField(_path, \"shift_duration\", EmployeeRow::shiftDuration, null, null, { row, value -> row.copy(shiftDuration = value) }, OracleTypes.intervalDayToSecond)\n\n override fun _path(): List = _path\n\n override fun columns(): List> = listOf(this.id().underlying, this.departmentId().underlying, this.managerId().underlying, this.email().underlying, this.firstName().underlying, this.lastName().underlying, this.salary().underlying, this.hiredAt().underlying, this.active().underlying, this.createdAt().underlying, this.metadata().underlying, this.resume().underlying, this.photo().underlying, this.probationPeriod().underlying, this.shiftDuration().underlying)\n\n override fun withPaths(_path: List): RelationStructure = Impl(_path)\n }\n\n val structure: Impl = Impl(emptyList())\n }\n}", - "DepartmentRow": "package showcase.showcase.department\n\nimport dev.typr.foundations.OracleTypes\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport dev.typr.foundations.kotlin.nullable\nimport java.math.BigDecimal\nimport showcase.showcase.company.CompanyId\n\n/** Table: showcase.department\n * Primary key: id\n */\ndata class DepartmentRow(\n val id: DepartmentId,\n /** Points to [showcase.showcase.company.CompanyRow.id] */\n val companyId: CompanyId,\n val name: String,\n val budget: BigDecimal?\n) {\n companion object {\n val _rowParser: RowParser = RowParsers.of(DepartmentId.oracleType, CompanyId.oracleType, OracleTypes.varchar2, KotlinDbTypes.OracleTypes.number.nullable(), { t0, t1, t2, t3 -> DepartmentRow(t0, t1, t2, t3) }, { row -> arrayOf(row.id, row.companyId, row.name, row.budget) })\n }\n}", - "DepartmentId": "package showcase.showcase.department\n\nimport dev.typr.foundations.OracleType\nimport dev.typr.foundations.OracleTypes\nimport dev.typr.foundations.kotlin.Bijection\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\n\n/** Type for the primary key of table `showcase.department` */\ndata class DepartmentId(val value: String) {\n override fun toString(): kotlin.String {\n return value.toString()\n }\n\n companion object {\n val _rowParser: RowParser =\n RowParsers.of(OracleTypes.varchar2.bimap(::DepartmentId, DepartmentId::value), { x -> x }, { id -> arrayOf(id) })\n\n val bijection: Bijection =\n Bijection.of(DepartmentId::value, ::DepartmentId)\n\n val oracleType: OracleType =\n OracleTypes.varchar2.bimap(::DepartmentId, DepartmentId::value)\n }\n}", - "DepartmentRepo": "package showcase.showcase.department\n\nimport dev.typr.foundations.kotlin.DeleteBuilder\nimport dev.typr.foundations.kotlin.SelectBuilder\nimport dev.typr.foundations.kotlin.UpdateBuilder\nimport java.sql.Connection\nimport kotlin.collections.Iterator\nimport kotlin.collections.List\nimport kotlin.collections.Map\n\ninterface DepartmentRepo {\n abstract fun delete(): DeleteBuilder\n\n abstract fun deleteById(\n id: DepartmentId,\n c: Connection\n ): Boolean\n\n abstract fun deleteByIds(\n ids: Array,\n c: Connection\n ): Int\n\n abstract fun insert(\n unsaved: DepartmentRow,\n c: Connection\n ): DepartmentRow\n\n abstract fun select(): SelectBuilder\n\n abstract fun selectAll(c: Connection): List\n\n abstract fun selectById(\n id: DepartmentId,\n c: Connection\n ): DepartmentRow?\n\n abstract fun selectByIds(\n ids: Array,\n c: Connection\n ): List\n\n abstract fun selectByIdsTracked(\n ids: Array,\n c: Connection\n ): Map\n\n abstract fun update(): UpdateBuilder\n\n abstract fun update(\n row: DepartmentRow,\n c: Connection\n ): Boolean\n\n abstract fun upsert(\n unsaved: DepartmentRow,\n c: Connection\n ): DepartmentRow\n\n abstract fun upsertBatch(\n unsaved: Iterator,\n c: Connection\n ): List\n}", - "DepartmentRepoMock": "package showcase.showcase.department\n\nimport dev.typr.foundations.kotlin.DeleteBuilder\nimport dev.typr.foundations.kotlin.DeleteBuilderMock\nimport dev.typr.foundations.kotlin.DeleteParams\nimport dev.typr.foundations.kotlin.SelectBuilder\nimport dev.typr.foundations.kotlin.SelectBuilderMock\nimport dev.typr.foundations.kotlin.SelectParams\nimport dev.typr.foundations.kotlin.UpdateBuilder\nimport dev.typr.foundations.kotlin.UpdateBuilderMock\nimport dev.typr.foundations.kotlin.UpdateParams\nimport java.lang.RuntimeException\nimport java.sql.Connection\nimport java.util.ArrayList\nimport kotlin.collections.Iterator\nimport kotlin.collections.List\nimport kotlin.collections.Map\nimport kotlin.collections.MutableMap\n\ndata class DepartmentRepoMock(val map: MutableMap = mutableMapOf()) : DepartmentRepo {\n override fun delete(): DeleteBuilder = DeleteBuilderMock(DepartmentFields.structure, { map.values.toList() }, DeleteParams.empty(), { row -> row.id }, { id -> map.remove(id) })\n\n override fun deleteById(\n id: DepartmentId,\n c: Connection\n ): Boolean = map.remove(id) != null\n\n override fun deleteByIds(\n ids: Array,\n c: Connection\n ): Int {\n var count = 0\n for (id in ids) {\n if (map.remove(id) != null) {\n count = count + 1\n }\n }\n return count\n }\n\n override fun insert(\n unsaved: DepartmentRow,\n c: Connection\n ): DepartmentRow {\n if (map.containsKey(unsaved.id)) {\n throw RuntimeException(\"id \" + unsaved.id + \" already exists\")\n }\n map[unsaved.id] = unsaved\n return unsaved\n }\n\n override fun select(): SelectBuilder = SelectBuilderMock(DepartmentFields.structure, { map.values.toList() }, SelectParams.empty())\n\n override fun selectAll(c: Connection): List = map.values.toList()\n\n override fun selectById(\n id: DepartmentId,\n c: Connection\n ): DepartmentRow? = map[id]\n\n override fun selectByIds(\n ids: Array,\n c: Connection\n ): List {\n val result = ArrayList()\n for (id in ids) {\n val opt = map[id]\n if (opt != null) {\n result.add(opt!!)\n }\n }\n return result\n }\n\n override fun selectByIdsTracked(\n ids: Array,\n c: Connection\n ): Map = selectByIds(ids, c).associateBy({ row: DepartmentRow -> row.id })\n\n override fun update(): UpdateBuilder = UpdateBuilderMock(DepartmentFields.structure, { map.values.toList() }, UpdateParams.empty(), { row -> row })\n\n override fun update(\n row: DepartmentRow,\n c: Connection\n ): Boolean {\n val shouldUpdate = map[row.id]?.takeIf({ oldRow -> (oldRow != row) }) != null\n if (shouldUpdate) {\n map[row.id] = row\n }\n return shouldUpdate\n }\n\n override fun upsert(\n unsaved: DepartmentRow,\n c: Connection\n ): DepartmentRow {\n map[unsaved.id] = unsaved\n return unsaved\n }\n\n override fun upsertBatch(\n unsaved: Iterator,\n c: Connection\n ): List {\n val result = ArrayList()\n while (unsaved.hasNext()) {\n val row = unsaved.next()\n map[row.id] = row\n result.add(row)\n }\n return result\n }\n}", - "ProjectAssignmentRow": "package showcase.showcase.project_assignment\n\nimport dev.typr.foundations.OracleTypes\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport dev.typr.foundations.kotlin.nullable\nimport java.math.BigDecimal\nimport java.time.LocalDateTime\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.employee.EmployeeId\nimport showcase.showcase.project.ProjectId\n\n/** Table: showcase.project_assignment\n * Composite primary key: employee_id, project_id\n */\ndata class ProjectAssignmentRow(\n /** Points to [showcase.showcase.employee.EmployeeRow.id] */\n val employeeId: EmployeeId,\n /** Points to [showcase.showcase.project.ProjectRow.id] */\n val projectId: ProjectId,\n val role: String,\n /** Default: 0 */\n val hoursAllocated: BigDecimal?,\n val startDate: LocalDateTime?,\n val endDate: LocalDateTime?\n) {\n fun compositeId(): ProjectAssignmentId = ProjectAssignmentId(employeeId, projectId)\n\n fun id(): ProjectAssignmentId = this.compositeId()\n\n fun toUnsavedRow(hoursAllocated: Defaulted): ProjectAssignmentRowUnsaved = ProjectAssignmentRowUnsaved(employeeId, projectId, role, startDate, endDate, hoursAllocated)\n\n companion object {\n val _rowParser: RowParser = RowParsers.of(EmployeeId.oracleType, ProjectId.oracleType, OracleTypes.varchar2, KotlinDbTypes.OracleTypes.number.nullable(), OracleTypes.date.nullable(), OracleTypes.date.nullable(), { t0, t1, t2, t3, t4, t5 -> ProjectAssignmentRow(t0, t1, t2, t3, t4, t5) }, { row -> arrayOf(row.employeeId, row.projectId, row.role, row.hoursAllocated, row.startDate, row.endDate) })\n\n fun apply(\n compositeId: ProjectAssignmentId,\n role: String,\n hoursAllocated: BigDecimal?,\n startDate: LocalDateTime?,\n endDate: LocalDateTime?\n ): ProjectAssignmentRow = ProjectAssignmentRow(compositeId.employeeId, compositeId.projectId, role, hoursAllocated, startDate, endDate)\n }\n}", - "ProjectAssignmentRowUnsaved": "package showcase.showcase.project_assignment\n\nimport java.math.BigDecimal\nimport java.time.LocalDateTime\nimport showcase.customtypes.Defaulted\nimport showcase.customtypes.Defaulted.UseDefault\nimport showcase.showcase.employee.EmployeeId\nimport showcase.showcase.project.ProjectId\n\n/** This class corresponds to a row in table `showcase.project_assignment` which has not been persisted yet */\ndata class ProjectAssignmentRowUnsaved(\n /** Points to [showcase.showcase.employee.EmployeeRow.id] */\n val employeeId: EmployeeId,\n /** Points to [showcase.showcase.project.ProjectRow.id] */\n val projectId: ProjectId,\n val role: String,\n val startDate: LocalDateTime? = null,\n val endDate: LocalDateTime? = null,\n /** Default: 0 */\n val hoursAllocated: Defaulted = UseDefault()\n) {\n fun toRow(hoursAllocatedDefault: () -> BigDecimal?): ProjectAssignmentRow = ProjectAssignmentRow(employeeId = employeeId, projectId = projectId, role = role, hoursAllocated = hoursAllocated.getOrElse(hoursAllocatedDefault), startDate = startDate, endDate = endDate)\n}", - "ProjectAssignmentId": "package showcase.showcase.project_assignment\n\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport showcase.showcase.employee.EmployeeId\nimport showcase.showcase.project.ProjectId\n\n/** Type for the composite primary key of table `showcase.project_assignment` */\ndata class ProjectAssignmentId(\n val employeeId: EmployeeId,\n val projectId: ProjectId\n) {\n companion object {\n val _rowParser: RowParser = RowParsers.of(EmployeeId.oracleType, ProjectId.oracleType, { t0, t1 -> ProjectAssignmentId(t0, t1) }, { row -> arrayOf(row.employeeId, row.projectId) })\n }\n}", - "ProjectAssignmentRepo": "package showcase.showcase.project_assignment\n\nimport dev.typr.foundations.kotlin.DeleteBuilder\nimport dev.typr.foundations.kotlin.SelectBuilder\nimport dev.typr.foundations.kotlin.UpdateBuilder\nimport java.sql.Connection\nimport kotlin.collections.Iterator\nimport kotlin.collections.List\nimport kotlin.collections.Map\n\ninterface ProjectAssignmentRepo {\n abstract fun delete(): DeleteBuilder\n\n abstract fun deleteById(\n compositeId: ProjectAssignmentId,\n c: Connection\n ): Boolean\n\n abstract fun deleteByIds(\n compositeIds: Array,\n c: Connection\n ): Int\n\n abstract fun insert(\n unsaved: ProjectAssignmentRow,\n c: Connection\n ): ProjectAssignmentRow\n\n abstract fun insert(\n unsaved: ProjectAssignmentRowUnsaved,\n c: Connection\n ): ProjectAssignmentRow\n\n abstract fun select(): SelectBuilder\n\n abstract fun selectAll(c: Connection): List\n\n abstract fun selectById(\n compositeId: ProjectAssignmentId,\n c: Connection\n ): ProjectAssignmentRow?\n\n abstract fun selectByIds(\n compositeIds: Array,\n c: Connection\n ): List\n\n abstract fun selectByIdsTracked(\n compositeIds: Array,\n c: Connection\n ): Map\n\n abstract fun update(): UpdateBuilder\n\n abstract fun update(\n row: ProjectAssignmentRow,\n c: Connection\n ): Boolean\n\n abstract fun upsert(\n unsaved: ProjectAssignmentRow,\n c: Connection\n ): ProjectAssignmentRow\n\n abstract fun upsertBatch(\n unsaved: Iterator,\n c: Connection\n ): List\n}", - "ProjectRow": "package showcase.showcase.project\n\nimport dev.typr.foundations.OracleTypes\nimport dev.typr.foundations.data.Json\nimport dev.typr.foundations.data.OracleIntervalDS\nimport dev.typr.foundations.data.OracleIntervalYM\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport dev.typr.foundations.kotlin.nullable\nimport java.math.BigDecimal\nimport java.time.LocalDateTime\nimport showcase.customtypes.Defaulted\n\n/** Table: showcase.project\n * Primary key: id\n */\ndata class ProjectRow(\n val id: ProjectId,\n val name: String,\n val description: String?,\n val startDate: LocalDateTime?,\n val endDate: LocalDateTime?,\n val budget: BigDecimal?,\n /** Default: 'planning' */\n val status: String?,\n /** Default: CURRENT_TIMESTAMP */\n val createdAt: LocalDateTime?,\n val metadata: Json?,\n val descriptionLong: String?,\n val attachments: ByteArray?,\n val estimatedDuration: OracleIntervalYM?,\n val actualDuration: OracleIntervalDS?,\n val xmlPlan: String?\n) {\n fun toUnsavedRow(\n status: Defaulted,\n createdAt: Defaulted\n ): ProjectRowUnsaved = ProjectRowUnsaved(id, name, description, startDate, endDate, budget, metadata, descriptionLong, attachments, estimatedDuration, actualDuration, xmlPlan, status, createdAt)\n\n companion object {\n val _rowParser: RowParser = RowParsers.of(ProjectId.oracleType, OracleTypes.varchar2, OracleTypes.varchar2.nullable(), OracleTypes.date.nullable(), OracleTypes.date.nullable(), KotlinDbTypes.OracleTypes.number.nullable(), OracleTypes.varchar2.nullable(), OracleTypes.timestamp.nullable(), OracleTypes.json.nullable(), OracleTypes.clob.nullable(), OracleTypes.blob.nullable(), OracleTypes.intervalYearToMonth.nullable(), OracleTypes.intervalDayToSecond.nullable(), OracleTypes.xmlType.nullable(), { t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13 -> ProjectRow(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13) }, { row -> arrayOf(row.id, row.name, row.description, row.startDate, row.endDate, row.budget, row.status, row.createdAt, row.metadata, row.descriptionLong, row.attachments, row.estimatedDuration, row.actualDuration, row.xmlPlan) })\n }\n}", - "ProjectId": "package showcase.showcase.project\n\nimport dev.typr.foundations.OracleType\nimport dev.typr.foundations.OracleTypes\nimport dev.typr.foundations.kotlin.Bijection\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\n\n/** Type for the primary key of table `showcase.project` */\ndata class ProjectId(val value: String) {\n override fun toString(): kotlin.String {\n return value.toString()\n }\n\n companion object {\n val _rowParser: RowParser =\n RowParsers.of(OracleTypes.varchar2.bimap(::ProjectId, ProjectId::value), { x -> x }, { id -> arrayOf(id) })\n\n val bijection: Bijection =\n Bijection.of(ProjectId::value, ::ProjectId)\n\n val oracleType: OracleType =\n OracleTypes.varchar2.bimap(::ProjectId, ProjectId::value)\n }\n}", - "EmployeeSummaryViewRow": "package showcase.showcase.employee_summary\n\nimport dev.typr.foundations.OracleTypes\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport dev.typr.foundations.kotlin.nullable\nimport java.math.BigDecimal\nimport java.time.LocalDateTime\nimport showcase.showcase.company.CompanyId\nimport showcase.showcase.department.DepartmentId\nimport showcase.showcase.employee.EmployeeId\n\n/** View: showcase.employee_summary\n * Summary view of employees with their department and company information\n */\ndata class EmployeeSummaryViewRow(\n /** Points to [showcase.showcase.employee.EmployeeRow.id] */\n val employeeId: EmployeeId,\n val email: String,\n val firstName: String,\n val lastName: String,\n val salary: BigDecimal?,\n val hiredAt: LocalDateTime?,\n val active: BigDecimal?,\n /** Points to [showcase.showcase.department.DepartmentRow.id] */\n val departmentId: DepartmentId,\n val departmentName: String,\n val departmentBudget: BigDecimal?,\n /** Points to [showcase.showcase.company.CompanyRow.id] */\n val companyId: CompanyId,\n val companyName: String,\n val managerId: String?,\n val managerFirstName: String?,\n val managerLastName: String?\n) {\n companion object {\n val _rowParser: RowParser = RowParsers.of(EmployeeId.oracleType, OracleTypes.varchar2, OracleTypes.varchar2, OracleTypes.varchar2, KotlinDbTypes.OracleTypes.number.nullable(), OracleTypes.date.nullable(), KotlinDbTypes.OracleTypes.number.nullable(), DepartmentId.oracleType, OracleTypes.varchar2, KotlinDbTypes.OracleTypes.number.nullable(), CompanyId.oracleType, OracleTypes.varchar2, OracleTypes.varchar2.nullable(), OracleTypes.varchar2.nullable(), OracleTypes.varchar2.nullable(), { t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14 -> EmployeeSummaryViewRow(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14) }, { row -> arrayOf(row.employeeId, row.email, row.firstName, row.lastName, row.salary, row.hiredAt, row.active, row.departmentId, row.departmentName, row.departmentBudget, row.companyId, row.companyName, row.managerId, row.managerFirstName, row.managerLastName) })\n }\n}", - "EmployeeSummaryViewRepo": "package showcase.showcase.employee_summary\n\nimport dev.typr.foundations.kotlin.SelectBuilder\nimport java.sql.Connection\nimport kotlin.collections.List\n\ninterface EmployeeSummaryViewRepo {\n abstract fun select(): SelectBuilder\n\n abstract fun selectAll(c: Connection): List\n}", - "CustomerOrderRow": "package showcase.showcase.customer_order\n\nimport dev.typr.foundations.OracleTypes\nimport dev.typr.foundations.data.Json\nimport dev.typr.foundations.data.OracleIntervalDS\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport dev.typr.foundations.kotlin.nullable\nimport java.math.BigDecimal\nimport java.time.LocalDateTime\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.address.AddressId\nimport showcase.showcase.customer.CustomerId\n\n/** Table: showcase.customer_order\n * Primary key: id\n */\ndata class CustomerOrderRow(\n val id: CustomerOrderId,\n /** Points to [showcase.showcase.customer.CustomerRow.id] */\n val customerId: CustomerId,\n /** Points to [showcase.showcase.address.AddressRow.id] */\n val shippingAddressId: AddressId?,\n /** Points to [showcase.showcase.address.AddressRow.id] */\n val billingAddressId: AddressId?,\n /** Default: 'pending' */\n val status: String?,\n val subtotal: BigDecimal,\n /** Default: 0 */\n val tax: BigDecimal?,\n /** Default: 0 */\n val shipping: BigDecimal?,\n val total: BigDecimal,\n val notes: String?,\n /** Default: CURRENT_TIMESTAMP */\n val createdAt: LocalDateTime?,\n val shippedAt: LocalDateTime?,\n val deliveredAt: LocalDateTime?,\n val metadata: Json?,\n val notesExtended: String?,\n val receiptData: ByteArray?,\n val processingTime: OracleIntervalDS?,\n val xmlInvoice: String?\n) {\n fun toUnsavedRow(\n status: Defaulted,\n tax: Defaulted,\n shipping: Defaulted,\n createdAt: Defaulted\n ): CustomerOrderRowUnsaved = CustomerOrderRowUnsaved(id, customerId, shippingAddressId, billingAddressId, subtotal, total, notes, shippedAt, deliveredAt, metadata, notesExtended, receiptData, processingTime, xmlInvoice, status, tax, shipping, createdAt)\n\n companion object {\n val _rowParser: RowParser = RowParsers.of(CustomerOrderId.oracleType, CustomerId.oracleType, AddressId.oracleType.nullable(), AddressId.oracleType.nullable(), OracleTypes.varchar2.nullable(), KotlinDbTypes.OracleTypes.number, KotlinDbTypes.OracleTypes.number.nullable(), KotlinDbTypes.OracleTypes.number.nullable(), KotlinDbTypes.OracleTypes.number, OracleTypes.varchar2.nullable(), OracleTypes.timestamp.nullable(), OracleTypes.timestamp.nullable(), OracleTypes.timestamp.nullable(), OracleTypes.json.nullable(), OracleTypes.clob.nullable(), OracleTypes.blob.nullable(), OracleTypes.intervalDayToSecond.nullable(), OracleTypes.xmlType.nullable(), { t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17 -> CustomerOrderRow(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17) }, { row -> arrayOf(row.id, row.customerId, row.shippingAddressId, row.billingAddressId, row.status, row.subtotal, row.tax, row.shipping, row.total, row.notes, row.createdAt, row.shippedAt, row.deliveredAt, row.metadata, row.notesExtended, row.receiptData, row.processingTime, row.xmlInvoice) })\n }\n}", - "CustomerOrderRepo": "package showcase.showcase.customer_order\n\nimport dev.typr.foundations.kotlin.DeleteBuilder\nimport dev.typr.foundations.kotlin.SelectBuilder\nimport dev.typr.foundations.kotlin.UpdateBuilder\nimport java.sql.Connection\nimport kotlin.collections.Iterator\nimport kotlin.collections.List\nimport kotlin.collections.Map\n\ninterface CustomerOrderRepo {\n abstract fun delete(): DeleteBuilder\n\n abstract fun deleteById(\n id: CustomerOrderId,\n c: Connection\n ): Boolean\n\n abstract fun deleteByIds(\n ids: Array,\n c: Connection\n ): Int\n\n abstract fun insert(\n unsaved: CustomerOrderRow,\n c: Connection\n ): CustomerOrderRow\n\n abstract fun insert(\n unsaved: CustomerOrderRowUnsaved,\n c: Connection\n ): CustomerOrderRow\n\n abstract fun select(): SelectBuilder\n\n abstract fun selectAll(c: Connection): List\n\n abstract fun selectById(\n id: CustomerOrderId,\n c: Connection\n ): CustomerOrderRow?\n\n abstract fun selectByIds(\n ids: Array,\n c: Connection\n ): List\n\n abstract fun selectByIdsTracked(\n ids: Array,\n c: Connection\n ): Map\n\n abstract fun update(): UpdateBuilder\n\n abstract fun update(\n row: CustomerOrderRow,\n c: Connection\n ): Boolean\n\n abstract fun upsert(\n unsaved: CustomerOrderRow,\n c: Connection\n ): CustomerOrderRow\n\n abstract fun upsertBatch(\n unsaved: Iterator,\n c: Connection\n ): List\n}", - "OrderItemRow": "package showcase.showcase.order_item\n\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport dev.typr.foundations.kotlin.nullable\nimport java.math.BigDecimal\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.customer_order.CustomerOrderId\nimport showcase.showcase.product.ProductId\n\n/** Table: showcase.order_item\n * Composite primary key: order_id, product_id\n */\ndata class OrderItemRow(\n /** Points to [showcase.showcase.customer_order.CustomerOrderRow.id] */\n val orderId: CustomerOrderId,\n /** Points to [showcase.showcase.product.ProductRow.id] */\n val productId: ProductId,\n val quantity: BigDecimal,\n val unitPrice: BigDecimal,\n /** Default: 0 */\n val discount: BigDecimal?\n) {\n fun compositeId(): OrderItemId = OrderItemId(orderId, productId)\n\n fun id(): OrderItemId = this.compositeId()\n\n fun toUnsavedRow(discount: Defaulted): OrderItemRowUnsaved = OrderItemRowUnsaved(orderId, productId, quantity, unitPrice, discount)\n\n companion object {\n val _rowParser: RowParser = RowParsers.of(CustomerOrderId.oracleType, ProductId.oracleType, KotlinDbTypes.OracleTypes.number, KotlinDbTypes.OracleTypes.number, KotlinDbTypes.OracleTypes.number.nullable(), { t0, t1, t2, t3, t4 -> OrderItemRow(t0, t1, t2, t3, t4) }, { row -> arrayOf(row.orderId, row.productId, row.quantity, row.unitPrice, row.discount) })\n\n fun apply(\n compositeId: OrderItemId,\n quantity: BigDecimal,\n unitPrice: BigDecimal,\n discount: BigDecimal?\n ): OrderItemRow = OrderItemRow(compositeId.orderId, compositeId.productId, quantity, unitPrice, discount)\n }\n}", - "OrderItemId": "package showcase.showcase.order_item\n\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport showcase.showcase.customer_order.CustomerOrderId\nimport showcase.showcase.product.ProductId\n\n/** Type for the composite primary key of table `showcase.order_item` */\ndata class OrderItemId(\n val orderId: CustomerOrderId,\n val productId: ProductId\n) {\n companion object {\n val _rowParser: RowParser = RowParsers.of(CustomerOrderId.oracleType, ProductId.oracleType, { t0, t1 -> OrderItemId(t0, t1) }, { row -> arrayOf(row.orderId, row.productId) })\n }\n}", - "ProductRow": "package showcase.showcase.product\n\nimport dev.typr.foundations.OracleTypes\nimport dev.typr.foundations.data.Json\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport dev.typr.foundations.kotlin.nullable\nimport java.math.BigDecimal\nimport java.time.LocalDateTime\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.category.CategoryId\n\n/** Table: showcase.product\n * Primary key: id\n */\ndata class ProductRow(\n val id: ProductId,\n /** Points to [showcase.showcase.category.CategoryRow.id] */\n val categoryId: CategoryId?,\n val name: String,\n val sku: String,\n val price: BigDecimal,\n val cost: BigDecimal?,\n /** Default: true */\n val inStock: BigDecimal?,\n /** Default: 0 */\n val quantity: BigDecimal?,\n val weight: BigDecimal?,\n /** Default: CURRENT_TIMESTAMP */\n val createdAt: LocalDateTime?,\n val attributes: Json?,\n val specifications: String?,\n val descriptionLong: String?,\n val thumbnail: ByteArray?,\n val xmlData: String?\n) {\n fun toUnsavedRow(\n inStock: Defaulted,\n quantity: Defaulted,\n createdAt: Defaulted\n ): ProductRowUnsaved = ProductRowUnsaved(id, categoryId, name, sku, price, cost, weight, attributes, specifications, descriptionLong, thumbnail, xmlData, inStock, quantity, createdAt)\n\n companion object {\n val _rowParser: RowParser = RowParsers.of(ProductId.oracleType, CategoryId.oracleType.nullable(), OracleTypes.varchar2, OracleTypes.varchar2, KotlinDbTypes.OracleTypes.number, KotlinDbTypes.OracleTypes.number.nullable(), KotlinDbTypes.OracleTypes.number.nullable(), KotlinDbTypes.OracleTypes.number.nullable(), KotlinDbTypes.OracleTypes.number.nullable(), OracleTypes.timestamp.nullable(), OracleTypes.json.nullable(), OracleTypes.clob.nullable(), OracleTypes.clob.nullable(), OracleTypes.blob.nullable(), OracleTypes.xmlType.nullable(), { t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14 -> ProductRow(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14) }, { row -> arrayOf(row.id, row.categoryId, row.name, row.sku, row.price, row.cost, row.inStock, row.quantity, row.weight, row.createdAt, row.attributes, row.specifications, row.descriptionLong, row.thumbnail, row.xmlData) })\n }\n}", - "ProductId": "package showcase.showcase.product\n\nimport dev.typr.foundations.OracleType\nimport dev.typr.foundations.OracleTypes\nimport dev.typr.foundations.kotlin.Bijection\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\n\n/** Type for the primary key of table `showcase.product` */\ndata class ProductId(val value: String) {\n override fun toString(): kotlin.String {\n return value.toString()\n }\n\n companion object {\n val _rowParser: RowParser =\n RowParsers.of(OracleTypes.varchar2.bimap(::ProductId, ProductId::value), { x -> x }, { id -> arrayOf(id) })\n\n val bijection: Bijection =\n Bijection.of(ProductId::value, ::ProductId)\n\n val oracleType: OracleType =\n OracleTypes.varchar2.bimap(::ProductId, ProductId::value)\n }\n}", - "CategoryRow": "package showcase.showcase.category\n\nimport dev.typr.foundations.OracleTypes\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport dev.typr.foundations.kotlin.nullable\n\n/** Table: showcase.category\n * Primary key: id\n */\ndata class CategoryRow(\n val id: CategoryId,\n /** Points to [showcase.showcase.category.CategoryRow.id] */\n val parentId: CategoryId?,\n val name: String,\n val description: String?\n) {\n companion object {\n val _rowParser: RowParser = RowParsers.of(CategoryId.oracleType, CategoryId.oracleType.nullable(), OracleTypes.varchar2, OracleTypes.varchar2.nullable(), { t0, t1, t2, t3 -> CategoryRow(t0, t1, t2, t3) }, { row -> arrayOf(row.id, row.parentId, row.name, row.description) })\n }\n}", - "CategoryId": "package showcase.showcase.category\n\nimport dev.typr.foundations.OracleType\nimport dev.typr.foundations.OracleTypes\nimport dev.typr.foundations.kotlin.Bijection\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\n\n/** Type for the primary key of table `showcase.category` */\ndata class CategoryId(val value: String) {\n override fun toString(): kotlin.String {\n return value.toString()\n }\n\n companion object {\n val _rowParser: RowParser =\n RowParsers.of(OracleTypes.varchar2.bimap(::CategoryId, CategoryId::value), { x -> x }, { id -> arrayOf(id) })\n\n val bijection: Bijection =\n Bijection.of(CategoryId::value, ::CategoryId)\n\n val oracleType: OracleType =\n OracleTypes.varchar2.bimap(::CategoryId, CategoryId::value)\n }\n}", - "AddressRow": "package showcase.showcase.address\n\nimport dev.typr.foundations.OracleTypes\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport dev.typr.foundations.kotlin.nullable\nimport java.math.BigDecimal\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.customer.CustomerId\n\n/** Table: showcase.address\n * Primary key: id\n */\ndata class AddressRow(\n val id: AddressId,\n /** Points to [showcase.showcase.customer.CustomerRow.id] */\n val customerId: CustomerId,\n val addressType: String,\n val street: String,\n val city: String,\n val state: String?,\n val postalCode: String?,\n val country: String,\n /** Default: false */\n val isDefault: BigDecimal?,\n val location: /* SDO_POINT (Oracle Spatial) */ String?,\n val notes: String?\n) {\n fun toUnsavedRow(isDefault: Defaulted): AddressRowUnsaved = AddressRowUnsaved(id, customerId, addressType, street, city, state, postalCode, country, location, notes, isDefault)\n\n companion object {\n val _rowParser: RowParser = RowParsers.of(AddressId.oracleType, CustomerId.oracleType, OracleTypes.varchar2, OracleTypes.varchar2, OracleTypes.varchar2, OracleTypes.varchar2.nullable(), OracleTypes.varchar2.nullable(), OracleTypes.varchar2, KotlinDbTypes.OracleTypes.number.nullable(), OracleTypes.varchar2.nullable(), OracleTypes.clob.nullable(), { t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10 -> AddressRow(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10) }, { row -> arrayOf(row.id, row.customerId, row.addressType, row.street, row.city, row.state, row.postalCode, row.country, row.isDefault, row.location, row.notes) })\n }\n}", - "AddressId": "package showcase.showcase.address\n\nimport dev.typr.foundations.OracleType\nimport dev.typr.foundations.OracleTypes\nimport dev.typr.foundations.kotlin.Bijection\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\n\n/** Type for the primary key of table `showcase.address` */\ndata class AddressId(val value: String) {\n override fun toString(): kotlin.String {\n return value.toString()\n }\n\n companion object {\n val _rowParser: RowParser =\n RowParsers.of(OracleTypes.varchar2.bimap(::AddressId, AddressId::value), { x -> x }, { id -> arrayOf(id) })\n\n val bijection: Bijection =\n Bijection.of(AddressId::value, ::AddressId)\n\n val oracleType: OracleType =\n OracleTypes.varchar2.bimap(::AddressId, AddressId::value)\n }\n}", - "Defaulted": "package showcase.customtypes\n\n\n\n/** This signals a value where if you don't provide it, postgres will generate it for you */\nsealed interface Defaulted {\n data class Provided(val value: T) : Defaulted {\n override fun fold(\n onDefault: () -> U,\n onProvided: (T) -> U\n ): U = onProvided(value)\n\n override fun getOrElse(onDefault: () -> T): T = value\n\n override fun visit(\n onDefault: () -> Unit,\n onProvided: (T) -> Unit\n ) {\n onProvided(value)\n }\n }\n\n class UseDefault : Defaulted {\n override fun fold(\n onDefault: () -> U,\n onProvided: (T) -> U\n ): U = onDefault()\n\n override fun getOrElse(onDefault: () -> T): T = onDefault()\n\n override fun visit(\n onDefault: () -> Unit,\n onProvided: (T) -> Unit\n ) {\n onDefault()\n }\n }\n\n abstract fun fold(\n onDefault: () -> U,\n onProvided: (T) -> U\n ): U\n\n abstract fun getOrElse(onDefault: () -> T): T\n\n abstract fun visit(\n onDefault: () -> Unit,\n onProvided: (T) -> Unit\n )\n}", - "TestInsert": "package showcase\n\nimport dev.typr.foundations.data.Json\nimport dev.typr.foundations.data.OracleIntervalDS\nimport dev.typr.foundations.data.OracleIntervalYM\nimport java.math.BigDecimal\nimport java.sql.Connection\nimport java.time.LocalDateTime\nimport java.util.Random\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.address.AddressId\nimport showcase.showcase.address.AddressRepoImpl\nimport showcase.showcase.address.AddressRow\nimport showcase.showcase.address.AddressRowUnsaved\nimport showcase.showcase.audit_log.AuditLogId\nimport showcase.showcase.audit_log.AuditLogRepoImpl\nimport showcase.showcase.audit_log.AuditLogRow\nimport showcase.showcase.audit_log.AuditLogRowUnsaved\nimport showcase.showcase.category.CategoryId\nimport showcase.showcase.category.CategoryRepoImpl\nimport showcase.showcase.category.CategoryRow\nimport showcase.showcase.company.CompanyId\nimport showcase.showcase.company.CompanyRepoImpl\nimport showcase.showcase.company.CompanyRow\nimport showcase.showcase.company.CompanyRowUnsaved\nimport showcase.showcase.customer.CustomerId\nimport showcase.showcase.customer.CustomerRepoImpl\nimport showcase.showcase.customer.CustomerRow\nimport showcase.showcase.customer.CustomerRowUnsaved\nimport showcase.showcase.customer_order.CustomerOrderId\nimport showcase.showcase.customer_order.CustomerOrderRepoImpl\nimport showcase.showcase.customer_order.CustomerOrderRow\nimport showcase.showcase.customer_order.CustomerOrderRowUnsaved\nimport showcase.showcase.department.DepartmentId\nimport showcase.showcase.department.DepartmentRepoImpl\nimport showcase.showcase.department.DepartmentRow\nimport showcase.showcase.employee.EmployeeId\nimport showcase.showcase.employee.EmployeeRepoImpl\nimport showcase.showcase.employee.EmployeeRow\nimport showcase.showcase.employee.EmployeeRowUnsaved\nimport showcase.showcase.order_item.OrderItemRepoImpl\nimport showcase.showcase.order_item.OrderItemRow\nimport showcase.showcase.order_item.OrderItemRowUnsaved\nimport showcase.showcase.product.ProductId\nimport showcase.showcase.product.ProductRepoImpl\nimport showcase.showcase.product.ProductRow\nimport showcase.showcase.product.ProductRowUnsaved\nimport showcase.showcase.project.ProjectId\nimport showcase.showcase.project.ProjectRepoImpl\nimport showcase.showcase.project.ProjectRow\nimport showcase.showcase.project.ProjectRowUnsaved\nimport showcase.showcase.project_assignment.ProjectAssignmentRepoImpl\nimport showcase.showcase.project_assignment.ProjectAssignmentRow\nimport showcase.showcase.project_assignment.ProjectAssignmentRowUnsaved\n\n/** Methods to generate random data for `Ident(TestInsert)` */\ndata class TestInsert(val random: Random) {\n fun showcaseAddress(\n id: AddressId,\n customerId: CustomerId,\n addressType: String,\n street: String,\n city: String,\n country: String,\n state: String?,\n postalCode: String?,\n location: /* SDO_POINT (Oracle Spatial) */ String?,\n notes: String?,\n isDefault: Defaulted,\n c: Connection\n ): AddressRow = (AddressRepoImpl()).insert(AddressRowUnsaved(id = id, customerId = customerId, addressType = addressType, street = street, city = city, state = state, postalCode = postalCode, country = country, location = location, notes = notes, isDefault = isDefault), c)\n\n fun showcaseAuditLog(\n id: AuditLogId,\n tableName: String,\n recordId: String,\n action: String,\n oldValues: String?,\n newValues: String?,\n changedBy: EmployeeId?,\n changedAt: Defaulted,\n c: Connection\n ): AuditLogRow = (AuditLogRepoImpl()).insert(AuditLogRowUnsaved(id = id, tableName = tableName, recordId = recordId, action = action, oldValues = oldValues, newValues = newValues, changedBy = changedBy, changedAt = changedAt), c)\n\n fun showcaseCategory(\n id: CategoryId,\n name: String,\n parentId: CategoryId?,\n description: String?,\n c: Connection\n ): CategoryRow = (CategoryRepoImpl()).insert(CategoryRow(id = id, parentId = parentId, name = name, description = description), c)\n\n fun showcaseCompany(\n id: CompanyId,\n name: String,\n foundedYear: BigDecimal?,\n active: Defaulted,\n createdAt: Defaulted,\n c: Connection\n ): CompanyRow = (CompanyRepoImpl()).insert(CompanyRowUnsaved(id = id, name = name, foundedYear = foundedYear, active = active, createdAt = createdAt), c)\n\n fun showcaseCustomer(\n id: CustomerId,\n email: String,\n firstName: String,\n lastName: String,\n phone: String?,\n preferences: Json?,\n avatar: ByteArray?,\n notes: String?,\n verified: Defaulted,\n createdAt: Defaulted,\n c: Connection\n ): CustomerRow = (CustomerRepoImpl()).insert(CustomerRowUnsaved(id = id, email = email, firstName = firstName, lastName = lastName, phone = phone, preferences = preferences, avatar = avatar, notes = notes, verified = verified, createdAt = createdAt), c)\n\n fun showcaseCustomerOrder(\n id: CustomerOrderId,\n customerId: CustomerId,\n shippingAddressId: AddressId?,\n billingAddressId: AddressId?,\n subtotal: BigDecimal,\n total: BigDecimal,\n notes: String?,\n shippedAt: LocalDateTime?,\n deliveredAt: LocalDateTime?,\n metadata: Json?,\n notesExtended: String?,\n receiptData: ByteArray?,\n processingTime: OracleIntervalDS?,\n xmlInvoice: String?,\n status: Defaulted,\n tax: Defaulted,\n shipping: Defaulted,\n createdAt: Defaulted,\n c: Connection\n ): CustomerOrderRow = (CustomerOrderRepoImpl()).insert(CustomerOrderRowUnsaved(id = id, customerId = customerId, shippingAddressId = shippingAddressId, billingAddressId = billingAddressId, subtotal = subtotal, total = total, notes = notes, shippedAt = shippedAt, deliveredAt = deliveredAt, metadata = metadata, notesExtended = notesExtended, receiptData = receiptData, processingTime = processingTime, xmlInvoice = xmlInvoice, status = status, tax = tax, shipping = shipping, createdAt = createdAt), c)\n\n fun showcaseDepartment(\n id: DepartmentId,\n companyId: CompanyId,\n name: String,\n budget: BigDecimal?,\n c: Connection\n ): DepartmentRow = (DepartmentRepoImpl()).insert(DepartmentRow(id = id, companyId = companyId, name = name, budget = budget), c)\n\n fun showcaseEmployee(\n id: EmployeeId,\n departmentId: DepartmentId,\n email: String,\n firstName: String,\n lastName: String,\n managerId: EmployeeId?,\n salary: BigDecimal?,\n hiredAt: LocalDateTime?,\n metadata: Json?,\n resume: String?,\n photo: ByteArray?,\n probationPeriod: OracleIntervalYM?,\n shiftDuration: OracleIntervalDS?,\n active: Defaulted,\n createdAt: Defaulted,\n c: Connection\n ): EmployeeRow = (EmployeeRepoImpl()).insert(EmployeeRowUnsaved(id = id, departmentId = departmentId, managerId = managerId, email = email, firstName = firstName, lastName = lastName, salary = salary, hiredAt = hiredAt, metadata = metadata, resume = resume, photo = photo, probationPeriod = probationPeriod, shiftDuration = shiftDuration, active = active, createdAt = createdAt), c)\n\n fun showcaseOrderItem(\n orderId: CustomerOrderId,\n productId: ProductId,\n quantity: BigDecimal,\n unitPrice: BigDecimal,\n discount: Defaulted,\n c: Connection\n ): OrderItemRow = (OrderItemRepoImpl()).insert(OrderItemRowUnsaved(orderId = orderId, productId = productId, quantity = quantity, unitPrice = unitPrice, discount = discount), c)\n\n fun showcaseProduct(\n id: ProductId,\n name: String,\n sku: String,\n categoryId: CategoryId?,\n price: BigDecimal,\n cost: BigDecimal?,\n weight: BigDecimal?,\n attributes: Json?,\n specifications: String?,\n descriptionLong: String?,\n thumbnail: ByteArray?,\n xmlData: String?,\n inStock: Defaulted,\n quantity: Defaulted,\n createdAt: Defaulted,\n c: Connection\n ): ProductRow = (ProductRepoImpl()).insert(ProductRowUnsaved(id = id, categoryId = categoryId, name = name, sku = sku, price = price, cost = cost, weight = weight, attributes = attributes, specifications = specifications, descriptionLong = descriptionLong, thumbnail = thumbnail, xmlData = xmlData, inStock = inStock, quantity = quantity, createdAt = createdAt), c)\n\n fun showcaseProject(\n id: ProjectId,\n name: String,\n description: String?,\n startDate: LocalDateTime?,\n endDate: LocalDateTime?,\n budget: BigDecimal?,\n metadata: Json?,\n descriptionLong: String?,\n attachments: ByteArray?,\n estimatedDuration: OracleIntervalYM?,\n actualDuration: OracleIntervalDS?,\n xmlPlan: String?,\n status: Defaulted,\n createdAt: Defaulted,\n c: Connection\n ): ProjectRow = (ProjectRepoImpl()).insert(ProjectRowUnsaved(id = id, name = name, description = description, startDate = startDate, endDate = endDate, budget = budget, metadata = metadata, descriptionLong = descriptionLong, attachments = attachments, estimatedDuration = estimatedDuration, actualDuration = actualDuration, xmlPlan = xmlPlan, status = status, createdAt = createdAt), c)\n\n fun showcaseProjectAssignment(\n employeeId: EmployeeId,\n projectId: ProjectId,\n role: String,\n startDate: LocalDateTime?,\n endDate: LocalDateTime?,\n hoursAllocated: Defaulted,\n c: Connection\n ): ProjectAssignmentRow = (ProjectAssignmentRepoImpl()).insert(ProjectAssignmentRowUnsaved(employeeId = employeeId, projectId = projectId, role = role, startDate = startDate, endDate = endDate, hoursAllocated = hoursAllocated), c)\n}" - }, - "scala": { - "CompanyRow": "package showcase.showcase.company\n\nimport dev.typr.foundations.OracleTypes\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport java.time.LocalDateTime\nimport showcase.customtypes.Defaulted\n\n/** Table: showcase.company\n * Primary key: id\n */\ncase class CompanyRow(\n id: CompanyId,\n name: String,\n foundedYear: Option[BigDecimal],\n /** Default: true */\n active: Option[BigDecimal],\n /** Default: CURRENT_TIMESTAMP */\n createdAt: Option[LocalDateTime]\n) {\n def toUnsavedRow(\n active: Defaulted[Option[BigDecimal]] = Defaulted.Provided(this.active),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.Provided(this.createdAt)\n ): CompanyRowUnsaved = {\n new CompanyRowUnsaved(\n id,\n name,\n foundedYear,\n active,\n createdAt\n )\n }\n}\n\nobject CompanyRow {\n val `_rowParser`: RowParser[CompanyRow] = RowParsers.of(CompanyId.oracleType, OracleTypes.varchar2, ScalaDbTypes.OracleTypes.number.nullable, ScalaDbTypes.OracleTypes.number.nullable, OracleTypes.timestamp.nullable)(CompanyRow.apply)(row => Array[Any](row.id, row.name, row.foundedYear, row.active, row.createdAt))\n}", - "CompanyRowUnsaved": "package showcase.showcase.company\n\nimport java.time.LocalDateTime\nimport showcase.customtypes.Defaulted\nimport showcase.customtypes.Defaulted.UseDefault\n\n/** This class corresponds to a row in table `showcase.company` which has not been persisted yet */\ncase class CompanyRowUnsaved(\n id: CompanyId,\n name: String,\n foundedYear: Option[BigDecimal] = None,\n /** Default: true */\n active: Defaulted[Option[BigDecimal]] = new UseDefault(),\n /** Default: CURRENT_TIMESTAMP */\n createdAt: Defaulted[Option[LocalDateTime]] = new UseDefault()\n) {\n def toRow(\n activeDefault: => Option[BigDecimal],\n createdAtDefault: => Option[LocalDateTime]\n ): CompanyRow = {\n new CompanyRow(\n id = id,\n name = name,\n foundedYear = foundedYear,\n active = active.getOrElse(activeDefault),\n createdAt = createdAt.getOrElse(createdAtDefault)\n )\n }\n}", - "CompanyId": "package showcase.showcase.company\n\nimport dev.typr.foundations.OracleType\nimport dev.typr.foundations.OracleTypes\nimport dev.typr.foundations.scala.Bijection\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\n\n/** Type for the primary key of table `showcase.company` */\ncase class CompanyId(value: String) extends scala.AnyVal\n\nobject CompanyId {\n given `_rowParser`: RowParser[CompanyId] = RowParsers.of(OracleTypes.varchar2.bimap(CompanyId.apply, _.value))(x => x)(id => Array[Any](id))\n\n given bijection: Bijection[CompanyId, String] = Bijection.apply[CompanyId, String](_.value)(CompanyId.apply)\n\n given oracleType: OracleType[CompanyId] = OracleTypes.varchar2.bimap(CompanyId.apply, _.value)\n}", - "CompanyRepo": "package showcase.showcase.company\n\nimport dev.typr.foundations.scala.DeleteBuilder\nimport dev.typr.foundations.scala.SelectBuilder\nimport dev.typr.foundations.scala.UpdateBuilder\nimport java.sql.Connection\n\ntrait CompanyRepo {\n def delete: DeleteBuilder[CompanyFields, CompanyRow]\n\n def deleteById(id: CompanyId)(using c: Connection): Boolean\n\n def deleteByIds(ids: Array[CompanyId])(using c: Connection): Int\n\n def insert(unsaved: CompanyRow)(using c: Connection): CompanyRow\n\n def insert(unsaved: CompanyRowUnsaved)(using c: Connection): CompanyRow\n\n def select: SelectBuilder[CompanyFields, CompanyRow]\n\n def selectAll(using c: Connection): List[CompanyRow]\n\n def selectById(id: CompanyId)(using c: Connection): Option[CompanyRow]\n\n def selectByIds(ids: Array[CompanyId])(using c: Connection): List[CompanyRow]\n\n def selectByIdsTracked(ids: Array[CompanyId])(using c: Connection): Map[CompanyId, CompanyRow]\n\n def update: UpdateBuilder[CompanyFields, CompanyRow]\n\n def update(row: CompanyRow)(using c: Connection): Boolean\n\n def upsert(unsaved: CompanyRow)(using c: Connection): CompanyRow\n\n def upsertBatch(unsaved: Iterator[CompanyRow])(using c: Connection): List[CompanyRow]\n}", - "CompanyRepoMock": "package showcase.showcase.company\n\nimport dev.typr.foundations.scala.DeleteBuilder\nimport dev.typr.foundations.scala.DeleteBuilderMock\nimport dev.typr.foundations.scala.DeleteParams\nimport dev.typr.foundations.scala.SelectBuilder\nimport dev.typr.foundations.scala.SelectBuilderMock\nimport dev.typr.foundations.scala.SelectParams\nimport dev.typr.foundations.scala.UpdateBuilder\nimport dev.typr.foundations.scala.UpdateBuilderMock\nimport dev.typr.foundations.scala.UpdateParams\nimport java.lang.RuntimeException\nimport java.sql.Connection\n\ncase class CompanyRepoMock(\n toRow: CompanyRowUnsaved => CompanyRow,\n map: scala.collection.mutable.Map[CompanyId, CompanyRow] = scala.collection.mutable.Map.empty[CompanyId, CompanyRow]\n) extends CompanyRepo {\n override def delete: DeleteBuilder[CompanyFields, CompanyRow] = DeleteBuilderMock(CompanyFields.structure, () => map.values.toList, DeleteParams.empty(), row => row.id, id => map.remove(id): @scala.annotation.nowarn)\n\n override def deleteById(id: CompanyId)(using c: Connection): Boolean = map.remove(id).isDefined\n\n override def deleteByIds(ids: Array[CompanyId])(using c: Connection): Int = {\n var count = 0\n ids.foreach { id => if (map.remove(id).isDefined) {\n count = count + 1\n } }\n return count\n }\n\n override def insert(unsaved: CompanyRow)(using c: Connection): CompanyRow = {\n if (map.contains(unsaved.id)) {\n throw new RuntimeException(s\"id ${unsaved.id} already exists\")\n }\n map.put(unsaved.id, unsaved): @scala.annotation.nowarn\n return unsaved\n }\n\n override def insert(unsaved: CompanyRowUnsaved)(using c: Connection): CompanyRow = insert(toRow(unsaved))(using c)\n\n override def select: SelectBuilder[CompanyFields, CompanyRow] = SelectBuilderMock(CompanyFields.structure, () => map.values.toList, SelectParams.empty())\n\n override def selectAll(using c: Connection): List[CompanyRow] = map.values.toList\n\n override def selectById(id: CompanyId)(using c: Connection): Option[CompanyRow] = map.get(id)\n\n override def selectByIds(ids: Array[CompanyId])(using c: Connection): List[CompanyRow] = ids.flatMap(map.get(_)).toList\n\n override def selectByIdsTracked(ids: Array[CompanyId])(using c: Connection): Map[CompanyId, CompanyRow] = selectByIds(ids)(using c).map(x => (((row: CompanyRow) => row.id).apply(x), x)).toMap\n\n override def update: UpdateBuilder[CompanyFields, CompanyRow] = UpdateBuilderMock(CompanyFields.structure, () => map.values.toList, UpdateParams.empty(), row => row)\n\n override def update(row: CompanyRow)(using c: Connection): Boolean = {\n val shouldUpdate = map.get(row.id).filter(oldRow => (oldRow != row)).isDefined\n if (shouldUpdate) {\n map.put(row.id, row): @scala.annotation.nowarn\n }\n return shouldUpdate\n }\n\n override def upsert(unsaved: CompanyRow)(using c: Connection): CompanyRow = {\n map.put(unsaved.id, unsaved): @scala.annotation.nowarn\n return unsaved\n }\n\n override def upsertBatch(unsaved: Iterator[CompanyRow])(using c: Connection): List[CompanyRow] = {\n unsaved.map { row =>\n map.put(row.id, row): @scala.annotation.nowarn\n row\n }.toList\n }\n}", - "EmployeeRow": "package showcase.showcase.employee\n\nimport dev.typr.foundations.OracleTypes\nimport dev.typr.foundations.data.Json\nimport dev.typr.foundations.data.OracleIntervalDS\nimport dev.typr.foundations.data.OracleIntervalYM\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport java.time.LocalDateTime\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.department.DepartmentId\n\n/** Table: showcase.employee\n * Primary key: id\n */\ncase class EmployeeRow(\n id: EmployeeId,\n /** Points to [[showcase.showcase.department.DepartmentRow.id]] */\n departmentId: DepartmentId,\n /** Points to [[showcase.showcase.employee.EmployeeRow.id]] */\n managerId: Option[EmployeeId],\n email: String,\n firstName: String,\n lastName: String,\n salary: Option[BigDecimal],\n hiredAt: Option[LocalDateTime],\n /** Default: true */\n active: Option[BigDecimal],\n /** Default: CURRENT_TIMESTAMP */\n createdAt: Option[LocalDateTime],\n metadata: Option[Json],\n resume: Option[String],\n photo: Option[Array[Byte]],\n probationPeriod: Option[OracleIntervalYM],\n shiftDuration: Option[OracleIntervalDS]\n) {\n def toUnsavedRow(\n active: Defaulted[Option[BigDecimal]] = Defaulted.Provided(this.active),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.Provided(this.createdAt)\n ): EmployeeRowUnsaved = {\n new EmployeeRowUnsaved(\n id,\n departmentId,\n managerId,\n email,\n firstName,\n lastName,\n salary,\n hiredAt,\n metadata,\n resume,\n photo,\n probationPeriod,\n shiftDuration,\n active,\n createdAt\n )\n }\n}\n\nobject EmployeeRow {\n val `_rowParser`: RowParser[EmployeeRow] = RowParsers.of(EmployeeId.oracleType, DepartmentId.oracleType, EmployeeId.oracleType.nullable, OracleTypes.varchar2, OracleTypes.varchar2, OracleTypes.varchar2, ScalaDbTypes.OracleTypes.number.nullable, OracleTypes.date.nullable, ScalaDbTypes.OracleTypes.number.nullable, OracleTypes.timestamp.nullable, OracleTypes.json.nullable, OracleTypes.clob.nullable, OracleTypes.blob.nullable, OracleTypes.intervalYearToMonth.nullable, OracleTypes.intervalDayToSecond.nullable)(EmployeeRow.apply)(row => Array[Any](row.id, row.departmentId, row.managerId, row.email, row.firstName, row.lastName, row.salary, row.hiredAt, row.active, row.createdAt, row.metadata, row.resume, row.photo, row.probationPeriod, row.shiftDuration))\n}", - "EmployeeRowUnsaved": "package showcase.showcase.employee\n\nimport dev.typr.foundations.data.Json\nimport dev.typr.foundations.data.OracleIntervalDS\nimport dev.typr.foundations.data.OracleIntervalYM\nimport java.time.LocalDateTime\nimport showcase.customtypes.Defaulted\nimport showcase.customtypes.Defaulted.UseDefault\nimport showcase.showcase.department.DepartmentId\n\n/** This class corresponds to a row in table `showcase.employee` which has not been persisted yet */\ncase class EmployeeRowUnsaved(\n id: EmployeeId,\n /** Points to [[showcase.showcase.department.DepartmentRow.id]] */\n departmentId: DepartmentId,\n /** Points to [[showcase.showcase.employee.EmployeeRow.id]] */\n managerId: Option[EmployeeId] = None,\n email: String,\n firstName: String,\n lastName: String,\n salary: Option[BigDecimal] = None,\n hiredAt: Option[LocalDateTime] = None,\n metadata: Option[Json] = None,\n resume: Option[String] = None,\n photo: Option[Array[Byte]] = None,\n probationPeriod: Option[OracleIntervalYM] = None,\n shiftDuration: Option[OracleIntervalDS] = None,\n /** Default: true */\n active: Defaulted[Option[BigDecimal]] = new UseDefault(),\n /** Default: CURRENT_TIMESTAMP */\n createdAt: Defaulted[Option[LocalDateTime]] = new UseDefault()\n) {\n def toRow(\n activeDefault: => Option[BigDecimal],\n createdAtDefault: => Option[LocalDateTime]\n ): EmployeeRow = {\n new EmployeeRow(\n id = id,\n departmentId = departmentId,\n managerId = managerId,\n email = email,\n firstName = firstName,\n lastName = lastName,\n salary = salary,\n hiredAt = hiredAt,\n active = active.getOrElse(activeDefault),\n createdAt = createdAt.getOrElse(createdAtDefault),\n metadata = metadata,\n resume = resume,\n photo = photo,\n probationPeriod = probationPeriod,\n shiftDuration = shiftDuration\n )\n }\n}", - "EmployeeId": "package showcase.showcase.employee\n\nimport dev.typr.foundations.OracleType\nimport dev.typr.foundations.OracleTypes\nimport dev.typr.foundations.scala.Bijection\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\n\n/** Type for the primary key of table `showcase.employee` */\ncase class EmployeeId(value: String) extends scala.AnyVal\n\nobject EmployeeId {\n given `_rowParser`: RowParser[EmployeeId] = RowParsers.of(OracleTypes.varchar2.bimap(EmployeeId.apply, _.value))(x => x)(id => Array[Any](id))\n\n given bijection: Bijection[EmployeeId, String] = Bijection.apply[EmployeeId, String](_.value)(EmployeeId.apply)\n\n given oracleType: OracleType[EmployeeId] = OracleTypes.varchar2.bimap(EmployeeId.apply, _.value)\n}", - "EmployeeRepo": "package showcase.showcase.employee\n\nimport dev.typr.foundations.scala.DeleteBuilder\nimport dev.typr.foundations.scala.SelectBuilder\nimport dev.typr.foundations.scala.UpdateBuilder\nimport java.sql.Connection\n\ntrait EmployeeRepo {\n def delete: DeleteBuilder[EmployeeFields, EmployeeRow]\n\n def deleteById(id: EmployeeId)(using c: Connection): Boolean\n\n def deleteByIds(ids: Array[EmployeeId])(using c: Connection): Int\n\n def insert(unsaved: EmployeeRow)(using c: Connection): EmployeeRow\n\n def insert(unsaved: EmployeeRowUnsaved)(using c: Connection): EmployeeRow\n\n def select: SelectBuilder[EmployeeFields, EmployeeRow]\n\n def selectAll(using c: Connection): List[EmployeeRow]\n\n def selectById(id: EmployeeId)(using c: Connection): Option[EmployeeRow]\n\n def selectByIds(ids: Array[EmployeeId])(using c: Connection): List[EmployeeRow]\n\n def selectByIdsTracked(ids: Array[EmployeeId])(using c: Connection): Map[EmployeeId, EmployeeRow]\n\n def selectByUniqueEmail(email: String)(using c: Connection): Option[EmployeeRow]\n\n def update: UpdateBuilder[EmployeeFields, EmployeeRow]\n\n def update(row: EmployeeRow)(using c: Connection): Boolean\n\n def upsert(unsaved: EmployeeRow)(using c: Connection): EmployeeRow\n\n def upsertBatch(unsaved: Iterator[EmployeeRow])(using c: Connection): List[EmployeeRow]\n}", - "EmployeeRepoImpl": "package showcase.showcase.employee\n\nimport dev.typr.foundations.OracleTypes\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.DeleteBuilder\nimport dev.typr.foundations.scala.Dialect\nimport dev.typr.foundations.scala.Fragment\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport dev.typr.foundations.scala.SelectBuilder\nimport dev.typr.foundations.scala.UpdateBuilder\nimport java.sql.Connection\nimport scala.collection.mutable.ListBuffer\nimport showcase.showcase.department.DepartmentId\nimport dev.typr.foundations.scala.Fragment.sql\n\nclass EmployeeRepoImpl extends EmployeeRepo {\n override def delete: DeleteBuilder[EmployeeFields, EmployeeRow] = DeleteBuilder.of(\"\"\"\"showcase\".\"employee\"\"\"\", EmployeeFields.structure, Dialect.ORACLE)\n\n override def deleteById(id: EmployeeId)(using c: Connection): Boolean = sql\"\"\"delete from \"showcase\".\"employee\" where \"id\" = ${Fragment.encode(EmployeeId.oracleType, id)}\"\"\".update().runUnchecked(c) > 0\n\n override def deleteByIds(ids: Array[EmployeeId])(using c: Connection): Int = {\n val fragments: ListBuffer[Fragment] = ListBuffer()\n ids.foreach { id => fragments.addOne(Fragment.encode(EmployeeId.oracleType, id)): @scala.annotation.nowarn }\n return Fragment.interpolate(Fragment.lit(\"\"\"delete from \"showcase\".\"employee\" where \"id\" in (\"\"\"), Fragment.comma(fragments), Fragment.lit(\")\")).update().runUnchecked(c)\n }\n\n override def insert(unsaved: EmployeeRow)(using c: Connection): EmployeeRow = {\n sql\"\"\"insert into \"showcase\".\"employee\"(\"id\", \"department_id\", \"manager_id\", \"email\", \"first_name\", \"last_name\", \"salary\", \"hired_at\", \"active\", \"created_at\", \"metadata\", \"resume\", \"photo\", \"probation_period\", \"shift_duration\")\n values (${Fragment.encode(EmployeeId.oracleType, unsaved.id)}, ${Fragment.encode(DepartmentId.oracleType, unsaved.departmentId)}, ${Fragment.encode(EmployeeId.oracleType.nullable, unsaved.managerId)}, ${Fragment.encode(OracleTypes.varchar2, unsaved.email)}, ${Fragment.encode(OracleTypes.varchar2, unsaved.firstName)}, ${Fragment.encode(OracleTypes.varchar2, unsaved.lastName)}, ${Fragment.encode(ScalaDbTypes.OracleTypes.number.nullable, unsaved.salary)}, ${Fragment.encode(OracleTypes.date.nullable, unsaved.hiredAt)}, ${Fragment.encode(ScalaDbTypes.OracleTypes.number.nullable, unsaved.active)}, ${Fragment.encode(OracleTypes.timestamp.nullable, unsaved.createdAt)}, ${Fragment.encode(OracleTypes.json.nullable, unsaved.metadata)}, ${Fragment.encode(OracleTypes.clob.nullable, unsaved.resume)}, ${Fragment.encode(OracleTypes.blob.nullable, unsaved.photo)}, ${Fragment.encode(OracleTypes.intervalYearToMonth.nullable, unsaved.probationPeriod)}, ${Fragment.encode(OracleTypes.intervalDayToSecond.nullable, unsaved.shiftDuration)})\n \"\"\"\n .updateReturningGeneratedKeys(Array[String](\"id\", \"department_id\", \"manager_id\", \"email\", \"first_name\", \"last_name\", \"salary\", \"hired_at\", \"active\", \"created_at\", \"metadata\", \"resume\", \"photo\", \"probation_period\", \"shift_duration\"), EmployeeRow.`_rowParser`.exactlyOne()).runUnchecked(c)\n }\n\n override def insert(unsaved: EmployeeRowUnsaved)(using c: Connection): EmployeeRow = {\n val columns: ListBuffer[Fragment] = ListBuffer()\n val values: ListBuffer[Fragment] = ListBuffer()\n columns.addOne(Fragment.lit(\"\"\"\"id\"\"\"\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(EmployeeId.oracleType, unsaved.id)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"\"\"\"department_id\"\"\"\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(DepartmentId.oracleType, unsaved.departmentId)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"\"\"\"manager_id\"\"\"\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(EmployeeId.oracleType.nullable, unsaved.managerId)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"\"\"\"email\"\"\"\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(OracleTypes.varchar2, unsaved.email)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"\"\"\"first_name\"\"\"\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(OracleTypes.varchar2, unsaved.firstName)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"\"\"\"last_name\"\"\"\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(OracleTypes.varchar2, unsaved.lastName)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"\"\"\"salary\"\"\"\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(ScalaDbTypes.OracleTypes.number.nullable, unsaved.salary)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"\"\"\"hired_at\"\"\"\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(OracleTypes.date.nullable, unsaved.hiredAt)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"\"\"\"metadata\"\"\"\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(OracleTypes.json.nullable, unsaved.metadata)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"\"\"\"resume\"\"\"\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(OracleTypes.clob.nullable, unsaved.resume)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"\"\"\"photo\"\"\"\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(OracleTypes.blob.nullable, unsaved.photo)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"\"\"\"probation_period\"\"\"\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(OracleTypes.intervalYearToMonth.nullable, unsaved.probationPeriod)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"\"\"\"shift_duration\"\"\"\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(OracleTypes.intervalDayToSecond.nullable, unsaved.shiftDuration)}\"): @scala.annotation.nowarn\n unsaved.active.visit(\n { },\n value => { columns.addOne(Fragment.lit(\"\"\"\"active\"\"\"\")): @scala.annotation.nowarn; values.addOne(sql\"${Fragment.encode(ScalaDbTypes.OracleTypes.number.nullable, value)}\"): @scala.annotation.nowarn }\n );\n unsaved.createdAt.visit(\n { },\n value => { columns.addOne(Fragment.lit(\"\"\"\"created_at\"\"\"\")): @scala.annotation.nowarn; values.addOne(sql\"${Fragment.encode(OracleTypes.timestamp.nullable, value)}\"): @scala.annotation.nowarn }\n );\n val q: Fragment = {\n sql\"\"\"insert into \"showcase\".\"employee\"(${Fragment.comma(columns)})\n values (${Fragment.comma(values)})\n \"\"\"\n }\n return q.updateReturningGeneratedKeys(Array[String](\"id\", \"department_id\", \"manager_id\", \"email\", \"first_name\", \"last_name\", \"salary\", \"hired_at\", \"active\", \"created_at\", \"metadata\", \"resume\", \"photo\", \"probation_period\", \"shift_duration\"), EmployeeRow.`_rowParser`.exactlyOne()).runUnchecked(c)\n }\n\n override def select: SelectBuilder[EmployeeFields, EmployeeRow] = SelectBuilder.of(\"\"\"\"showcase\".\"employee\"\"\"\", EmployeeFields.structure, EmployeeRow.`_rowParser`, Dialect.ORACLE)\n\n override def selectAll(using c: Connection): List[EmployeeRow] = {\n sql\"\"\"select \"id\", \"department_id\", \"manager_id\", \"email\", \"first_name\", \"last_name\", \"salary\", \"hired_at\", \"active\", \"created_at\", \"metadata\", \"resume\", \"photo\", \"probation_period\", \"shift_duration\"\n from \"showcase\".\"employee\"\n \"\"\".query(EmployeeRow.`_rowParser`.all()).runUnchecked(c)\n }\n\n override def selectById(id: EmployeeId)(using c: Connection): Option[EmployeeRow] = {\n sql\"\"\"select \"id\", \"department_id\", \"manager_id\", \"email\", \"first_name\", \"last_name\", \"salary\", \"hired_at\", \"active\", \"created_at\", \"metadata\", \"resume\", \"photo\", \"probation_period\", \"shift_duration\"\n from \"showcase\".\"employee\"\n where \"id\" = ${Fragment.encode(EmployeeId.oracleType, id)}\"\"\".query(EmployeeRow.`_rowParser`.first()).runUnchecked(c)\n }\n\n override def selectByIds(ids: Array[EmployeeId])(using c: Connection): List[EmployeeRow] = {\n val fragments: ListBuffer[Fragment] = ListBuffer()\n ids.foreach { id => fragments.addOne(Fragment.encode(EmployeeId.oracleType, id)): @scala.annotation.nowarn }\n return Fragment.interpolate(Fragment.lit(\"\"\"select \"id\", \"department_id\", \"manager_id\", \"email\", \"first_name\", \"last_name\", \"salary\", \"hired_at\", \"active\", \"created_at\", \"metadata\", \"resume\", \"photo\", \"probation_period\", \"shift_duration\" from \"showcase\".\"employee\" where \"id\" in (\"\"\"), Fragment.comma(fragments), Fragment.lit(\")\")).query(EmployeeRow.`_rowParser`.all()).runUnchecked(c)\n }\n\n override def selectByIdsTracked(ids: Array[EmployeeId])(using c: Connection): Map[EmployeeId, EmployeeRow] = {\n val ret: scala.collection.mutable.Map[EmployeeId, EmployeeRow] = scala.collection.mutable.Map.empty[EmployeeId, EmployeeRow]\n selectByIds(ids)(using c).foreach(row => ret.put(row.id, row): @scala.annotation.nowarn)\n return ret.toMap\n }\n\n override def selectByUniqueEmail(email: String)(using c: Connection): Option[EmployeeRow] = {\n sql\"\"\"select \"id\", \"department_id\", \"manager_id\", \"email\", \"first_name\", \"last_name\", \"salary\", \"hired_at\", \"active\", \"created_at\", \"metadata\", \"resume\", \"photo\", \"probation_period\", \"shift_duration\"\n from \"showcase\".\"employee\"\n where \"email\" = ${Fragment.encode(OracleTypes.varchar2, email)}\n \"\"\".query(EmployeeRow.`_rowParser`.first()).runUnchecked(c)\n }\n\n override def update: UpdateBuilder[EmployeeFields, EmployeeRow] = UpdateBuilder.of(\"\"\"\"showcase\".\"employee\"\"\"\", EmployeeFields.structure, EmployeeRow.`_rowParser`, Dialect.ORACLE)\n\n override def update(row: EmployeeRow)(using c: Connection): Boolean = {\n val id: EmployeeId = row.id\n return sql\"\"\"update \"showcase\".\"employee\"\n set \"department_id\" = ${Fragment.encode(DepartmentId.oracleType, row.departmentId)},\n \"manager_id\" = ${Fragment.encode(EmployeeId.oracleType.nullable, row.managerId)},\n \"email\" = ${Fragment.encode(OracleTypes.varchar2, row.email)},\n \"first_name\" = ${Fragment.encode(OracleTypes.varchar2, row.firstName)},\n \"last_name\" = ${Fragment.encode(OracleTypes.varchar2, row.lastName)},\n \"salary\" = ${Fragment.encode(ScalaDbTypes.OracleTypes.number.nullable, row.salary)},\n \"hired_at\" = ${Fragment.encode(OracleTypes.date.nullable, row.hiredAt)},\n \"active\" = ${Fragment.encode(ScalaDbTypes.OracleTypes.number.nullable, row.active)},\n \"created_at\" = ${Fragment.encode(OracleTypes.timestamp.nullable, row.createdAt)},\n \"metadata\" = ${Fragment.encode(OracleTypes.json.nullable, row.metadata)},\n \"resume\" = ${Fragment.encode(OracleTypes.clob.nullable, row.resume)},\n \"photo\" = ${Fragment.encode(OracleTypes.blob.nullable, row.photo)},\n \"probation_period\" = ${Fragment.encode(OracleTypes.intervalYearToMonth.nullable, row.probationPeriod)},\n \"shift_duration\" = ${Fragment.encode(OracleTypes.intervalDayToSecond.nullable, row.shiftDuration)}\n where \"id\" = ${Fragment.encode(EmployeeId.oracleType, id)}\"\"\".update().runUnchecked(c) > 0\n }\n\n override def upsert(unsaved: EmployeeRow)(using c: Connection): EmployeeRow = {\n sql\"\"\"MERGE INTO \"showcase\".\"employee\" t\n USING (SELECT ${Fragment.encode(EmployeeId.oracleType, unsaved.id)}, ${Fragment.encode(DepartmentId.oracleType, unsaved.departmentId)}, ${Fragment.encode(EmployeeId.oracleType.nullable, unsaved.managerId)}, ${Fragment.encode(OracleTypes.varchar2, unsaved.email)}, ${Fragment.encode(OracleTypes.varchar2, unsaved.firstName)}, ${Fragment.encode(OracleTypes.varchar2, unsaved.lastName)}, ${Fragment.encode(ScalaDbTypes.OracleTypes.number.nullable, unsaved.salary)}, ${Fragment.encode(OracleTypes.date.nullable, unsaved.hiredAt)}, ${Fragment.encode(ScalaDbTypes.OracleTypes.number.nullable, unsaved.active)}, ${Fragment.encode(OracleTypes.timestamp.nullable, unsaved.createdAt)}, ${Fragment.encode(OracleTypes.json.nullable, unsaved.metadata)}, ${Fragment.encode(OracleTypes.clob.nullable, unsaved.resume)}, ${Fragment.encode(OracleTypes.blob.nullable, unsaved.photo)}, ${Fragment.encode(OracleTypes.intervalYearToMonth.nullable, unsaved.probationPeriod)}, ${Fragment.encode(OracleTypes.intervalDayToSecond.nullable, unsaved.shiftDuration)} FROM DUAL) s\n ON (\"id\")\n WHEN MATCHED THEN UPDATE SET t.\"department_id\" = s.\"department_id\",\n t.\"manager_id\" = s.\"manager_id\",\n t.\"email\" = s.\"email\",\n t.\"first_name\" = s.\"first_name\",\n t.\"last_name\" = s.\"last_name\",\n t.\"salary\" = s.\"salary\",\n t.\"hired_at\" = s.\"hired_at\",\n t.\"active\" = s.\"active\",\n t.\"created_at\" = s.\"created_at\",\n t.\"metadata\" = s.\"metadata\",\n t.\"resume\" = s.\"resume\",\n t.\"photo\" = s.\"photo\",\n t.\"probation_period\" = s.\"probation_period\",\n t.\"shift_duration\" = s.\"shift_duration\"\n WHEN NOT MATCHED THEN INSERT (\"id\", \"department_id\", \"manager_id\", \"email\", \"first_name\", \"last_name\", \"salary\", \"hired_at\", \"active\", \"created_at\", \"metadata\", \"resume\", \"photo\", \"probation_period\", \"shift_duration\") VALUES (${Fragment.encode(EmployeeId.oracleType, unsaved.id)}, ${Fragment.encode(DepartmentId.oracleType, unsaved.departmentId)}, ${Fragment.encode(EmployeeId.oracleType.nullable, unsaved.managerId)}, ${Fragment.encode(OracleTypes.varchar2, unsaved.email)}, ${Fragment.encode(OracleTypes.varchar2, unsaved.firstName)}, ${Fragment.encode(OracleTypes.varchar2, unsaved.lastName)}, ${Fragment.encode(ScalaDbTypes.OracleTypes.number.nullable, unsaved.salary)}, ${Fragment.encode(OracleTypes.date.nullable, unsaved.hiredAt)}, ${Fragment.encode(ScalaDbTypes.OracleTypes.number.nullable, unsaved.active)}, ${Fragment.encode(OracleTypes.timestamp.nullable, unsaved.createdAt)}, ${Fragment.encode(OracleTypes.json.nullable, unsaved.metadata)}, ${Fragment.encode(OracleTypes.clob.nullable, unsaved.resume)}, ${Fragment.encode(OracleTypes.blob.nullable, unsaved.photo)}, ${Fragment.encode(OracleTypes.intervalYearToMonth.nullable, unsaved.probationPeriod)}, ${Fragment.encode(OracleTypes.intervalDayToSecond.nullable, unsaved.shiftDuration)})\"\"\"\n .updateReturning(EmployeeRow.`_rowParser`.exactlyOne())\n .runUnchecked(c)\n }\n\n override def upsertBatch(unsaved: Iterator[EmployeeRow])(using c: Connection): List[EmployeeRow] = {\n sql\"\"\"MERGE INTO \"showcase\".\"employee\" t\n USING (SELECT ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? FROM DUAL) s\n ON (\"id\")\n WHEN MATCHED THEN UPDATE SET t.\"department_id\" = s.\"department_id\",\n t.\"manager_id\" = s.\"manager_id\",\n t.\"email\" = s.\"email\",\n t.\"first_name\" = s.\"first_name\",\n t.\"last_name\" = s.\"last_name\",\n t.\"salary\" = s.\"salary\",\n t.\"hired_at\" = s.\"hired_at\",\n t.\"active\" = s.\"active\",\n t.\"created_at\" = s.\"created_at\",\n t.\"metadata\" = s.\"metadata\",\n t.\"resume\" = s.\"resume\",\n t.\"photo\" = s.\"photo\",\n t.\"probation_period\" = s.\"probation_period\",\n t.\"shift_duration\" = s.\"shift_duration\"\n WHEN NOT MATCHED THEN INSERT (\"id\", \"department_id\", \"manager_id\", \"email\", \"first_name\", \"last_name\", \"salary\", \"hired_at\", \"active\", \"created_at\", \"metadata\", \"resume\", \"photo\", \"probation_period\", \"shift_duration\") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\"\"\"\n .updateReturningEach(EmployeeRow.`_rowParser`, unsaved)\n .runUnchecked(c)\n }\n}", - "EmployeeRepoMock": "package showcase.showcase.employee\n\nimport dev.typr.foundations.scala.DeleteBuilder\nimport dev.typr.foundations.scala.DeleteBuilderMock\nimport dev.typr.foundations.scala.DeleteParams\nimport dev.typr.foundations.scala.SelectBuilder\nimport dev.typr.foundations.scala.SelectBuilderMock\nimport dev.typr.foundations.scala.SelectParams\nimport dev.typr.foundations.scala.UpdateBuilder\nimport dev.typr.foundations.scala.UpdateBuilderMock\nimport dev.typr.foundations.scala.UpdateParams\nimport java.lang.RuntimeException\nimport java.sql.Connection\n\ncase class EmployeeRepoMock(\n toRow: EmployeeRowUnsaved => EmployeeRow,\n map: scala.collection.mutable.Map[EmployeeId, EmployeeRow] = scala.collection.mutable.Map.empty[EmployeeId, EmployeeRow]\n) extends EmployeeRepo {\n override def delete: DeleteBuilder[EmployeeFields, EmployeeRow] = DeleteBuilderMock(EmployeeFields.structure, () => map.values.toList, DeleteParams.empty(), row => row.id, id => map.remove(id): @scala.annotation.nowarn)\n\n override def deleteById(id: EmployeeId)(using c: Connection): Boolean = map.remove(id).isDefined\n\n override def deleteByIds(ids: Array[EmployeeId])(using c: Connection): Int = {\n var count = 0\n ids.foreach { id => if (map.remove(id).isDefined) {\n count = count + 1\n } }\n return count\n }\n\n override def insert(unsaved: EmployeeRow)(using c: Connection): EmployeeRow = {\n if (map.contains(unsaved.id)) {\n throw new RuntimeException(s\"id ${unsaved.id} already exists\")\n }\n map.put(unsaved.id, unsaved): @scala.annotation.nowarn\n return unsaved\n }\n\n override def insert(unsaved: EmployeeRowUnsaved)(using c: Connection): EmployeeRow = insert(toRow(unsaved))(using c)\n\n override def select: SelectBuilder[EmployeeFields, EmployeeRow] = SelectBuilderMock(EmployeeFields.structure, () => map.values.toList, SelectParams.empty())\n\n override def selectAll(using c: Connection): List[EmployeeRow] = map.values.toList\n\n override def selectById(id: EmployeeId)(using c: Connection): Option[EmployeeRow] = map.get(id)\n\n override def selectByIds(ids: Array[EmployeeId])(using c: Connection): List[EmployeeRow] = ids.flatMap(map.get(_)).toList\n\n override def selectByIdsTracked(ids: Array[EmployeeId])(using c: Connection): Map[EmployeeId, EmployeeRow] = selectByIds(ids)(using c).map(x => (((row: EmployeeRow) => row.id).apply(x), x)).toMap\n\n override def selectByUniqueEmail(email: String)(using c: Connection): Option[EmployeeRow] = map.values.toList.find(v => (email == v.email))\n\n override def update: UpdateBuilder[EmployeeFields, EmployeeRow] = UpdateBuilderMock(EmployeeFields.structure, () => map.values.toList, UpdateParams.empty(), row => row)\n\n override def update(row: EmployeeRow)(using c: Connection): Boolean = {\n val shouldUpdate = map.get(row.id).filter(oldRow => (oldRow != row)).isDefined\n if (shouldUpdate) {\n map.put(row.id, row): @scala.annotation.nowarn\n }\n return shouldUpdate\n }\n\n override def upsert(unsaved: EmployeeRow)(using c: Connection): EmployeeRow = {\n map.put(unsaved.id, unsaved): @scala.annotation.nowarn\n return unsaved\n }\n\n override def upsertBatch(unsaved: Iterator[EmployeeRow])(using c: Connection): List[EmployeeRow] = {\n unsaved.map { row =>\n map.put(row.id, row): @scala.annotation.nowarn\n row\n }.toList\n }\n}", - "EmployeeFields": "package showcase.showcase.employee\n\nimport dev.typr.foundations.OracleTypes\nimport dev.typr.foundations.RowParser\nimport dev.typr.foundations.data.Json\nimport dev.typr.foundations.data.OracleIntervalDS\nimport dev.typr.foundations.data.OracleIntervalYM\nimport dev.typr.foundations.dsl.FieldsExpr0\nimport dev.typr.foundations.dsl.Path\nimport dev.typr.foundations.dsl.SqlExpr.FieldLike\nimport dev.typr.foundations.scala.ForeignKey\nimport dev.typr.foundations.scala.RelationStructure\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport dev.typr.foundations.scala.SqlExpr.Field\nimport dev.typr.foundations.scala.SqlExpr.IdField\nimport dev.typr.foundations.scala.SqlExpr.OptField\nimport java.time.LocalDateTime\nimport showcase.showcase.department.DepartmentFields\nimport showcase.showcase.department.DepartmentId\nimport showcase.showcase.department.DepartmentRow\n\ntrait EmployeeFields extends FieldsExpr0[EmployeeRow] {\n def id: IdField[EmployeeId, EmployeeRow]\n\n def departmentId: Field[DepartmentId, EmployeeRow]\n\n def managerId: OptField[EmployeeId, EmployeeRow]\n\n def email: Field[String, EmployeeRow]\n\n def firstName: Field[String, EmployeeRow]\n\n def lastName: Field[String, EmployeeRow]\n\n def salary: OptField[BigDecimal, EmployeeRow]\n\n def hiredAt: OptField[LocalDateTime, EmployeeRow]\n\n def active: OptField[BigDecimal, EmployeeRow]\n\n def createdAt: OptField[LocalDateTime, EmployeeRow]\n\n def metadata: OptField[Json, EmployeeRow]\n\n def resume: OptField[String, EmployeeRow]\n\n def photo: OptField[Array[Byte], EmployeeRow]\n\n def probationPeriod: OptField[OracleIntervalYM, EmployeeRow]\n\n def shiftDuration: OptField[OracleIntervalDS, EmployeeRow]\n\n def fkDepartment: ForeignKey[DepartmentFields, DepartmentRow] = ForeignKey.of[DepartmentFields, DepartmentRow](\"employee_department_fk\").withColumnPair[DepartmentId](departmentId, _.id)\n\n def fkEmployee: ForeignKey[EmployeeFields, EmployeeRow] = ForeignKey.of[EmployeeFields, EmployeeRow](\"employee_manager_fk\").withColumnPair[EmployeeId](managerId, _.id)\n\n override def columns: java.util.List[FieldLike[?, EmployeeRow]]\n\n override def rowParser: RowParser[EmployeeRow] = EmployeeRow._rowParser.underlying\n}\n\nobject EmployeeFields {\n case class Impl(val `_path`: java.util.List[Path]) extends EmployeeFields with RelationStructure[EmployeeFields, EmployeeRow] {\n\n override def id: IdField[EmployeeId, EmployeeRow] = {\n new IdField[EmployeeId, EmployeeRow](\n _path,\n \"id\",\n _.id,\n None,\n None,\n (row, value) => row.copy(id = value),\n EmployeeId.oracleType\n )\n }\n\n override def departmentId: Field[DepartmentId, EmployeeRow] = {\n new Field[DepartmentId, EmployeeRow](\n _path,\n \"department_id\",\n _.departmentId,\n None,\n None,\n (row, value) => row.copy(departmentId = value),\n DepartmentId.oracleType\n )\n }\n\n override def managerId: OptField[EmployeeId, EmployeeRow] = {\n new OptField[EmployeeId, EmployeeRow](\n _path,\n \"manager_id\",\n _.managerId,\n None,\n None,\n (row, value) => row.copy(managerId = value),\n EmployeeId.oracleType\n )\n }\n\n override def email: Field[String, EmployeeRow] = {\n new Field[String, EmployeeRow](\n _path,\n \"email\",\n _.email,\n None,\n None,\n (row, value) => row.copy(email = value),\n OracleTypes.varchar2\n )\n }\n\n override def firstName: Field[String, EmployeeRow] = {\n new Field[String, EmployeeRow](\n _path,\n \"first_name\",\n _.firstName,\n None,\n None,\n (row, value) => row.copy(firstName = value),\n OracleTypes.varchar2\n )\n }\n\n override def lastName: Field[String, EmployeeRow] = {\n new Field[String, EmployeeRow](\n _path,\n \"last_name\",\n _.lastName,\n None,\n None,\n (row, value) => row.copy(lastName = value),\n OracleTypes.varchar2\n )\n }\n\n override def salary: OptField[BigDecimal, EmployeeRow] = {\n new OptField[BigDecimal, EmployeeRow](\n _path,\n \"salary\",\n _.salary,\n None,\n None,\n (row, value) => row.copy(salary = value),\n ScalaDbTypes.OracleTypes.number\n )\n }\n\n override def hiredAt: OptField[LocalDateTime, EmployeeRow] = {\n new OptField[LocalDateTime, EmployeeRow](\n _path,\n \"hired_at\",\n _.hiredAt,\n None,\n None,\n (row, value) => row.copy(hiredAt = value),\n OracleTypes.date\n )\n }\n\n override def active: OptField[BigDecimal, EmployeeRow] = {\n new OptField[BigDecimal, EmployeeRow](\n _path,\n \"active\",\n _.active,\n None,\n None,\n (row, value) => row.copy(active = value),\n ScalaDbTypes.OracleTypes.number\n )\n }\n\n override def createdAt: OptField[LocalDateTime, EmployeeRow] = {\n new OptField[LocalDateTime, EmployeeRow](\n _path,\n \"created_at\",\n _.createdAt,\n None,\n None,\n (row, value) => row.copy(createdAt = value),\n OracleTypes.timestamp\n )\n }\n\n override def metadata: OptField[Json, EmployeeRow] = {\n new OptField[Json, EmployeeRow](\n _path,\n \"metadata\",\n _.metadata,\n None,\n None,\n (row, value) => row.copy(metadata = value),\n OracleTypes.json\n )\n }\n\n override def resume: OptField[String, EmployeeRow] = {\n new OptField[String, EmployeeRow](\n _path,\n \"resume\",\n _.resume,\n None,\n None,\n (row, value) => row.copy(resume = value),\n OracleTypes.clob\n )\n }\n\n override def photo: OptField[Array[Byte], EmployeeRow] = {\n new OptField[Array[Byte], EmployeeRow](\n _path,\n \"photo\",\n _.photo,\n None,\n None,\n (row, value) => row.copy(photo = value),\n OracleTypes.blob\n )\n }\n\n override def probationPeriod: OptField[OracleIntervalYM, EmployeeRow] = {\n new OptField[OracleIntervalYM, EmployeeRow](\n _path,\n \"probation_period\",\n _.probationPeriod,\n None,\n None,\n (row, value) => row.copy(probationPeriod = value),\n OracleTypes.intervalYearToMonth\n )\n }\n\n override def shiftDuration: OptField[OracleIntervalDS, EmployeeRow] = {\n new OptField[OracleIntervalDS, EmployeeRow](\n _path,\n \"shift_duration\",\n _.shiftDuration,\n None,\n None,\n (row, value) => row.copy(shiftDuration = value),\n OracleTypes.intervalDayToSecond\n )\n }\n\n override def columns: java.util.List[FieldLike[?, EmployeeRow]] = java.util.List.of(this.id.underlying, this.departmentId.underlying, this.managerId.underlying, this.email.underlying, this.firstName.underlying, this.lastName.underlying, this.salary.underlying, this.hiredAt.underlying, this.active.underlying, this.createdAt.underlying, this.metadata.underlying, this.resume.underlying, this.photo.underlying, this.probationPeriod.underlying, this.shiftDuration.underlying)\n\n override def withPaths(`_path`: java.util.List[Path]): RelationStructure[EmployeeFields, EmployeeRow] = new Impl(`_path`)\n }\n\n def structure: Impl = new Impl(java.util.Collections.emptyList())\n}", - "DepartmentRow": "package showcase.showcase.department\n\nimport dev.typr.foundations.OracleTypes\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport showcase.showcase.company.CompanyId\n\n/** Table: showcase.department\n * Primary key: id\n */\ncase class DepartmentRow(\n id: DepartmentId,\n /** Points to [[showcase.showcase.company.CompanyRow.id]] */\n companyId: CompanyId,\n name: String,\n budget: Option[BigDecimal]\n)\n\nobject DepartmentRow {\n val `_rowParser`: RowParser[DepartmentRow] = RowParsers.of(DepartmentId.oracleType, CompanyId.oracleType, OracleTypes.varchar2, ScalaDbTypes.OracleTypes.number.nullable)(DepartmentRow.apply)(row => Array[Any](row.id, row.companyId, row.name, row.budget))\n}", - "DepartmentId": "package showcase.showcase.department\n\nimport dev.typr.foundations.OracleType\nimport dev.typr.foundations.OracleTypes\nimport dev.typr.foundations.scala.Bijection\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\n\n/** Type for the primary key of table `showcase.department` */\ncase class DepartmentId(value: String) extends scala.AnyVal\n\nobject DepartmentId {\n given `_rowParser`: RowParser[DepartmentId] = RowParsers.of(OracleTypes.varchar2.bimap(DepartmentId.apply, _.value))(x => x)(id => Array[Any](id))\n\n given bijection: Bijection[DepartmentId, String] = Bijection.apply[DepartmentId, String](_.value)(DepartmentId.apply)\n\n given oracleType: OracleType[DepartmentId] = OracleTypes.varchar2.bimap(DepartmentId.apply, _.value)\n}", - "DepartmentRepo": "package showcase.showcase.department\n\nimport dev.typr.foundations.scala.DeleteBuilder\nimport dev.typr.foundations.scala.SelectBuilder\nimport dev.typr.foundations.scala.UpdateBuilder\nimport java.sql.Connection\n\ntrait DepartmentRepo {\n def delete: DeleteBuilder[DepartmentFields, DepartmentRow]\n\n def deleteById(id: DepartmentId)(using c: Connection): Boolean\n\n def deleteByIds(ids: Array[DepartmentId])(using c: Connection): Int\n\n def insert(unsaved: DepartmentRow)(using c: Connection): DepartmentRow\n\n def select: SelectBuilder[DepartmentFields, DepartmentRow]\n\n def selectAll(using c: Connection): List[DepartmentRow]\n\n def selectById(id: DepartmentId)(using c: Connection): Option[DepartmentRow]\n\n def selectByIds(ids: Array[DepartmentId])(using c: Connection): List[DepartmentRow]\n\n def selectByIdsTracked(ids: Array[DepartmentId])(using c: Connection): Map[DepartmentId, DepartmentRow]\n\n def update: UpdateBuilder[DepartmentFields, DepartmentRow]\n\n def update(row: DepartmentRow)(using c: Connection): Boolean\n\n def upsert(unsaved: DepartmentRow)(using c: Connection): DepartmentRow\n\n def upsertBatch(unsaved: Iterator[DepartmentRow])(using c: Connection): List[DepartmentRow]\n}", - "DepartmentRepoMock": "package showcase.showcase.department\n\nimport dev.typr.foundations.scala.DeleteBuilder\nimport dev.typr.foundations.scala.DeleteBuilderMock\nimport dev.typr.foundations.scala.DeleteParams\nimport dev.typr.foundations.scala.SelectBuilder\nimport dev.typr.foundations.scala.SelectBuilderMock\nimport dev.typr.foundations.scala.SelectParams\nimport dev.typr.foundations.scala.UpdateBuilder\nimport dev.typr.foundations.scala.UpdateBuilderMock\nimport dev.typr.foundations.scala.UpdateParams\nimport java.lang.RuntimeException\nimport java.sql.Connection\n\ncase class DepartmentRepoMock(map: scala.collection.mutable.Map[DepartmentId, DepartmentRow] = scala.collection.mutable.Map.empty[DepartmentId, DepartmentRow]) extends DepartmentRepo {\n override def delete: DeleteBuilder[DepartmentFields, DepartmentRow] = DeleteBuilderMock(DepartmentFields.structure, () => map.values.toList, DeleteParams.empty(), row => row.id, id => map.remove(id): @scala.annotation.nowarn)\n\n override def deleteById(id: DepartmentId)(using c: Connection): Boolean = map.remove(id).isDefined\n\n override def deleteByIds(ids: Array[DepartmentId])(using c: Connection): Int = {\n var count = 0\n ids.foreach { id => if (map.remove(id).isDefined) {\n count = count + 1\n } }\n return count\n }\n\n override def insert(unsaved: DepartmentRow)(using c: Connection): DepartmentRow = {\n if (map.contains(unsaved.id)) {\n throw new RuntimeException(s\"id ${unsaved.id} already exists\")\n }\n map.put(unsaved.id, unsaved): @scala.annotation.nowarn\n return unsaved\n }\n\n override def select: SelectBuilder[DepartmentFields, DepartmentRow] = SelectBuilderMock(DepartmentFields.structure, () => map.values.toList, SelectParams.empty())\n\n override def selectAll(using c: Connection): List[DepartmentRow] = map.values.toList\n\n override def selectById(id: DepartmentId)(using c: Connection): Option[DepartmentRow] = map.get(id)\n\n override def selectByIds(ids: Array[DepartmentId])(using c: Connection): List[DepartmentRow] = ids.flatMap(map.get(_)).toList\n\n override def selectByIdsTracked(ids: Array[DepartmentId])(using c: Connection): Map[DepartmentId, DepartmentRow] = selectByIds(ids)(using c).map(x => (((row: DepartmentRow) => row.id).apply(x), x)).toMap\n\n override def update: UpdateBuilder[DepartmentFields, DepartmentRow] = UpdateBuilderMock(DepartmentFields.structure, () => map.values.toList, UpdateParams.empty(), row => row)\n\n override def update(row: DepartmentRow)(using c: Connection): Boolean = {\n val shouldUpdate = map.get(row.id).filter(oldRow => (oldRow != row)).isDefined\n if (shouldUpdate) {\n map.put(row.id, row): @scala.annotation.nowarn\n }\n return shouldUpdate\n }\n\n override def upsert(unsaved: DepartmentRow)(using c: Connection): DepartmentRow = {\n map.put(unsaved.id, unsaved): @scala.annotation.nowarn\n return unsaved\n }\n\n override def upsertBatch(unsaved: Iterator[DepartmentRow])(using c: Connection): List[DepartmentRow] = {\n unsaved.map { row =>\n map.put(row.id, row): @scala.annotation.nowarn\n row\n }.toList\n }\n}", - "ProjectAssignmentRow": "package showcase.showcase.project_assignment\n\nimport dev.typr.foundations.OracleTypes\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport java.time.LocalDateTime\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.employee.EmployeeId\nimport showcase.showcase.project.ProjectId\n\n/** Table: showcase.project_assignment\n * Composite primary key: employee_id, project_id\n */\ncase class ProjectAssignmentRow(\n /** Points to [[showcase.showcase.employee.EmployeeRow.id]] */\n employeeId: EmployeeId,\n /** Points to [[showcase.showcase.project.ProjectRow.id]] */\n projectId: ProjectId,\n role: String,\n /** Default: 0 */\n hoursAllocated: Option[BigDecimal],\n startDate: Option[LocalDateTime],\n endDate: Option[LocalDateTime]\n) {\n def compositeId: ProjectAssignmentId = new ProjectAssignmentId(employeeId, projectId)\n\n def id: ProjectAssignmentId = this.compositeId\n\n def toUnsavedRow(hoursAllocated: Defaulted[Option[BigDecimal]] = Defaulted.Provided(this.hoursAllocated)): ProjectAssignmentRowUnsaved = {\n new ProjectAssignmentRowUnsaved(\n employeeId,\n projectId,\n role,\n startDate,\n endDate,\n hoursAllocated\n )\n }\n}\n\nobject ProjectAssignmentRow {\n val `_rowParser`: RowParser[ProjectAssignmentRow] = RowParsers.of(EmployeeId.oracleType, ProjectId.oracleType, OracleTypes.varchar2, ScalaDbTypes.OracleTypes.number.nullable, OracleTypes.date.nullable, OracleTypes.date.nullable)(ProjectAssignmentRow.apply)(row => Array[Any](row.employeeId, row.projectId, row.role, row.hoursAllocated, row.startDate, row.endDate))\n\n def apply(\n compositeId: ProjectAssignmentId,\n role: String,\n hoursAllocated: Option[BigDecimal],\n startDate: Option[LocalDateTime],\n endDate: Option[LocalDateTime]\n ): ProjectAssignmentRow = {\n new ProjectAssignmentRow(\n compositeId.employeeId,\n compositeId.projectId,\n role,\n hoursAllocated,\n startDate,\n endDate\n )\n }\n}", - "ProjectAssignmentRowUnsaved": "package showcase.showcase.project_assignment\n\nimport java.time.LocalDateTime\nimport showcase.customtypes.Defaulted\nimport showcase.customtypes.Defaulted.UseDefault\nimport showcase.showcase.employee.EmployeeId\nimport showcase.showcase.project.ProjectId\n\n/** This class corresponds to a row in table `showcase.project_assignment` which has not been persisted yet */\ncase class ProjectAssignmentRowUnsaved(\n /** Points to [[showcase.showcase.employee.EmployeeRow.id]] */\n employeeId: EmployeeId,\n /** Points to [[showcase.showcase.project.ProjectRow.id]] */\n projectId: ProjectId,\n role: String,\n startDate: Option[LocalDateTime] = None,\n endDate: Option[LocalDateTime] = None,\n /** Default: 0 */\n hoursAllocated: Defaulted[Option[BigDecimal]] = new UseDefault()\n) {\n def toRow(hoursAllocatedDefault: => Option[BigDecimal]): ProjectAssignmentRow = {\n new ProjectAssignmentRow(\n employeeId = employeeId,\n projectId = projectId,\n role = role,\n hoursAllocated = hoursAllocated.getOrElse(hoursAllocatedDefault),\n startDate = startDate,\n endDate = endDate\n )\n }\n}", - "ProjectAssignmentId": "package showcase.showcase.project_assignment\n\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport showcase.showcase.employee.EmployeeId\nimport showcase.showcase.project.ProjectId\n\n/** Type for the composite primary key of table `showcase.project_assignment` */\ncase class ProjectAssignmentId(\n employeeId: EmployeeId,\n projectId: ProjectId\n)\n\nobject ProjectAssignmentId {\n val `_rowParser`: RowParser[ProjectAssignmentId] = RowParsers.of(EmployeeId.oracleType, ProjectId.oracleType)(ProjectAssignmentId.apply)(row => Array[Any](row.employeeId, row.projectId))\n}", - "ProjectAssignmentRepo": "package showcase.showcase.project_assignment\n\nimport dev.typr.foundations.scala.DeleteBuilder\nimport dev.typr.foundations.scala.SelectBuilder\nimport dev.typr.foundations.scala.UpdateBuilder\nimport java.sql.Connection\n\ntrait ProjectAssignmentRepo {\n def delete: DeleteBuilder[ProjectAssignmentFields, ProjectAssignmentRow]\n\n def deleteById(compositeId: ProjectAssignmentId)(using c: Connection): Boolean\n\n def deleteByIds(compositeIds: Array[ProjectAssignmentId])(using c: Connection): Int\n\n def insert(unsaved: ProjectAssignmentRow)(using c: Connection): ProjectAssignmentRow\n\n def insert(unsaved: ProjectAssignmentRowUnsaved)(using c: Connection): ProjectAssignmentRow\n\n def select: SelectBuilder[ProjectAssignmentFields, ProjectAssignmentRow]\n\n def selectAll(using c: Connection): List[ProjectAssignmentRow]\n\n def selectById(compositeId: ProjectAssignmentId)(using c: Connection): Option[ProjectAssignmentRow]\n\n def selectByIds(compositeIds: Array[ProjectAssignmentId])(using c: Connection): List[ProjectAssignmentRow]\n\n def selectByIdsTracked(compositeIds: Array[ProjectAssignmentId])(using c: Connection): Map[ProjectAssignmentId, ProjectAssignmentRow]\n\n def update: UpdateBuilder[ProjectAssignmentFields, ProjectAssignmentRow]\n\n def update(row: ProjectAssignmentRow)(using c: Connection): Boolean\n\n def upsert(unsaved: ProjectAssignmentRow)(using c: Connection): ProjectAssignmentRow\n\n def upsertBatch(unsaved: Iterator[ProjectAssignmentRow])(using c: Connection): List[ProjectAssignmentRow]\n}", - "ProjectRow": "package showcase.showcase.project\n\nimport dev.typr.foundations.OracleTypes\nimport dev.typr.foundations.data.Json\nimport dev.typr.foundations.data.OracleIntervalDS\nimport dev.typr.foundations.data.OracleIntervalYM\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport java.time.LocalDateTime\nimport showcase.customtypes.Defaulted\n\n/** Table: showcase.project\n * Primary key: id\n */\ncase class ProjectRow(\n id: ProjectId,\n name: String,\n description: Option[String],\n startDate: Option[LocalDateTime],\n endDate: Option[LocalDateTime],\n budget: Option[BigDecimal],\n /** Default: 'planning' */\n status: Option[String],\n /** Default: CURRENT_TIMESTAMP */\n createdAt: Option[LocalDateTime],\n metadata: Option[Json],\n descriptionLong: Option[String],\n attachments: Option[Array[Byte]],\n estimatedDuration: Option[OracleIntervalYM],\n actualDuration: Option[OracleIntervalDS],\n xmlPlan: Option[String]\n) {\n def toUnsavedRow(\n status: Defaulted[Option[String]] = Defaulted.Provided(this.status),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.Provided(this.createdAt)\n ): ProjectRowUnsaved = {\n new ProjectRowUnsaved(\n id,\n name,\n description,\n startDate,\n endDate,\n budget,\n metadata,\n descriptionLong,\n attachments,\n estimatedDuration,\n actualDuration,\n xmlPlan,\n status,\n createdAt\n )\n }\n}\n\nobject ProjectRow {\n val `_rowParser`: RowParser[ProjectRow] = RowParsers.of(ProjectId.oracleType, OracleTypes.varchar2, OracleTypes.varchar2.nullable, OracleTypes.date.nullable, OracleTypes.date.nullable, ScalaDbTypes.OracleTypes.number.nullable, OracleTypes.varchar2.nullable, OracleTypes.timestamp.nullable, OracleTypes.json.nullable, OracleTypes.clob.nullable, OracleTypes.blob.nullable, OracleTypes.intervalYearToMonth.nullable, OracleTypes.intervalDayToSecond.nullable, OracleTypes.xmlType.nullable)(ProjectRow.apply)(row => Array[Any](row.id, row.name, row.description, row.startDate, row.endDate, row.budget, row.status, row.createdAt, row.metadata, row.descriptionLong, row.attachments, row.estimatedDuration, row.actualDuration, row.xmlPlan))\n}", - "ProjectId": "package showcase.showcase.project\n\nimport dev.typr.foundations.OracleType\nimport dev.typr.foundations.OracleTypes\nimport dev.typr.foundations.scala.Bijection\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\n\n/** Type for the primary key of table `showcase.project` */\ncase class ProjectId(value: String) extends scala.AnyVal\n\nobject ProjectId {\n given `_rowParser`: RowParser[ProjectId] = RowParsers.of(OracleTypes.varchar2.bimap(ProjectId.apply, _.value))(x => x)(id => Array[Any](id))\n\n given bijection: Bijection[ProjectId, String] = Bijection.apply[ProjectId, String](_.value)(ProjectId.apply)\n\n given oracleType: OracleType[ProjectId] = OracleTypes.varchar2.bimap(ProjectId.apply, _.value)\n}", - "EmployeeSummaryViewRow": "package showcase.showcase.employee_summary\n\nimport dev.typr.foundations.OracleTypes\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport java.time.LocalDateTime\nimport showcase.showcase.company.CompanyId\nimport showcase.showcase.department.DepartmentId\nimport showcase.showcase.employee.EmployeeId\n\n/** View: showcase.employee_summary\n * Summary view of employees with their department and company information\n */\ncase class EmployeeSummaryViewRow(\n /** Points to [[showcase.showcase.employee.EmployeeRow.id]] */\n employeeId: EmployeeId,\n email: String,\n firstName: String,\n lastName: String,\n salary: Option[BigDecimal],\n hiredAt: Option[LocalDateTime],\n active: Option[BigDecimal],\n /** Points to [[showcase.showcase.department.DepartmentRow.id]] */\n departmentId: DepartmentId,\n departmentName: String,\n departmentBudget: Option[BigDecimal],\n /** Points to [[showcase.showcase.company.CompanyRow.id]] */\n companyId: CompanyId,\n companyName: String,\n managerId: Option[String],\n managerFirstName: Option[String],\n managerLastName: Option[String]\n)\n\nobject EmployeeSummaryViewRow {\n val `_rowParser`: RowParser[EmployeeSummaryViewRow] = RowParsers.of(EmployeeId.oracleType, OracleTypes.varchar2, OracleTypes.varchar2, OracleTypes.varchar2, ScalaDbTypes.OracleTypes.number.nullable, OracleTypes.date.nullable, ScalaDbTypes.OracleTypes.number.nullable, DepartmentId.oracleType, OracleTypes.varchar2, ScalaDbTypes.OracleTypes.number.nullable, CompanyId.oracleType, OracleTypes.varchar2, OracleTypes.varchar2.nullable, OracleTypes.varchar2.nullable, OracleTypes.varchar2.nullable)(EmployeeSummaryViewRow.apply)(row => Array[Any](row.employeeId, row.email, row.firstName, row.lastName, row.salary, row.hiredAt, row.active, row.departmentId, row.departmentName, row.departmentBudget, row.companyId, row.companyName, row.managerId, row.managerFirstName, row.managerLastName))\n}", - "EmployeeSummaryViewRepo": "package showcase.showcase.employee_summary\n\nimport dev.typr.foundations.scala.SelectBuilder\nimport java.sql.Connection\n\ntrait EmployeeSummaryViewRepo {\n def select: SelectBuilder[EmployeeSummaryViewFields, EmployeeSummaryViewRow]\n\n def selectAll(using c: Connection): List[EmployeeSummaryViewRow]\n}", - "CustomerOrderRow": "package showcase.showcase.customer_order\n\nimport dev.typr.foundations.OracleTypes\nimport dev.typr.foundations.data.Json\nimport dev.typr.foundations.data.OracleIntervalDS\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport java.time.LocalDateTime\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.address.AddressId\nimport showcase.showcase.customer.CustomerId\n\n/** Table: showcase.customer_order\n * Primary key: id\n */\ncase class CustomerOrderRow(\n id: CustomerOrderId,\n /** Points to [[showcase.showcase.customer.CustomerRow.id]] */\n customerId: CustomerId,\n /** Points to [[showcase.showcase.address.AddressRow.id]] */\n shippingAddressId: Option[AddressId],\n /** Points to [[showcase.showcase.address.AddressRow.id]] */\n billingAddressId: Option[AddressId],\n /** Default: 'pending' */\n status: Option[String],\n subtotal: BigDecimal,\n /** Default: 0 */\n tax: Option[BigDecimal],\n /** Default: 0 */\n shipping: Option[BigDecimal],\n total: BigDecimal,\n notes: Option[String],\n /** Default: CURRENT_TIMESTAMP */\n createdAt: Option[LocalDateTime],\n shippedAt: Option[LocalDateTime],\n deliveredAt: Option[LocalDateTime],\n metadata: Option[Json],\n notesExtended: Option[String],\n receiptData: Option[Array[Byte]],\n processingTime: Option[OracleIntervalDS],\n xmlInvoice: Option[String]\n) {\n def toUnsavedRow(\n status: Defaulted[Option[String]] = Defaulted.Provided(this.status),\n tax: Defaulted[Option[BigDecimal]] = Defaulted.Provided(this.tax),\n shipping: Defaulted[Option[BigDecimal]] = Defaulted.Provided(this.shipping),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.Provided(this.createdAt)\n ): CustomerOrderRowUnsaved = {\n new CustomerOrderRowUnsaved(\n id,\n customerId,\n shippingAddressId,\n billingAddressId,\n subtotal,\n total,\n notes,\n shippedAt,\n deliveredAt,\n metadata,\n notesExtended,\n receiptData,\n processingTime,\n xmlInvoice,\n status,\n tax,\n shipping,\n createdAt\n )\n }\n}\n\nobject CustomerOrderRow {\n val `_rowParser`: RowParser[CustomerOrderRow] = RowParsers.of(CustomerOrderId.oracleType, CustomerId.oracleType, AddressId.oracleType.nullable, AddressId.oracleType.nullable, OracleTypes.varchar2.nullable, ScalaDbTypes.OracleTypes.number, ScalaDbTypes.OracleTypes.number.nullable, ScalaDbTypes.OracleTypes.number.nullable, ScalaDbTypes.OracleTypes.number, OracleTypes.varchar2.nullable, OracleTypes.timestamp.nullable, OracleTypes.timestamp.nullable, OracleTypes.timestamp.nullable, OracleTypes.json.nullable, OracleTypes.clob.nullable, OracleTypes.blob.nullable, OracleTypes.intervalDayToSecond.nullable, OracleTypes.xmlType.nullable)(CustomerOrderRow.apply)(row => Array[Any](row.id, row.customerId, row.shippingAddressId, row.billingAddressId, row.status, row.subtotal, row.tax, row.shipping, row.total, row.notes, row.createdAt, row.shippedAt, row.deliveredAt, row.metadata, row.notesExtended, row.receiptData, row.processingTime, row.xmlInvoice))\n}", - "CustomerOrderRepo": "package showcase.showcase.customer_order\n\nimport dev.typr.foundations.scala.DeleteBuilder\nimport dev.typr.foundations.scala.SelectBuilder\nimport dev.typr.foundations.scala.UpdateBuilder\nimport java.sql.Connection\n\ntrait CustomerOrderRepo {\n def delete: DeleteBuilder[CustomerOrderFields, CustomerOrderRow]\n\n def deleteById(id: CustomerOrderId)(using c: Connection): Boolean\n\n def deleteByIds(ids: Array[CustomerOrderId])(using c: Connection): Int\n\n def insert(unsaved: CustomerOrderRow)(using c: Connection): CustomerOrderRow\n\n def insert(unsaved: CustomerOrderRowUnsaved)(using c: Connection): CustomerOrderRow\n\n def select: SelectBuilder[CustomerOrderFields, CustomerOrderRow]\n\n def selectAll(using c: Connection): List[CustomerOrderRow]\n\n def selectById(id: CustomerOrderId)(using c: Connection): Option[CustomerOrderRow]\n\n def selectByIds(ids: Array[CustomerOrderId])(using c: Connection): List[CustomerOrderRow]\n\n def selectByIdsTracked(ids: Array[CustomerOrderId])(using c: Connection): Map[CustomerOrderId, CustomerOrderRow]\n\n def update: UpdateBuilder[CustomerOrderFields, CustomerOrderRow]\n\n def update(row: CustomerOrderRow)(using c: Connection): Boolean\n\n def upsert(unsaved: CustomerOrderRow)(using c: Connection): CustomerOrderRow\n\n def upsertBatch(unsaved: Iterator[CustomerOrderRow])(using c: Connection): List[CustomerOrderRow]\n}", - "OrderItemRow": "package showcase.showcase.order_item\n\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.customer_order.CustomerOrderId\nimport showcase.showcase.product.ProductId\n\n/** Table: showcase.order_item\n * Composite primary key: order_id, product_id\n */\ncase class OrderItemRow(\n /** Points to [[showcase.showcase.customer_order.CustomerOrderRow.id]] */\n orderId: CustomerOrderId,\n /** Points to [[showcase.showcase.product.ProductRow.id]] */\n productId: ProductId,\n quantity: BigDecimal,\n unitPrice: BigDecimal,\n /** Default: 0 */\n discount: Option[BigDecimal]\n) {\n def compositeId: OrderItemId = new OrderItemId(orderId, productId)\n\n def id: OrderItemId = this.compositeId\n\n def toUnsavedRow(discount: Defaulted[Option[BigDecimal]] = Defaulted.Provided(this.discount)): OrderItemRowUnsaved = {\n new OrderItemRowUnsaved(\n orderId,\n productId,\n quantity,\n unitPrice,\n discount\n )\n }\n}\n\nobject OrderItemRow {\n val `_rowParser`: RowParser[OrderItemRow] = RowParsers.of(CustomerOrderId.oracleType, ProductId.oracleType, ScalaDbTypes.OracleTypes.number, ScalaDbTypes.OracleTypes.number, ScalaDbTypes.OracleTypes.number.nullable)(OrderItemRow.apply)(row => Array[Any](row.orderId, row.productId, row.quantity, row.unitPrice, row.discount))\n\n def apply(\n compositeId: OrderItemId,\n quantity: BigDecimal,\n unitPrice: BigDecimal,\n discount: Option[BigDecimal]\n ): OrderItemRow = {\n new OrderItemRow(\n compositeId.orderId,\n compositeId.productId,\n quantity,\n unitPrice,\n discount\n )\n }\n}", - "OrderItemId": "package showcase.showcase.order_item\n\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport showcase.showcase.customer_order.CustomerOrderId\nimport showcase.showcase.product.ProductId\n\n/** Type for the composite primary key of table `showcase.order_item` */\ncase class OrderItemId(\n orderId: CustomerOrderId,\n productId: ProductId\n)\n\nobject OrderItemId {\n val `_rowParser`: RowParser[OrderItemId] = RowParsers.of(CustomerOrderId.oracleType, ProductId.oracleType)(OrderItemId.apply)(row => Array[Any](row.orderId, row.productId))\n}", - "ProductRow": "package showcase.showcase.product\n\nimport dev.typr.foundations.OracleTypes\nimport dev.typr.foundations.data.Json\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport java.time.LocalDateTime\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.category.CategoryId\n\n/** Table: showcase.product\n * Primary key: id\n */\ncase class ProductRow(\n id: ProductId,\n /** Points to [[showcase.showcase.category.CategoryRow.id]] */\n categoryId: Option[CategoryId],\n name: String,\n sku: String,\n price: BigDecimal,\n cost: Option[BigDecimal],\n /** Default: true */\n inStock: Option[BigDecimal],\n /** Default: 0 */\n quantity: Option[BigDecimal],\n weight: Option[BigDecimal],\n /** Default: CURRENT_TIMESTAMP */\n createdAt: Option[LocalDateTime],\n attributes: Option[Json],\n specifications: Option[String],\n descriptionLong: Option[String],\n thumbnail: Option[Array[Byte]],\n xmlData: Option[String]\n) {\n def toUnsavedRow(\n inStock: Defaulted[Option[BigDecimal]] = Defaulted.Provided(this.inStock),\n quantity: Defaulted[Option[BigDecimal]] = Defaulted.Provided(this.quantity),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.Provided(this.createdAt)\n ): ProductRowUnsaved = {\n new ProductRowUnsaved(\n id,\n categoryId,\n name,\n sku,\n price,\n cost,\n weight,\n attributes,\n specifications,\n descriptionLong,\n thumbnail,\n xmlData,\n inStock,\n quantity,\n createdAt\n )\n }\n}\n\nobject ProductRow {\n val `_rowParser`: RowParser[ProductRow] = RowParsers.of(ProductId.oracleType, CategoryId.oracleType.nullable, OracleTypes.varchar2, OracleTypes.varchar2, ScalaDbTypes.OracleTypes.number, ScalaDbTypes.OracleTypes.number.nullable, ScalaDbTypes.OracleTypes.number.nullable, ScalaDbTypes.OracleTypes.number.nullable, ScalaDbTypes.OracleTypes.number.nullable, OracleTypes.timestamp.nullable, OracleTypes.json.nullable, OracleTypes.clob.nullable, OracleTypes.clob.nullable, OracleTypes.blob.nullable, OracleTypes.xmlType.nullable)(ProductRow.apply)(row => Array[Any](row.id, row.categoryId, row.name, row.sku, row.price, row.cost, row.inStock, row.quantity, row.weight, row.createdAt, row.attributes, row.specifications, row.descriptionLong, row.thumbnail, row.xmlData))\n}", - "ProductId": "package showcase.showcase.product\n\nimport dev.typr.foundations.OracleType\nimport dev.typr.foundations.OracleTypes\nimport dev.typr.foundations.scala.Bijection\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\n\n/** Type for the primary key of table `showcase.product` */\ncase class ProductId(value: String) extends scala.AnyVal\n\nobject ProductId {\n given `_rowParser`: RowParser[ProductId] = RowParsers.of(OracleTypes.varchar2.bimap(ProductId.apply, _.value))(x => x)(id => Array[Any](id))\n\n given bijection: Bijection[ProductId, String] = Bijection.apply[ProductId, String](_.value)(ProductId.apply)\n\n given oracleType: OracleType[ProductId] = OracleTypes.varchar2.bimap(ProductId.apply, _.value)\n}", - "CategoryRow": "package showcase.showcase.category\n\nimport dev.typr.foundations.OracleTypes\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\n\n/** Table: showcase.category\n * Primary key: id\n */\ncase class CategoryRow(\n id: CategoryId,\n /** Points to [[showcase.showcase.category.CategoryRow.id]] */\n parentId: Option[CategoryId],\n name: String,\n description: Option[String]\n)\n\nobject CategoryRow {\n val `_rowParser`: RowParser[CategoryRow] = RowParsers.of(CategoryId.oracleType, CategoryId.oracleType.nullable, OracleTypes.varchar2, OracleTypes.varchar2.nullable)(CategoryRow.apply)(row => Array[Any](row.id, row.parentId, row.name, row.description))\n}", - "CategoryId": "package showcase.showcase.category\n\nimport dev.typr.foundations.OracleType\nimport dev.typr.foundations.OracleTypes\nimport dev.typr.foundations.scala.Bijection\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\n\n/** Type for the primary key of table `showcase.category` */\ncase class CategoryId(value: String) extends scala.AnyVal\n\nobject CategoryId {\n given `_rowParser`: RowParser[CategoryId] = RowParsers.of(OracleTypes.varchar2.bimap(CategoryId.apply, _.value))(x => x)(id => Array[Any](id))\n\n given bijection: Bijection[CategoryId, String] = Bijection.apply[CategoryId, String](_.value)(CategoryId.apply)\n\n given oracleType: OracleType[CategoryId] = OracleTypes.varchar2.bimap(CategoryId.apply, _.value)\n}", - "AddressRow": "package showcase.showcase.address\n\nimport dev.typr.foundations.OracleTypes\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.customer.CustomerId\n\n/** Table: showcase.address\n * Primary key: id\n */\ncase class AddressRow(\n id: AddressId,\n /** Points to [[showcase.showcase.customer.CustomerRow.id]] */\n customerId: CustomerId,\n addressType: String,\n street: String,\n city: String,\n state: Option[String],\n postalCode: Option[String],\n country: String,\n /** Default: false */\n isDefault: Option[BigDecimal],\n location: Option[/* SDO_POINT (Oracle Spatial) */ String],\n notes: Option[String]\n) {\n def toUnsavedRow(isDefault: Defaulted[Option[BigDecimal]] = Defaulted.Provided(this.isDefault)): AddressRowUnsaved = {\n new AddressRowUnsaved(\n id,\n customerId,\n addressType,\n street,\n city,\n state,\n postalCode,\n country,\n location,\n notes,\n isDefault\n )\n }\n}\n\nobject AddressRow {\n val `_rowParser`: RowParser[AddressRow] = RowParsers.of(AddressId.oracleType, CustomerId.oracleType, OracleTypes.varchar2, OracleTypes.varchar2, OracleTypes.varchar2, OracleTypes.varchar2.nullable, OracleTypes.varchar2.nullable, OracleTypes.varchar2, ScalaDbTypes.OracleTypes.number.nullable, OracleTypes.varchar2.nullable, OracleTypes.clob.nullable)(AddressRow.apply)(row => Array[Any](row.id, row.customerId, row.addressType, row.street, row.city, row.state, row.postalCode, row.country, row.isDefault, row.location, row.notes))\n}", - "AddressId": "package showcase.showcase.address\n\nimport dev.typr.foundations.OracleType\nimport dev.typr.foundations.OracleTypes\nimport dev.typr.foundations.scala.Bijection\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\n\n/** Type for the primary key of table `showcase.address` */\ncase class AddressId(value: String) extends scala.AnyVal\n\nobject AddressId {\n given `_rowParser`: RowParser[AddressId] = RowParsers.of(OracleTypes.varchar2.bimap(AddressId.apply, _.value))(x => x)(id => Array[Any](id))\n\n given bijection: Bijection[AddressId, String] = Bijection.apply[AddressId, String](_.value)(AddressId.apply)\n\n given oracleType: OracleType[AddressId] = OracleTypes.varchar2.bimap(AddressId.apply, _.value)\n}", - "Defaulted": "package showcase.customtypes\n\n\n\n/** This signals a value where if you don't provide it, postgres will generate it for you */\nsealed trait Defaulted[T] {\n def fold[U](\n onDefault: => U,\n onProvided: T => U\n ): U\n\n def getOrElse(onDefault: => T): T\n\n def visit(\n onDefault: => Unit,\n onProvided: T => Unit\n ): Unit\n}\n\nobject Defaulted {\n case class Provided[T](value: T) extends Defaulted[T] {\n override def fold[U](\n onDefault: => U,\n onProvided: T => U\n ): U = onProvided(value)\n\n override def getOrElse(onDefault: => T): T = value\n\n override def visit(\n onDefault: => Unit,\n onProvided: T => Unit\n ): Unit = onProvided(value)\n }\n\n case class UseDefault[T]() extends Defaulted[T] {\n override def fold[U](\n onDefault: => U,\n onProvided: T => U\n ): U = onDefault\n\n override def getOrElse(onDefault: => T): T = onDefault\n\n override def visit(\n onDefault: => Unit,\n onProvided: T => Unit\n ): Unit = onDefault\n }\n}", - "TestInsert": "package showcase\n\nimport dev.typr.foundations.data.Json\nimport dev.typr.foundations.data.OracleIntervalDS\nimport dev.typr.foundations.data.OracleIntervalYM\nimport java.sql.Connection\nimport java.time.LocalDateTime\nimport scala.util.Random\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.address.AddressId\nimport showcase.showcase.address.AddressRepoImpl\nimport showcase.showcase.address.AddressRow\nimport showcase.showcase.address.AddressRowUnsaved\nimport showcase.showcase.audit_log.AuditLogId\nimport showcase.showcase.audit_log.AuditLogRepoImpl\nimport showcase.showcase.audit_log.AuditLogRow\nimport showcase.showcase.audit_log.AuditLogRowUnsaved\nimport showcase.showcase.category.CategoryId\nimport showcase.showcase.category.CategoryRepoImpl\nimport showcase.showcase.category.CategoryRow\nimport showcase.showcase.company.CompanyId\nimport showcase.showcase.company.CompanyRepoImpl\nimport showcase.showcase.company.CompanyRow\nimport showcase.showcase.company.CompanyRowUnsaved\nimport showcase.showcase.customer.CustomerId\nimport showcase.showcase.customer.CustomerRepoImpl\nimport showcase.showcase.customer.CustomerRow\nimport showcase.showcase.customer.CustomerRowUnsaved\nimport showcase.showcase.customer_order.CustomerOrderId\nimport showcase.showcase.customer_order.CustomerOrderRepoImpl\nimport showcase.showcase.customer_order.CustomerOrderRow\nimport showcase.showcase.customer_order.CustomerOrderRowUnsaved\nimport showcase.showcase.department.DepartmentId\nimport showcase.showcase.department.DepartmentRepoImpl\nimport showcase.showcase.department.DepartmentRow\nimport showcase.showcase.employee.EmployeeId\nimport showcase.showcase.employee.EmployeeRepoImpl\nimport showcase.showcase.employee.EmployeeRow\nimport showcase.showcase.employee.EmployeeRowUnsaved\nimport showcase.showcase.order_item.OrderItemRepoImpl\nimport showcase.showcase.order_item.OrderItemRow\nimport showcase.showcase.order_item.OrderItemRowUnsaved\nimport showcase.showcase.product.ProductId\nimport showcase.showcase.product.ProductRepoImpl\nimport showcase.showcase.product.ProductRow\nimport showcase.showcase.product.ProductRowUnsaved\nimport showcase.showcase.project.ProjectId\nimport showcase.showcase.project.ProjectRepoImpl\nimport showcase.showcase.project.ProjectRow\nimport showcase.showcase.project.ProjectRowUnsaved\nimport showcase.showcase.project_assignment.ProjectAssignmentRepoImpl\nimport showcase.showcase.project_assignment.ProjectAssignmentRow\nimport showcase.showcase.project_assignment.ProjectAssignmentRowUnsaved\n\n/** Methods to generate random data for `Ident(TestInsert)` */\ncase class TestInsert(random: Random) {\n def showcaseAddress(\n customerId: CustomerId,\n id: AddressId = AddressId(random.alphanumeric.take(20).mkString),\n addressType: String = random.alphanumeric.take(20).mkString,\n street: String = random.alphanumeric.take(20).mkString,\n city: String = random.alphanumeric.take(20).mkString,\n state: Option[String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n postalCode: Option[String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n country: String = random.alphanumeric.take(20).mkString,\n location: Option[/* SDO_POINT (Oracle Spatial) */ String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n notes: Option[String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n isDefault: Defaulted[Option[BigDecimal]] = Defaulted.UseDefault()\n )(using c: Connection): AddressRow = {\n (new AddressRepoImpl()).insert(new AddressRowUnsaved(\n id = id,\n customerId = customerId,\n addressType = addressType,\n street = street,\n city = city,\n state = state,\n postalCode = postalCode,\n country = country,\n location = location,\n notes = notes,\n isDefault = isDefault\n ))(using c)\n }\n\n def showcaseAuditLog(\n id: AuditLogId = AuditLogId(random.alphanumeric.take(20).mkString),\n tableName: String = random.alphanumeric.take(20).mkString,\n recordId: String = random.alphanumeric.take(20).mkString,\n action: String = random.alphanumeric.take(20).mkString,\n oldValues: Option[String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n newValues: Option[String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n changedBy: Option[EmployeeId] = None,\n changedAt: Defaulted[Option[LocalDateTime]] = Defaulted.UseDefault()\n )(using c: Connection): AuditLogRow = {\n (new AuditLogRepoImpl()).insert(new AuditLogRowUnsaved(\n id = id,\n tableName = tableName,\n recordId = recordId,\n action = action,\n oldValues = oldValues,\n newValues = newValues,\n changedBy = changedBy,\n changedAt = changedAt\n ))(using c)\n }\n\n def showcaseCategory(\n id: CategoryId = CategoryId(random.alphanumeric.take(20).mkString),\n parentId: Option[CategoryId] = None,\n name: String = random.alphanumeric.take(20).mkString,\n description: Option[String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString)\n )(using c: Connection): CategoryRow = {\n (new CategoryRepoImpl()).insert(new CategoryRow(\n id = id,\n parentId = parentId,\n name = name,\n description = description\n ))(using c)\n }\n\n def showcaseCompany(\n id: CompanyId = CompanyId(random.alphanumeric.take(20).mkString),\n name: String = random.alphanumeric.take(20).mkString,\n foundedYear: Option[BigDecimal] = if (random.nextBoolean()) None else Some(BigDecimal.decimal(random.nextDouble())),\n active: Defaulted[Option[BigDecimal]] = Defaulted.UseDefault(),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.UseDefault()\n )(using c: Connection): CompanyRow = {\n (new CompanyRepoImpl()).insert(new CompanyRowUnsaved(\n id = id,\n name = name,\n foundedYear = foundedYear,\n active = active,\n createdAt = createdAt\n ))(using c)\n }\n\n def showcaseCustomer(\n id: CustomerId = CustomerId(random.alphanumeric.take(20).mkString),\n email: String = random.alphanumeric.take(20).mkString,\n firstName: String = random.alphanumeric.take(20).mkString,\n lastName: String = random.alphanumeric.take(20).mkString,\n phone: Option[String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n preferences: Option[Json] = None,\n avatar: Option[Array[Byte]] = None,\n notes: Option[String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n verified: Defaulted[Option[BigDecimal]] = Defaulted.UseDefault(),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.UseDefault()\n )(using c: Connection): CustomerRow = {\n (new CustomerRepoImpl()).insert(new CustomerRowUnsaved(\n id = id,\n email = email,\n firstName = firstName,\n lastName = lastName,\n phone = phone,\n preferences = preferences,\n avatar = avatar,\n notes = notes,\n verified = verified,\n createdAt = createdAt\n ))(using c)\n }\n\n def showcaseCustomerOrder(\n customerId: CustomerId,\n id: CustomerOrderId = CustomerOrderId(random.alphanumeric.take(20).mkString),\n shippingAddressId: Option[AddressId] = None,\n billingAddressId: Option[AddressId] = None,\n subtotal: BigDecimal = BigDecimal.decimal(random.nextDouble()),\n total: BigDecimal = BigDecimal.decimal(random.nextDouble()),\n notes: Option[String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n shippedAt: Option[LocalDateTime] = None,\n deliveredAt: Option[LocalDateTime] = None,\n metadata: Option[Json] = None,\n notesExtended: Option[String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n receiptData: Option[Array[Byte]] = None,\n processingTime: Option[OracleIntervalDS] = None,\n xmlInvoice: Option[String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n status: Defaulted[Option[String]] = Defaulted.UseDefault(),\n tax: Defaulted[Option[BigDecimal]] = Defaulted.UseDefault(),\n shipping: Defaulted[Option[BigDecimal]] = Defaulted.UseDefault(),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.UseDefault()\n )(using c: Connection): CustomerOrderRow = {\n (new CustomerOrderRepoImpl()).insert(new CustomerOrderRowUnsaved(\n id = id,\n customerId = customerId,\n shippingAddressId = shippingAddressId,\n billingAddressId = billingAddressId,\n subtotal = subtotal,\n total = total,\n notes = notes,\n shippedAt = shippedAt,\n deliveredAt = deliveredAt,\n metadata = metadata,\n notesExtended = notesExtended,\n receiptData = receiptData,\n processingTime = processingTime,\n xmlInvoice = xmlInvoice,\n status = status,\n tax = tax,\n shipping = shipping,\n createdAt = createdAt\n ))(using c)\n }\n\n def showcaseDepartment(\n companyId: CompanyId,\n id: DepartmentId = DepartmentId(random.alphanumeric.take(20).mkString),\n name: String = random.alphanumeric.take(20).mkString,\n budget: Option[BigDecimal] = if (random.nextBoolean()) None else Some(BigDecimal.decimal(random.nextDouble()))\n )(using c: Connection): DepartmentRow = {\n (new DepartmentRepoImpl()).insert(new DepartmentRow(\n id = id,\n companyId = companyId,\n name = name,\n budget = budget\n ))(using c)\n }\n\n def showcaseEmployee(\n departmentId: DepartmentId,\n id: EmployeeId = EmployeeId(random.alphanumeric.take(20).mkString),\n managerId: Option[EmployeeId] = None,\n email: String = random.alphanumeric.take(20).mkString,\n firstName: String = random.alphanumeric.take(20).mkString,\n lastName: String = random.alphanumeric.take(20).mkString,\n salary: Option[BigDecimal] = if (random.nextBoolean()) None else Some(BigDecimal.decimal(random.nextDouble())),\n hiredAt: Option[LocalDateTime] = None,\n metadata: Option[Json] = None,\n resume: Option[String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n photo: Option[Array[Byte]] = None,\n probationPeriod: Option[OracleIntervalYM] = None,\n shiftDuration: Option[OracleIntervalDS] = None,\n active: Defaulted[Option[BigDecimal]] = Defaulted.UseDefault(),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.UseDefault()\n )(using c: Connection): EmployeeRow = {\n (new EmployeeRepoImpl()).insert(new EmployeeRowUnsaved(\n id = id,\n departmentId = departmentId,\n managerId = managerId,\n email = email,\n firstName = firstName,\n lastName = lastName,\n salary = salary,\n hiredAt = hiredAt,\n metadata = metadata,\n resume = resume,\n photo = photo,\n probationPeriod = probationPeriod,\n shiftDuration = shiftDuration,\n active = active,\n createdAt = createdAt\n ))(using c)\n }\n\n def showcaseOrderItem(\n orderId: CustomerOrderId,\n productId: ProductId,\n quantity: BigDecimal = BigDecimal.decimal(random.nextDouble()),\n unitPrice: BigDecimal = BigDecimal.decimal(random.nextDouble()),\n discount: Defaulted[Option[BigDecimal]] = Defaulted.UseDefault()\n )(using c: Connection): OrderItemRow = {\n (new OrderItemRepoImpl()).insert(new OrderItemRowUnsaved(\n orderId = orderId,\n productId = productId,\n quantity = quantity,\n unitPrice = unitPrice,\n discount = discount\n ))(using c)\n }\n\n def showcaseProduct(\n id: ProductId = ProductId(random.alphanumeric.take(20).mkString),\n categoryId: Option[CategoryId] = None,\n name: String = random.alphanumeric.take(20).mkString,\n sku: String = random.alphanumeric.take(20).mkString,\n price: BigDecimal = BigDecimal.decimal(random.nextDouble()),\n cost: Option[BigDecimal] = if (random.nextBoolean()) None else Some(BigDecimal.decimal(random.nextDouble())),\n weight: Option[BigDecimal] = if (random.nextBoolean()) None else Some(BigDecimal.decimal(random.nextDouble())),\n attributes: Option[Json] = None,\n specifications: Option[String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n descriptionLong: Option[String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n thumbnail: Option[Array[Byte]] = None,\n xmlData: Option[String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n inStock: Defaulted[Option[BigDecimal]] = Defaulted.UseDefault(),\n quantity: Defaulted[Option[BigDecimal]] = Defaulted.UseDefault(),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.UseDefault()\n )(using c: Connection): ProductRow = {\n (new ProductRepoImpl()).insert(new ProductRowUnsaved(\n id = id,\n categoryId = categoryId,\n name = name,\n sku = sku,\n price = price,\n cost = cost,\n weight = weight,\n attributes = attributes,\n specifications = specifications,\n descriptionLong = descriptionLong,\n thumbnail = thumbnail,\n xmlData = xmlData,\n inStock = inStock,\n quantity = quantity,\n createdAt = createdAt\n ))(using c)\n }\n\n def showcaseProject(\n id: ProjectId = ProjectId(random.alphanumeric.take(20).mkString),\n name: String = random.alphanumeric.take(20).mkString,\n description: Option[String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n startDate: Option[LocalDateTime] = None,\n endDate: Option[LocalDateTime] = None,\n budget: Option[BigDecimal] = if (random.nextBoolean()) None else Some(BigDecimal.decimal(random.nextDouble())),\n metadata: Option[Json] = None,\n descriptionLong: Option[String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n attachments: Option[Array[Byte]] = None,\n estimatedDuration: Option[OracleIntervalYM] = None,\n actualDuration: Option[OracleIntervalDS] = None,\n xmlPlan: Option[String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n status: Defaulted[Option[String]] = Defaulted.UseDefault(),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.UseDefault()\n )(using c: Connection): ProjectRow = {\n (new ProjectRepoImpl()).insert(new ProjectRowUnsaved(\n id = id,\n name = name,\n description = description,\n startDate = startDate,\n endDate = endDate,\n budget = budget,\n metadata = metadata,\n descriptionLong = descriptionLong,\n attachments = attachments,\n estimatedDuration = estimatedDuration,\n actualDuration = actualDuration,\n xmlPlan = xmlPlan,\n status = status,\n createdAt = createdAt\n ))(using c)\n }\n\n def showcaseProjectAssignment(\n employeeId: EmployeeId,\n projectId: ProjectId,\n role: String = random.alphanumeric.take(20).mkString,\n startDate: Option[LocalDateTime] = None,\n endDate: Option[LocalDateTime] = None,\n hoursAllocated: Defaulted[Option[BigDecimal]] = Defaulted.UseDefault()\n )(using c: Connection): ProjectAssignmentRow = {\n (new ProjectAssignmentRepoImpl()).insert(new ProjectAssignmentRowUnsaved(\n employeeId = employeeId,\n projectId = projectId,\n role = role,\n startDate = startDate,\n endDate = endDate,\n hoursAllocated = hoursAllocated\n ))(using c)\n }\n}" - } - }, - "sqlserver": { - "java": { - "CompanyRow": "package showcase.showcase.company;\n\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport dev.typr.foundations.SqlServerTypes;\nimport java.time.LocalDateTime;\nimport java.util.Optional;\nimport showcase.customtypes.Defaulted;\n\n/** Table: showcase.company\n * Primary key: id\n */\npublic record CompanyRow(\n CompanyId id,\n String name,\n Optional foundedYear,\n /** Default: true */\n Optional active,\n /** Default: CURRENT_TIMESTAMP */\n Optional createdAt\n) {\n public CompanyRow withId(CompanyId id) {\n return new CompanyRow(id, name, foundedYear, active, createdAt);\n };\n\n public CompanyRow withName(String name) {\n return new CompanyRow(id, name, foundedYear, active, createdAt);\n };\n\n public CompanyRow withFoundedYear(Optional foundedYear) {\n return new CompanyRow(id, name, foundedYear, active, createdAt);\n };\n\n /** Default: true */\n public CompanyRow withActive(Optional active) {\n return new CompanyRow(id, name, foundedYear, active, createdAt);\n };\n\n /** Default: CURRENT_TIMESTAMP */\n public CompanyRow withCreatedAt(Optional createdAt) {\n return new CompanyRow(id, name, foundedYear, active, createdAt);\n };\n\n public static RowParser _rowParser = RowParsers.of(CompanyId.sqlServerType, SqlServerTypes.nvarchar, SqlServerTypes.int_.opt(), SqlServerTypes.bit.opt(), SqlServerTypes.datetime2.opt(), CompanyRow::new, row -> new Object[]{row.id(), row.name(), row.foundedYear(), row.active(), row.createdAt()});;\n\n public CompanyRowUnsaved toUnsavedRow(\n Defaulted> active,\n Defaulted> createdAt\n ) {\n return new CompanyRowUnsaved(id, name, foundedYear, active, createdAt);\n };\n}", - "CompanyRowUnsaved": "package showcase.showcase.company;\n\nimport java.time.LocalDateTime;\nimport java.util.Optional;\nimport showcase.customtypes.Defaulted;\nimport showcase.customtypes.Defaulted.UseDefault;\n\n/** This class corresponds to a row in table `showcase.company` which has not been persisted yet */\npublic record CompanyRowUnsaved(\n CompanyId id,\n String name,\n Optional foundedYear,\n /** Default: true */\n Defaulted> active,\n /** Default: CURRENT_TIMESTAMP */\n Defaulted> createdAt\n) {\n public CompanyRowUnsaved(\n CompanyId id,\n String name\n ) {\n this(id, name, Optional.empty(), new UseDefault<>(), new UseDefault<>());\n };\n\n public CompanyRowUnsaved withId(CompanyId id) {\n return new CompanyRowUnsaved(id, name, foundedYear, active, createdAt);\n };\n\n public CompanyRowUnsaved withName(String name) {\n return new CompanyRowUnsaved(id, name, foundedYear, active, createdAt);\n };\n\n public CompanyRowUnsaved withFoundedYear(Optional foundedYear) {\n return new CompanyRowUnsaved(id, name, foundedYear, active, createdAt);\n };\n\n /** Default: true */\n public CompanyRowUnsaved withActive(Defaulted> active) {\n return new CompanyRowUnsaved(id, name, foundedYear, active, createdAt);\n };\n\n /** Default: CURRENT_TIMESTAMP */\n public CompanyRowUnsaved withCreatedAt(Defaulted> createdAt) {\n return new CompanyRowUnsaved(id, name, foundedYear, active, createdAt);\n };\n\n public CompanyRow toRow(\n java.util.function.Supplier> activeDefault,\n java.util.function.Supplier> createdAtDefault\n ) {\n return new CompanyRow(id, name, foundedYear, active.getOrElse(activeDefault), createdAt.getOrElse(createdAtDefault));\n };\n}", - "CompanyId": "package showcase.showcase.company;\n\nimport dev.typr.foundations.SqlServerType;\nimport dev.typr.foundations.SqlServerTypes;\nimport dev.typr.foundations.dsl.Bijection;\n\n/** Type for the primary key of table `showcase.company` */\npublic record CompanyId(String value) {\n public CompanyId withValue(String value) {\n return new CompanyId(value);\n };\n\n @Override\n public java.lang.String toString() {\n return value.toString();\n };\n\n static public Bijection bijection =\n Bijection.of(CompanyId::value, CompanyId::new);\n\n static public SqlServerType sqlServerType =\n SqlServerTypes.nvarchar.bimap(CompanyId::new, CompanyId::value);\n}", - "CompanyRepo": "package showcase.showcase.company;\n\nimport dev.typr.foundations.dsl.DeleteBuilder;\nimport dev.typr.foundations.dsl.SelectBuilder;\nimport dev.typr.foundations.dsl.UpdateBuilder;\nimport java.sql.Connection;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\n\npublic interface CompanyRepo {\n DeleteBuilder delete();\n\n Boolean deleteById(\n CompanyId id,\n Connection c\n );\n\n Integer deleteByIds(\n CompanyId[] ids,\n Connection c\n );\n\n CompanyRow insert(\n CompanyRow unsaved,\n Connection c\n );\n\n CompanyRow insert(\n CompanyRowUnsaved unsaved,\n Connection c\n );\n\n SelectBuilder select();\n\n List selectAll(Connection c);\n\n Optional selectById(\n CompanyId id,\n Connection c\n );\n\n List selectByIds(\n CompanyId[] ids,\n Connection c\n );\n\n Map selectByIdsTracked(\n CompanyId[] ids,\n Connection c\n );\n\n UpdateBuilder update();\n\n Boolean update(\n CompanyRow row,\n Connection c\n );\n\n CompanyRow upsert(\n CompanyRow unsaved,\n Connection c\n );\n\n List upsertBatch(\n Iterator unsaved,\n Connection c\n );\n}", - "CompanyRepoMock": "package showcase.showcase.company;\n\nimport dev.typr.foundations.dsl.DeleteBuilder;\nimport dev.typr.foundations.dsl.DeleteBuilderMock;\nimport dev.typr.foundations.dsl.DeleteParams;\nimport dev.typr.foundations.dsl.SelectBuilder;\nimport dev.typr.foundations.dsl.SelectBuilderMock;\nimport dev.typr.foundations.dsl.SelectParams;\nimport dev.typr.foundations.dsl.UpdateBuilder;\nimport dev.typr.foundations.dsl.UpdateBuilderMock;\nimport dev.typr.foundations.dsl.UpdateParams;\nimport java.lang.RuntimeException;\nimport java.sql.Connection;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\nimport java.util.function.Function;\nimport java.util.stream.Collectors;\n\npublic record CompanyRepoMock(\n java.util.function.Function toRow,\n HashMap map\n) implements CompanyRepo {\n public CompanyRepoMock(java.util.function.Function toRow) {\n this(toRow, new HashMap());\n };\n\n public CompanyRepoMock withToRow(java.util.function.Function toRow) {\n return new CompanyRepoMock(toRow, map);\n };\n\n public CompanyRepoMock withMap(HashMap map) {\n return new CompanyRepoMock(toRow, map);\n };\n\n @Override\n public DeleteBuilder delete() {\n return new DeleteBuilderMock<>(CompanyFields.structure(), () -> new ArrayList<>(map.values()), DeleteParams.empty(), row -> row.id(), id -> map.remove(id));\n };\n\n @Override\n public Boolean deleteById(\n CompanyId id,\n Connection c\n ) {\n return Optional.ofNullable(map.remove(id)).isPresent();\n };\n\n @Override\n public Integer deleteByIds(\n CompanyId[] ids,\n Connection c\n ) {\n var count = 0;\n for (var id : ids) {\n if (Optional.ofNullable(map.remove(id)).isPresent()) {\n count = count + 1;;\n };\n };\n return count;\n };\n\n @Override\n public CompanyRow insert(\n CompanyRow unsaved,\n Connection c\n ) {\n if (map.containsKey(unsaved.id())) {\n throw new RuntimeException(\"id \" + unsaved.id() + \" already exists\");\n };\n map.put(unsaved.id(), unsaved);\n return unsaved;\n };\n\n @Override\n public CompanyRow insert(\n CompanyRowUnsaved unsaved,\n Connection c\n ) {\n return insert(toRow.apply(unsaved), c);\n };\n\n @Override\n public SelectBuilder select() {\n return new SelectBuilderMock<>(CompanyFields.structure(), () -> new ArrayList<>(map.values()), SelectParams.empty());\n };\n\n @Override\n public List selectAll(Connection c) {\n return new ArrayList<>(map.values());\n };\n\n @Override\n public Optional selectById(\n CompanyId id,\n Connection c\n ) {\n return Optional.ofNullable(map.get(id));\n };\n\n @Override\n public List selectByIds(\n CompanyId[] ids,\n Connection c\n ) {\n var result = new ArrayList();\n for (var id : ids) {\n var opt = Optional.ofNullable(map.get(id));\n if (opt.isPresent()) {\n result.add(opt.get());\n };\n };\n return result;\n };\n\n @Override\n public Map selectByIdsTracked(\n CompanyId[] ids,\n Connection c\n ) {\n return selectByIds(ids, c).stream().collect(Collectors.toMap((CompanyRow row) -> row.id(), Function.identity()));\n };\n\n @Override\n public UpdateBuilder update() {\n return new UpdateBuilderMock<>(CompanyFields.structure(), () -> new ArrayList<>(map.values()), UpdateParams.empty(), row -> row);\n };\n\n @Override\n public Boolean update(\n CompanyRow row,\n Connection c\n ) {\n var shouldUpdate = Optional.ofNullable(map.get(row.id())).filter(oldRow -> !oldRow.equals(row)).isPresent();\n if (shouldUpdate) {\n map.put(row.id(), row);;\n };\n return shouldUpdate;\n };\n\n @Override\n public CompanyRow upsert(\n CompanyRow unsaved,\n Connection c\n ) {\n map.put(unsaved.id(), unsaved);\n return unsaved;\n };\n\n @Override\n public List upsertBatch(\n Iterator unsaved,\n Connection c\n ) {\n var result = new ArrayList();\n while (unsaved.hasNext()) {\n var row = unsaved.next();\n map.put(row.id(), row);\n result.add(row);\n };\n return result;\n };\n}", - "EmployeeRow": "package showcase.showcase.employee;\n\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport dev.typr.foundations.SqlServerTypes;\nimport dev.typr.foundations.data.Json;\nimport java.math.BigDecimal;\nimport java.time.LocalDate;\nimport java.time.LocalDateTime;\nimport java.time.OffsetDateTime;\nimport java.util.Optional;\nimport java.util.UUID;\nimport showcase.customtypes.Defaulted;\nimport showcase.showcase.department.DepartmentId;\n\n/** Table: showcase.employee\n * Primary key: id\n */\npublic record EmployeeRow(\n EmployeeId id,\n /** Points to {@link showcase.showcase.department.DepartmentRow#id()} */\n DepartmentId departmentId,\n /** Points to {@link showcase.showcase.employee.EmployeeRow#id()} */\n Optional managerId,\n String email,\n String firstName,\n String lastName,\n Optional salary,\n Optional hiredAt,\n /** Default: true */\n Optional active,\n /** Default: CURRENT_TIMESTAMP */\n Optional createdAt,\n Optional metadata,\n Optional resume,\n Optional photo,\n Optional employeeUid,\n Optional lastModified,\n Optional rowVersion,\n Optional orgPath\n) {\n public EmployeeRow withId(EmployeeId id) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, metadata, resume, photo, employeeUid, lastModified, rowVersion, orgPath);\n };\n\n /** Points to {@link showcase.showcase.department.DepartmentRow#id()} */\n public EmployeeRow withDepartmentId(DepartmentId departmentId) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, metadata, resume, photo, employeeUid, lastModified, rowVersion, orgPath);\n };\n\n /** Points to {@link showcase.showcase.employee.EmployeeRow#id()} */\n public EmployeeRow withManagerId(Optional managerId) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, metadata, resume, photo, employeeUid, lastModified, rowVersion, orgPath);\n };\n\n public EmployeeRow withEmail(String email) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, metadata, resume, photo, employeeUid, lastModified, rowVersion, orgPath);\n };\n\n public EmployeeRow withFirstName(String firstName) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, metadata, resume, photo, employeeUid, lastModified, rowVersion, orgPath);\n };\n\n public EmployeeRow withLastName(String lastName) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, metadata, resume, photo, employeeUid, lastModified, rowVersion, orgPath);\n };\n\n public EmployeeRow withSalary(Optional salary) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, metadata, resume, photo, employeeUid, lastModified, rowVersion, orgPath);\n };\n\n public EmployeeRow withHiredAt(Optional hiredAt) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, metadata, resume, photo, employeeUid, lastModified, rowVersion, orgPath);\n };\n\n /** Default: true */\n public EmployeeRow withActive(Optional active) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, metadata, resume, photo, employeeUid, lastModified, rowVersion, orgPath);\n };\n\n /** Default: CURRENT_TIMESTAMP */\n public EmployeeRow withCreatedAt(Optional createdAt) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, metadata, resume, photo, employeeUid, lastModified, rowVersion, orgPath);\n };\n\n public EmployeeRow withMetadata(Optional metadata) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, metadata, resume, photo, employeeUid, lastModified, rowVersion, orgPath);\n };\n\n public EmployeeRow withResume(Optional resume) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, metadata, resume, photo, employeeUid, lastModified, rowVersion, orgPath);\n };\n\n public EmployeeRow withPhoto(Optional photo) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, metadata, resume, photo, employeeUid, lastModified, rowVersion, orgPath);\n };\n\n public EmployeeRow withEmployeeUid(Optional employeeUid) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, metadata, resume, photo, employeeUid, lastModified, rowVersion, orgPath);\n };\n\n public EmployeeRow withLastModified(Optional lastModified) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, metadata, resume, photo, employeeUid, lastModified, rowVersion, orgPath);\n };\n\n public EmployeeRow withRowVersion(Optional rowVersion) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, metadata, resume, photo, employeeUid, lastModified, rowVersion, orgPath);\n };\n\n public EmployeeRow withOrgPath(Optional orgPath) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active, createdAt, metadata, resume, photo, employeeUid, lastModified, rowVersion, orgPath);\n };\n\n public static RowParser _rowParser = RowParsers.of(EmployeeId.sqlServerType, DepartmentId.sqlServerType, EmployeeId.sqlServerType.opt(), SqlServerTypes.nvarchar, SqlServerTypes.nvarchar, SqlServerTypes.nvarchar, SqlServerTypes.decimal.opt(), SqlServerTypes.date.opt(), SqlServerTypes.bit.opt(), SqlServerTypes.datetime2.opt(), SqlServerTypes.json.opt(), SqlServerTypes.xml.opt(), SqlServerTypes.varbinary.opt(), SqlServerTypes.uniqueidentifier.opt(), SqlServerTypes.datetimeoffset.opt(), SqlServerTypes.rowversion.opt(), SqlServerTypes.hierarchyid.opt(), EmployeeRow::new, row -> new Object[]{row.id(), row.departmentId(), row.managerId(), row.email(), row.firstName(), row.lastName(), row.salary(), row.hiredAt(), row.active(), row.createdAt(), row.metadata(), row.resume(), row.photo(), row.employeeUid(), row.lastModified(), row.rowVersion(), row.orgPath()});;\n\n public EmployeeRowUnsaved toUnsavedRow(\n Defaulted> active,\n Defaulted> createdAt\n ) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, metadata, resume, photo, employeeUid, lastModified, rowVersion, orgPath, active, createdAt);\n };\n}", - "EmployeeRowUnsaved": "package showcase.showcase.employee;\n\nimport dev.typr.foundations.data.Json;\nimport java.math.BigDecimal;\nimport java.time.LocalDate;\nimport java.time.LocalDateTime;\nimport java.time.OffsetDateTime;\nimport java.util.Optional;\nimport java.util.UUID;\nimport showcase.customtypes.Defaulted;\nimport showcase.customtypes.Defaulted.UseDefault;\nimport showcase.showcase.department.DepartmentId;\n\n/** This class corresponds to a row in table `showcase.employee` which has not been persisted yet */\npublic record EmployeeRowUnsaved(\n EmployeeId id,\n /** Points to {@link showcase.showcase.department.DepartmentRow#id()} */\n DepartmentId departmentId,\n /** Points to {@link showcase.showcase.employee.EmployeeRow#id()} */\n Optional managerId,\n String email,\n String firstName,\n String lastName,\n Optional salary,\n Optional hiredAt,\n Optional metadata,\n Optional resume,\n Optional photo,\n Optional employeeUid,\n Optional lastModified,\n Optional rowVersion,\n Optional orgPath,\n /** Default: true */\n Defaulted> active,\n /** Default: CURRENT_TIMESTAMP */\n Defaulted> createdAt\n) {\n public EmployeeRowUnsaved(\n EmployeeId id,\n /** Points to {@link showcase.showcase.department.DepartmentRow#id()} */\n DepartmentId departmentId,\n String email,\n String firstName,\n String lastName\n ) {\n this(id, departmentId, Optional.empty(), email, firstName, lastName, Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), new UseDefault<>(), new UseDefault<>());\n };\n\n public EmployeeRowUnsaved withId(EmployeeId id) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, metadata, resume, photo, employeeUid, lastModified, rowVersion, orgPath, active, createdAt);\n };\n\n /** Points to {@link showcase.showcase.department.DepartmentRow#id()} */\n public EmployeeRowUnsaved withDepartmentId(DepartmentId departmentId) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, metadata, resume, photo, employeeUid, lastModified, rowVersion, orgPath, active, createdAt);\n };\n\n /** Points to {@link showcase.showcase.employee.EmployeeRow#id()} */\n public EmployeeRowUnsaved withManagerId(Optional managerId) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, metadata, resume, photo, employeeUid, lastModified, rowVersion, orgPath, active, createdAt);\n };\n\n public EmployeeRowUnsaved withEmail(String email) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, metadata, resume, photo, employeeUid, lastModified, rowVersion, orgPath, active, createdAt);\n };\n\n public EmployeeRowUnsaved withFirstName(String firstName) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, metadata, resume, photo, employeeUid, lastModified, rowVersion, orgPath, active, createdAt);\n };\n\n public EmployeeRowUnsaved withLastName(String lastName) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, metadata, resume, photo, employeeUid, lastModified, rowVersion, orgPath, active, createdAt);\n };\n\n public EmployeeRowUnsaved withSalary(Optional salary) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, metadata, resume, photo, employeeUid, lastModified, rowVersion, orgPath, active, createdAt);\n };\n\n public EmployeeRowUnsaved withHiredAt(Optional hiredAt) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, metadata, resume, photo, employeeUid, lastModified, rowVersion, orgPath, active, createdAt);\n };\n\n public EmployeeRowUnsaved withMetadata(Optional metadata) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, metadata, resume, photo, employeeUid, lastModified, rowVersion, orgPath, active, createdAt);\n };\n\n public EmployeeRowUnsaved withResume(Optional resume) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, metadata, resume, photo, employeeUid, lastModified, rowVersion, orgPath, active, createdAt);\n };\n\n public EmployeeRowUnsaved withPhoto(Optional photo) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, metadata, resume, photo, employeeUid, lastModified, rowVersion, orgPath, active, createdAt);\n };\n\n public EmployeeRowUnsaved withEmployeeUid(Optional employeeUid) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, metadata, resume, photo, employeeUid, lastModified, rowVersion, orgPath, active, createdAt);\n };\n\n public EmployeeRowUnsaved withLastModified(Optional lastModified) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, metadata, resume, photo, employeeUid, lastModified, rowVersion, orgPath, active, createdAt);\n };\n\n public EmployeeRowUnsaved withRowVersion(Optional rowVersion) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, metadata, resume, photo, employeeUid, lastModified, rowVersion, orgPath, active, createdAt);\n };\n\n public EmployeeRowUnsaved withOrgPath(Optional orgPath) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, metadata, resume, photo, employeeUid, lastModified, rowVersion, orgPath, active, createdAt);\n };\n\n /** Default: true */\n public EmployeeRowUnsaved withActive(Defaulted> active) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, metadata, resume, photo, employeeUid, lastModified, rowVersion, orgPath, active, createdAt);\n };\n\n /** Default: CURRENT_TIMESTAMP */\n public EmployeeRowUnsaved withCreatedAt(Defaulted> createdAt) {\n return new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, metadata, resume, photo, employeeUid, lastModified, rowVersion, orgPath, active, createdAt);\n };\n\n public EmployeeRow toRow(\n java.util.function.Supplier> activeDefault,\n java.util.function.Supplier> createdAtDefault\n ) {\n return new EmployeeRow(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, active.getOrElse(activeDefault), createdAt.getOrElse(createdAtDefault), metadata, resume, photo, employeeUid, lastModified, rowVersion, orgPath);\n };\n}", - "EmployeeId": "package showcase.showcase.employee;\n\nimport dev.typr.foundations.SqlServerType;\nimport dev.typr.foundations.SqlServerTypes;\nimport dev.typr.foundations.dsl.Bijection;\n\n/** Type for the primary key of table `showcase.employee` */\npublic record EmployeeId(String value) {\n public EmployeeId withValue(String value) {\n return new EmployeeId(value);\n };\n\n @Override\n public java.lang.String toString() {\n return value.toString();\n };\n\n static public Bijection bijection =\n Bijection.of(EmployeeId::value, EmployeeId::new);\n\n static public SqlServerType sqlServerType =\n SqlServerTypes.nvarchar.bimap(EmployeeId::new, EmployeeId::value);\n}", - "EmployeeRepo": "package showcase.showcase.employee;\n\nimport dev.typr.foundations.dsl.DeleteBuilder;\nimport dev.typr.foundations.dsl.SelectBuilder;\nimport dev.typr.foundations.dsl.UpdateBuilder;\nimport java.sql.Connection;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\n\npublic interface EmployeeRepo {\n DeleteBuilder delete();\n\n Boolean deleteById(\n EmployeeId id,\n Connection c\n );\n\n Integer deleteByIds(\n EmployeeId[] ids,\n Connection c\n );\n\n EmployeeRow insert(\n EmployeeRow unsaved,\n Connection c\n );\n\n EmployeeRow insert(\n EmployeeRowUnsaved unsaved,\n Connection c\n );\n\n SelectBuilder select();\n\n List selectAll(Connection c);\n\n Optional selectById(\n EmployeeId id,\n Connection c\n );\n\n List selectByIds(\n EmployeeId[] ids,\n Connection c\n );\n\n Map selectByIdsTracked(\n EmployeeId[] ids,\n Connection c\n );\n\n Optional selectByUniqueEmail(\n String email,\n Connection c\n );\n\n UpdateBuilder update();\n\n Boolean update(\n EmployeeRow row,\n Connection c\n );\n\n EmployeeRow upsert(\n EmployeeRow unsaved,\n Connection c\n );\n\n List upsertBatch(\n Iterator unsaved,\n Connection c\n );\n}", - "EmployeeRepoImpl": "package showcase.showcase.employee;\n\nimport dev.typr.foundations.Fragment;\nimport dev.typr.foundations.SqlServerTypes;\nimport dev.typr.foundations.dsl.DeleteBuilder;\nimport dev.typr.foundations.dsl.Dialect;\nimport dev.typr.foundations.dsl.SelectBuilder;\nimport dev.typr.foundations.dsl.UpdateBuilder;\nimport java.sql.Connection;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\nimport showcase.showcase.department.DepartmentId;\nimport static dev.typr.foundations.Fragment.interpolate;\n\npublic class EmployeeRepoImpl implements EmployeeRepo {\n @Override\n public DeleteBuilder delete() {\n return DeleteBuilder.of(\"[showcase].[employee]\", EmployeeFields.structure(), Dialect.SQLSERVER);\n };\n\n @Override\n public Boolean deleteById(\n EmployeeId id,\n Connection c\n ) {\n return interpolate(Fragment.lit(\"delete from [showcase].[employee] where [id] = \"), Fragment.encode(EmployeeId.sqlServerType, id), Fragment.lit(\"\")).update().runUnchecked(c) > 0;\n };\n\n @Override\n public Integer deleteByIds(\n EmployeeId[] ids,\n Connection c\n ) {\n ArrayList fragments = new ArrayList<>();\n for (var id : ids) { fragments.add(Fragment.encode(EmployeeId.sqlServerType, id)); };\n return Fragment.interpolate(Fragment.lit(\"delete from [showcase].[employee] where [id] in (\"), Fragment.comma(fragments), Fragment.lit(\")\")).update().runUnchecked(c);\n };\n\n @Override\n public EmployeeRow insert(\n EmployeeRow unsaved,\n Connection c\n ) {\n return interpolate(Fragment.lit(\"insert into [showcase].[employee]([id], [department_id], [manager_id], [email], [first_name], [last_name], [salary], [hired_at], [active], [created_at], [metadata], [resume], [photo], [employee_uid], [last_modified], [row_version], [org_path])\\nOUTPUT INSERTED.[id], INSERTED.[department_id], INSERTED.[manager_id], INSERTED.[email], INSERTED.[first_name], INSERTED.[last_name], INSERTED.[salary], INSERTED.[hired_at], INSERTED.[active], INSERTED.[created_at], INSERTED.[metadata], INSERTED.[resume], INSERTED.[photo], INSERTED.[employee_uid], INSERTED.[last_modified], INSERTED.[row_version], INSERTED.[org_path]\\nvalues (\"), Fragment.encode(EmployeeId.sqlServerType, unsaved.id()), Fragment.lit(\", \"), Fragment.encode(DepartmentId.sqlServerType, unsaved.departmentId()), Fragment.lit(\", \"), Fragment.encode(EmployeeId.sqlServerType.opt(), unsaved.managerId()), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.nvarchar, unsaved.email()), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.nvarchar, unsaved.firstName()), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.nvarchar, unsaved.lastName()), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.decimal.opt(), unsaved.salary()), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.date.opt(), unsaved.hiredAt()), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.bit.opt(), unsaved.active()), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.datetime2.opt(), unsaved.createdAt()), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.json.opt(), unsaved.metadata()), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.xml.opt(), unsaved.resume()), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.varbinary.opt(), unsaved.photo()), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.uniqueidentifier.opt(), unsaved.employeeUid()), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.datetimeoffset.opt(), unsaved.lastModified()), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.rowversion.opt(), unsaved.rowVersion()), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.hierarchyid.opt(), unsaved.orgPath()), Fragment.lit(\")\\n\"))\n .updateReturning(EmployeeRow._rowParser.exactlyOne()).runUnchecked(c);\n };\n\n @Override\n public EmployeeRow insert(\n EmployeeRowUnsaved unsaved,\n Connection c\n ) {\n ArrayList columns = new ArrayList<>();;\n ArrayList values = new ArrayList<>();;\n columns.add(Fragment.lit(\"[id]\"));\n values.add(interpolate(Fragment.encode(EmployeeId.sqlServerType, unsaved.id()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"[department_id]\"));\n values.add(interpolate(Fragment.encode(DepartmentId.sqlServerType, unsaved.departmentId()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"[manager_id]\"));\n values.add(interpolate(Fragment.encode(EmployeeId.sqlServerType.opt(), unsaved.managerId()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"[email]\"));\n values.add(interpolate(Fragment.encode(SqlServerTypes.nvarchar, unsaved.email()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"[first_name]\"));\n values.add(interpolate(Fragment.encode(SqlServerTypes.nvarchar, unsaved.firstName()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"[last_name]\"));\n values.add(interpolate(Fragment.encode(SqlServerTypes.nvarchar, unsaved.lastName()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"[salary]\"));\n values.add(interpolate(Fragment.encode(SqlServerTypes.decimal.opt(), unsaved.salary()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"[hired_at]\"));\n values.add(interpolate(Fragment.encode(SqlServerTypes.date.opt(), unsaved.hiredAt()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"[metadata]\"));\n values.add(interpolate(Fragment.encode(SqlServerTypes.json.opt(), unsaved.metadata()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"[resume]\"));\n values.add(interpolate(Fragment.encode(SqlServerTypes.xml.opt(), unsaved.resume()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"[photo]\"));\n values.add(interpolate(Fragment.encode(SqlServerTypes.varbinary.opt(), unsaved.photo()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"[employee_uid]\"));\n values.add(interpolate(Fragment.encode(SqlServerTypes.uniqueidentifier.opt(), unsaved.employeeUid()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"[last_modified]\"));\n values.add(interpolate(Fragment.encode(SqlServerTypes.datetimeoffset.opt(), unsaved.lastModified()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"[row_version]\"));\n values.add(interpolate(Fragment.encode(SqlServerTypes.rowversion.opt(), unsaved.rowVersion()), Fragment.lit(\"\")));\n columns.add(Fragment.lit(\"[org_path]\"));\n values.add(interpolate(Fragment.encode(SqlServerTypes.hierarchyid.opt(), unsaved.orgPath()), Fragment.lit(\"\")));\n unsaved.active().visit(\n () -> {\n \n },\n value -> {\n columns.add(Fragment.lit(\"[active]\"));\n values.add(interpolate(Fragment.encode(SqlServerTypes.bit.opt(), value), Fragment.lit(\"\")));\n }\n );;\n unsaved.createdAt().visit(\n () -> {\n \n },\n value -> {\n columns.add(Fragment.lit(\"[created_at]\"));\n values.add(interpolate(Fragment.encode(SqlServerTypes.datetime2.opt(), value), Fragment.lit(\"\")));\n }\n );;\n Fragment q = interpolate(Fragment.lit(\"insert into [showcase].[employee](\"), Fragment.comma(columns), Fragment.lit(\")\\nOUTPUT INSERTED.[id], INSERTED.[department_id], INSERTED.[manager_id], INSERTED.[email], INSERTED.[first_name], INSERTED.[last_name], INSERTED.[salary], INSERTED.[hired_at], INSERTED.[active], INSERTED.[created_at], INSERTED.[metadata], INSERTED.[resume], INSERTED.[photo], INSERTED.[employee_uid], INSERTED.[last_modified], INSERTED.[row_version], INSERTED.[org_path]\\nvalues (\"), Fragment.comma(values), Fragment.lit(\")\\n\"));;\n return q.updateReturning(EmployeeRow._rowParser.exactlyOne()).runUnchecked(c);\n };\n\n @Override\n public SelectBuilder select() {\n return SelectBuilder.of(\"[showcase].[employee]\", EmployeeFields.structure(), EmployeeRow._rowParser, Dialect.SQLSERVER);\n };\n\n @Override\n public List selectAll(Connection c) {\n return interpolate(Fragment.lit(\"select [id], [department_id], [manager_id], [email], [first_name], [last_name], [salary], [hired_at], [active], [created_at], [metadata], [resume], [photo], [employee_uid], [last_modified], [row_version], [org_path]\\nfrom [showcase].[employee]\\n\")).query(EmployeeRow._rowParser.all()).runUnchecked(c);\n };\n\n @Override\n public Optional selectById(\n EmployeeId id,\n Connection c\n ) {\n return interpolate(Fragment.lit(\"select [id], [department_id], [manager_id], [email], [first_name], [last_name], [salary], [hired_at], [active], [created_at], [metadata], [resume], [photo], [employee_uid], [last_modified], [row_version], [org_path]\\nfrom [showcase].[employee]\\nwhere [id] = \"), Fragment.encode(EmployeeId.sqlServerType, id), Fragment.lit(\"\")).query(EmployeeRow._rowParser.first()).runUnchecked(c);\n };\n\n @Override\n public List selectByIds(\n EmployeeId[] ids,\n Connection c\n ) {\n ArrayList fragments = new ArrayList<>();\n for (var id : ids) { fragments.add(Fragment.encode(EmployeeId.sqlServerType, id)); };\n return Fragment.interpolate(Fragment.lit(\"select [id], [department_id], [manager_id], [email], [first_name], [last_name], [salary], [hired_at], [active], [created_at], [metadata], [resume], [photo], [employee_uid], [last_modified], [row_version], [org_path] from [showcase].[employee] where [id] in (\"), Fragment.comma(fragments), Fragment.lit(\")\")).query(EmployeeRow._rowParser.all()).runUnchecked(c);\n };\n\n @Override\n public Map selectByIdsTracked(\n EmployeeId[] ids,\n Connection c\n ) {\n HashMap ret = new HashMap();\n selectByIds(ids, c).forEach(row -> ret.put(row.id(), row));\n return ret;\n };\n\n @Override\n public Optional selectByUniqueEmail(\n String email,\n Connection c\n ) {\n return interpolate(Fragment.lit(\"select [id], [department_id], [manager_id], [email], [first_name], [last_name], [salary], [hired_at], [active], [created_at], [metadata], [resume], [photo], [employee_uid], [last_modified], [row_version], [org_path]\\nfrom [showcase].[employee]\\nwhere [email] = \"), Fragment.encode(SqlServerTypes.nvarchar, email), Fragment.lit(\"\\n\")).query(EmployeeRow._rowParser.first()).runUnchecked(c);\n };\n\n @Override\n public UpdateBuilder update() {\n return UpdateBuilder.of(\"[showcase].[employee]\", EmployeeFields.structure(), EmployeeRow._rowParser, Dialect.SQLSERVER);\n };\n\n @Override\n public Boolean update(\n EmployeeRow row,\n Connection c\n ) {\n EmployeeId id = row.id();;\n return interpolate(Fragment.lit(\"update [showcase].[employee]\\nset [department_id] = \"), Fragment.encode(DepartmentId.sqlServerType, row.departmentId()), Fragment.lit(\",\\n[manager_id] = \"), Fragment.encode(EmployeeId.sqlServerType.opt(), row.managerId()), Fragment.lit(\",\\n[email] = \"), Fragment.encode(SqlServerTypes.nvarchar, row.email()), Fragment.lit(\",\\n[first_name] = \"), Fragment.encode(SqlServerTypes.nvarchar, row.firstName()), Fragment.lit(\",\\n[last_name] = \"), Fragment.encode(SqlServerTypes.nvarchar, row.lastName()), Fragment.lit(\",\\n[salary] = \"), Fragment.encode(SqlServerTypes.decimal.opt(), row.salary()), Fragment.lit(\",\\n[hired_at] = \"), Fragment.encode(SqlServerTypes.date.opt(), row.hiredAt()), Fragment.lit(\",\\n[active] = \"), Fragment.encode(SqlServerTypes.bit.opt(), row.active()), Fragment.lit(\",\\n[created_at] = \"), Fragment.encode(SqlServerTypes.datetime2.opt(), row.createdAt()), Fragment.lit(\",\\n[metadata] = \"), Fragment.encode(SqlServerTypes.json.opt(), row.metadata()), Fragment.lit(\",\\n[resume] = \"), Fragment.encode(SqlServerTypes.xml.opt(), row.resume()), Fragment.lit(\",\\n[photo] = \"), Fragment.encode(SqlServerTypes.varbinary.opt(), row.photo()), Fragment.lit(\",\\n[employee_uid] = \"), Fragment.encode(SqlServerTypes.uniqueidentifier.opt(), row.employeeUid()), Fragment.lit(\",\\n[last_modified] = \"), Fragment.encode(SqlServerTypes.datetimeoffset.opt(), row.lastModified()), Fragment.lit(\",\\n[row_version] = \"), Fragment.encode(SqlServerTypes.rowversion.opt(), row.rowVersion()), Fragment.lit(\",\\n[org_path] = \"), Fragment.encode(SqlServerTypes.hierarchyid.opt(), row.orgPath()), Fragment.lit(\"\\nwhere [id] = \"), Fragment.encode(EmployeeId.sqlServerType, id), Fragment.lit(\"\")).update().runUnchecked(c) > 0;\n };\n\n @Override\n public EmployeeRow upsert(\n EmployeeRow unsaved,\n Connection c\n ) {\n return interpolate(Fragment.lit(\"MERGE INTO [showcase].[employee] AS target\\nUSING (VALUES (\"), Fragment.encode(EmployeeId.sqlServerType, unsaved.id()), Fragment.lit(\", \"), Fragment.encode(DepartmentId.sqlServerType, unsaved.departmentId()), Fragment.lit(\", \"), Fragment.encode(EmployeeId.sqlServerType.opt(), unsaved.managerId()), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.nvarchar, unsaved.email()), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.nvarchar, unsaved.firstName()), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.nvarchar, unsaved.lastName()), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.decimal.opt(), unsaved.salary()), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.date.opt(), unsaved.hiredAt()), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.bit.opt(), unsaved.active()), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.datetime2.opt(), unsaved.createdAt()), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.json.opt(), unsaved.metadata()), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.xml.opt(), unsaved.resume()), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.varbinary.opt(), unsaved.photo()), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.uniqueidentifier.opt(), unsaved.employeeUid()), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.datetimeoffset.opt(), unsaved.lastModified()), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.rowversion.opt(), unsaved.rowVersion()), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.hierarchyid.opt(), unsaved.orgPath()), Fragment.lit(\")) AS source([id], [department_id], [manager_id], [email], [first_name], [last_name], [salary], [hired_at], [active], [created_at], [metadata], [resume], [photo], [employee_uid], [last_modified], [row_version], [org_path])\\nON target.[id] = source.[id]\\nWHEN MATCHED THEN UPDATE SET [department_id] = source.[department_id],\\n[manager_id] = source.[manager_id],\\n[email] = source.[email],\\n[first_name] = source.[first_name],\\n[last_name] = source.[last_name],\\n[salary] = source.[salary],\\n[hired_at] = source.[hired_at],\\n[active] = source.[active],\\n[created_at] = source.[created_at],\\n[metadata] = source.[metadata],\\n[resume] = source.[resume],\\n[photo] = source.[photo],\\n[employee_uid] = source.[employee_uid],\\n[last_modified] = source.[last_modified],\\n[row_version] = source.[row_version],\\n[org_path] = source.[org_path]\\nWHEN NOT MATCHED THEN INSERT ([id], [department_id], [manager_id], [email], [first_name], [last_name], [salary], [hired_at], [active], [created_at], [metadata], [resume], [photo], [employee_uid], [last_modified], [row_version], [org_path]) VALUES (\"), Fragment.encode(EmployeeId.sqlServerType, unsaved.id()), Fragment.lit(\", \"), Fragment.encode(DepartmentId.sqlServerType, unsaved.departmentId()), Fragment.lit(\", \"), Fragment.encode(EmployeeId.sqlServerType.opt(), unsaved.managerId()), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.nvarchar, unsaved.email()), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.nvarchar, unsaved.firstName()), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.nvarchar, unsaved.lastName()), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.decimal.opt(), unsaved.salary()), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.date.opt(), unsaved.hiredAt()), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.bit.opt(), unsaved.active()), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.datetime2.opt(), unsaved.createdAt()), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.json.opt(), unsaved.metadata()), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.xml.opt(), unsaved.resume()), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.varbinary.opt(), unsaved.photo()), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.uniqueidentifier.opt(), unsaved.employeeUid()), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.datetimeoffset.opt(), unsaved.lastModified()), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.rowversion.opt(), unsaved.rowVersion()), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.hierarchyid.opt(), unsaved.orgPath()), Fragment.lit(\")\\nOUTPUT INSERTED.[id], INSERTED.[department_id], INSERTED.[manager_id], INSERTED.[email], INSERTED.[first_name], INSERTED.[last_name], INSERTED.[salary], INSERTED.[hired_at], INSERTED.[active], INSERTED.[created_at], INSERTED.[metadata], INSERTED.[resume], INSERTED.[photo], INSERTED.[employee_uid], INSERTED.[last_modified], INSERTED.[row_version], INSERTED.[org_path];\"))\n .updateReturning(EmployeeRow._rowParser.exactlyOne())\n .runUnchecked(c);\n };\n\n @Override\n public List upsertBatch(\n Iterator unsaved,\n Connection c\n ) {\n return interpolate(Fragment.lit(\"MERGE INTO [showcase].[employee] AS target\\nUSING (VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)) AS source([id], [department_id], [manager_id], [email], [first_name], [last_name], [salary], [hired_at], [active], [created_at], [metadata], [resume], [photo], [employee_uid], [last_modified], [row_version], [org_path])\\nON target.[id] = source.[id]\\nWHEN MATCHED THEN UPDATE SET [department_id] = source.[department_id],\\n[manager_id] = source.[manager_id],\\n[email] = source.[email],\\n[first_name] = source.[first_name],\\n[last_name] = source.[last_name],\\n[salary] = source.[salary],\\n[hired_at] = source.[hired_at],\\n[active] = source.[active],\\n[created_at] = source.[created_at],\\n[metadata] = source.[metadata],\\n[resume] = source.[resume],\\n[photo] = source.[photo],\\n[employee_uid] = source.[employee_uid],\\n[last_modified] = source.[last_modified],\\n[row_version] = source.[row_version],\\n[org_path] = source.[org_path]\\nWHEN NOT MATCHED THEN INSERT ([id], [department_id], [manager_id], [email], [first_name], [last_name], [salary], [hired_at], [active], [created_at], [metadata], [resume], [photo], [employee_uid], [last_modified], [row_version], [org_path]) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\\nOUTPUT INSERTED.[id], INSERTED.[department_id], INSERTED.[manager_id], INSERTED.[email], INSERTED.[first_name], INSERTED.[last_name], INSERTED.[salary], INSERTED.[hired_at], INSERTED.[active], INSERTED.[created_at], INSERTED.[metadata], INSERTED.[resume], INSERTED.[photo], INSERTED.[employee_uid], INSERTED.[last_modified], INSERTED.[row_version], INSERTED.[org_path];\"))\n .updateReturningEach(EmployeeRow._rowParser, unsaved)\n .runUnchecked(c);\n };\n}", - "EmployeeRepoMock": "package showcase.showcase.employee;\n\nimport dev.typr.foundations.dsl.DeleteBuilder;\nimport dev.typr.foundations.dsl.DeleteBuilderMock;\nimport dev.typr.foundations.dsl.DeleteParams;\nimport dev.typr.foundations.dsl.SelectBuilder;\nimport dev.typr.foundations.dsl.SelectBuilderMock;\nimport dev.typr.foundations.dsl.SelectParams;\nimport dev.typr.foundations.dsl.UpdateBuilder;\nimport dev.typr.foundations.dsl.UpdateBuilderMock;\nimport dev.typr.foundations.dsl.UpdateParams;\nimport java.lang.RuntimeException;\nimport java.sql.Connection;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\nimport java.util.function.Function;\nimport java.util.stream.Collectors;\n\npublic record EmployeeRepoMock(\n java.util.function.Function toRow,\n HashMap map\n) implements EmployeeRepo {\n public EmployeeRepoMock(java.util.function.Function toRow) {\n this(toRow, new HashMap());\n };\n\n public EmployeeRepoMock withToRow(java.util.function.Function toRow) {\n return new EmployeeRepoMock(toRow, map);\n };\n\n public EmployeeRepoMock withMap(HashMap map) {\n return new EmployeeRepoMock(toRow, map);\n };\n\n @Override\n public DeleteBuilder delete() {\n return new DeleteBuilderMock<>(EmployeeFields.structure(), () -> new ArrayList<>(map.values()), DeleteParams.empty(), row -> row.id(), id -> map.remove(id));\n };\n\n @Override\n public Boolean deleteById(\n EmployeeId id,\n Connection c\n ) {\n return Optional.ofNullable(map.remove(id)).isPresent();\n };\n\n @Override\n public Integer deleteByIds(\n EmployeeId[] ids,\n Connection c\n ) {\n var count = 0;\n for (var id : ids) {\n if (Optional.ofNullable(map.remove(id)).isPresent()) {\n count = count + 1;;\n };\n };\n return count;\n };\n\n @Override\n public EmployeeRow insert(\n EmployeeRow unsaved,\n Connection c\n ) {\n if (map.containsKey(unsaved.id())) {\n throw new RuntimeException(\"id \" + unsaved.id() + \" already exists\");\n };\n map.put(unsaved.id(), unsaved);\n return unsaved;\n };\n\n @Override\n public EmployeeRow insert(\n EmployeeRowUnsaved unsaved,\n Connection c\n ) {\n return insert(toRow.apply(unsaved), c);\n };\n\n @Override\n public SelectBuilder select() {\n return new SelectBuilderMock<>(EmployeeFields.structure(), () -> new ArrayList<>(map.values()), SelectParams.empty());\n };\n\n @Override\n public List selectAll(Connection c) {\n return new ArrayList<>(map.values());\n };\n\n @Override\n public Optional selectById(\n EmployeeId id,\n Connection c\n ) {\n return Optional.ofNullable(map.get(id));\n };\n\n @Override\n public List selectByIds(\n EmployeeId[] ids,\n Connection c\n ) {\n var result = new ArrayList();\n for (var id : ids) {\n var opt = Optional.ofNullable(map.get(id));\n if (opt.isPresent()) {\n result.add(opt.get());\n };\n };\n return result;\n };\n\n @Override\n public Map selectByIdsTracked(\n EmployeeId[] ids,\n Connection c\n ) {\n return selectByIds(ids, c).stream().collect(Collectors.toMap((EmployeeRow row) -> row.id(), Function.identity()));\n };\n\n @Override\n public Optional selectByUniqueEmail(\n String email,\n Connection c\n ) {\n return new ArrayList<>(map.values()).stream().filter(v -> email.equals(v.email())).findFirst();\n };\n\n @Override\n public UpdateBuilder update() {\n return new UpdateBuilderMock<>(EmployeeFields.structure(), () -> new ArrayList<>(map.values()), UpdateParams.empty(), row -> row);\n };\n\n @Override\n public Boolean update(\n EmployeeRow row,\n Connection c\n ) {\n var shouldUpdate = Optional.ofNullable(map.get(row.id())).filter(oldRow -> !oldRow.equals(row)).isPresent();\n if (shouldUpdate) {\n map.put(row.id(), row);;\n };\n return shouldUpdate;\n };\n\n @Override\n public EmployeeRow upsert(\n EmployeeRow unsaved,\n Connection c\n ) {\n map.put(unsaved.id(), unsaved);\n return unsaved;\n };\n\n @Override\n public List upsertBatch(\n Iterator unsaved,\n Connection c\n ) {\n var result = new ArrayList();\n while (unsaved.hasNext()) {\n var row = unsaved.next();\n map.put(row.id(), row);\n result.add(row);\n };\n return result;\n };\n}", - "EmployeeFields": "package showcase.showcase.employee;\n\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.SqlServerTypes;\nimport dev.typr.foundations.data.Json;\nimport dev.typr.foundations.dsl.FieldsExpr;\nimport dev.typr.foundations.dsl.ForeignKey;\nimport dev.typr.foundations.dsl.Path;\nimport dev.typr.foundations.dsl.RelationStructure;\nimport dev.typr.foundations.dsl.SqlExpr.Field;\nimport dev.typr.foundations.dsl.SqlExpr.FieldLike;\nimport dev.typr.foundations.dsl.SqlExpr.IdField;\nimport dev.typr.foundations.dsl.SqlExpr.OptField;\nimport java.math.BigDecimal;\nimport java.time.LocalDate;\nimport java.time.LocalDateTime;\nimport java.time.OffsetDateTime;\nimport java.util.List;\nimport java.util.Optional;\nimport java.util.UUID;\nimport showcase.showcase.department.DepartmentFields;\nimport showcase.showcase.department.DepartmentId;\nimport showcase.showcase.department.DepartmentRow;\n\npublic interface EmployeeFields extends FieldsExpr {\n record Impl(List _path) implements EmployeeFields, RelationStructure {\n @Override\n public IdField id() {\n return new IdField(_path, \"id\", EmployeeRow::id, Optional.empty(), Optional.empty(), (row, value) -> row.withId(value), EmployeeId.sqlServerType);\n };\n\n @Override\n public Field departmentId() {\n return new Field(_path, \"department_id\", EmployeeRow::departmentId, Optional.empty(), Optional.empty(), (row, value) -> row.withDepartmentId(value), DepartmentId.sqlServerType);\n };\n\n @Override\n public OptField managerId() {\n return new OptField(_path, \"manager_id\", EmployeeRow::managerId, Optional.empty(), Optional.empty(), (row, value) -> row.withManagerId(value), EmployeeId.sqlServerType);\n };\n\n @Override\n public Field email() {\n return new Field(_path, \"email\", EmployeeRow::email, Optional.empty(), Optional.empty(), (row, value) -> row.withEmail(value), SqlServerTypes.nvarchar);\n };\n\n @Override\n public Field firstName() {\n return new Field(_path, \"first_name\", EmployeeRow::firstName, Optional.empty(), Optional.empty(), (row, value) -> row.withFirstName(value), SqlServerTypes.nvarchar);\n };\n\n @Override\n public Field lastName() {\n return new Field(_path, \"last_name\", EmployeeRow::lastName, Optional.empty(), Optional.empty(), (row, value) -> row.withLastName(value), SqlServerTypes.nvarchar);\n };\n\n @Override\n public OptField salary() {\n return new OptField(_path, \"salary\", EmployeeRow::salary, Optional.empty(), Optional.empty(), (row, value) -> row.withSalary(value), SqlServerTypes.decimal);\n };\n\n @Override\n public OptField hiredAt() {\n return new OptField(_path, \"hired_at\", EmployeeRow::hiredAt, Optional.empty(), Optional.empty(), (row, value) -> row.withHiredAt(value), SqlServerTypes.date);\n };\n\n @Override\n public OptField active() {\n return new OptField(_path, \"active\", EmployeeRow::active, Optional.empty(), Optional.empty(), (row, value) -> row.withActive(value), SqlServerTypes.bit);\n };\n\n @Override\n public OptField createdAt() {\n return new OptField(_path, \"created_at\", EmployeeRow::createdAt, Optional.empty(), Optional.empty(), (row, value) -> row.withCreatedAt(value), SqlServerTypes.datetime2);\n };\n\n @Override\n public OptField metadata() {\n return new OptField(_path, \"metadata\", EmployeeRow::metadata, Optional.empty(), Optional.empty(), (row, value) -> row.withMetadata(value), SqlServerTypes.json);\n };\n\n @Override\n public OptField resume() {\n return new OptField(_path, \"resume\", EmployeeRow::resume, Optional.empty(), Optional.empty(), (row, value) -> row.withResume(value), SqlServerTypes.xml);\n };\n\n @Override\n public OptField photo() {\n return new OptField(_path, \"photo\", EmployeeRow::photo, Optional.empty(), Optional.empty(), (row, value) -> row.withPhoto(value), SqlServerTypes.varbinary);\n };\n\n @Override\n public OptField employeeUid() {\n return new OptField(_path, \"employee_uid\", EmployeeRow::employeeUid, Optional.empty(), Optional.empty(), (row, value) -> row.withEmployeeUid(value), SqlServerTypes.uniqueidentifier);\n };\n\n @Override\n public OptField lastModified() {\n return new OptField(_path, \"last_modified\", EmployeeRow::lastModified, Optional.empty(), Optional.empty(), (row, value) -> row.withLastModified(value), SqlServerTypes.datetimeoffset);\n };\n\n @Override\n public OptField rowVersion() {\n return new OptField(_path, \"row_version\", EmployeeRow::rowVersion, Optional.empty(), Optional.empty(), (row, value) -> row.withRowVersion(value), SqlServerTypes.rowversion);\n };\n\n @Override\n public OptField orgPath() {\n return new OptField(_path, \"org_path\", EmployeeRow::orgPath, Optional.empty(), Optional.empty(), (row, value) -> row.withOrgPath(value), SqlServerTypes.hierarchyid);\n };\n\n @Override\n public List> columns() {\n return java.util.List.of(this.id(), this.departmentId(), this.managerId(), this.email(), this.firstName(), this.lastName(), this.salary(), this.hiredAt(), this.active(), this.createdAt(), this.metadata(), this.resume(), this.photo(), this.employeeUid(), this.lastModified(), this.rowVersion(), this.orgPath());\n };\n\n @Override\n public RelationStructure withPaths(List _path) {\n return new Impl(_path);\n };\n };\n\n static Impl structure() {\n return new Impl(java.util.Collections.emptyList());\n };\n\n IdField id();\n\n Field departmentId();\n\n OptField managerId();\n\n Field email();\n\n Field firstName();\n\n Field lastName();\n\n OptField salary();\n\n OptField hiredAt();\n\n OptField active();\n\n OptField createdAt();\n\n OptField metadata();\n\n OptField resume();\n\n OptField photo();\n\n OptField employeeUid();\n\n OptField lastModified();\n\n OptField rowVersion();\n\n OptField orgPath();\n\n default ForeignKey fkDepartment() {\n return ForeignKey.of(\"employee_department_fk\").withColumnPair(departmentId(), DepartmentFields::id);\n };\n\n default ForeignKey fkEmployee() {\n return ForeignKey.of(\"employee_manager_fk\").withColumnPair(managerId(), EmployeeFields::id);\n };\n\n @Override\n List> columns();\n\n @Override\n default RowParser rowParser() {\n return EmployeeRow._rowParser;\n };\n}", - "DepartmentRow": "package showcase.showcase.department;\n\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport dev.typr.foundations.SqlServerTypes;\nimport java.math.BigDecimal;\nimport java.util.Optional;\nimport showcase.showcase.company.CompanyId;\n\n/** Table: showcase.department\n * Primary key: id\n */\npublic record DepartmentRow(\n DepartmentId id,\n /** Points to {@link showcase.showcase.company.CompanyRow#id()} */\n CompanyId companyId,\n String name,\n Optional budget\n) {\n public DepartmentRow withId(DepartmentId id) {\n return new DepartmentRow(id, companyId, name, budget);\n };\n\n /** Points to {@link showcase.showcase.company.CompanyRow#id()} */\n public DepartmentRow withCompanyId(CompanyId companyId) {\n return new DepartmentRow(id, companyId, name, budget);\n };\n\n public DepartmentRow withName(String name) {\n return new DepartmentRow(id, companyId, name, budget);\n };\n\n public DepartmentRow withBudget(Optional budget) {\n return new DepartmentRow(id, companyId, name, budget);\n };\n\n public static RowParser _rowParser = RowParsers.of(DepartmentId.sqlServerType, CompanyId.sqlServerType, SqlServerTypes.nvarchar, SqlServerTypes.decimal.opt(), DepartmentRow::new, row -> new Object[]{row.id(), row.companyId(), row.name(), row.budget()});;\n}", - "DepartmentId": "package showcase.showcase.department;\n\nimport dev.typr.foundations.SqlServerType;\nimport dev.typr.foundations.SqlServerTypes;\nimport dev.typr.foundations.dsl.Bijection;\n\n/** Type for the primary key of table `showcase.department` */\npublic record DepartmentId(String value) {\n public DepartmentId withValue(String value) {\n return new DepartmentId(value);\n };\n\n @Override\n public java.lang.String toString() {\n return value.toString();\n };\n\n static public Bijection bijection =\n Bijection.of(DepartmentId::value, DepartmentId::new);\n\n static public SqlServerType sqlServerType =\n SqlServerTypes.nvarchar.bimap(DepartmentId::new, DepartmentId::value);\n}", - "DepartmentRepo": "package showcase.showcase.department;\n\nimport dev.typr.foundations.dsl.DeleteBuilder;\nimport dev.typr.foundations.dsl.SelectBuilder;\nimport dev.typr.foundations.dsl.UpdateBuilder;\nimport java.sql.Connection;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\n\npublic interface DepartmentRepo {\n DeleteBuilder delete();\n\n Boolean deleteById(\n DepartmentId id,\n Connection c\n );\n\n Integer deleteByIds(\n DepartmentId[] ids,\n Connection c\n );\n\n DepartmentRow insert(\n DepartmentRow unsaved,\n Connection c\n );\n\n SelectBuilder select();\n\n List selectAll(Connection c);\n\n Optional selectById(\n DepartmentId id,\n Connection c\n );\n\n List selectByIds(\n DepartmentId[] ids,\n Connection c\n );\n\n Map selectByIdsTracked(\n DepartmentId[] ids,\n Connection c\n );\n\n UpdateBuilder update();\n\n Boolean update(\n DepartmentRow row,\n Connection c\n );\n\n DepartmentRow upsert(\n DepartmentRow unsaved,\n Connection c\n );\n\n List upsertBatch(\n Iterator unsaved,\n Connection c\n );\n}", - "DepartmentRepoMock": "package showcase.showcase.department;\n\nimport dev.typr.foundations.dsl.DeleteBuilder;\nimport dev.typr.foundations.dsl.DeleteBuilderMock;\nimport dev.typr.foundations.dsl.DeleteParams;\nimport dev.typr.foundations.dsl.SelectBuilder;\nimport dev.typr.foundations.dsl.SelectBuilderMock;\nimport dev.typr.foundations.dsl.SelectParams;\nimport dev.typr.foundations.dsl.UpdateBuilder;\nimport dev.typr.foundations.dsl.UpdateBuilderMock;\nimport dev.typr.foundations.dsl.UpdateParams;\nimport java.lang.RuntimeException;\nimport java.sql.Connection;\nimport java.util.ArrayList;\nimport java.util.HashMap;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\nimport java.util.function.Function;\nimport java.util.stream.Collectors;\n\npublic record DepartmentRepoMock(HashMap map) implements DepartmentRepo {\n public DepartmentRepoMock() {\n this(new HashMap());\n };\n\n public DepartmentRepoMock withMap(HashMap map) {\n return new DepartmentRepoMock(map);\n };\n\n @Override\n public DeleteBuilder delete() {\n return new DeleteBuilderMock<>(DepartmentFields.structure(), () -> new ArrayList<>(map.values()), DeleteParams.empty(), row -> row.id(), id -> map.remove(id));\n };\n\n @Override\n public Boolean deleteById(\n DepartmentId id,\n Connection c\n ) {\n return Optional.ofNullable(map.remove(id)).isPresent();\n };\n\n @Override\n public Integer deleteByIds(\n DepartmentId[] ids,\n Connection c\n ) {\n var count = 0;\n for (var id : ids) {\n if (Optional.ofNullable(map.remove(id)).isPresent()) {\n count = count + 1;;\n };\n };\n return count;\n };\n\n @Override\n public DepartmentRow insert(\n DepartmentRow unsaved,\n Connection c\n ) {\n if (map.containsKey(unsaved.id())) {\n throw new RuntimeException(\"id \" + unsaved.id() + \" already exists\");\n };\n map.put(unsaved.id(), unsaved);\n return unsaved;\n };\n\n @Override\n public SelectBuilder select() {\n return new SelectBuilderMock<>(DepartmentFields.structure(), () -> new ArrayList<>(map.values()), SelectParams.empty());\n };\n\n @Override\n public List selectAll(Connection c) {\n return new ArrayList<>(map.values());\n };\n\n @Override\n public Optional selectById(\n DepartmentId id,\n Connection c\n ) {\n return Optional.ofNullable(map.get(id));\n };\n\n @Override\n public List selectByIds(\n DepartmentId[] ids,\n Connection c\n ) {\n var result = new ArrayList();\n for (var id : ids) {\n var opt = Optional.ofNullable(map.get(id));\n if (opt.isPresent()) {\n result.add(opt.get());\n };\n };\n return result;\n };\n\n @Override\n public Map selectByIdsTracked(\n DepartmentId[] ids,\n Connection c\n ) {\n return selectByIds(ids, c).stream().collect(Collectors.toMap((DepartmentRow row) -> row.id(), Function.identity()));\n };\n\n @Override\n public UpdateBuilder update() {\n return new UpdateBuilderMock<>(DepartmentFields.structure(), () -> new ArrayList<>(map.values()), UpdateParams.empty(), row -> row);\n };\n\n @Override\n public Boolean update(\n DepartmentRow row,\n Connection c\n ) {\n var shouldUpdate = Optional.ofNullable(map.get(row.id())).filter(oldRow -> !oldRow.equals(row)).isPresent();\n if (shouldUpdate) {\n map.put(row.id(), row);;\n };\n return shouldUpdate;\n };\n\n @Override\n public DepartmentRow upsert(\n DepartmentRow unsaved,\n Connection c\n ) {\n map.put(unsaved.id(), unsaved);\n return unsaved;\n };\n\n @Override\n public List upsertBatch(\n Iterator unsaved,\n Connection c\n ) {\n var result = new ArrayList();\n while (unsaved.hasNext()) {\n var row = unsaved.next();\n map.put(row.id(), row);\n result.add(row);\n };\n return result;\n };\n}", - "ProjectAssignmentRow": "package showcase.showcase.project_assignment;\n\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport dev.typr.foundations.SqlServerTypes;\nimport java.time.LocalDate;\nimport java.util.Optional;\nimport showcase.customtypes.Defaulted;\nimport showcase.showcase.employee.EmployeeId;\nimport showcase.showcase.project.ProjectId;\n\n/** Table: showcase.project_assignment\n * Composite primary key: employee_id, project_id\n */\npublic record ProjectAssignmentRow(\n /** Points to {@link showcase.showcase.employee.EmployeeRow#id()} */\n EmployeeId employeeId,\n /** Points to {@link showcase.showcase.project.ProjectRow#id()} */\n ProjectId projectId,\n String role,\n /** Default: 0 */\n Optional hoursAllocated,\n Optional startDate,\n Optional endDate\n) {\n /** Points to {@link showcase.showcase.employee.EmployeeRow#id()} */\n public ProjectAssignmentRow withEmployeeId(EmployeeId employeeId) {\n return new ProjectAssignmentRow(employeeId, projectId, role, hoursAllocated, startDate, endDate);\n };\n\n /** Points to {@link showcase.showcase.project.ProjectRow#id()} */\n public ProjectAssignmentRow withProjectId(ProjectId projectId) {\n return new ProjectAssignmentRow(employeeId, projectId, role, hoursAllocated, startDate, endDate);\n };\n\n public ProjectAssignmentRow withRole(String role) {\n return new ProjectAssignmentRow(employeeId, projectId, role, hoursAllocated, startDate, endDate);\n };\n\n /** Default: 0 */\n public ProjectAssignmentRow withHoursAllocated(Optional hoursAllocated) {\n return new ProjectAssignmentRow(employeeId, projectId, role, hoursAllocated, startDate, endDate);\n };\n\n public ProjectAssignmentRow withStartDate(Optional startDate) {\n return new ProjectAssignmentRow(employeeId, projectId, role, hoursAllocated, startDate, endDate);\n };\n\n public ProjectAssignmentRow withEndDate(Optional endDate) {\n return new ProjectAssignmentRow(employeeId, projectId, role, hoursAllocated, startDate, endDate);\n };\n\n public static RowParser _rowParser = RowParsers.of(EmployeeId.sqlServerType, ProjectId.sqlServerType, SqlServerTypes.nvarchar, SqlServerTypes.int_.opt(), SqlServerTypes.date.opt(), SqlServerTypes.date.opt(), ProjectAssignmentRow::new, row -> new Object[]{row.employeeId(), row.projectId(), row.role(), row.hoursAllocated(), row.startDate(), row.endDate()});;\n\n static public ProjectAssignmentRow apply(\n ProjectAssignmentId compositeId,\n String role,\n Optional hoursAllocated,\n Optional startDate,\n Optional endDate\n ) {\n return new ProjectAssignmentRow(compositeId.employeeId(), compositeId.projectId(), role, hoursAllocated, startDate, endDate);\n };\n\n public ProjectAssignmentId compositeId() {\n return new ProjectAssignmentId(employeeId, projectId);\n };\n\n public ProjectAssignmentId id() {\n return this.compositeId();\n };\n\n public ProjectAssignmentRowUnsaved toUnsavedRow(Defaulted> hoursAllocated) {\n return new ProjectAssignmentRowUnsaved(employeeId, projectId, role, startDate, endDate, hoursAllocated);\n };\n}", - "ProjectAssignmentRowUnsaved": "package showcase.showcase.project_assignment;\n\nimport java.time.LocalDate;\nimport java.util.Optional;\nimport showcase.customtypes.Defaulted;\nimport showcase.customtypes.Defaulted.UseDefault;\nimport showcase.showcase.employee.EmployeeId;\nimport showcase.showcase.project.ProjectId;\n\n/** This class corresponds to a row in table `showcase.project_assignment` which has not been persisted yet */\npublic record ProjectAssignmentRowUnsaved(\n /** Points to {@link showcase.showcase.employee.EmployeeRow#id()} */\n EmployeeId employeeId,\n /** Points to {@link showcase.showcase.project.ProjectRow#id()} */\n ProjectId projectId,\n String role,\n Optional startDate,\n Optional endDate,\n /** Default: 0 */\n Defaulted> hoursAllocated\n) {\n public ProjectAssignmentRowUnsaved(\n /** Points to {@link showcase.showcase.employee.EmployeeRow#id()} */\n EmployeeId employeeId,\n /** Points to {@link showcase.showcase.project.ProjectRow#id()} */\n ProjectId projectId,\n String role\n ) {\n this(employeeId, projectId, role, Optional.empty(), Optional.empty(), new UseDefault<>());\n };\n\n /** Points to {@link showcase.showcase.employee.EmployeeRow#id()} */\n public ProjectAssignmentRowUnsaved withEmployeeId(EmployeeId employeeId) {\n return new ProjectAssignmentRowUnsaved(employeeId, projectId, role, startDate, endDate, hoursAllocated);\n };\n\n /** Points to {@link showcase.showcase.project.ProjectRow#id()} */\n public ProjectAssignmentRowUnsaved withProjectId(ProjectId projectId) {\n return new ProjectAssignmentRowUnsaved(employeeId, projectId, role, startDate, endDate, hoursAllocated);\n };\n\n public ProjectAssignmentRowUnsaved withRole(String role) {\n return new ProjectAssignmentRowUnsaved(employeeId, projectId, role, startDate, endDate, hoursAllocated);\n };\n\n public ProjectAssignmentRowUnsaved withStartDate(Optional startDate) {\n return new ProjectAssignmentRowUnsaved(employeeId, projectId, role, startDate, endDate, hoursAllocated);\n };\n\n public ProjectAssignmentRowUnsaved withEndDate(Optional endDate) {\n return new ProjectAssignmentRowUnsaved(employeeId, projectId, role, startDate, endDate, hoursAllocated);\n };\n\n /** Default: 0 */\n public ProjectAssignmentRowUnsaved withHoursAllocated(Defaulted> hoursAllocated) {\n return new ProjectAssignmentRowUnsaved(employeeId, projectId, role, startDate, endDate, hoursAllocated);\n };\n\n public ProjectAssignmentRow toRow(java.util.function.Supplier> hoursAllocatedDefault) {\n return new ProjectAssignmentRow(employeeId, projectId, role, hoursAllocated.getOrElse(hoursAllocatedDefault), startDate, endDate);\n };\n}", - "ProjectAssignmentId": "package showcase.showcase.project_assignment;\n\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport showcase.showcase.employee.EmployeeId;\nimport showcase.showcase.project.ProjectId;\n\n/** Type for the composite primary key of table `showcase.project_assignment` */\npublic record ProjectAssignmentId(\n EmployeeId employeeId,\n ProjectId projectId\n) {\n public ProjectAssignmentId withEmployeeId(EmployeeId employeeId) {\n return new ProjectAssignmentId(employeeId, projectId);\n };\n\n public ProjectAssignmentId withProjectId(ProjectId projectId) {\n return new ProjectAssignmentId(employeeId, projectId);\n };\n\n public static RowParser _rowParser = RowParsers.of(EmployeeId.sqlServerType, ProjectId.sqlServerType, ProjectAssignmentId::new, row -> new Object[]{row.employeeId(), row.projectId()});;\n}", - "ProjectAssignmentRepo": "package showcase.showcase.project_assignment;\n\nimport dev.typr.foundations.dsl.DeleteBuilder;\nimport dev.typr.foundations.dsl.SelectBuilder;\nimport dev.typr.foundations.dsl.UpdateBuilder;\nimport java.sql.Connection;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\n\npublic interface ProjectAssignmentRepo {\n DeleteBuilder delete();\n\n Boolean deleteById(\n ProjectAssignmentId compositeId,\n Connection c\n );\n\n Integer deleteByIds(\n ProjectAssignmentId[] compositeIds,\n Connection c\n );\n\n ProjectAssignmentRow insert(\n ProjectAssignmentRow unsaved,\n Connection c\n );\n\n ProjectAssignmentRow insert(\n ProjectAssignmentRowUnsaved unsaved,\n Connection c\n );\n\n SelectBuilder select();\n\n List selectAll(Connection c);\n\n Optional selectById(\n ProjectAssignmentId compositeId,\n Connection c\n );\n\n List selectByIds(\n ProjectAssignmentId[] compositeIds,\n Connection c\n );\n\n Map selectByIdsTracked(\n ProjectAssignmentId[] compositeIds,\n Connection c\n );\n\n UpdateBuilder update();\n\n Boolean update(\n ProjectAssignmentRow row,\n Connection c\n );\n\n ProjectAssignmentRow upsert(\n ProjectAssignmentRow unsaved,\n Connection c\n );\n\n List upsertBatch(\n Iterator unsaved,\n Connection c\n );\n}", - "ProjectRow": "package showcase.showcase.project;\n\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport dev.typr.foundations.SqlServerTypes;\nimport dev.typr.foundations.data.Json;\nimport java.math.BigDecimal;\nimport java.time.LocalDate;\nimport java.time.LocalDateTime;\nimport java.util.Optional;\nimport java.util.UUID;\nimport showcase.customtypes.Defaulted;\n\n/** Table: showcase.project\n * Primary key: id\n */\npublic record ProjectRow(\n ProjectId id,\n String name,\n Optional description,\n Optional startDate,\n Optional endDate,\n Optional budget,\n /** Default: 'planning' */\n Optional status,\n /** Default: CURRENT_TIMESTAMP */\n Optional createdAt,\n Optional projectUid,\n Optional metadata,\n Optional xmlPlan,\n Optional attachments,\n Optional rowVersion,\n Optional totalBudget,\n Optional orgPath\n) {\n public ProjectRow withId(ProjectId id) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, projectUid, metadata, xmlPlan, attachments, rowVersion, totalBudget, orgPath);\n };\n\n public ProjectRow withName(String name) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, projectUid, metadata, xmlPlan, attachments, rowVersion, totalBudget, orgPath);\n };\n\n public ProjectRow withDescription(Optional description) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, projectUid, metadata, xmlPlan, attachments, rowVersion, totalBudget, orgPath);\n };\n\n public ProjectRow withStartDate(Optional startDate) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, projectUid, metadata, xmlPlan, attachments, rowVersion, totalBudget, orgPath);\n };\n\n public ProjectRow withEndDate(Optional endDate) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, projectUid, metadata, xmlPlan, attachments, rowVersion, totalBudget, orgPath);\n };\n\n public ProjectRow withBudget(Optional budget) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, projectUid, metadata, xmlPlan, attachments, rowVersion, totalBudget, orgPath);\n };\n\n /** Default: 'planning' */\n public ProjectRow withStatus(Optional status) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, projectUid, metadata, xmlPlan, attachments, rowVersion, totalBudget, orgPath);\n };\n\n /** Default: CURRENT_TIMESTAMP */\n public ProjectRow withCreatedAt(Optional createdAt) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, projectUid, metadata, xmlPlan, attachments, rowVersion, totalBudget, orgPath);\n };\n\n public ProjectRow withProjectUid(Optional projectUid) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, projectUid, metadata, xmlPlan, attachments, rowVersion, totalBudget, orgPath);\n };\n\n public ProjectRow withMetadata(Optional metadata) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, projectUid, metadata, xmlPlan, attachments, rowVersion, totalBudget, orgPath);\n };\n\n public ProjectRow withXmlPlan(Optional xmlPlan) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, projectUid, metadata, xmlPlan, attachments, rowVersion, totalBudget, orgPath);\n };\n\n public ProjectRow withAttachments(Optional attachments) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, projectUid, metadata, xmlPlan, attachments, rowVersion, totalBudget, orgPath);\n };\n\n public ProjectRow withRowVersion(Optional rowVersion) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, projectUid, metadata, xmlPlan, attachments, rowVersion, totalBudget, orgPath);\n };\n\n public ProjectRow withTotalBudget(Optional totalBudget) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, projectUid, metadata, xmlPlan, attachments, rowVersion, totalBudget, orgPath);\n };\n\n public ProjectRow withOrgPath(Optional orgPath) {\n return new ProjectRow(id, name, description, startDate, endDate, budget, status, createdAt, projectUid, metadata, xmlPlan, attachments, rowVersion, totalBudget, orgPath);\n };\n\n public static RowParser _rowParser = RowParsers.of(ProjectId.sqlServerType, SqlServerTypes.nvarchar, SqlServerTypes.nvarchar.opt(), SqlServerTypes.date.opt(), SqlServerTypes.date.opt(), SqlServerTypes.decimal.opt(), SqlServerTypes.nvarchar.opt(), SqlServerTypes.datetime2.opt(), SqlServerTypes.uniqueidentifier.opt(), SqlServerTypes.json.opt(), SqlServerTypes.xml.opt(), SqlServerTypes.varbinary.opt(), SqlServerTypes.rowversion.opt(), SqlServerTypes.money.opt(), SqlServerTypes.hierarchyid.opt(), ProjectRow::new, row -> new Object[]{row.id(), row.name(), row.description(), row.startDate(), row.endDate(), row.budget(), row.status(), row.createdAt(), row.projectUid(), row.metadata(), row.xmlPlan(), row.attachments(), row.rowVersion(), row.totalBudget(), row.orgPath()});;\n\n public ProjectRowUnsaved toUnsavedRow(\n Defaulted> status,\n Defaulted> createdAt\n ) {\n return new ProjectRowUnsaved(id, name, description, startDate, endDate, budget, projectUid, metadata, xmlPlan, attachments, rowVersion, totalBudget, orgPath, status, createdAt);\n };\n}", - "ProjectId": "package showcase.showcase.project;\n\nimport dev.typr.foundations.SqlServerType;\nimport dev.typr.foundations.SqlServerTypes;\nimport dev.typr.foundations.dsl.Bijection;\n\n/** Type for the primary key of table `showcase.project` */\npublic record ProjectId(String value) {\n public ProjectId withValue(String value) {\n return new ProjectId(value);\n };\n\n @Override\n public java.lang.String toString() {\n return value.toString();\n };\n\n static public Bijection bijection =\n Bijection.of(ProjectId::value, ProjectId::new);\n\n static public SqlServerType sqlServerType =\n SqlServerTypes.nvarchar.bimap(ProjectId::new, ProjectId::value);\n}", - "EmployeeSummaryViewRow": "package showcase.showcase.employee_summary;\n\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport dev.typr.foundations.SqlServerTypes;\nimport java.math.BigDecimal;\nimport java.time.LocalDate;\nimport java.util.Optional;\nimport showcase.showcase.company.CompanyId;\nimport showcase.showcase.department.DepartmentId;\nimport showcase.showcase.employee.EmployeeId;\n\n/** View: showcase.employee_summary\n * Summary view of employees with their department and company information\n */\npublic record EmployeeSummaryViewRow(\n /** Points to {@link showcase.showcase.employee.EmployeeRow#id()} */\n EmployeeId employeeId,\n String email,\n String firstName,\n String lastName,\n Optional salary,\n Optional hiredAt,\n Optional active,\n /** Points to {@link showcase.showcase.department.DepartmentRow#id()} */\n DepartmentId departmentId,\n String departmentName,\n Optional departmentBudget,\n /** Points to {@link showcase.showcase.company.CompanyRow#id()} */\n CompanyId companyId,\n String companyName,\n Optional managerId,\n Optional managerFirstName,\n Optional managerLastName\n) {\n /** Points to {@link showcase.showcase.employee.EmployeeRow#id()} */\n public EmployeeSummaryViewRow withEmployeeId(EmployeeId employeeId) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withEmail(String email) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withFirstName(String firstName) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withLastName(String lastName) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withSalary(Optional salary) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withHiredAt(Optional hiredAt) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withActive(Optional active) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n /** Points to {@link showcase.showcase.department.DepartmentRow#id()} */\n public EmployeeSummaryViewRow withDepartmentId(DepartmentId departmentId) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withDepartmentName(String departmentName) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withDepartmentBudget(Optional departmentBudget) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n /** Points to {@link showcase.showcase.company.CompanyRow#id()} */\n public EmployeeSummaryViewRow withCompanyId(CompanyId companyId) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withCompanyName(String companyName) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withManagerId(Optional managerId) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withManagerFirstName(Optional managerFirstName) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public EmployeeSummaryViewRow withManagerLastName(Optional managerLastName) {\n return new EmployeeSummaryViewRow(employeeId, email, firstName, lastName, salary, hiredAt, active, departmentId, departmentName, departmentBudget, companyId, companyName, managerId, managerFirstName, managerLastName);\n };\n\n public static RowParser _rowParser = RowParsers.of(EmployeeId.sqlServerType, SqlServerTypes.nvarchar, SqlServerTypes.nvarchar, SqlServerTypes.nvarchar, SqlServerTypes.decimal.opt(), SqlServerTypes.date.opt(), SqlServerTypes.bit.opt(), DepartmentId.sqlServerType, SqlServerTypes.nvarchar, SqlServerTypes.decimal.opt(), CompanyId.sqlServerType, SqlServerTypes.nvarchar, SqlServerTypes.nvarchar.opt(), SqlServerTypes.nvarchar.opt(), SqlServerTypes.nvarchar.opt(), EmployeeSummaryViewRow::new, row -> new Object[]{row.employeeId(), row.email(), row.firstName(), row.lastName(), row.salary(), row.hiredAt(), row.active(), row.departmentId(), row.departmentName(), row.departmentBudget(), row.companyId(), row.companyName(), row.managerId(), row.managerFirstName(), row.managerLastName()});;\n}", - "EmployeeSummaryViewRepo": "package showcase.showcase.employee_summary;\n\nimport dev.typr.foundations.dsl.SelectBuilder;\nimport java.sql.Connection;\nimport java.util.List;\n\npublic interface EmployeeSummaryViewRepo {\n SelectBuilder select();\n\n List selectAll(Connection c);\n}", - "CustomerOrderRow": "package showcase.showcase.customer_order;\n\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport dev.typr.foundations.SqlServerTypes;\nimport dev.typr.foundations.data.Json;\nimport java.math.BigDecimal;\nimport java.time.LocalDateTime;\nimport java.util.Optional;\nimport java.util.UUID;\nimport showcase.customtypes.Defaulted;\nimport showcase.showcase.address.AddressId;\nimport showcase.showcase.customer.CustomerId;\n\n/** Table: showcase.customer_order\n * Primary key: id\n */\npublic record CustomerOrderRow(\n CustomerOrderId id,\n /** Points to {@link showcase.showcase.customer.CustomerRow#id()} */\n CustomerId customerId,\n /** Points to {@link showcase.showcase.address.AddressRow#id()} */\n Optional shippingAddressId,\n /** Points to {@link showcase.showcase.address.AddressRow#id()} */\n Optional billingAddressId,\n /** Default: 'pending' */\n Optional status,\n BigDecimal subtotal,\n /** Default: 0 */\n Optional tax,\n /** Default: 0 */\n Optional shipping,\n BigDecimal total,\n Optional notes,\n /** Default: CURRENT_TIMESTAMP */\n Optional createdAt,\n Optional shippedAt,\n Optional deliveredAt,\n Optional orderUid,\n Optional metadata,\n Optional xmlInvoice,\n Optional receiptData,\n Optional rowVersion,\n Optional orderAmount\n) {\n public CustomerOrderRow withId(CustomerOrderId id) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderUid, metadata, xmlInvoice, receiptData, rowVersion, orderAmount);\n };\n\n /** Points to {@link showcase.showcase.customer.CustomerRow#id()} */\n public CustomerOrderRow withCustomerId(CustomerId customerId) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderUid, metadata, xmlInvoice, receiptData, rowVersion, orderAmount);\n };\n\n /** Points to {@link showcase.showcase.address.AddressRow#id()} */\n public CustomerOrderRow withShippingAddressId(Optional shippingAddressId) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderUid, metadata, xmlInvoice, receiptData, rowVersion, orderAmount);\n };\n\n /** Points to {@link showcase.showcase.address.AddressRow#id()} */\n public CustomerOrderRow withBillingAddressId(Optional billingAddressId) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderUid, metadata, xmlInvoice, receiptData, rowVersion, orderAmount);\n };\n\n /** Default: 'pending' */\n public CustomerOrderRow withStatus(Optional status) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderUid, metadata, xmlInvoice, receiptData, rowVersion, orderAmount);\n };\n\n public CustomerOrderRow withSubtotal(BigDecimal subtotal) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderUid, metadata, xmlInvoice, receiptData, rowVersion, orderAmount);\n };\n\n /** Default: 0 */\n public CustomerOrderRow withTax(Optional tax) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderUid, metadata, xmlInvoice, receiptData, rowVersion, orderAmount);\n };\n\n /** Default: 0 */\n public CustomerOrderRow withShipping(Optional shipping) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderUid, metadata, xmlInvoice, receiptData, rowVersion, orderAmount);\n };\n\n public CustomerOrderRow withTotal(BigDecimal total) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderUid, metadata, xmlInvoice, receiptData, rowVersion, orderAmount);\n };\n\n public CustomerOrderRow withNotes(Optional notes) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderUid, metadata, xmlInvoice, receiptData, rowVersion, orderAmount);\n };\n\n /** Default: CURRENT_TIMESTAMP */\n public CustomerOrderRow withCreatedAt(Optional createdAt) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderUid, metadata, xmlInvoice, receiptData, rowVersion, orderAmount);\n };\n\n public CustomerOrderRow withShippedAt(Optional shippedAt) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderUid, metadata, xmlInvoice, receiptData, rowVersion, orderAmount);\n };\n\n public CustomerOrderRow withDeliveredAt(Optional deliveredAt) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderUid, metadata, xmlInvoice, receiptData, rowVersion, orderAmount);\n };\n\n public CustomerOrderRow withOrderUid(Optional orderUid) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderUid, metadata, xmlInvoice, receiptData, rowVersion, orderAmount);\n };\n\n public CustomerOrderRow withMetadata(Optional metadata) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderUid, metadata, xmlInvoice, receiptData, rowVersion, orderAmount);\n };\n\n public CustomerOrderRow withXmlInvoice(Optional xmlInvoice) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderUid, metadata, xmlInvoice, receiptData, rowVersion, orderAmount);\n };\n\n public CustomerOrderRow withReceiptData(Optional receiptData) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderUid, metadata, xmlInvoice, receiptData, rowVersion, orderAmount);\n };\n\n public CustomerOrderRow withRowVersion(Optional rowVersion) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderUid, metadata, xmlInvoice, receiptData, rowVersion, orderAmount);\n };\n\n public CustomerOrderRow withOrderAmount(Optional orderAmount) {\n return new CustomerOrderRow(id, customerId, shippingAddressId, billingAddressId, status, subtotal, tax, shipping, total, notes, createdAt, shippedAt, deliveredAt, orderUid, metadata, xmlInvoice, receiptData, rowVersion, orderAmount);\n };\n\n public static RowParser _rowParser = RowParsers.of(CustomerOrderId.sqlServerType, CustomerId.sqlServerType, AddressId.sqlServerType.opt(), AddressId.sqlServerType.opt(), SqlServerTypes.nvarchar.opt(), SqlServerTypes.decimal, SqlServerTypes.decimal.opt(), SqlServerTypes.decimal.opt(), SqlServerTypes.decimal, SqlServerTypes.nvarchar.opt(), SqlServerTypes.datetime2.opt(), SqlServerTypes.datetime2.opt(), SqlServerTypes.datetime2.opt(), SqlServerTypes.uniqueidentifier.opt(), SqlServerTypes.json.opt(), SqlServerTypes.xml.opt(), SqlServerTypes.varbinary.opt(), SqlServerTypes.rowversion.opt(), SqlServerTypes.money.opt(), CustomerOrderRow::new, row -> new Object[]{row.id(), row.customerId(), row.shippingAddressId(), row.billingAddressId(), row.status(), row.subtotal(), row.tax(), row.shipping(), row.total(), row.notes(), row.createdAt(), row.shippedAt(), row.deliveredAt(), row.orderUid(), row.metadata(), row.xmlInvoice(), row.receiptData(), row.rowVersion(), row.orderAmount()});;\n\n public CustomerOrderRowUnsaved toUnsavedRow(\n Defaulted> status,\n Defaulted> tax,\n Defaulted> shipping,\n Defaulted> createdAt\n ) {\n return new CustomerOrderRowUnsaved(id, customerId, shippingAddressId, billingAddressId, subtotal, total, notes, shippedAt, deliveredAt, orderUid, metadata, xmlInvoice, receiptData, rowVersion, orderAmount, status, tax, shipping, createdAt);\n };\n}", - "CustomerOrderRepo": "package showcase.showcase.customer_order;\n\nimport dev.typr.foundations.dsl.DeleteBuilder;\nimport dev.typr.foundations.dsl.SelectBuilder;\nimport dev.typr.foundations.dsl.UpdateBuilder;\nimport java.sql.Connection;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Optional;\n\npublic interface CustomerOrderRepo {\n DeleteBuilder delete();\n\n Boolean deleteById(\n CustomerOrderId id,\n Connection c\n );\n\n Integer deleteByIds(\n CustomerOrderId[] ids,\n Connection c\n );\n\n CustomerOrderRow insert(\n CustomerOrderRow unsaved,\n Connection c\n );\n\n CustomerOrderRow insert(\n CustomerOrderRowUnsaved unsaved,\n Connection c\n );\n\n SelectBuilder select();\n\n List selectAll(Connection c);\n\n Optional selectById(\n CustomerOrderId id,\n Connection c\n );\n\n List selectByIds(\n CustomerOrderId[] ids,\n Connection c\n );\n\n Map selectByIdsTracked(\n CustomerOrderId[] ids,\n Connection c\n );\n\n UpdateBuilder update();\n\n Boolean update(\n CustomerOrderRow row,\n Connection c\n );\n\n CustomerOrderRow upsert(\n CustomerOrderRow unsaved,\n Connection c\n );\n\n List upsertBatch(\n Iterator unsaved,\n Connection c\n );\n}", - "OrderItemRow": "package showcase.showcase.order_item;\n\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport dev.typr.foundations.SqlServerTypes;\nimport java.math.BigDecimal;\nimport java.util.Optional;\nimport showcase.customtypes.Defaulted;\nimport showcase.showcase.customer_order.CustomerOrderId;\nimport showcase.showcase.product.ProductId;\n\n/** Table: showcase.order_item\n * Composite primary key: order_id, product_id\n */\npublic record OrderItemRow(\n /** Points to {@link showcase.showcase.customer_order.CustomerOrderRow#id()} */\n CustomerOrderId orderId,\n /** Points to {@link showcase.showcase.product.ProductRow#id()} */\n ProductId productId,\n Integer quantity,\n BigDecimal unitPrice,\n /** Default: 0 */\n Optional discount\n) {\n /** Points to {@link showcase.showcase.customer_order.CustomerOrderRow#id()} */\n public OrderItemRow withOrderId(CustomerOrderId orderId) {\n return new OrderItemRow(orderId, productId, quantity, unitPrice, discount);\n };\n\n /** Points to {@link showcase.showcase.product.ProductRow#id()} */\n public OrderItemRow withProductId(ProductId productId) {\n return new OrderItemRow(orderId, productId, quantity, unitPrice, discount);\n };\n\n public OrderItemRow withQuantity(Integer quantity) {\n return new OrderItemRow(orderId, productId, quantity, unitPrice, discount);\n };\n\n public OrderItemRow withUnitPrice(BigDecimal unitPrice) {\n return new OrderItemRow(orderId, productId, quantity, unitPrice, discount);\n };\n\n /** Default: 0 */\n public OrderItemRow withDiscount(Optional discount) {\n return new OrderItemRow(orderId, productId, quantity, unitPrice, discount);\n };\n\n public static RowParser _rowParser = RowParsers.of(CustomerOrderId.sqlServerType, ProductId.sqlServerType, SqlServerTypes.int_, SqlServerTypes.decimal, SqlServerTypes.decimal.opt(), OrderItemRow::new, row -> new Object[]{row.orderId(), row.productId(), row.quantity(), row.unitPrice(), row.discount()});;\n\n static public OrderItemRow apply(\n OrderItemId compositeId,\n Integer quantity,\n BigDecimal unitPrice,\n Optional discount\n ) {\n return new OrderItemRow(compositeId.orderId(), compositeId.productId(), quantity, unitPrice, discount);\n };\n\n public OrderItemId compositeId() {\n return new OrderItemId(orderId, productId);\n };\n\n public OrderItemId id() {\n return this.compositeId();\n };\n\n public OrderItemRowUnsaved toUnsavedRow(Defaulted> discount) {\n return new OrderItemRowUnsaved(orderId, productId, quantity, unitPrice, discount);\n };\n}", - "OrderItemId": "package showcase.showcase.order_item;\n\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport showcase.showcase.customer_order.CustomerOrderId;\nimport showcase.showcase.product.ProductId;\n\n/** Type for the composite primary key of table `showcase.order_item` */\npublic record OrderItemId(\n CustomerOrderId orderId,\n ProductId productId\n) {\n public OrderItemId withOrderId(CustomerOrderId orderId) {\n return new OrderItemId(orderId, productId);\n };\n\n public OrderItemId withProductId(ProductId productId) {\n return new OrderItemId(orderId, productId);\n };\n\n public static RowParser _rowParser = RowParsers.of(CustomerOrderId.sqlServerType, ProductId.sqlServerType, OrderItemId::new, row -> new Object[]{row.orderId(), row.productId()});;\n}", - "ProductRow": "package showcase.showcase.product;\n\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport dev.typr.foundations.SqlServerTypes;\nimport dev.typr.foundations.data.Json;\nimport java.math.BigDecimal;\nimport java.time.LocalDateTime;\nimport java.util.Optional;\nimport java.util.UUID;\nimport showcase.customtypes.Defaulted;\nimport showcase.showcase.category.CategoryId;\n\n/** Table: showcase.product\n * Primary key: id\n */\npublic record ProductRow(\n ProductId id,\n /** Points to {@link showcase.showcase.category.CategoryRow#id()} */\n Optional categoryId,\n String name,\n String sku,\n BigDecimal price,\n Optional cost,\n /** Default: true */\n Optional inStock,\n /** Default: 0 */\n Optional quantity,\n Optional weight,\n /** Default: CURRENT_TIMESTAMP */\n Optional createdAt,\n Optional attributes,\n Optional specifications,\n Optional descriptionLong,\n Optional thumbnail,\n Optional productUid,\n Optional listPrice\n) {\n public ProductRow withId(ProductId id) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, attributes, specifications, descriptionLong, thumbnail, productUid, listPrice);\n };\n\n /** Points to {@link showcase.showcase.category.CategoryRow#id()} */\n public ProductRow withCategoryId(Optional categoryId) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, attributes, specifications, descriptionLong, thumbnail, productUid, listPrice);\n };\n\n public ProductRow withName(String name) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, attributes, specifications, descriptionLong, thumbnail, productUid, listPrice);\n };\n\n public ProductRow withSku(String sku) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, attributes, specifications, descriptionLong, thumbnail, productUid, listPrice);\n };\n\n public ProductRow withPrice(BigDecimal price) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, attributes, specifications, descriptionLong, thumbnail, productUid, listPrice);\n };\n\n public ProductRow withCost(Optional cost) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, attributes, specifications, descriptionLong, thumbnail, productUid, listPrice);\n };\n\n /** Default: true */\n public ProductRow withInStock(Optional inStock) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, attributes, specifications, descriptionLong, thumbnail, productUid, listPrice);\n };\n\n /** Default: 0 */\n public ProductRow withQuantity(Optional quantity) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, attributes, specifications, descriptionLong, thumbnail, productUid, listPrice);\n };\n\n public ProductRow withWeight(Optional weight) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, attributes, specifications, descriptionLong, thumbnail, productUid, listPrice);\n };\n\n /** Default: CURRENT_TIMESTAMP */\n public ProductRow withCreatedAt(Optional createdAt) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, attributes, specifications, descriptionLong, thumbnail, productUid, listPrice);\n };\n\n public ProductRow withAttributes(Optional attributes) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, attributes, specifications, descriptionLong, thumbnail, productUid, listPrice);\n };\n\n public ProductRow withSpecifications(Optional specifications) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, attributes, specifications, descriptionLong, thumbnail, productUid, listPrice);\n };\n\n public ProductRow withDescriptionLong(Optional descriptionLong) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, attributes, specifications, descriptionLong, thumbnail, productUid, listPrice);\n };\n\n public ProductRow withThumbnail(Optional thumbnail) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, attributes, specifications, descriptionLong, thumbnail, productUid, listPrice);\n };\n\n public ProductRow withProductUid(Optional productUid) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, attributes, specifications, descriptionLong, thumbnail, productUid, listPrice);\n };\n\n public ProductRow withListPrice(Optional listPrice) {\n return new ProductRow(id, categoryId, name, sku, price, cost, inStock, quantity, weight, createdAt, attributes, specifications, descriptionLong, thumbnail, productUid, listPrice);\n };\n\n public static RowParser _rowParser = RowParsers.of(ProductId.sqlServerType, CategoryId.sqlServerType.opt(), SqlServerTypes.nvarchar, SqlServerTypes.nvarchar, SqlServerTypes.decimal, SqlServerTypes.decimal.opt(), SqlServerTypes.bit.opt(), SqlServerTypes.int_.opt(), SqlServerTypes.decimal.opt(), SqlServerTypes.datetime2.opt(), SqlServerTypes.json.opt(), SqlServerTypes.xml.opt(), SqlServerTypes.nvarchar.opt(), SqlServerTypes.varbinary.opt(), SqlServerTypes.uniqueidentifier.opt(), SqlServerTypes.money.opt(), ProductRow::new, row -> new Object[]{row.id(), row.categoryId(), row.name(), row.sku(), row.price(), row.cost(), row.inStock(), row.quantity(), row.weight(), row.createdAt(), row.attributes(), row.specifications(), row.descriptionLong(), row.thumbnail(), row.productUid(), row.listPrice()});;\n\n public ProductRowUnsaved toUnsavedRow(\n Defaulted> inStock,\n Defaulted> quantity,\n Defaulted> createdAt\n ) {\n return new ProductRowUnsaved(id, categoryId, name, sku, price, cost, weight, attributes, specifications, descriptionLong, thumbnail, productUid, listPrice, inStock, quantity, createdAt);\n };\n}", - "ProductId": "package showcase.showcase.product;\n\nimport dev.typr.foundations.SqlServerType;\nimport dev.typr.foundations.SqlServerTypes;\nimport dev.typr.foundations.dsl.Bijection;\n\n/** Type for the primary key of table `showcase.product` */\npublic record ProductId(String value) {\n public ProductId withValue(String value) {\n return new ProductId(value);\n };\n\n @Override\n public java.lang.String toString() {\n return value.toString();\n };\n\n static public Bijection bijection =\n Bijection.of(ProductId::value, ProductId::new);\n\n static public SqlServerType sqlServerType =\n SqlServerTypes.nvarchar.bimap(ProductId::new, ProductId::value);\n}", - "CategoryRow": "package showcase.showcase.category;\n\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport dev.typr.foundations.SqlServerTypes;\nimport java.util.Optional;\n\n/** Table: showcase.category\n * Primary key: id\n */\npublic record CategoryRow(\n CategoryId id,\n /** Points to {@link showcase.showcase.category.CategoryRow#id()} */\n Optional parentId,\n String name,\n Optional description\n) {\n public CategoryRow withId(CategoryId id) {\n return new CategoryRow(id, parentId, name, description);\n };\n\n /** Points to {@link showcase.showcase.category.CategoryRow#id()} */\n public CategoryRow withParentId(Optional parentId) {\n return new CategoryRow(id, parentId, name, description);\n };\n\n public CategoryRow withName(String name) {\n return new CategoryRow(id, parentId, name, description);\n };\n\n public CategoryRow withDescription(Optional description) {\n return new CategoryRow(id, parentId, name, description);\n };\n\n public static RowParser _rowParser = RowParsers.of(CategoryId.sqlServerType, CategoryId.sqlServerType.opt(), SqlServerTypes.nvarchar, SqlServerTypes.nvarchar.opt(), CategoryRow::new, row -> new Object[]{row.id(), row.parentId(), row.name(), row.description()});;\n}", - "CategoryId": "package showcase.showcase.category;\n\nimport dev.typr.foundations.SqlServerType;\nimport dev.typr.foundations.SqlServerTypes;\nimport dev.typr.foundations.dsl.Bijection;\n\n/** Type for the primary key of table `showcase.category` */\npublic record CategoryId(String value) {\n public CategoryId withValue(String value) {\n return new CategoryId(value);\n };\n\n @Override\n public java.lang.String toString() {\n return value.toString();\n };\n\n static public Bijection bijection =\n Bijection.of(CategoryId::value, CategoryId::new);\n\n static public SqlServerType sqlServerType =\n SqlServerTypes.nvarchar.bimap(CategoryId::new, CategoryId::value);\n}", - "AddressRow": "package showcase.showcase.address;\n\nimport com.microsoft.sqlserver.jdbc.Geography;\nimport com.microsoft.sqlserver.jdbc.Geometry;\nimport dev.typr.foundations.RowParser;\nimport dev.typr.foundations.RowParsers;\nimport dev.typr.foundations.SqlServerTypes;\nimport java.util.Optional;\nimport showcase.customtypes.Defaulted;\nimport showcase.showcase.customer.CustomerId;\n\n/** Table: showcase.address\n * Primary key: id\n */\npublic record AddressRow(\n AddressId id,\n /** Points to {@link showcase.showcase.customer.CustomerRow#id()} */\n CustomerId customerId,\n String addressType,\n String street,\n String city,\n Optional state,\n Optional postalCode,\n String country,\n /** Default: false */\n Optional isDefault,\n Optional location,\n Optional deliveryZone\n) {\n public AddressRow withId(AddressId id) {\n return new AddressRow(id, customerId, addressType, street, city, state, postalCode, country, isDefault, location, deliveryZone);\n };\n\n /** Points to {@link showcase.showcase.customer.CustomerRow#id()} */\n public AddressRow withCustomerId(CustomerId customerId) {\n return new AddressRow(id, customerId, addressType, street, city, state, postalCode, country, isDefault, location, deliveryZone);\n };\n\n public AddressRow withAddressType(String addressType) {\n return new AddressRow(id, customerId, addressType, street, city, state, postalCode, country, isDefault, location, deliveryZone);\n };\n\n public AddressRow withStreet(String street) {\n return new AddressRow(id, customerId, addressType, street, city, state, postalCode, country, isDefault, location, deliveryZone);\n };\n\n public AddressRow withCity(String city) {\n return new AddressRow(id, customerId, addressType, street, city, state, postalCode, country, isDefault, location, deliveryZone);\n };\n\n public AddressRow withState(Optional state) {\n return new AddressRow(id, customerId, addressType, street, city, state, postalCode, country, isDefault, location, deliveryZone);\n };\n\n public AddressRow withPostalCode(Optional postalCode) {\n return new AddressRow(id, customerId, addressType, street, city, state, postalCode, country, isDefault, location, deliveryZone);\n };\n\n public AddressRow withCountry(String country) {\n return new AddressRow(id, customerId, addressType, street, city, state, postalCode, country, isDefault, location, deliveryZone);\n };\n\n /** Default: false */\n public AddressRow withIsDefault(Optional isDefault) {\n return new AddressRow(id, customerId, addressType, street, city, state, postalCode, country, isDefault, location, deliveryZone);\n };\n\n public AddressRow withLocation(Optional location) {\n return new AddressRow(id, customerId, addressType, street, city, state, postalCode, country, isDefault, location, deliveryZone);\n };\n\n public AddressRow withDeliveryZone(Optional deliveryZone) {\n return new AddressRow(id, customerId, addressType, street, city, state, postalCode, country, isDefault, location, deliveryZone);\n };\n\n public static RowParser _rowParser = RowParsers.of(AddressId.sqlServerType, CustomerId.sqlServerType, SqlServerTypes.nvarchar, SqlServerTypes.nvarchar, SqlServerTypes.nvarchar, SqlServerTypes.nvarchar.opt(), SqlServerTypes.nvarchar.opt(), SqlServerTypes.nvarchar, SqlServerTypes.bit.opt(), SqlServerTypes.geography.opt(), SqlServerTypes.geometry.opt(), AddressRow::new, row -> new Object[]{row.id(), row.customerId(), row.addressType(), row.street(), row.city(), row.state(), row.postalCode(), row.country(), row.isDefault(), row.location(), row.deliveryZone()});;\n\n public AddressRowUnsaved toUnsavedRow(Defaulted> isDefault) {\n return new AddressRowUnsaved(id, customerId, addressType, street, city, state, postalCode, country, location, deliveryZone, isDefault);\n };\n}", - "AddressId": "package showcase.showcase.address;\n\nimport dev.typr.foundations.SqlServerType;\nimport dev.typr.foundations.SqlServerTypes;\nimport dev.typr.foundations.dsl.Bijection;\n\n/** Type for the primary key of table `showcase.address` */\npublic record AddressId(String value) {\n public AddressId withValue(String value) {\n return new AddressId(value);\n };\n\n @Override\n public java.lang.String toString() {\n return value.toString();\n };\n\n static public Bijection bijection =\n Bijection.of(AddressId::value, AddressId::new);\n\n static public SqlServerType sqlServerType =\n SqlServerTypes.nvarchar.bimap(AddressId::new, AddressId::value);\n}", - "Defaulted": "package showcase.customtypes;\n\n\n\n/** This signals a value where if you don't provide it, postgres will generate it for you */\npublic sealed interface Defaulted permits Defaulted.Provided, Defaulted.UseDefault {\n record Provided(T value) implements Defaulted {\n public Provided withValue(T value) {\n return new Provided<>(value);\n };\n\n @Override\n public U fold(\n java.util.function.Supplier onDefault,\n java.util.function.Function onProvided\n ) {\n return onProvided.apply(value);\n };\n\n @Override\n public T getOrElse(java.util.function.Supplier onDefault) {\n return value;\n };\n\n @Override\n public void visit(\n java.lang.Runnable onDefault,\n java.util.function.Consumer onProvided\n ) {\n onProvided.accept(value);\n };\n };\n\n record UseDefault() implements Defaulted {\n @Override\n public U fold(\n java.util.function.Supplier onDefault,\n java.util.function.Function onProvided\n ) {\n return onDefault.get();\n };\n\n @Override\n public T getOrElse(java.util.function.Supplier onDefault) {\n return onDefault.get();\n };\n\n @Override\n public void visit(\n java.lang.Runnable onDefault,\n java.util.function.Consumer onProvided\n ) {\n onDefault.run();\n };\n };\n\n U fold(\n java.util.function.Supplier onDefault,\n java.util.function.Function onProvided\n );\n\n T getOrElse(java.util.function.Supplier onDefault);\n\n void visit(\n java.lang.Runnable onDefault,\n java.util.function.Consumer onProvided\n );\n}", - "TestInsert": "package showcase;\n\nimport com.microsoft.sqlserver.jdbc.Geography;\nimport com.microsoft.sqlserver.jdbc.Geometry;\nimport dev.typr.foundations.data.Json;\nimport dev.typr.foundations.internal.RandomHelper;\nimport java.math.BigDecimal;\nimport java.sql.Connection;\nimport java.time.LocalDate;\nimport java.time.LocalDateTime;\nimport java.time.OffsetDateTime;\nimport java.util.Optional;\nimport java.util.Random;\nimport java.util.UUID;\nimport showcase.customtypes.Defaulted;\nimport showcase.showcase.address.AddressId;\nimport showcase.showcase.address.AddressRepoImpl;\nimport showcase.showcase.address.AddressRow;\nimport showcase.showcase.address.AddressRowUnsaved;\nimport showcase.showcase.audit_log.AuditLogId;\nimport showcase.showcase.audit_log.AuditLogRepoImpl;\nimport showcase.showcase.audit_log.AuditLogRow;\nimport showcase.showcase.audit_log.AuditLogRowUnsaved;\nimport showcase.showcase.category.CategoryId;\nimport showcase.showcase.category.CategoryRepoImpl;\nimport showcase.showcase.category.CategoryRow;\nimport showcase.showcase.company.CompanyId;\nimport showcase.showcase.company.CompanyRepoImpl;\nimport showcase.showcase.company.CompanyRow;\nimport showcase.showcase.company.CompanyRowUnsaved;\nimport showcase.showcase.customer.CustomerId;\nimport showcase.showcase.customer.CustomerRepoImpl;\nimport showcase.showcase.customer.CustomerRow;\nimport showcase.showcase.customer.CustomerRowUnsaved;\nimport showcase.showcase.customer_order.CustomerOrderId;\nimport showcase.showcase.customer_order.CustomerOrderRepoImpl;\nimport showcase.showcase.customer_order.CustomerOrderRow;\nimport showcase.showcase.customer_order.CustomerOrderRowUnsaved;\nimport showcase.showcase.department.DepartmentId;\nimport showcase.showcase.department.DepartmentRepoImpl;\nimport showcase.showcase.department.DepartmentRow;\nimport showcase.showcase.employee.EmployeeId;\nimport showcase.showcase.employee.EmployeeRepoImpl;\nimport showcase.showcase.employee.EmployeeRow;\nimport showcase.showcase.employee.EmployeeRowUnsaved;\nimport showcase.showcase.order_item.OrderItemRepoImpl;\nimport showcase.showcase.order_item.OrderItemRow;\nimport showcase.showcase.order_item.OrderItemRowUnsaved;\nimport showcase.showcase.product.ProductId;\nimport showcase.showcase.product.ProductRepoImpl;\nimport showcase.showcase.product.ProductRow;\nimport showcase.showcase.product.ProductRowUnsaved;\nimport showcase.showcase.project.ProjectId;\nimport showcase.showcase.project.ProjectRepoImpl;\nimport showcase.showcase.project.ProjectRow;\nimport showcase.showcase.project.ProjectRowUnsaved;\nimport showcase.showcase.project_assignment.ProjectAssignmentRepoImpl;\nimport showcase.showcase.project_assignment.ProjectAssignmentRow;\nimport showcase.showcase.project_assignment.ProjectAssignmentRowUnsaved;\n\n/** Methods to generate random data for `Ident(TestInsert)` */\npublic record TestInsert(Random random) {\n public TestInsert withRandom(Random random) {\n return new TestInsert(random);\n };\n\n public AddressRow showcaseAddress(\n CustomerId customerId,\n AddressId id,\n String addressType,\n String street,\n String city,\n Optional state,\n Optional postalCode,\n String country,\n Optional location,\n Optional deliveryZone,\n Defaulted> isDefault,\n Connection c\n ) {\n return (new AddressRepoImpl()).insert(new AddressRowUnsaved(id, customerId, addressType, street, city, state, postalCode, country, location, deliveryZone, isDefault), c);\n };\n\n public AuditLogRow showcaseAuditLog(\n AuditLogId id,\n String tableName,\n String recordId,\n String action,\n Optional oldValues,\n Optional newValues,\n Optional changedBy,\n Defaulted> changedAt,\n Connection c\n ) {\n return (new AuditLogRepoImpl()).insert(new AuditLogRowUnsaved(id, tableName, recordId, action, oldValues, newValues, changedBy, changedAt), c);\n };\n\n public CategoryRow showcaseCategory(\n CategoryId id,\n Optional parentId,\n String name,\n Optional description,\n Connection c\n ) {\n return (new CategoryRepoImpl()).insert(new CategoryRow(id, parentId, name, description), c);\n };\n\n public CompanyRow showcaseCompany(\n CompanyId id,\n String name,\n Optional foundedYear,\n Defaulted> active,\n Defaulted> createdAt,\n Connection c\n ) {\n return (new CompanyRepoImpl()).insert(new CompanyRowUnsaved(id, name, foundedYear, active, createdAt), c);\n };\n\n public CustomerRow showcaseCustomer(\n CustomerId id,\n String email,\n String firstName,\n String lastName,\n Optional phone,\n Optional preferences,\n Optional avatar,\n Optional customerUid,\n Optional creditLimit,\n Defaulted> verified,\n Defaulted> createdAt,\n Connection c\n ) {\n return (new CustomerRepoImpl()).insert(new CustomerRowUnsaved(id, email, firstName, lastName, phone, preferences, avatar, customerUid, creditLimit, verified, createdAt), c);\n };\n\n public CustomerOrderRow showcaseCustomerOrder(\n CustomerId customerId,\n CustomerOrderId id,\n Optional shippingAddressId,\n Optional billingAddressId,\n BigDecimal subtotal,\n BigDecimal total,\n Optional notes,\n Optional shippedAt,\n Optional deliveredAt,\n Optional orderUid,\n Optional metadata,\n Optional xmlInvoice,\n Optional receiptData,\n Optional rowVersion,\n Optional orderAmount,\n Defaulted> status,\n Defaulted> tax,\n Defaulted> shipping,\n Defaulted> createdAt,\n Connection c\n ) {\n return (new CustomerOrderRepoImpl()).insert(new CustomerOrderRowUnsaved(id, customerId, shippingAddressId, billingAddressId, subtotal, total, notes, shippedAt, deliveredAt, orderUid, metadata, xmlInvoice, receiptData, rowVersion, orderAmount, status, tax, shipping, createdAt), c);\n };\n\n public DepartmentRow showcaseDepartment(\n CompanyId companyId,\n DepartmentId id,\n String name,\n Optional budget,\n Connection c\n ) {\n return (new DepartmentRepoImpl()).insert(new DepartmentRow(id, companyId, name, budget), c);\n };\n\n public EmployeeRow showcaseEmployee(\n DepartmentId departmentId,\n EmployeeId id,\n Optional managerId,\n String email,\n String firstName,\n String lastName,\n Optional salary,\n Optional hiredAt,\n Optional metadata,\n Optional resume,\n Optional photo,\n Optional employeeUid,\n Optional lastModified,\n Optional rowVersion,\n Optional orgPath,\n Defaulted> active,\n Defaulted> createdAt,\n Connection c\n ) {\n return (new EmployeeRepoImpl()).insert(new EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, metadata, resume, photo, employeeUid, lastModified, rowVersion, orgPath, active, createdAt), c);\n };\n\n public OrderItemRow showcaseOrderItem(\n CustomerOrderId orderId,\n ProductId productId,\n Integer quantity,\n BigDecimal unitPrice,\n Defaulted> discount,\n Connection c\n ) {\n return (new OrderItemRepoImpl()).insert(new OrderItemRowUnsaved(orderId, productId, quantity, unitPrice, discount), c);\n };\n\n public ProductRow showcaseProduct(\n ProductId id,\n Optional categoryId,\n String name,\n String sku,\n BigDecimal price,\n Optional cost,\n Optional weight,\n Optional attributes,\n Optional specifications,\n Optional descriptionLong,\n Optional thumbnail,\n Optional productUid,\n Optional listPrice,\n Defaulted> inStock,\n Defaulted> quantity,\n Defaulted> createdAt,\n Connection c\n ) {\n return (new ProductRepoImpl()).insert(new ProductRowUnsaved(id, categoryId, name, sku, price, cost, weight, attributes, specifications, descriptionLong, thumbnail, productUid, listPrice, inStock, quantity, createdAt), c);\n };\n\n public ProjectRow showcaseProject(\n ProjectId id,\n String name,\n Optional description,\n Optional startDate,\n Optional endDate,\n Optional budget,\n Optional projectUid,\n Optional metadata,\n Optional xmlPlan,\n Optional attachments,\n Optional rowVersion,\n Optional totalBudget,\n Optional orgPath,\n Defaulted> status,\n Defaulted> createdAt,\n Connection c\n ) {\n return (new ProjectRepoImpl()).insert(new ProjectRowUnsaved(id, name, description, startDate, endDate, budget, projectUid, metadata, xmlPlan, attachments, rowVersion, totalBudget, orgPath, status, createdAt), c);\n };\n\n public ProjectAssignmentRow showcaseProjectAssignment(\n EmployeeId employeeId,\n ProjectId projectId,\n String role,\n Optional startDate,\n Optional endDate,\n Defaulted> hoursAllocated,\n Connection c\n ) {\n return (new ProjectAssignmentRepoImpl()).insert(new ProjectAssignmentRowUnsaved(employeeId, projectId, role, startDate, endDate, hoursAllocated), c);\n };\n}" - }, - "kotlin": { - "CompanyRow": "package showcase.showcase.company\n\nimport dev.typr.foundations.SqlServerTypes\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport dev.typr.foundations.kotlin.nullable\nimport java.time.LocalDateTime\nimport showcase.customtypes.Defaulted\n\n/** Table: showcase.company\n * Primary key: id\n */\ndata class CompanyRow(\n val id: CompanyId,\n val name: String,\n val foundedYear: Int?,\n /** Default: true */\n val active: Boolean?,\n /** Default: CURRENT_TIMESTAMP */\n val createdAt: LocalDateTime?\n) {\n fun toUnsavedRow(\n active: Defaulted,\n createdAt: Defaulted\n ): CompanyRowUnsaved = CompanyRowUnsaved(id, name, foundedYear, active, createdAt)\n\n companion object {\n val _rowParser: RowParser = RowParsers.of(CompanyId.sqlServerType, SqlServerTypes.nvarchar, KotlinDbTypes.SqlServerTypes.int_.nullable(), KotlinDbTypes.SqlServerTypes.bit.nullable(), SqlServerTypes.datetime2.nullable(), { t0, t1, t2, t3, t4 -> CompanyRow(t0, t1, t2, t3, t4) }, { row -> arrayOf(row.id, row.name, row.foundedYear, row.active, row.createdAt) })\n }\n}", - "CompanyRowUnsaved": "package showcase.showcase.company\n\nimport java.time.LocalDateTime\nimport showcase.customtypes.Defaulted\nimport showcase.customtypes.Defaulted.UseDefault\n\n/** This class corresponds to a row in table `showcase.company` which has not been persisted yet */\ndata class CompanyRowUnsaved(\n val id: CompanyId,\n val name: String,\n val foundedYear: Int? = null,\n /** Default: true */\n val active: Defaulted = UseDefault(),\n /** Default: CURRENT_TIMESTAMP */\n val createdAt: Defaulted = UseDefault()\n) {\n fun toRow(\n activeDefault: () -> Boolean?,\n createdAtDefault: () -> LocalDateTime?\n ): CompanyRow = CompanyRow(id = id, name = name, foundedYear = foundedYear, active = active.getOrElse(activeDefault), createdAt = createdAt.getOrElse(createdAtDefault))\n}", - "CompanyId": "package showcase.showcase.company\n\nimport dev.typr.foundations.SqlServerType\nimport dev.typr.foundations.SqlServerTypes\nimport dev.typr.foundations.kotlin.Bijection\n\n/** Type for the primary key of table `showcase.company` */\ndata class CompanyId(val value: String) {\n override fun toString(): kotlin.String {\n return value.toString()\n }\n\n companion object {\n val bijection: Bijection =\n Bijection.of(CompanyId::value, ::CompanyId)\n\n val sqlServerType: SqlServerType =\n SqlServerTypes.nvarchar.bimap(::CompanyId, CompanyId::value)\n }\n}", - "CompanyRepo": "package showcase.showcase.company\n\nimport dev.typr.foundations.kotlin.DeleteBuilder\nimport dev.typr.foundations.kotlin.SelectBuilder\nimport dev.typr.foundations.kotlin.UpdateBuilder\nimport java.sql.Connection\nimport kotlin.collections.Iterator\nimport kotlin.collections.List\nimport kotlin.collections.Map\n\ninterface CompanyRepo {\n abstract fun delete(): DeleteBuilder\n\n abstract fun deleteById(\n id: CompanyId,\n c: Connection\n ): Boolean\n\n abstract fun deleteByIds(\n ids: Array,\n c: Connection\n ): Int\n\n abstract fun insert(\n unsaved: CompanyRow,\n c: Connection\n ): CompanyRow\n\n abstract fun insert(\n unsaved: CompanyRowUnsaved,\n c: Connection\n ): CompanyRow\n\n abstract fun select(): SelectBuilder\n\n abstract fun selectAll(c: Connection): List\n\n abstract fun selectById(\n id: CompanyId,\n c: Connection\n ): CompanyRow?\n\n abstract fun selectByIds(\n ids: Array,\n c: Connection\n ): List\n\n abstract fun selectByIdsTracked(\n ids: Array,\n c: Connection\n ): Map\n\n abstract fun update(): UpdateBuilder\n\n abstract fun update(\n row: CompanyRow,\n c: Connection\n ): Boolean\n\n abstract fun upsert(\n unsaved: CompanyRow,\n c: Connection\n ): CompanyRow\n\n abstract fun upsertBatch(\n unsaved: Iterator,\n c: Connection\n ): List\n}", - "CompanyRepoMock": "package showcase.showcase.company\n\nimport dev.typr.foundations.kotlin.DeleteBuilder\nimport dev.typr.foundations.kotlin.DeleteBuilderMock\nimport dev.typr.foundations.kotlin.DeleteParams\nimport dev.typr.foundations.kotlin.SelectBuilder\nimport dev.typr.foundations.kotlin.SelectBuilderMock\nimport dev.typr.foundations.kotlin.SelectParams\nimport dev.typr.foundations.kotlin.UpdateBuilder\nimport dev.typr.foundations.kotlin.UpdateBuilderMock\nimport dev.typr.foundations.kotlin.UpdateParams\nimport java.lang.RuntimeException\nimport java.sql.Connection\nimport java.util.ArrayList\nimport kotlin.collections.Iterator\nimport kotlin.collections.List\nimport kotlin.collections.Map\nimport kotlin.collections.MutableMap\n\ndata class CompanyRepoMock(\n val toRow: (CompanyRowUnsaved) -> CompanyRow,\n val map: MutableMap = mutableMapOf()\n) : CompanyRepo {\n override fun delete(): DeleteBuilder = DeleteBuilderMock(CompanyFields.structure, { map.values.toList() }, DeleteParams.empty(), { row -> row.id }, { id -> map.remove(id) })\n\n override fun deleteById(\n id: CompanyId,\n c: Connection\n ): Boolean = map.remove(id) != null\n\n override fun deleteByIds(\n ids: Array,\n c: Connection\n ): Int {\n var count = 0\n for (id in ids) {\n if (map.remove(id) != null) {\n count = count + 1\n }\n }\n return count\n }\n\n override fun insert(\n unsaved: CompanyRow,\n c: Connection\n ): CompanyRow {\n if (map.containsKey(unsaved.id)) {\n throw RuntimeException(\"id \" + unsaved.id + \" already exists\")\n }\n map[unsaved.id] = unsaved\n return unsaved\n }\n\n override fun insert(\n unsaved: CompanyRowUnsaved,\n c: Connection\n ): CompanyRow = insert(toRow(unsaved), c)\n\n override fun select(): SelectBuilder = SelectBuilderMock(CompanyFields.structure, { map.values.toList() }, SelectParams.empty())\n\n override fun selectAll(c: Connection): List = map.values.toList()\n\n override fun selectById(\n id: CompanyId,\n c: Connection\n ): CompanyRow? = map[id]\n\n override fun selectByIds(\n ids: Array,\n c: Connection\n ): List {\n val result = ArrayList()\n for (id in ids) {\n val opt = map[id]\n if (opt != null) {\n result.add(opt!!)\n }\n }\n return result\n }\n\n override fun selectByIdsTracked(\n ids: Array,\n c: Connection\n ): Map = selectByIds(ids, c).associateBy({ row: CompanyRow -> row.id })\n\n override fun update(): UpdateBuilder = UpdateBuilderMock(CompanyFields.structure, { map.values.toList() }, UpdateParams.empty(), { row -> row })\n\n override fun update(\n row: CompanyRow,\n c: Connection\n ): Boolean {\n val shouldUpdate = map[row.id]?.takeIf({ oldRow -> (oldRow != row) }) != null\n if (shouldUpdate) {\n map[row.id] = row\n }\n return shouldUpdate\n }\n\n override fun upsert(\n unsaved: CompanyRow,\n c: Connection\n ): CompanyRow {\n map[unsaved.id] = unsaved\n return unsaved\n }\n\n override fun upsertBatch(\n unsaved: Iterator,\n c: Connection\n ): List {\n val result = ArrayList()\n while (unsaved.hasNext()) {\n val row = unsaved.next()\n map[row.id] = row\n result.add(row)\n }\n return result\n }\n}", - "EmployeeRow": "package showcase.showcase.employee\n\nimport dev.typr.foundations.SqlServerTypes\nimport dev.typr.foundations.data.Json\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport dev.typr.foundations.kotlin.nullable\nimport java.math.BigDecimal\nimport java.time.LocalDate\nimport java.time.LocalDateTime\nimport java.time.OffsetDateTime\nimport java.util.UUID\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.department.DepartmentId\n\n/** Table: showcase.employee\n * Primary key: id\n */\ndata class EmployeeRow(\n val id: EmployeeId,\n /** Points to [showcase.showcase.department.DepartmentRow.id] */\n val departmentId: DepartmentId,\n /** Points to [showcase.showcase.employee.EmployeeRow.id] */\n val managerId: EmployeeId?,\n val email: String,\n val firstName: String,\n val lastName: String,\n val salary: BigDecimal?,\n val hiredAt: LocalDate?,\n /** Default: true */\n val active: Boolean?,\n /** Default: CURRENT_TIMESTAMP */\n val createdAt: LocalDateTime?,\n val metadata: Json?,\n val resume: /* XML */ String?,\n val photo: ByteArray?,\n val employeeUid: UUID?,\n val lastModified: OffsetDateTime?,\n val rowVersion: /* ROWVERSION/TIMESTAMP */ ByteArray?,\n val orgPath: /* HIERARCHYID */ String?\n) {\n fun toUnsavedRow(\n active: Defaulted,\n createdAt: Defaulted\n ): EmployeeRowUnsaved = EmployeeRowUnsaved(id, departmentId, managerId, email, firstName, lastName, salary, hiredAt, metadata, resume, photo, employeeUid, lastModified, rowVersion, orgPath, active, createdAt)\n\n companion object {\n val _rowParser: RowParser = RowParsers.of(EmployeeId.sqlServerType, DepartmentId.sqlServerType, EmployeeId.sqlServerType.nullable(), SqlServerTypes.nvarchar, SqlServerTypes.nvarchar, SqlServerTypes.nvarchar, KotlinDbTypes.SqlServerTypes.decimal.nullable(), SqlServerTypes.date.nullable(), KotlinDbTypes.SqlServerTypes.bit.nullable(), SqlServerTypes.datetime2.nullable(), SqlServerTypes.json.nullable(), SqlServerTypes.xml.nullable(), SqlServerTypes.varbinary.nullable(), SqlServerTypes.uniqueidentifier.nullable(), SqlServerTypes.datetimeoffset.nullable(), SqlServerTypes.rowversion.nullable(), SqlServerTypes.hierarchyid.nullable(), { t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16 -> EmployeeRow(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16) }, { row -> arrayOf(row.id, row.departmentId, row.managerId, row.email, row.firstName, row.lastName, row.salary, row.hiredAt, row.active, row.createdAt, row.metadata, row.resume, row.photo, row.employeeUid, row.lastModified, row.rowVersion, row.orgPath) })\n }\n}", - "EmployeeRowUnsaved": "package showcase.showcase.employee\n\nimport dev.typr.foundations.data.Json\nimport java.math.BigDecimal\nimport java.time.LocalDate\nimport java.time.LocalDateTime\nimport java.time.OffsetDateTime\nimport java.util.UUID\nimport showcase.customtypes.Defaulted\nimport showcase.customtypes.Defaulted.UseDefault\nimport showcase.showcase.department.DepartmentId\n\n/** This class corresponds to a row in table `showcase.employee` which has not been persisted yet */\ndata class EmployeeRowUnsaved(\n val id: EmployeeId,\n /** Points to [showcase.showcase.department.DepartmentRow.id] */\n val departmentId: DepartmentId,\n /** Points to [showcase.showcase.employee.EmployeeRow.id] */\n val managerId: EmployeeId? = null,\n val email: String,\n val firstName: String,\n val lastName: String,\n val salary: BigDecimal? = null,\n val hiredAt: LocalDate? = null,\n val metadata: Json? = null,\n val resume: /* XML */ String? = null,\n val photo: ByteArray? = null,\n val employeeUid: UUID? = null,\n val lastModified: OffsetDateTime? = null,\n val rowVersion: /* ROWVERSION/TIMESTAMP */ ByteArray? = null,\n val orgPath: /* HIERARCHYID */ String? = null,\n /** Default: true */\n val active: Defaulted = UseDefault(),\n /** Default: CURRENT_TIMESTAMP */\n val createdAt: Defaulted = UseDefault()\n) {\n fun toRow(\n activeDefault: () -> Boolean?,\n createdAtDefault: () -> LocalDateTime?\n ): EmployeeRow = EmployeeRow(id = id, departmentId = departmentId, managerId = managerId, email = email, firstName = firstName, lastName = lastName, salary = salary, hiredAt = hiredAt, active = active.getOrElse(activeDefault), createdAt = createdAt.getOrElse(createdAtDefault), metadata = metadata, resume = resume, photo = photo, employeeUid = employeeUid, lastModified = lastModified, rowVersion = rowVersion, orgPath = orgPath)\n}", - "EmployeeId": "package showcase.showcase.employee\n\nimport dev.typr.foundations.SqlServerType\nimport dev.typr.foundations.SqlServerTypes\nimport dev.typr.foundations.kotlin.Bijection\n\n/** Type for the primary key of table `showcase.employee` */\ndata class EmployeeId(val value: String) {\n override fun toString(): kotlin.String {\n return value.toString()\n }\n\n companion object {\n val bijection: Bijection =\n Bijection.of(EmployeeId::value, ::EmployeeId)\n\n val sqlServerType: SqlServerType =\n SqlServerTypes.nvarchar.bimap(::EmployeeId, EmployeeId::value)\n }\n}", - "EmployeeRepo": "package showcase.showcase.employee\n\nimport dev.typr.foundations.kotlin.DeleteBuilder\nimport dev.typr.foundations.kotlin.SelectBuilder\nimport dev.typr.foundations.kotlin.UpdateBuilder\nimport java.sql.Connection\nimport kotlin.collections.Iterator\nimport kotlin.collections.List\nimport kotlin.collections.Map\n\ninterface EmployeeRepo {\n abstract fun delete(): DeleteBuilder\n\n abstract fun deleteById(\n id: EmployeeId,\n c: Connection\n ): Boolean\n\n abstract fun deleteByIds(\n ids: Array,\n c: Connection\n ): Int\n\n abstract fun insert(\n unsaved: EmployeeRow,\n c: Connection\n ): EmployeeRow\n\n abstract fun insert(\n unsaved: EmployeeRowUnsaved,\n c: Connection\n ): EmployeeRow\n\n abstract fun select(): SelectBuilder\n\n abstract fun selectAll(c: Connection): List\n\n abstract fun selectById(\n id: EmployeeId,\n c: Connection\n ): EmployeeRow?\n\n abstract fun selectByIds(\n ids: Array,\n c: Connection\n ): List\n\n abstract fun selectByIdsTracked(\n ids: Array,\n c: Connection\n ): Map\n\n abstract fun selectByUniqueEmail(\n email: String,\n c: Connection\n ): EmployeeRow?\n\n abstract fun update(): UpdateBuilder\n\n abstract fun update(\n row: EmployeeRow,\n c: Connection\n ): Boolean\n\n abstract fun upsert(\n unsaved: EmployeeRow,\n c: Connection\n ): EmployeeRow\n\n abstract fun upsertBatch(\n unsaved: Iterator,\n c: Connection\n ): List\n}", - "EmployeeRepoImpl": "package showcase.showcase.employee\n\nimport dev.typr.foundations.SqlServerTypes\nimport dev.typr.foundations.kotlin.DeleteBuilder\nimport dev.typr.foundations.kotlin.Dialect\nimport dev.typr.foundations.kotlin.Fragment\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.SelectBuilder\nimport dev.typr.foundations.kotlin.UpdateBuilder\nimport dev.typr.foundations.kotlin.nullable\nimport java.sql.Connection\nimport java.util.ArrayList\nimport kotlin.collections.Iterator\nimport kotlin.collections.List\nimport kotlin.collections.Map\nimport kotlin.collections.MutableMap\nimport showcase.showcase.department.DepartmentId\n\nclass EmployeeRepoImpl() : EmployeeRepo {\n override fun delete(): DeleteBuilder = DeleteBuilder.of(\"[showcase].[employee]\", EmployeeFields.structure, Dialect.SQLSERVER)\n\n override fun deleteById(\n id: EmployeeId,\n c: Connection\n ): Boolean = Fragment.interpolate(Fragment.lit(\"delete from [showcase].[employee] where [id] = \"), Fragment.encode(EmployeeId.sqlServerType, id), Fragment.lit(\"\")).update().runUnchecked(c) > 0\n\n override fun deleteByIds(\n ids: Array,\n c: Connection\n ): Int {\n val fragments: ArrayList = ArrayList()\n for (id in ids) { fragments.add(Fragment.encode(EmployeeId.sqlServerType, id)) }\n return Fragment.interpolate(Fragment.lit(\"delete from [showcase].[employee] where [id] in (\"), Fragment.comma(fragments.toMutableList()), Fragment.lit(\")\")).update().runUnchecked(c)\n }\n\n override fun insert(\n unsaved: EmployeeRow,\n c: Connection\n ): EmployeeRow = Fragment.interpolate(Fragment.lit(\"insert into [showcase].[employee]([id], [department_id], [manager_id], [email], [first_name], [last_name], [salary], [hired_at], [active], [created_at], [metadata], [resume], [photo], [employee_uid], [last_modified], [row_version], [org_path])\\nOUTPUT INSERTED.[id], INSERTED.[department_id], INSERTED.[manager_id], INSERTED.[email], INSERTED.[first_name], INSERTED.[last_name], INSERTED.[salary], INSERTED.[hired_at], INSERTED.[active], INSERTED.[created_at], INSERTED.[metadata], INSERTED.[resume], INSERTED.[photo], INSERTED.[employee_uid], INSERTED.[last_modified], INSERTED.[row_version], INSERTED.[org_path]\\nvalues (\"), Fragment.encode(EmployeeId.sqlServerType, unsaved.id), Fragment.lit(\", \"), Fragment.encode(DepartmentId.sqlServerType, unsaved.departmentId), Fragment.lit(\", \"), Fragment.encode(EmployeeId.sqlServerType.nullable(), unsaved.managerId), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.nvarchar, unsaved.email), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.nvarchar, unsaved.firstName), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.nvarchar, unsaved.lastName), Fragment.lit(\", \"), Fragment.encode(KotlinDbTypes.SqlServerTypes.decimal.nullable(), unsaved.salary), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.date.nullable(), unsaved.hiredAt), Fragment.lit(\", \"), Fragment.encode(KotlinDbTypes.SqlServerTypes.bit.nullable(), unsaved.active), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.datetime2.nullable(), unsaved.createdAt), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.json.nullable(), unsaved.metadata), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.xml.nullable(), unsaved.resume), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.varbinary.nullable(), unsaved.photo), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.uniqueidentifier.nullable(), unsaved.employeeUid), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.datetimeoffset.nullable(), unsaved.lastModified), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.rowversion.nullable(), unsaved.rowVersion), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.hierarchyid.nullable(), unsaved.orgPath), Fragment.lit(\")\\n\"))\n .updateReturning(EmployeeRow._rowParser.exactlyOne()).runUnchecked(c)\n\n override fun insert(\n unsaved: EmployeeRowUnsaved,\n c: Connection\n ): EmployeeRow {\n val columns: ArrayList = ArrayList()\n val values: ArrayList = ArrayList()\n columns.add(Fragment.lit(\"[id]\"))\n values.add(Fragment.interpolate(Fragment.encode(EmployeeId.sqlServerType, unsaved.id), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"[department_id]\"))\n values.add(Fragment.interpolate(Fragment.encode(DepartmentId.sqlServerType, unsaved.departmentId), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"[manager_id]\"))\n values.add(Fragment.interpolate(Fragment.encode(EmployeeId.sqlServerType.nullable(), unsaved.managerId), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"[email]\"))\n values.add(Fragment.interpolate(Fragment.encode(SqlServerTypes.nvarchar, unsaved.email), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"[first_name]\"))\n values.add(Fragment.interpolate(Fragment.encode(SqlServerTypes.nvarchar, unsaved.firstName), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"[last_name]\"))\n values.add(Fragment.interpolate(Fragment.encode(SqlServerTypes.nvarchar, unsaved.lastName), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"[salary]\"))\n values.add(Fragment.interpolate(Fragment.encode(KotlinDbTypes.SqlServerTypes.decimal.nullable(), unsaved.salary), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"[hired_at]\"))\n values.add(Fragment.interpolate(Fragment.encode(SqlServerTypes.date.nullable(), unsaved.hiredAt), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"[metadata]\"))\n values.add(Fragment.interpolate(Fragment.encode(SqlServerTypes.json.nullable(), unsaved.metadata), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"[resume]\"))\n values.add(Fragment.interpolate(Fragment.encode(SqlServerTypes.xml.nullable(), unsaved.resume), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"[photo]\"))\n values.add(Fragment.interpolate(Fragment.encode(SqlServerTypes.varbinary.nullable(), unsaved.photo), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"[employee_uid]\"))\n values.add(Fragment.interpolate(Fragment.encode(SqlServerTypes.uniqueidentifier.nullable(), unsaved.employeeUid), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"[last_modified]\"))\n values.add(Fragment.interpolate(Fragment.encode(SqlServerTypes.datetimeoffset.nullable(), unsaved.lastModified), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"[row_version]\"))\n values.add(Fragment.interpolate(Fragment.encode(SqlServerTypes.rowversion.nullable(), unsaved.rowVersion), Fragment.lit(\"\")))\n columns.add(Fragment.lit(\"[org_path]\"))\n values.add(Fragment.interpolate(Fragment.encode(SqlServerTypes.hierarchyid.nullable(), unsaved.orgPath), Fragment.lit(\"\")))\n unsaved.active.visit(\n { },\n { value -> columns.add(Fragment.lit(\"[active]\"))\n values.add(Fragment.interpolate(Fragment.encode(KotlinDbTypes.SqlServerTypes.bit.nullable(), value), Fragment.lit(\"\"))) }\n );\n unsaved.createdAt.visit(\n { },\n { value -> columns.add(Fragment.lit(\"[created_at]\"))\n values.add(Fragment.interpolate(Fragment.encode(SqlServerTypes.datetime2.nullable(), value), Fragment.lit(\"\"))) }\n );\n val q: Fragment = Fragment.interpolate(Fragment.lit(\"insert into [showcase].[employee](\"), Fragment.comma(columns.toMutableList()), Fragment.lit(\")\\nOUTPUT INSERTED.[id], INSERTED.[department_id], INSERTED.[manager_id], INSERTED.[email], INSERTED.[first_name], INSERTED.[last_name], INSERTED.[salary], INSERTED.[hired_at], INSERTED.[active], INSERTED.[created_at], INSERTED.[metadata], INSERTED.[resume], INSERTED.[photo], INSERTED.[employee_uid], INSERTED.[last_modified], INSERTED.[row_version], INSERTED.[org_path]\\nvalues (\"), Fragment.comma(values.toMutableList()), Fragment.lit(\")\\n\"))\n return q.updateReturning(EmployeeRow._rowParser.exactlyOne()).runUnchecked(c)\n }\n\n override fun select(): SelectBuilder = SelectBuilder.of(\"[showcase].[employee]\", EmployeeFields.structure, EmployeeRow._rowParser, Dialect.SQLSERVER)\n\n override fun selectAll(c: Connection): List = Fragment.interpolate(Fragment.lit(\"select [id], [department_id], [manager_id], [email], [first_name], [last_name], [salary], [hired_at], [active], [created_at], [metadata], [resume], [photo], [employee_uid], [last_modified], [row_version], [org_path]\\nfrom [showcase].[employee]\\n\")).query(EmployeeRow._rowParser.all()).runUnchecked(c)\n\n override fun selectById(\n id: EmployeeId,\n c: Connection\n ): EmployeeRow? = Fragment.interpolate(Fragment.lit(\"select [id], [department_id], [manager_id], [email], [first_name], [last_name], [salary], [hired_at], [active], [created_at], [metadata], [resume], [photo], [employee_uid], [last_modified], [row_version], [org_path]\\nfrom [showcase].[employee]\\nwhere [id] = \"), Fragment.encode(EmployeeId.sqlServerType, id), Fragment.lit(\"\")).query(EmployeeRow._rowParser.first()).runUnchecked(c)\n\n override fun selectByIds(\n ids: Array,\n c: Connection\n ): List {\n val fragments: ArrayList = ArrayList()\n for (id in ids) { fragments.add(Fragment.encode(EmployeeId.sqlServerType, id)) }\n return Fragment.interpolate(Fragment.lit(\"select [id], [department_id], [manager_id], [email], [first_name], [last_name], [salary], [hired_at], [active], [created_at], [metadata], [resume], [photo], [employee_uid], [last_modified], [row_version], [org_path] from [showcase].[employee] where [id] in (\"), Fragment.comma(fragments.toMutableList()), Fragment.lit(\")\")).query(EmployeeRow._rowParser.all()).runUnchecked(c)\n }\n\n override fun selectByIdsTracked(\n ids: Array,\n c: Connection\n ): Map {\n val ret: MutableMap = mutableMapOf()\n selectByIds(ids, c).forEach({ row -> ret.put(row.id, row) })\n return ret.toMap()\n }\n\n override fun selectByUniqueEmail(\n email: String,\n c: Connection\n ): EmployeeRow? = Fragment.interpolate(Fragment.lit(\"select [id], [department_id], [manager_id], [email], [first_name], [last_name], [salary], [hired_at], [active], [created_at], [metadata], [resume], [photo], [employee_uid], [last_modified], [row_version], [org_path]\\nfrom [showcase].[employee]\\nwhere [email] = \"), Fragment.encode(SqlServerTypes.nvarchar, email), Fragment.lit(\"\\n\")).query(EmployeeRow._rowParser.first()).runUnchecked(c)\n\n override fun update(): UpdateBuilder = UpdateBuilder.of(\"[showcase].[employee]\", EmployeeFields.structure, EmployeeRow._rowParser, Dialect.SQLSERVER)\n\n override fun update(\n row: EmployeeRow,\n c: Connection\n ): Boolean {\n val id: EmployeeId = row.id\n return Fragment.interpolate(Fragment.lit(\"update [showcase].[employee]\\nset [department_id] = \"), Fragment.encode(DepartmentId.sqlServerType, row.departmentId), Fragment.lit(\",\\n[manager_id] = \"), Fragment.encode(EmployeeId.sqlServerType.nullable(), row.managerId), Fragment.lit(\",\\n[email] = \"), Fragment.encode(SqlServerTypes.nvarchar, row.email), Fragment.lit(\",\\n[first_name] = \"), Fragment.encode(SqlServerTypes.nvarchar, row.firstName), Fragment.lit(\",\\n[last_name] = \"), Fragment.encode(SqlServerTypes.nvarchar, row.lastName), Fragment.lit(\",\\n[salary] = \"), Fragment.encode(KotlinDbTypes.SqlServerTypes.decimal.nullable(), row.salary), Fragment.lit(\",\\n[hired_at] = \"), Fragment.encode(SqlServerTypes.date.nullable(), row.hiredAt), Fragment.lit(\",\\n[active] = \"), Fragment.encode(KotlinDbTypes.SqlServerTypes.bit.nullable(), row.active), Fragment.lit(\",\\n[created_at] = \"), Fragment.encode(SqlServerTypes.datetime2.nullable(), row.createdAt), Fragment.lit(\",\\n[metadata] = \"), Fragment.encode(SqlServerTypes.json.nullable(), row.metadata), Fragment.lit(\",\\n[resume] = \"), Fragment.encode(SqlServerTypes.xml.nullable(), row.resume), Fragment.lit(\",\\n[photo] = \"), Fragment.encode(SqlServerTypes.varbinary.nullable(), row.photo), Fragment.lit(\",\\n[employee_uid] = \"), Fragment.encode(SqlServerTypes.uniqueidentifier.nullable(), row.employeeUid), Fragment.lit(\",\\n[last_modified] = \"), Fragment.encode(SqlServerTypes.datetimeoffset.nullable(), row.lastModified), Fragment.lit(\",\\n[row_version] = \"), Fragment.encode(SqlServerTypes.rowversion.nullable(), row.rowVersion), Fragment.lit(\",\\n[org_path] = \"), Fragment.encode(SqlServerTypes.hierarchyid.nullable(), row.orgPath), Fragment.lit(\"\\nwhere [id] = \"), Fragment.encode(EmployeeId.sqlServerType, id), Fragment.lit(\"\")).update().runUnchecked(c) > 0\n }\n\n override fun upsert(\n unsaved: EmployeeRow,\n c: Connection\n ): EmployeeRow = Fragment.interpolate(Fragment.lit(\"MERGE INTO [showcase].[employee] AS target\\nUSING (VALUES (\"), Fragment.encode(EmployeeId.sqlServerType, unsaved.id), Fragment.lit(\", \"), Fragment.encode(DepartmentId.sqlServerType, unsaved.departmentId), Fragment.lit(\", \"), Fragment.encode(EmployeeId.sqlServerType.nullable(), unsaved.managerId), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.nvarchar, unsaved.email), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.nvarchar, unsaved.firstName), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.nvarchar, unsaved.lastName), Fragment.lit(\", \"), Fragment.encode(KotlinDbTypes.SqlServerTypes.decimal.nullable(), unsaved.salary), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.date.nullable(), unsaved.hiredAt), Fragment.lit(\", \"), Fragment.encode(KotlinDbTypes.SqlServerTypes.bit.nullable(), unsaved.active), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.datetime2.nullable(), unsaved.createdAt), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.json.nullable(), unsaved.metadata), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.xml.nullable(), unsaved.resume), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.varbinary.nullable(), unsaved.photo), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.uniqueidentifier.nullable(), unsaved.employeeUid), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.datetimeoffset.nullable(), unsaved.lastModified), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.rowversion.nullable(), unsaved.rowVersion), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.hierarchyid.nullable(), unsaved.orgPath), Fragment.lit(\")) AS source([id], [department_id], [manager_id], [email], [first_name], [last_name], [salary], [hired_at], [active], [created_at], [metadata], [resume], [photo], [employee_uid], [last_modified], [row_version], [org_path])\\nON target.[id] = source.[id]\\nWHEN MATCHED THEN UPDATE SET [department_id] = source.[department_id],\\n[manager_id] = source.[manager_id],\\n[email] = source.[email],\\n[first_name] = source.[first_name],\\n[last_name] = source.[last_name],\\n[salary] = source.[salary],\\n[hired_at] = source.[hired_at],\\n[active] = source.[active],\\n[created_at] = source.[created_at],\\n[metadata] = source.[metadata],\\n[resume] = source.[resume],\\n[photo] = source.[photo],\\n[employee_uid] = source.[employee_uid],\\n[last_modified] = source.[last_modified],\\n[row_version] = source.[row_version],\\n[org_path] = source.[org_path]\\nWHEN NOT MATCHED THEN INSERT ([id], [department_id], [manager_id], [email], [first_name], [last_name], [salary], [hired_at], [active], [created_at], [metadata], [resume], [photo], [employee_uid], [last_modified], [row_version], [org_path]) VALUES (\"), Fragment.encode(EmployeeId.sqlServerType, unsaved.id), Fragment.lit(\", \"), Fragment.encode(DepartmentId.sqlServerType, unsaved.departmentId), Fragment.lit(\", \"), Fragment.encode(EmployeeId.sqlServerType.nullable(), unsaved.managerId), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.nvarchar, unsaved.email), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.nvarchar, unsaved.firstName), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.nvarchar, unsaved.lastName), Fragment.lit(\", \"), Fragment.encode(KotlinDbTypes.SqlServerTypes.decimal.nullable(), unsaved.salary), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.date.nullable(), unsaved.hiredAt), Fragment.lit(\", \"), Fragment.encode(KotlinDbTypes.SqlServerTypes.bit.nullable(), unsaved.active), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.datetime2.nullable(), unsaved.createdAt), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.json.nullable(), unsaved.metadata), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.xml.nullable(), unsaved.resume), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.varbinary.nullable(), unsaved.photo), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.uniqueidentifier.nullable(), unsaved.employeeUid), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.datetimeoffset.nullable(), unsaved.lastModified), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.rowversion.nullable(), unsaved.rowVersion), Fragment.lit(\", \"), Fragment.encode(SqlServerTypes.hierarchyid.nullable(), unsaved.orgPath), Fragment.lit(\")\\nOUTPUT INSERTED.[id], INSERTED.[department_id], INSERTED.[manager_id], INSERTED.[email], INSERTED.[first_name], INSERTED.[last_name], INSERTED.[salary], INSERTED.[hired_at], INSERTED.[active], INSERTED.[created_at], INSERTED.[metadata], INSERTED.[resume], INSERTED.[photo], INSERTED.[employee_uid], INSERTED.[last_modified], INSERTED.[row_version], INSERTED.[org_path];\"))\n .updateReturning(EmployeeRow._rowParser.exactlyOne())\n .runUnchecked(c)\n\n override fun upsertBatch(\n unsaved: Iterator,\n c: Connection\n ): List = Fragment.interpolate(Fragment.lit(\"MERGE INTO [showcase].[employee] AS target\\nUSING (VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)) AS source([id], [department_id], [manager_id], [email], [first_name], [last_name], [salary], [hired_at], [active], [created_at], [metadata], [resume], [photo], [employee_uid], [last_modified], [row_version], [org_path])\\nON target.[id] = source.[id]\\nWHEN MATCHED THEN UPDATE SET [department_id] = source.[department_id],\\n[manager_id] = source.[manager_id],\\n[email] = source.[email],\\n[first_name] = source.[first_name],\\n[last_name] = source.[last_name],\\n[salary] = source.[salary],\\n[hired_at] = source.[hired_at],\\n[active] = source.[active],\\n[created_at] = source.[created_at],\\n[metadata] = source.[metadata],\\n[resume] = source.[resume],\\n[photo] = source.[photo],\\n[employee_uid] = source.[employee_uid],\\n[last_modified] = source.[last_modified],\\n[row_version] = source.[row_version],\\n[org_path] = source.[org_path]\\nWHEN NOT MATCHED THEN INSERT ([id], [department_id], [manager_id], [email], [first_name], [last_name], [salary], [hired_at], [active], [created_at], [metadata], [resume], [photo], [employee_uid], [last_modified], [row_version], [org_path]) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\\nOUTPUT INSERTED.[id], INSERTED.[department_id], INSERTED.[manager_id], INSERTED.[email], INSERTED.[first_name], INSERTED.[last_name], INSERTED.[salary], INSERTED.[hired_at], INSERTED.[active], INSERTED.[created_at], INSERTED.[metadata], INSERTED.[resume], INSERTED.[photo], INSERTED.[employee_uid], INSERTED.[last_modified], INSERTED.[row_version], INSERTED.[org_path];\"))\n .updateReturningEach(EmployeeRow._rowParser, unsaved)\n .runUnchecked(c)\n}", - "EmployeeRepoMock": "package showcase.showcase.employee\n\nimport dev.typr.foundations.kotlin.DeleteBuilder\nimport dev.typr.foundations.kotlin.DeleteBuilderMock\nimport dev.typr.foundations.kotlin.DeleteParams\nimport dev.typr.foundations.kotlin.SelectBuilder\nimport dev.typr.foundations.kotlin.SelectBuilderMock\nimport dev.typr.foundations.kotlin.SelectParams\nimport dev.typr.foundations.kotlin.UpdateBuilder\nimport dev.typr.foundations.kotlin.UpdateBuilderMock\nimport dev.typr.foundations.kotlin.UpdateParams\nimport java.lang.RuntimeException\nimport java.sql.Connection\nimport java.util.ArrayList\nimport kotlin.collections.Iterator\nimport kotlin.collections.List\nimport kotlin.collections.Map\nimport kotlin.collections.MutableMap\n\ndata class EmployeeRepoMock(\n val toRow: (EmployeeRowUnsaved) -> EmployeeRow,\n val map: MutableMap = mutableMapOf()\n) : EmployeeRepo {\n override fun delete(): DeleteBuilder = DeleteBuilderMock(EmployeeFields.structure, { map.values.toList() }, DeleteParams.empty(), { row -> row.id }, { id -> map.remove(id) })\n\n override fun deleteById(\n id: EmployeeId,\n c: Connection\n ): Boolean = map.remove(id) != null\n\n override fun deleteByIds(\n ids: Array,\n c: Connection\n ): Int {\n var count = 0\n for (id in ids) {\n if (map.remove(id) != null) {\n count = count + 1\n }\n }\n return count\n }\n\n override fun insert(\n unsaved: EmployeeRow,\n c: Connection\n ): EmployeeRow {\n if (map.containsKey(unsaved.id)) {\n throw RuntimeException(\"id \" + unsaved.id + \" already exists\")\n }\n map[unsaved.id] = unsaved\n return unsaved\n }\n\n override fun insert(\n unsaved: EmployeeRowUnsaved,\n c: Connection\n ): EmployeeRow = insert(toRow(unsaved), c)\n\n override fun select(): SelectBuilder = SelectBuilderMock(EmployeeFields.structure, { map.values.toList() }, SelectParams.empty())\n\n override fun selectAll(c: Connection): List = map.values.toList()\n\n override fun selectById(\n id: EmployeeId,\n c: Connection\n ): EmployeeRow? = map[id]\n\n override fun selectByIds(\n ids: Array,\n c: Connection\n ): List {\n val result = ArrayList()\n for (id in ids) {\n val opt = map[id]\n if (opt != null) {\n result.add(opt!!)\n }\n }\n return result\n }\n\n override fun selectByIdsTracked(\n ids: Array,\n c: Connection\n ): Map = selectByIds(ids, c).associateBy({ row: EmployeeRow -> row.id })\n\n override fun selectByUniqueEmail(\n email: String,\n c: Connection\n ): EmployeeRow? = map.values.toList().find({ v -> (email == v.email) })\n\n override fun update(): UpdateBuilder = UpdateBuilderMock(EmployeeFields.structure, { map.values.toList() }, UpdateParams.empty(), { row -> row })\n\n override fun update(\n row: EmployeeRow,\n c: Connection\n ): Boolean {\n val shouldUpdate = map[row.id]?.takeIf({ oldRow -> (oldRow != row) }) != null\n if (shouldUpdate) {\n map[row.id] = row\n }\n return shouldUpdate\n }\n\n override fun upsert(\n unsaved: EmployeeRow,\n c: Connection\n ): EmployeeRow {\n map[unsaved.id] = unsaved\n return unsaved\n }\n\n override fun upsertBatch(\n unsaved: Iterator,\n c: Connection\n ): List {\n val result = ArrayList()\n while (unsaved.hasNext()) {\n val row = unsaved.next()\n map[row.id] = row\n result.add(row)\n }\n return result\n }\n}", - "EmployeeFields": "package showcase.showcase.employee\n\nimport dev.typr.foundations.RowParser\nimport dev.typr.foundations.SqlServerTypes\nimport dev.typr.foundations.data.Json\nimport dev.typr.foundations.dsl.FieldsExpr\nimport dev.typr.foundations.dsl.Path\nimport dev.typr.foundations.dsl.SqlExpr.FieldLike\nimport dev.typr.foundations.kotlin.ForeignKey\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.RelationStructure\nimport dev.typr.foundations.kotlin.SqlExpr.Field\nimport dev.typr.foundations.kotlin.SqlExpr.IdField\nimport dev.typr.foundations.kotlin.SqlExpr.OptField\nimport java.math.BigDecimal\nimport java.time.LocalDate\nimport java.time.LocalDateTime\nimport java.time.OffsetDateTime\nimport java.util.UUID\nimport kotlin.collections.List\nimport showcase.showcase.department.DepartmentFields\nimport showcase.showcase.department.DepartmentId\nimport showcase.showcase.department.DepartmentRow\n\ninterface EmployeeFields : FieldsExpr {\n abstract fun active(): OptField\n\n abstract override fun columns(): List>\n\n abstract fun createdAt(): OptField\n\n abstract fun departmentId(): Field\n\n abstract fun email(): Field\n\n abstract fun employeeUid(): OptField\n\n abstract fun firstName(): Field\n\n fun fkDepartment(): ForeignKey = ForeignKey.of(\"employee_department_fk\").withColumnPair(departmentId(), DepartmentFields::id)\n\n fun fkEmployee(): ForeignKey = ForeignKey.of(\"employee_manager_fk\").withColumnPair(managerId(), EmployeeFields::id)\n\n abstract fun hiredAt(): OptField\n\n abstract fun id(): IdField\n\n abstract fun lastModified(): OptField\n\n abstract fun lastName(): Field\n\n abstract fun managerId(): OptField\n\n abstract fun metadata(): OptField\n\n abstract fun orgPath(): OptField\n\n abstract fun photo(): OptField\n\n abstract fun resume(): OptField\n\n override fun rowParser(): RowParser = EmployeeRow._rowParser.underlying\n\n abstract fun rowVersion(): OptField\n\n abstract fun salary(): OptField\n\n companion object {\n data class Impl(val _path: List) : EmployeeFields, RelationStructure {\n override fun id(): IdField = IdField(_path, \"id\", EmployeeRow::id, null, null, { row, value -> row.copy(id = value) }, EmployeeId.sqlServerType)\n\n override fun departmentId(): Field = Field(_path, \"department_id\", EmployeeRow::departmentId, null, null, { row, value -> row.copy(departmentId = value) }, DepartmentId.sqlServerType)\n\n override fun managerId(): OptField = OptField(_path, \"manager_id\", EmployeeRow::managerId, null, null, { row, value -> row.copy(managerId = value) }, EmployeeId.sqlServerType)\n\n override fun email(): Field = Field(_path, \"email\", EmployeeRow::email, null, null, { row, value -> row.copy(email = value) }, SqlServerTypes.nvarchar)\n\n override fun firstName(): Field = Field(_path, \"first_name\", EmployeeRow::firstName, null, null, { row, value -> row.copy(firstName = value) }, SqlServerTypes.nvarchar)\n\n override fun lastName(): Field = Field(_path, \"last_name\", EmployeeRow::lastName, null, null, { row, value -> row.copy(lastName = value) }, SqlServerTypes.nvarchar)\n\n override fun salary(): OptField = OptField(_path, \"salary\", EmployeeRow::salary, null, null, { row, value -> row.copy(salary = value) }, KotlinDbTypes.SqlServerTypes.decimal)\n\n override fun hiredAt(): OptField = OptField(_path, \"hired_at\", EmployeeRow::hiredAt, null, null, { row, value -> row.copy(hiredAt = value) }, SqlServerTypes.date)\n\n override fun active(): OptField = OptField(_path, \"active\", EmployeeRow::active, null, null, { row, value -> row.copy(active = value) }, KotlinDbTypes.SqlServerTypes.bit)\n\n override fun createdAt(): OptField = OptField(_path, \"created_at\", EmployeeRow::createdAt, null, null, { row, value -> row.copy(createdAt = value) }, SqlServerTypes.datetime2)\n\n override fun metadata(): OptField = OptField(_path, \"metadata\", EmployeeRow::metadata, null, null, { row, value -> row.copy(metadata = value) }, SqlServerTypes.json)\n\n override fun resume(): OptField = OptField(_path, \"resume\", EmployeeRow::resume, null, null, { row, value -> row.copy(resume = value) }, SqlServerTypes.xml)\n\n override fun photo(): OptField = OptField(_path, \"photo\", EmployeeRow::photo, null, null, { row, value -> row.copy(photo = value) }, SqlServerTypes.varbinary)\n\n override fun employeeUid(): OptField = OptField(_path, \"employee_uid\", EmployeeRow::employeeUid, null, null, { row, value -> row.copy(employeeUid = value) }, SqlServerTypes.uniqueidentifier)\n\n override fun lastModified(): OptField = OptField(_path, \"last_modified\", EmployeeRow::lastModified, null, null, { row, value -> row.copy(lastModified = value) }, SqlServerTypes.datetimeoffset)\n\n override fun rowVersion(): OptField = OptField(_path, \"row_version\", EmployeeRow::rowVersion, null, null, { row, value -> row.copy(rowVersion = value) }, SqlServerTypes.rowversion)\n\n override fun orgPath(): OptField = OptField(_path, \"org_path\", EmployeeRow::orgPath, null, null, { row, value -> row.copy(orgPath = value) }, SqlServerTypes.hierarchyid)\n\n override fun _path(): List = _path\n\n override fun columns(): List> = listOf(this.id().underlying, this.departmentId().underlying, this.managerId().underlying, this.email().underlying, this.firstName().underlying, this.lastName().underlying, this.salary().underlying, this.hiredAt().underlying, this.active().underlying, this.createdAt().underlying, this.metadata().underlying, this.resume().underlying, this.photo().underlying, this.employeeUid().underlying, this.lastModified().underlying, this.rowVersion().underlying, this.orgPath().underlying)\n\n override fun withPaths(_path: List): RelationStructure = Impl(_path)\n }\n\n val structure: Impl = Impl(emptyList())\n }\n}", - "DepartmentRow": "package showcase.showcase.department\n\nimport dev.typr.foundations.SqlServerTypes\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport dev.typr.foundations.kotlin.nullable\nimport java.math.BigDecimal\nimport showcase.showcase.company.CompanyId\n\n/** Table: showcase.department\n * Primary key: id\n */\ndata class DepartmentRow(\n val id: DepartmentId,\n /** Points to [showcase.showcase.company.CompanyRow.id] */\n val companyId: CompanyId,\n val name: String,\n val budget: BigDecimal?\n) {\n companion object {\n val _rowParser: RowParser = RowParsers.of(DepartmentId.sqlServerType, CompanyId.sqlServerType, SqlServerTypes.nvarchar, KotlinDbTypes.SqlServerTypes.decimal.nullable(), { t0, t1, t2, t3 -> DepartmentRow(t0, t1, t2, t3) }, { row -> arrayOf(row.id, row.companyId, row.name, row.budget) })\n }\n}", - "DepartmentId": "package showcase.showcase.department\n\nimport dev.typr.foundations.SqlServerType\nimport dev.typr.foundations.SqlServerTypes\nimport dev.typr.foundations.kotlin.Bijection\n\n/** Type for the primary key of table `showcase.department` */\ndata class DepartmentId(val value: String) {\n override fun toString(): kotlin.String {\n return value.toString()\n }\n\n companion object {\n val bijection: Bijection =\n Bijection.of(DepartmentId::value, ::DepartmentId)\n\n val sqlServerType: SqlServerType =\n SqlServerTypes.nvarchar.bimap(::DepartmentId, DepartmentId::value)\n }\n}", - "DepartmentRepo": "package showcase.showcase.department\n\nimport dev.typr.foundations.kotlin.DeleteBuilder\nimport dev.typr.foundations.kotlin.SelectBuilder\nimport dev.typr.foundations.kotlin.UpdateBuilder\nimport java.sql.Connection\nimport kotlin.collections.Iterator\nimport kotlin.collections.List\nimport kotlin.collections.Map\n\ninterface DepartmentRepo {\n abstract fun delete(): DeleteBuilder\n\n abstract fun deleteById(\n id: DepartmentId,\n c: Connection\n ): Boolean\n\n abstract fun deleteByIds(\n ids: Array,\n c: Connection\n ): Int\n\n abstract fun insert(\n unsaved: DepartmentRow,\n c: Connection\n ): DepartmentRow\n\n abstract fun select(): SelectBuilder\n\n abstract fun selectAll(c: Connection): List\n\n abstract fun selectById(\n id: DepartmentId,\n c: Connection\n ): DepartmentRow?\n\n abstract fun selectByIds(\n ids: Array,\n c: Connection\n ): List\n\n abstract fun selectByIdsTracked(\n ids: Array,\n c: Connection\n ): Map\n\n abstract fun update(): UpdateBuilder\n\n abstract fun update(\n row: DepartmentRow,\n c: Connection\n ): Boolean\n\n abstract fun upsert(\n unsaved: DepartmentRow,\n c: Connection\n ): DepartmentRow\n\n abstract fun upsertBatch(\n unsaved: Iterator,\n c: Connection\n ): List\n}", - "DepartmentRepoMock": "package showcase.showcase.department\n\nimport dev.typr.foundations.kotlin.DeleteBuilder\nimport dev.typr.foundations.kotlin.DeleteBuilderMock\nimport dev.typr.foundations.kotlin.DeleteParams\nimport dev.typr.foundations.kotlin.SelectBuilder\nimport dev.typr.foundations.kotlin.SelectBuilderMock\nimport dev.typr.foundations.kotlin.SelectParams\nimport dev.typr.foundations.kotlin.UpdateBuilder\nimport dev.typr.foundations.kotlin.UpdateBuilderMock\nimport dev.typr.foundations.kotlin.UpdateParams\nimport java.lang.RuntimeException\nimport java.sql.Connection\nimport java.util.ArrayList\nimport kotlin.collections.Iterator\nimport kotlin.collections.List\nimport kotlin.collections.Map\nimport kotlin.collections.MutableMap\n\ndata class DepartmentRepoMock(val map: MutableMap = mutableMapOf()) : DepartmentRepo {\n override fun delete(): DeleteBuilder = DeleteBuilderMock(DepartmentFields.structure, { map.values.toList() }, DeleteParams.empty(), { row -> row.id }, { id -> map.remove(id) })\n\n override fun deleteById(\n id: DepartmentId,\n c: Connection\n ): Boolean = map.remove(id) != null\n\n override fun deleteByIds(\n ids: Array,\n c: Connection\n ): Int {\n var count = 0\n for (id in ids) {\n if (map.remove(id) != null) {\n count = count + 1\n }\n }\n return count\n }\n\n override fun insert(\n unsaved: DepartmentRow,\n c: Connection\n ): DepartmentRow {\n if (map.containsKey(unsaved.id)) {\n throw RuntimeException(\"id \" + unsaved.id + \" already exists\")\n }\n map[unsaved.id] = unsaved\n return unsaved\n }\n\n override fun select(): SelectBuilder = SelectBuilderMock(DepartmentFields.structure, { map.values.toList() }, SelectParams.empty())\n\n override fun selectAll(c: Connection): List = map.values.toList()\n\n override fun selectById(\n id: DepartmentId,\n c: Connection\n ): DepartmentRow? = map[id]\n\n override fun selectByIds(\n ids: Array,\n c: Connection\n ): List {\n val result = ArrayList()\n for (id in ids) {\n val opt = map[id]\n if (opt != null) {\n result.add(opt!!)\n }\n }\n return result\n }\n\n override fun selectByIdsTracked(\n ids: Array,\n c: Connection\n ): Map = selectByIds(ids, c).associateBy({ row: DepartmentRow -> row.id })\n\n override fun update(): UpdateBuilder = UpdateBuilderMock(DepartmentFields.structure, { map.values.toList() }, UpdateParams.empty(), { row -> row })\n\n override fun update(\n row: DepartmentRow,\n c: Connection\n ): Boolean {\n val shouldUpdate = map[row.id]?.takeIf({ oldRow -> (oldRow != row) }) != null\n if (shouldUpdate) {\n map[row.id] = row\n }\n return shouldUpdate\n }\n\n override fun upsert(\n unsaved: DepartmentRow,\n c: Connection\n ): DepartmentRow {\n map[unsaved.id] = unsaved\n return unsaved\n }\n\n override fun upsertBatch(\n unsaved: Iterator,\n c: Connection\n ): List {\n val result = ArrayList()\n while (unsaved.hasNext()) {\n val row = unsaved.next()\n map[row.id] = row\n result.add(row)\n }\n return result\n }\n}", - "ProjectAssignmentRow": "package showcase.showcase.project_assignment\n\nimport dev.typr.foundations.SqlServerTypes\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport dev.typr.foundations.kotlin.nullable\nimport java.time.LocalDate\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.employee.EmployeeId\nimport showcase.showcase.project.ProjectId\n\n/** Table: showcase.project_assignment\n * Composite primary key: employee_id, project_id\n */\ndata class ProjectAssignmentRow(\n /** Points to [showcase.showcase.employee.EmployeeRow.id] */\n val employeeId: EmployeeId,\n /** Points to [showcase.showcase.project.ProjectRow.id] */\n val projectId: ProjectId,\n val role: String,\n /** Default: 0 */\n val hoursAllocated: Int?,\n val startDate: LocalDate?,\n val endDate: LocalDate?\n) {\n fun compositeId(): ProjectAssignmentId = ProjectAssignmentId(employeeId, projectId)\n\n fun id(): ProjectAssignmentId = this.compositeId()\n\n fun toUnsavedRow(hoursAllocated: Defaulted): ProjectAssignmentRowUnsaved = ProjectAssignmentRowUnsaved(employeeId, projectId, role, startDate, endDate, hoursAllocated)\n\n companion object {\n val _rowParser: RowParser = RowParsers.of(EmployeeId.sqlServerType, ProjectId.sqlServerType, SqlServerTypes.nvarchar, KotlinDbTypes.SqlServerTypes.int_.nullable(), SqlServerTypes.date.nullable(), SqlServerTypes.date.nullable(), { t0, t1, t2, t3, t4, t5 -> ProjectAssignmentRow(t0, t1, t2, t3, t4, t5) }, { row -> arrayOf(row.employeeId, row.projectId, row.role, row.hoursAllocated, row.startDate, row.endDate) })\n\n fun apply(\n compositeId: ProjectAssignmentId,\n role: String,\n hoursAllocated: Int?,\n startDate: LocalDate?,\n endDate: LocalDate?\n ): ProjectAssignmentRow = ProjectAssignmentRow(compositeId.employeeId, compositeId.projectId, role, hoursAllocated, startDate, endDate)\n }\n}", - "ProjectAssignmentRowUnsaved": "package showcase.showcase.project_assignment\n\nimport java.time.LocalDate\nimport showcase.customtypes.Defaulted\nimport showcase.customtypes.Defaulted.UseDefault\nimport showcase.showcase.employee.EmployeeId\nimport showcase.showcase.project.ProjectId\n\n/** This class corresponds to a row in table `showcase.project_assignment` which has not been persisted yet */\ndata class ProjectAssignmentRowUnsaved(\n /** Points to [showcase.showcase.employee.EmployeeRow.id] */\n val employeeId: EmployeeId,\n /** Points to [showcase.showcase.project.ProjectRow.id] */\n val projectId: ProjectId,\n val role: String,\n val startDate: LocalDate? = null,\n val endDate: LocalDate? = null,\n /** Default: 0 */\n val hoursAllocated: Defaulted = UseDefault()\n) {\n fun toRow(hoursAllocatedDefault: () -> Int?): ProjectAssignmentRow = ProjectAssignmentRow(employeeId = employeeId, projectId = projectId, role = role, hoursAllocated = hoursAllocated.getOrElse(hoursAllocatedDefault), startDate = startDate, endDate = endDate)\n}", - "ProjectAssignmentId": "package showcase.showcase.project_assignment\n\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport showcase.showcase.employee.EmployeeId\nimport showcase.showcase.project.ProjectId\n\n/** Type for the composite primary key of table `showcase.project_assignment` */\ndata class ProjectAssignmentId(\n val employeeId: EmployeeId,\n val projectId: ProjectId\n) {\n companion object {\n val _rowParser: RowParser = RowParsers.of(EmployeeId.sqlServerType, ProjectId.sqlServerType, { t0, t1 -> ProjectAssignmentId(t0, t1) }, { row -> arrayOf(row.employeeId, row.projectId) })\n }\n}", - "ProjectAssignmentRepo": "package showcase.showcase.project_assignment\n\nimport dev.typr.foundations.kotlin.DeleteBuilder\nimport dev.typr.foundations.kotlin.SelectBuilder\nimport dev.typr.foundations.kotlin.UpdateBuilder\nimport java.sql.Connection\nimport kotlin.collections.Iterator\nimport kotlin.collections.List\nimport kotlin.collections.Map\n\ninterface ProjectAssignmentRepo {\n abstract fun delete(): DeleteBuilder\n\n abstract fun deleteById(\n compositeId: ProjectAssignmentId,\n c: Connection\n ): Boolean\n\n abstract fun deleteByIds(\n compositeIds: Array,\n c: Connection\n ): Int\n\n abstract fun insert(\n unsaved: ProjectAssignmentRow,\n c: Connection\n ): ProjectAssignmentRow\n\n abstract fun insert(\n unsaved: ProjectAssignmentRowUnsaved,\n c: Connection\n ): ProjectAssignmentRow\n\n abstract fun select(): SelectBuilder\n\n abstract fun selectAll(c: Connection): List\n\n abstract fun selectById(\n compositeId: ProjectAssignmentId,\n c: Connection\n ): ProjectAssignmentRow?\n\n abstract fun selectByIds(\n compositeIds: Array,\n c: Connection\n ): List\n\n abstract fun selectByIdsTracked(\n compositeIds: Array,\n c: Connection\n ): Map\n\n abstract fun update(): UpdateBuilder\n\n abstract fun update(\n row: ProjectAssignmentRow,\n c: Connection\n ): Boolean\n\n abstract fun upsert(\n unsaved: ProjectAssignmentRow,\n c: Connection\n ): ProjectAssignmentRow\n\n abstract fun upsertBatch(\n unsaved: Iterator,\n c: Connection\n ): List\n}", - "ProjectRow": "package showcase.showcase.project\n\nimport dev.typr.foundations.SqlServerTypes\nimport dev.typr.foundations.data.Json\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport dev.typr.foundations.kotlin.nullable\nimport java.math.BigDecimal\nimport java.time.LocalDate\nimport java.time.LocalDateTime\nimport java.util.UUID\nimport showcase.customtypes.Defaulted\n\n/** Table: showcase.project\n * Primary key: id\n */\ndata class ProjectRow(\n val id: ProjectId,\n val name: String,\n val description: String?,\n val startDate: LocalDate?,\n val endDate: LocalDate?,\n val budget: BigDecimal?,\n /** Default: 'planning' */\n val status: String?,\n /** Default: CURRENT_TIMESTAMP */\n val createdAt: LocalDateTime?,\n val projectUid: UUID?,\n val metadata: Json?,\n val xmlPlan: /* XML */ String?,\n val attachments: ByteArray?,\n val rowVersion: /* ROWVERSION/TIMESTAMP */ ByteArray?,\n val totalBudget: BigDecimal?,\n val orgPath: /* HIERARCHYID */ String?\n) {\n fun toUnsavedRow(\n status: Defaulted,\n createdAt: Defaulted\n ): ProjectRowUnsaved = ProjectRowUnsaved(id, name, description, startDate, endDate, budget, projectUid, metadata, xmlPlan, attachments, rowVersion, totalBudget, orgPath, status, createdAt)\n\n companion object {\n val _rowParser: RowParser = RowParsers.of(ProjectId.sqlServerType, SqlServerTypes.nvarchar, SqlServerTypes.nvarchar.nullable(), SqlServerTypes.date.nullable(), SqlServerTypes.date.nullable(), KotlinDbTypes.SqlServerTypes.decimal.nullable(), SqlServerTypes.nvarchar.nullable(), SqlServerTypes.datetime2.nullable(), SqlServerTypes.uniqueidentifier.nullable(), SqlServerTypes.json.nullable(), SqlServerTypes.xml.nullable(), SqlServerTypes.varbinary.nullable(), SqlServerTypes.rowversion.nullable(), KotlinDbTypes.SqlServerTypes.money.nullable(), SqlServerTypes.hierarchyid.nullable(), { t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14 -> ProjectRow(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14) }, { row -> arrayOf(row.id, row.name, row.description, row.startDate, row.endDate, row.budget, row.status, row.createdAt, row.projectUid, row.metadata, row.xmlPlan, row.attachments, row.rowVersion, row.totalBudget, row.orgPath) })\n }\n}", - "ProjectId": "package showcase.showcase.project\n\nimport dev.typr.foundations.SqlServerType\nimport dev.typr.foundations.SqlServerTypes\nimport dev.typr.foundations.kotlin.Bijection\n\n/** Type for the primary key of table `showcase.project` */\ndata class ProjectId(val value: String) {\n override fun toString(): kotlin.String {\n return value.toString()\n }\n\n companion object {\n val bijection: Bijection =\n Bijection.of(ProjectId::value, ::ProjectId)\n\n val sqlServerType: SqlServerType =\n SqlServerTypes.nvarchar.bimap(::ProjectId, ProjectId::value)\n }\n}", - "EmployeeSummaryViewRow": "package showcase.showcase.employee_summary\n\nimport dev.typr.foundations.SqlServerTypes\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport dev.typr.foundations.kotlin.nullable\nimport java.math.BigDecimal\nimport java.time.LocalDate\nimport showcase.showcase.company.CompanyId\nimport showcase.showcase.department.DepartmentId\nimport showcase.showcase.employee.EmployeeId\n\n/** View: showcase.employee_summary\n * Summary view of employees with their department and company information\n */\ndata class EmployeeSummaryViewRow(\n /** Points to [showcase.showcase.employee.EmployeeRow.id] */\n val employeeId: EmployeeId,\n val email: String,\n val firstName: String,\n val lastName: String,\n val salary: BigDecimal?,\n val hiredAt: LocalDate?,\n val active: Boolean?,\n /** Points to [showcase.showcase.department.DepartmentRow.id] */\n val departmentId: DepartmentId,\n val departmentName: String,\n val departmentBudget: BigDecimal?,\n /** Points to [showcase.showcase.company.CompanyRow.id] */\n val companyId: CompanyId,\n val companyName: String,\n val managerId: String?,\n val managerFirstName: String?,\n val managerLastName: String?\n) {\n companion object {\n val _rowParser: RowParser = RowParsers.of(EmployeeId.sqlServerType, SqlServerTypes.nvarchar, SqlServerTypes.nvarchar, SqlServerTypes.nvarchar, KotlinDbTypes.SqlServerTypes.decimal.nullable(), SqlServerTypes.date.nullable(), KotlinDbTypes.SqlServerTypes.bit.nullable(), DepartmentId.sqlServerType, SqlServerTypes.nvarchar, KotlinDbTypes.SqlServerTypes.decimal.nullable(), CompanyId.sqlServerType, SqlServerTypes.nvarchar, SqlServerTypes.nvarchar.nullable(), SqlServerTypes.nvarchar.nullable(), SqlServerTypes.nvarchar.nullable(), { t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14 -> EmployeeSummaryViewRow(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14) }, { row -> arrayOf(row.employeeId, row.email, row.firstName, row.lastName, row.salary, row.hiredAt, row.active, row.departmentId, row.departmentName, row.departmentBudget, row.companyId, row.companyName, row.managerId, row.managerFirstName, row.managerLastName) })\n }\n}", - "EmployeeSummaryViewRepo": "package showcase.showcase.employee_summary\n\nimport dev.typr.foundations.kotlin.SelectBuilder\nimport java.sql.Connection\nimport kotlin.collections.List\n\ninterface EmployeeSummaryViewRepo {\n abstract fun select(): SelectBuilder\n\n abstract fun selectAll(c: Connection): List\n}", - "CustomerOrderRow": "package showcase.showcase.customer_order\n\nimport dev.typr.foundations.SqlServerTypes\nimport dev.typr.foundations.data.Json\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport dev.typr.foundations.kotlin.nullable\nimport java.math.BigDecimal\nimport java.time.LocalDateTime\nimport java.util.UUID\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.address.AddressId\nimport showcase.showcase.customer.CustomerId\n\n/** Table: showcase.customer_order\n * Primary key: id\n */\ndata class CustomerOrderRow(\n val id: CustomerOrderId,\n /** Points to [showcase.showcase.customer.CustomerRow.id] */\n val customerId: CustomerId,\n /** Points to [showcase.showcase.address.AddressRow.id] */\n val shippingAddressId: AddressId?,\n /** Points to [showcase.showcase.address.AddressRow.id] */\n val billingAddressId: AddressId?,\n /** Default: 'pending' */\n val status: String?,\n val subtotal: BigDecimal,\n /** Default: 0 */\n val tax: BigDecimal?,\n /** Default: 0 */\n val shipping: BigDecimal?,\n val total: BigDecimal,\n val notes: String?,\n /** Default: CURRENT_TIMESTAMP */\n val createdAt: LocalDateTime?,\n val shippedAt: LocalDateTime?,\n val deliveredAt: LocalDateTime?,\n val orderUid: UUID?,\n val metadata: Json?,\n val xmlInvoice: /* XML */ String?,\n val receiptData: ByteArray?,\n val rowVersion: /* ROWVERSION/TIMESTAMP */ ByteArray?,\n val orderAmount: BigDecimal?\n) {\n fun toUnsavedRow(\n status: Defaulted,\n tax: Defaulted,\n shipping: Defaulted,\n createdAt: Defaulted\n ): CustomerOrderRowUnsaved = CustomerOrderRowUnsaved(id, customerId, shippingAddressId, billingAddressId, subtotal, total, notes, shippedAt, deliveredAt, orderUid, metadata, xmlInvoice, receiptData, rowVersion, orderAmount, status, tax, shipping, createdAt)\n\n companion object {\n val _rowParser: RowParser = RowParsers.of(CustomerOrderId.sqlServerType, CustomerId.sqlServerType, AddressId.sqlServerType.nullable(), AddressId.sqlServerType.nullable(), SqlServerTypes.nvarchar.nullable(), KotlinDbTypes.SqlServerTypes.decimal, KotlinDbTypes.SqlServerTypes.decimal.nullable(), KotlinDbTypes.SqlServerTypes.decimal.nullable(), KotlinDbTypes.SqlServerTypes.decimal, SqlServerTypes.nvarchar.nullable(), SqlServerTypes.datetime2.nullable(), SqlServerTypes.datetime2.nullable(), SqlServerTypes.datetime2.nullable(), SqlServerTypes.uniqueidentifier.nullable(), SqlServerTypes.json.nullable(), SqlServerTypes.xml.nullable(), SqlServerTypes.varbinary.nullable(), SqlServerTypes.rowversion.nullable(), KotlinDbTypes.SqlServerTypes.money.nullable(), { t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17, t18 -> CustomerOrderRow(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17, t18) }, { row -> arrayOf(row.id, row.customerId, row.shippingAddressId, row.billingAddressId, row.status, row.subtotal, row.tax, row.shipping, row.total, row.notes, row.createdAt, row.shippedAt, row.deliveredAt, row.orderUid, row.metadata, row.xmlInvoice, row.receiptData, row.rowVersion, row.orderAmount) })\n }\n}", - "CustomerOrderRepo": "package showcase.showcase.customer_order\n\nimport dev.typr.foundations.kotlin.DeleteBuilder\nimport dev.typr.foundations.kotlin.SelectBuilder\nimport dev.typr.foundations.kotlin.UpdateBuilder\nimport java.sql.Connection\nimport kotlin.collections.Iterator\nimport kotlin.collections.List\nimport kotlin.collections.Map\n\ninterface CustomerOrderRepo {\n abstract fun delete(): DeleteBuilder\n\n abstract fun deleteById(\n id: CustomerOrderId,\n c: Connection\n ): Boolean\n\n abstract fun deleteByIds(\n ids: Array,\n c: Connection\n ): Int\n\n abstract fun insert(\n unsaved: CustomerOrderRow,\n c: Connection\n ): CustomerOrderRow\n\n abstract fun insert(\n unsaved: CustomerOrderRowUnsaved,\n c: Connection\n ): CustomerOrderRow\n\n abstract fun select(): SelectBuilder\n\n abstract fun selectAll(c: Connection): List\n\n abstract fun selectById(\n id: CustomerOrderId,\n c: Connection\n ): CustomerOrderRow?\n\n abstract fun selectByIds(\n ids: Array,\n c: Connection\n ): List\n\n abstract fun selectByIdsTracked(\n ids: Array,\n c: Connection\n ): Map\n\n abstract fun update(): UpdateBuilder\n\n abstract fun update(\n row: CustomerOrderRow,\n c: Connection\n ): Boolean\n\n abstract fun upsert(\n unsaved: CustomerOrderRow,\n c: Connection\n ): CustomerOrderRow\n\n abstract fun upsertBatch(\n unsaved: Iterator,\n c: Connection\n ): List\n}", - "OrderItemRow": "package showcase.showcase.order_item\n\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport dev.typr.foundations.kotlin.nullable\nimport java.math.BigDecimal\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.customer_order.CustomerOrderId\nimport showcase.showcase.product.ProductId\n\n/** Table: showcase.order_item\n * Composite primary key: order_id, product_id\n */\ndata class OrderItemRow(\n /** Points to [showcase.showcase.customer_order.CustomerOrderRow.id] */\n val orderId: CustomerOrderId,\n /** Points to [showcase.showcase.product.ProductRow.id] */\n val productId: ProductId,\n val quantity: Int,\n val unitPrice: BigDecimal,\n /** Default: 0 */\n val discount: BigDecimal?\n) {\n fun compositeId(): OrderItemId = OrderItemId(orderId, productId)\n\n fun id(): OrderItemId = this.compositeId()\n\n fun toUnsavedRow(discount: Defaulted): OrderItemRowUnsaved = OrderItemRowUnsaved(orderId, productId, quantity, unitPrice, discount)\n\n companion object {\n val _rowParser: RowParser = RowParsers.of(CustomerOrderId.sqlServerType, ProductId.sqlServerType, KotlinDbTypes.SqlServerTypes.int_, KotlinDbTypes.SqlServerTypes.decimal, KotlinDbTypes.SqlServerTypes.decimal.nullable(), { t0, t1, t2, t3, t4 -> OrderItemRow(t0, t1, t2, t3, t4) }, { row -> arrayOf(row.orderId, row.productId, row.quantity, row.unitPrice, row.discount) })\n\n fun apply(\n compositeId: OrderItemId,\n quantity: Int,\n unitPrice: BigDecimal,\n discount: BigDecimal?\n ): OrderItemRow = OrderItemRow(compositeId.orderId, compositeId.productId, quantity, unitPrice, discount)\n }\n}", - "OrderItemId": "package showcase.showcase.order_item\n\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport showcase.showcase.customer_order.CustomerOrderId\nimport showcase.showcase.product.ProductId\n\n/** Type for the composite primary key of table `showcase.order_item` */\ndata class OrderItemId(\n val orderId: CustomerOrderId,\n val productId: ProductId\n) {\n companion object {\n val _rowParser: RowParser = RowParsers.of(CustomerOrderId.sqlServerType, ProductId.sqlServerType, { t0, t1 -> OrderItemId(t0, t1) }, { row -> arrayOf(row.orderId, row.productId) })\n }\n}", - "ProductRow": "package showcase.showcase.product\n\nimport dev.typr.foundations.SqlServerTypes\nimport dev.typr.foundations.data.Json\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport dev.typr.foundations.kotlin.nullable\nimport java.math.BigDecimal\nimport java.time.LocalDateTime\nimport java.util.UUID\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.category.CategoryId\n\n/** Table: showcase.product\n * Primary key: id\n */\ndata class ProductRow(\n val id: ProductId,\n /** Points to [showcase.showcase.category.CategoryRow.id] */\n val categoryId: CategoryId?,\n val name: String,\n val sku: String,\n val price: BigDecimal,\n val cost: BigDecimal?,\n /** Default: true */\n val inStock: Boolean?,\n /** Default: 0 */\n val quantity: Int?,\n val weight: BigDecimal?,\n /** Default: CURRENT_TIMESTAMP */\n val createdAt: LocalDateTime?,\n val attributes: Json?,\n val specifications: /* XML */ String?,\n val descriptionLong: String?,\n val thumbnail: ByteArray?,\n val productUid: UUID?,\n val listPrice: BigDecimal?\n) {\n fun toUnsavedRow(\n inStock: Defaulted,\n quantity: Defaulted,\n createdAt: Defaulted\n ): ProductRowUnsaved = ProductRowUnsaved(id, categoryId, name, sku, price, cost, weight, attributes, specifications, descriptionLong, thumbnail, productUid, listPrice, inStock, quantity, createdAt)\n\n companion object {\n val _rowParser: RowParser = RowParsers.of(ProductId.sqlServerType, CategoryId.sqlServerType.nullable(), SqlServerTypes.nvarchar, SqlServerTypes.nvarchar, KotlinDbTypes.SqlServerTypes.decimal, KotlinDbTypes.SqlServerTypes.decimal.nullable(), KotlinDbTypes.SqlServerTypes.bit.nullable(), KotlinDbTypes.SqlServerTypes.int_.nullable(), KotlinDbTypes.SqlServerTypes.decimal.nullable(), SqlServerTypes.datetime2.nullable(), SqlServerTypes.json.nullable(), SqlServerTypes.xml.nullable(), SqlServerTypes.nvarchar.nullable(), SqlServerTypes.varbinary.nullable(), SqlServerTypes.uniqueidentifier.nullable(), KotlinDbTypes.SqlServerTypes.money.nullable(), { t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15 -> ProductRow(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15) }, { row -> arrayOf(row.id, row.categoryId, row.name, row.sku, row.price, row.cost, row.inStock, row.quantity, row.weight, row.createdAt, row.attributes, row.specifications, row.descriptionLong, row.thumbnail, row.productUid, row.listPrice) })\n }\n}", - "ProductId": "package showcase.showcase.product\n\nimport dev.typr.foundations.SqlServerType\nimport dev.typr.foundations.SqlServerTypes\nimport dev.typr.foundations.kotlin.Bijection\n\n/** Type for the primary key of table `showcase.product` */\ndata class ProductId(val value: String) {\n override fun toString(): kotlin.String {\n return value.toString()\n }\n\n companion object {\n val bijection: Bijection =\n Bijection.of(ProductId::value, ::ProductId)\n\n val sqlServerType: SqlServerType =\n SqlServerTypes.nvarchar.bimap(::ProductId, ProductId::value)\n }\n}", - "CategoryRow": "package showcase.showcase.category\n\nimport dev.typr.foundations.SqlServerTypes\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport dev.typr.foundations.kotlin.nullable\n\n/** Table: showcase.category\n * Primary key: id\n */\ndata class CategoryRow(\n val id: CategoryId,\n /** Points to [showcase.showcase.category.CategoryRow.id] */\n val parentId: CategoryId?,\n val name: String,\n val description: String?\n) {\n companion object {\n val _rowParser: RowParser = RowParsers.of(CategoryId.sqlServerType, CategoryId.sqlServerType.nullable(), SqlServerTypes.nvarchar, SqlServerTypes.nvarchar.nullable(), { t0, t1, t2, t3 -> CategoryRow(t0, t1, t2, t3) }, { row -> arrayOf(row.id, row.parentId, row.name, row.description) })\n }\n}", - "CategoryId": "package showcase.showcase.category\n\nimport dev.typr.foundations.SqlServerType\nimport dev.typr.foundations.SqlServerTypes\nimport dev.typr.foundations.kotlin.Bijection\n\n/** Type for the primary key of table `showcase.category` */\ndata class CategoryId(val value: String) {\n override fun toString(): kotlin.String {\n return value.toString()\n }\n\n companion object {\n val bijection: Bijection =\n Bijection.of(CategoryId::value, ::CategoryId)\n\n val sqlServerType: SqlServerType =\n SqlServerTypes.nvarchar.bimap(::CategoryId, CategoryId::value)\n }\n}", - "AddressRow": "package showcase.showcase.address\n\nimport com.microsoft.sqlserver.jdbc.Geography\nimport com.microsoft.sqlserver.jdbc.Geometry\nimport dev.typr.foundations.SqlServerTypes\nimport dev.typr.foundations.kotlin.KotlinDbTypes\nimport dev.typr.foundations.kotlin.RowParser\nimport dev.typr.foundations.kotlin.RowParsers\nimport dev.typr.foundations.kotlin.nullable\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.customer.CustomerId\n\n/** Table: showcase.address\n * Primary key: id\n */\ndata class AddressRow(\n val id: AddressId,\n /** Points to [showcase.showcase.customer.CustomerRow.id] */\n val customerId: CustomerId,\n val addressType: String,\n val street: String,\n val city: String,\n val state: String?,\n val postalCode: String?,\n val country: String,\n /** Default: false */\n val isDefault: Boolean?,\n val location: Geography?,\n val deliveryZone: Geometry?\n) {\n fun toUnsavedRow(isDefault: Defaulted): AddressRowUnsaved = AddressRowUnsaved(id, customerId, addressType, street, city, state, postalCode, country, location, deliveryZone, isDefault)\n\n companion object {\n val _rowParser: RowParser = RowParsers.of(AddressId.sqlServerType, CustomerId.sqlServerType, SqlServerTypes.nvarchar, SqlServerTypes.nvarchar, SqlServerTypes.nvarchar, SqlServerTypes.nvarchar.nullable(), SqlServerTypes.nvarchar.nullable(), SqlServerTypes.nvarchar, KotlinDbTypes.SqlServerTypes.bit.nullable(), SqlServerTypes.geography.nullable(), SqlServerTypes.geometry.nullable(), { t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10 -> AddressRow(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10) }, { row -> arrayOf(row.id, row.customerId, row.addressType, row.street, row.city, row.state, row.postalCode, row.country, row.isDefault, row.location, row.deliveryZone) })\n }\n}", - "AddressId": "package showcase.showcase.address\n\nimport dev.typr.foundations.SqlServerType\nimport dev.typr.foundations.SqlServerTypes\nimport dev.typr.foundations.kotlin.Bijection\n\n/** Type for the primary key of table `showcase.address` */\ndata class AddressId(val value: String) {\n override fun toString(): kotlin.String {\n return value.toString()\n }\n\n companion object {\n val bijection: Bijection =\n Bijection.of(AddressId::value, ::AddressId)\n\n val sqlServerType: SqlServerType =\n SqlServerTypes.nvarchar.bimap(::AddressId, AddressId::value)\n }\n}", - "Defaulted": "package showcase.customtypes\n\n\n\n/** This signals a value where if you don't provide it, postgres will generate it for you */\nsealed interface Defaulted {\n data class Provided(val value: T) : Defaulted {\n override fun fold(\n onDefault: () -> U,\n onProvided: (T) -> U\n ): U = onProvided(value)\n\n override fun getOrElse(onDefault: () -> T): T = value\n\n override fun visit(\n onDefault: () -> Unit,\n onProvided: (T) -> Unit\n ) {\n onProvided(value)\n }\n }\n\n class UseDefault : Defaulted {\n override fun fold(\n onDefault: () -> U,\n onProvided: (T) -> U\n ): U = onDefault()\n\n override fun getOrElse(onDefault: () -> T): T = onDefault()\n\n override fun visit(\n onDefault: () -> Unit,\n onProvided: (T) -> Unit\n ) {\n onDefault()\n }\n }\n\n abstract fun fold(\n onDefault: () -> U,\n onProvided: (T) -> U\n ): U\n\n abstract fun getOrElse(onDefault: () -> T): T\n\n abstract fun visit(\n onDefault: () -> Unit,\n onProvided: (T) -> Unit\n )\n}", - "TestInsert": "package showcase\n\nimport com.microsoft.sqlserver.jdbc.Geography\nimport com.microsoft.sqlserver.jdbc.Geometry\nimport dev.typr.foundations.data.Json\nimport java.math.BigDecimal\nimport java.sql.Connection\nimport java.time.LocalDate\nimport java.time.LocalDateTime\nimport java.time.OffsetDateTime\nimport java.util.Random\nimport java.util.UUID\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.address.AddressId\nimport showcase.showcase.address.AddressRepoImpl\nimport showcase.showcase.address.AddressRow\nimport showcase.showcase.address.AddressRowUnsaved\nimport showcase.showcase.audit_log.AuditLogId\nimport showcase.showcase.audit_log.AuditLogRepoImpl\nimport showcase.showcase.audit_log.AuditLogRow\nimport showcase.showcase.audit_log.AuditLogRowUnsaved\nimport showcase.showcase.category.CategoryId\nimport showcase.showcase.category.CategoryRepoImpl\nimport showcase.showcase.category.CategoryRow\nimport showcase.showcase.company.CompanyId\nimport showcase.showcase.company.CompanyRepoImpl\nimport showcase.showcase.company.CompanyRow\nimport showcase.showcase.company.CompanyRowUnsaved\nimport showcase.showcase.customer.CustomerId\nimport showcase.showcase.customer.CustomerRepoImpl\nimport showcase.showcase.customer.CustomerRow\nimport showcase.showcase.customer.CustomerRowUnsaved\nimport showcase.showcase.customer_order.CustomerOrderId\nimport showcase.showcase.customer_order.CustomerOrderRepoImpl\nimport showcase.showcase.customer_order.CustomerOrderRow\nimport showcase.showcase.customer_order.CustomerOrderRowUnsaved\nimport showcase.showcase.department.DepartmentId\nimport showcase.showcase.department.DepartmentRepoImpl\nimport showcase.showcase.department.DepartmentRow\nimport showcase.showcase.employee.EmployeeId\nimport showcase.showcase.employee.EmployeeRepoImpl\nimport showcase.showcase.employee.EmployeeRow\nimport showcase.showcase.employee.EmployeeRowUnsaved\nimport showcase.showcase.order_item.OrderItemRepoImpl\nimport showcase.showcase.order_item.OrderItemRow\nimport showcase.showcase.order_item.OrderItemRowUnsaved\nimport showcase.showcase.product.ProductId\nimport showcase.showcase.product.ProductRepoImpl\nimport showcase.showcase.product.ProductRow\nimport showcase.showcase.product.ProductRowUnsaved\nimport showcase.showcase.project.ProjectId\nimport showcase.showcase.project.ProjectRepoImpl\nimport showcase.showcase.project.ProjectRow\nimport showcase.showcase.project.ProjectRowUnsaved\nimport showcase.showcase.project_assignment.ProjectAssignmentRepoImpl\nimport showcase.showcase.project_assignment.ProjectAssignmentRow\nimport showcase.showcase.project_assignment.ProjectAssignmentRowUnsaved\n\n/** Methods to generate random data for `Ident(TestInsert)` */\ndata class TestInsert(val random: Random) {\n fun showcaseAddress(\n id: AddressId,\n customerId: CustomerId,\n addressType: String,\n street: String,\n city: String,\n country: String,\n state: String?,\n postalCode: String?,\n location: Geography?,\n deliveryZone: Geometry?,\n isDefault: Defaulted,\n c: Connection\n ): AddressRow = (AddressRepoImpl()).insert(AddressRowUnsaved(id = id, customerId = customerId, addressType = addressType, street = street, city = city, state = state, postalCode = postalCode, country = country, location = location, deliveryZone = deliveryZone, isDefault = isDefault), c)\n\n fun showcaseAuditLog(\n id: AuditLogId,\n tableName: String,\n recordId: String,\n action: String,\n oldValues: String?,\n newValues: String?,\n changedBy: EmployeeId?,\n changedAt: Defaulted,\n c: Connection\n ): AuditLogRow = (AuditLogRepoImpl()).insert(AuditLogRowUnsaved(id = id, tableName = tableName, recordId = recordId, action = action, oldValues = oldValues, newValues = newValues, changedBy = changedBy, changedAt = changedAt), c)\n\n fun showcaseCategory(\n id: CategoryId,\n name: String,\n parentId: CategoryId?,\n description: String?,\n c: Connection\n ): CategoryRow = (CategoryRepoImpl()).insert(CategoryRow(id = id, parentId = parentId, name = name, description = description), c)\n\n fun showcaseCompany(\n id: CompanyId,\n name: String,\n foundedYear: Int?,\n active: Defaulted,\n createdAt: Defaulted,\n c: Connection\n ): CompanyRow = (CompanyRepoImpl()).insert(CompanyRowUnsaved(id = id, name = name, foundedYear = foundedYear, active = active, createdAt = createdAt), c)\n\n fun showcaseCustomer(\n id: CustomerId,\n email: String,\n firstName: String,\n lastName: String,\n phone: String?,\n preferences: Json?,\n avatar: ByteArray?,\n customerUid: UUID?,\n creditLimit: BigDecimal?,\n verified: Defaulted,\n createdAt: Defaulted,\n c: Connection\n ): CustomerRow = (CustomerRepoImpl()).insert(CustomerRowUnsaved(id = id, email = email, firstName = firstName, lastName = lastName, phone = phone, preferences = preferences, avatar = avatar, customerUid = customerUid, creditLimit = creditLimit, verified = verified, createdAt = createdAt), c)\n\n fun showcaseCustomerOrder(\n id: CustomerOrderId,\n customerId: CustomerId,\n shippingAddressId: AddressId?,\n billingAddressId: AddressId?,\n subtotal: BigDecimal,\n total: BigDecimal,\n notes: String?,\n shippedAt: LocalDateTime?,\n deliveredAt: LocalDateTime?,\n orderUid: UUID?,\n metadata: Json?,\n xmlInvoice: /* XML */ String?,\n receiptData: ByteArray?,\n rowVersion: /* ROWVERSION/TIMESTAMP */ ByteArray?,\n orderAmount: BigDecimal?,\n status: Defaulted,\n tax: Defaulted,\n shipping: Defaulted,\n createdAt: Defaulted,\n c: Connection\n ): CustomerOrderRow = (CustomerOrderRepoImpl()).insert(CustomerOrderRowUnsaved(id = id, customerId = customerId, shippingAddressId = shippingAddressId, billingAddressId = billingAddressId, subtotal = subtotal, total = total, notes = notes, shippedAt = shippedAt, deliveredAt = deliveredAt, orderUid = orderUid, metadata = metadata, xmlInvoice = xmlInvoice, receiptData = receiptData, rowVersion = rowVersion, orderAmount = orderAmount, status = status, tax = tax, shipping = shipping, createdAt = createdAt), c)\n\n fun showcaseDepartment(\n id: DepartmentId,\n companyId: CompanyId,\n name: String,\n budget: BigDecimal?,\n c: Connection\n ): DepartmentRow = (DepartmentRepoImpl()).insert(DepartmentRow(id = id, companyId = companyId, name = name, budget = budget), c)\n\n fun showcaseEmployee(\n id: EmployeeId,\n departmentId: DepartmentId,\n email: String,\n firstName: String,\n lastName: String,\n managerId: EmployeeId?,\n salary: BigDecimal?,\n hiredAt: LocalDate?,\n metadata: Json?,\n resume: /* XML */ String?,\n photo: ByteArray?,\n employeeUid: UUID?,\n lastModified: OffsetDateTime?,\n rowVersion: /* ROWVERSION/TIMESTAMP */ ByteArray?,\n orgPath: /* HIERARCHYID */ String?,\n active: Defaulted,\n createdAt: Defaulted,\n c: Connection\n ): EmployeeRow = (EmployeeRepoImpl()).insert(EmployeeRowUnsaved(id = id, departmentId = departmentId, managerId = managerId, email = email, firstName = firstName, lastName = lastName, salary = salary, hiredAt = hiredAt, metadata = metadata, resume = resume, photo = photo, employeeUid = employeeUid, lastModified = lastModified, rowVersion = rowVersion, orgPath = orgPath, active = active, createdAt = createdAt), c)\n\n fun showcaseOrderItem(\n orderId: CustomerOrderId,\n productId: ProductId,\n quantity: Int,\n unitPrice: BigDecimal,\n discount: Defaulted,\n c: Connection\n ): OrderItemRow = (OrderItemRepoImpl()).insert(OrderItemRowUnsaved(orderId = orderId, productId = productId, quantity = quantity, unitPrice = unitPrice, discount = discount), c)\n\n fun showcaseProduct(\n id: ProductId,\n name: String,\n sku: String,\n categoryId: CategoryId?,\n price: BigDecimal,\n cost: BigDecimal?,\n weight: BigDecimal?,\n attributes: Json?,\n specifications: /* XML */ String?,\n descriptionLong: String?,\n thumbnail: ByteArray?,\n productUid: UUID?,\n listPrice: BigDecimal?,\n inStock: Defaulted,\n quantity: Defaulted,\n createdAt: Defaulted,\n c: Connection\n ): ProductRow = (ProductRepoImpl()).insert(ProductRowUnsaved(id = id, categoryId = categoryId, name = name, sku = sku, price = price, cost = cost, weight = weight, attributes = attributes, specifications = specifications, descriptionLong = descriptionLong, thumbnail = thumbnail, productUid = productUid, listPrice = listPrice, inStock = inStock, quantity = quantity, createdAt = createdAt), c)\n\n fun showcaseProject(\n id: ProjectId,\n name: String,\n description: String?,\n startDate: LocalDate?,\n endDate: LocalDate?,\n budget: BigDecimal?,\n projectUid: UUID?,\n metadata: Json?,\n xmlPlan: /* XML */ String?,\n attachments: ByteArray?,\n rowVersion: /* ROWVERSION/TIMESTAMP */ ByteArray?,\n totalBudget: BigDecimal?,\n orgPath: /* HIERARCHYID */ String?,\n status: Defaulted,\n createdAt: Defaulted,\n c: Connection\n ): ProjectRow = (ProjectRepoImpl()).insert(ProjectRowUnsaved(id = id, name = name, description = description, startDate = startDate, endDate = endDate, budget = budget, projectUid = projectUid, metadata = metadata, xmlPlan = xmlPlan, attachments = attachments, rowVersion = rowVersion, totalBudget = totalBudget, orgPath = orgPath, status = status, createdAt = createdAt), c)\n\n fun showcaseProjectAssignment(\n employeeId: EmployeeId,\n projectId: ProjectId,\n role: String,\n startDate: LocalDate?,\n endDate: LocalDate?,\n hoursAllocated: Defaulted,\n c: Connection\n ): ProjectAssignmentRow = (ProjectAssignmentRepoImpl()).insert(ProjectAssignmentRowUnsaved(employeeId = employeeId, projectId = projectId, role = role, startDate = startDate, endDate = endDate, hoursAllocated = hoursAllocated), c)\n}" - }, - "scala": { - "CompanyRow": "package showcase.showcase.company\n\nimport dev.typr.foundations.SqlServerTypes\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport java.time.LocalDateTime\nimport showcase.customtypes.Defaulted\n\n/** Table: showcase.company\n * Primary key: id\n */\ncase class CompanyRow(\n id: CompanyId,\n name: String,\n foundedYear: Option[Int],\n /** Default: true */\n active: Option[Boolean],\n /** Default: CURRENT_TIMESTAMP */\n createdAt: Option[LocalDateTime]\n) {\n def toUnsavedRow(\n active: Defaulted[Option[Boolean]] = Defaulted.Provided(this.active),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.Provided(this.createdAt)\n ): CompanyRowUnsaved = {\n new CompanyRowUnsaved(\n id,\n name,\n foundedYear,\n active,\n createdAt\n )\n }\n}\n\nobject CompanyRow {\n val `_rowParser`: RowParser[CompanyRow] = RowParsers.of(CompanyId.sqlServerType, SqlServerTypes.nvarchar, ScalaDbTypes.SqlServerTypes.int_.nullable, ScalaDbTypes.SqlServerTypes.bit.nullable, SqlServerTypes.datetime2.nullable)(CompanyRow.apply)(row => Array[Any](row.id, row.name, row.foundedYear, row.active, row.createdAt))\n}", - "CompanyRowUnsaved": "package showcase.showcase.company\n\nimport java.time.LocalDateTime\nimport showcase.customtypes.Defaulted\nimport showcase.customtypes.Defaulted.UseDefault\n\n/** This class corresponds to a row in table `showcase.company` which has not been persisted yet */\ncase class CompanyRowUnsaved(\n id: CompanyId,\n name: String,\n foundedYear: Option[Int] = None,\n /** Default: true */\n active: Defaulted[Option[Boolean]] = new UseDefault(),\n /** Default: CURRENT_TIMESTAMP */\n createdAt: Defaulted[Option[LocalDateTime]] = new UseDefault()\n) {\n def toRow(\n activeDefault: => Option[Boolean],\n createdAtDefault: => Option[LocalDateTime]\n ): CompanyRow = {\n new CompanyRow(\n id = id,\n name = name,\n foundedYear = foundedYear,\n active = active.getOrElse(activeDefault),\n createdAt = createdAt.getOrElse(createdAtDefault)\n )\n }\n}", - "CompanyId": "package showcase.showcase.company\n\nimport dev.typr.foundations.SqlServerType\nimport dev.typr.foundations.SqlServerTypes\nimport dev.typr.foundations.scala.Bijection\n\n/** Type for the primary key of table `showcase.company` */\ncase class CompanyId(value: String) extends scala.AnyVal\n\nobject CompanyId {\n given bijection: Bijection[CompanyId, String] = Bijection.apply[CompanyId, String](_.value)(CompanyId.apply)\n\n given sqlServerType: SqlServerType[CompanyId] = SqlServerTypes.nvarchar.bimap(CompanyId.apply, _.value)\n}", - "CompanyRepo": "package showcase.showcase.company\n\nimport dev.typr.foundations.scala.DeleteBuilder\nimport dev.typr.foundations.scala.SelectBuilder\nimport dev.typr.foundations.scala.UpdateBuilder\nimport java.sql.Connection\n\ntrait CompanyRepo {\n def delete: DeleteBuilder[CompanyFields, CompanyRow]\n\n def deleteById(id: CompanyId)(using c: Connection): Boolean\n\n def deleteByIds(ids: Array[CompanyId])(using c: Connection): Int\n\n def insert(unsaved: CompanyRow)(using c: Connection): CompanyRow\n\n def insert(unsaved: CompanyRowUnsaved)(using c: Connection): CompanyRow\n\n def select: SelectBuilder[CompanyFields, CompanyRow]\n\n def selectAll(using c: Connection): List[CompanyRow]\n\n def selectById(id: CompanyId)(using c: Connection): Option[CompanyRow]\n\n def selectByIds(ids: Array[CompanyId])(using c: Connection): List[CompanyRow]\n\n def selectByIdsTracked(ids: Array[CompanyId])(using c: Connection): Map[CompanyId, CompanyRow]\n\n def update: UpdateBuilder[CompanyFields, CompanyRow]\n\n def update(row: CompanyRow)(using c: Connection): Boolean\n\n def upsert(unsaved: CompanyRow)(using c: Connection): CompanyRow\n\n def upsertBatch(unsaved: Iterator[CompanyRow])(using c: Connection): List[CompanyRow]\n}", - "CompanyRepoMock": "package showcase.showcase.company\n\nimport dev.typr.foundations.scala.DeleteBuilder\nimport dev.typr.foundations.scala.DeleteBuilderMock\nimport dev.typr.foundations.scala.DeleteParams\nimport dev.typr.foundations.scala.SelectBuilder\nimport dev.typr.foundations.scala.SelectBuilderMock\nimport dev.typr.foundations.scala.SelectParams\nimport dev.typr.foundations.scala.UpdateBuilder\nimport dev.typr.foundations.scala.UpdateBuilderMock\nimport dev.typr.foundations.scala.UpdateParams\nimport java.lang.RuntimeException\nimport java.sql.Connection\n\ncase class CompanyRepoMock(\n toRow: CompanyRowUnsaved => CompanyRow,\n map: scala.collection.mutable.Map[CompanyId, CompanyRow] = scala.collection.mutable.Map.empty[CompanyId, CompanyRow]\n) extends CompanyRepo {\n override def delete: DeleteBuilder[CompanyFields, CompanyRow] = DeleteBuilderMock(CompanyFields.structure, () => map.values.toList, DeleteParams.empty(), row => row.id, id => map.remove(id): @scala.annotation.nowarn)\n\n override def deleteById(id: CompanyId)(using c: Connection): Boolean = map.remove(id).isDefined\n\n override def deleteByIds(ids: Array[CompanyId])(using c: Connection): Int = {\n var count = 0\n ids.foreach { id => if (map.remove(id).isDefined) {\n count = count + 1\n } }\n return count\n }\n\n override def insert(unsaved: CompanyRow)(using c: Connection): CompanyRow = {\n if (map.contains(unsaved.id)) {\n throw new RuntimeException(s\"id ${unsaved.id} already exists\")\n }\n map.put(unsaved.id, unsaved): @scala.annotation.nowarn\n return unsaved\n }\n\n override def insert(unsaved: CompanyRowUnsaved)(using c: Connection): CompanyRow = insert(toRow(unsaved))(using c)\n\n override def select: SelectBuilder[CompanyFields, CompanyRow] = SelectBuilderMock(CompanyFields.structure, () => map.values.toList, SelectParams.empty())\n\n override def selectAll(using c: Connection): List[CompanyRow] = map.values.toList\n\n override def selectById(id: CompanyId)(using c: Connection): Option[CompanyRow] = map.get(id)\n\n override def selectByIds(ids: Array[CompanyId])(using c: Connection): List[CompanyRow] = ids.flatMap(map.get(_)).toList\n\n override def selectByIdsTracked(ids: Array[CompanyId])(using c: Connection): Map[CompanyId, CompanyRow] = selectByIds(ids)(using c).map(x => (((row: CompanyRow) => row.id).apply(x), x)).toMap\n\n override def update: UpdateBuilder[CompanyFields, CompanyRow] = UpdateBuilderMock(CompanyFields.structure, () => map.values.toList, UpdateParams.empty(), row => row)\n\n override def update(row: CompanyRow)(using c: Connection): Boolean = {\n val shouldUpdate = map.get(row.id).filter(oldRow => (oldRow != row)).isDefined\n if (shouldUpdate) {\n map.put(row.id, row): @scala.annotation.nowarn\n }\n return shouldUpdate\n }\n\n override def upsert(unsaved: CompanyRow)(using c: Connection): CompanyRow = {\n map.put(unsaved.id, unsaved): @scala.annotation.nowarn\n return unsaved\n }\n\n override def upsertBatch(unsaved: Iterator[CompanyRow])(using c: Connection): List[CompanyRow] = {\n unsaved.map { row =>\n map.put(row.id, row): @scala.annotation.nowarn\n row\n }.toList\n }\n}", - "EmployeeRow": "package showcase.showcase.employee\n\nimport dev.typr.foundations.SqlServerTypes\nimport dev.typr.foundations.data.Json\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport java.time.LocalDate\nimport java.time.LocalDateTime\nimport java.time.OffsetDateTime\nimport java.util.UUID\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.department.DepartmentId\n\n/** Table: showcase.employee\n * Primary key: id\n */\ncase class EmployeeRow(\n id: EmployeeId,\n /** Points to [[showcase.showcase.department.DepartmentRow.id]] */\n departmentId: DepartmentId,\n /** Points to [[showcase.showcase.employee.EmployeeRow.id]] */\n managerId: Option[EmployeeId],\n email: String,\n firstName: String,\n lastName: String,\n salary: Option[BigDecimal],\n hiredAt: Option[LocalDate],\n /** Default: true */\n active: Option[Boolean],\n /** Default: CURRENT_TIMESTAMP */\n createdAt: Option[LocalDateTime],\n metadata: Option[Json],\n resume: Option[/* XML */ String],\n photo: Option[Array[Byte]],\n employeeUid: Option[UUID],\n lastModified: Option[OffsetDateTime],\n rowVersion: Option[/* ROWVERSION/TIMESTAMP */ Array[Byte]],\n orgPath: Option[/* HIERARCHYID */ String]\n) {\n def toUnsavedRow(\n active: Defaulted[Option[Boolean]] = Defaulted.Provided(this.active),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.Provided(this.createdAt)\n ): EmployeeRowUnsaved = {\n new EmployeeRowUnsaved(\n id,\n departmentId,\n managerId,\n email,\n firstName,\n lastName,\n salary,\n hiredAt,\n metadata,\n resume,\n photo,\n employeeUid,\n lastModified,\n rowVersion,\n orgPath,\n active,\n createdAt\n )\n }\n}\n\nobject EmployeeRow {\n val `_rowParser`: RowParser[EmployeeRow] = RowParsers.of(EmployeeId.sqlServerType, DepartmentId.sqlServerType, EmployeeId.sqlServerType.nullable, SqlServerTypes.nvarchar, SqlServerTypes.nvarchar, SqlServerTypes.nvarchar, ScalaDbTypes.SqlServerTypes.decimal.nullable, SqlServerTypes.date.nullable, ScalaDbTypes.SqlServerTypes.bit.nullable, SqlServerTypes.datetime2.nullable, SqlServerTypes.json.nullable, SqlServerTypes.xml.nullable, SqlServerTypes.varbinary.nullable, SqlServerTypes.uniqueidentifier.nullable, SqlServerTypes.datetimeoffset.nullable, SqlServerTypes.rowversion.nullable, SqlServerTypes.hierarchyid.nullable)(EmployeeRow.apply)(row => Array[Any](row.id, row.departmentId, row.managerId, row.email, row.firstName, row.lastName, row.salary, row.hiredAt, row.active, row.createdAt, row.metadata, row.resume, row.photo, row.employeeUid, row.lastModified, row.rowVersion, row.orgPath))\n}", - "EmployeeRowUnsaved": "package showcase.showcase.employee\n\nimport dev.typr.foundations.data.Json\nimport java.time.LocalDate\nimport java.time.LocalDateTime\nimport java.time.OffsetDateTime\nimport java.util.UUID\nimport showcase.customtypes.Defaulted\nimport showcase.customtypes.Defaulted.UseDefault\nimport showcase.showcase.department.DepartmentId\n\n/** This class corresponds to a row in table `showcase.employee` which has not been persisted yet */\ncase class EmployeeRowUnsaved(\n id: EmployeeId,\n /** Points to [[showcase.showcase.department.DepartmentRow.id]] */\n departmentId: DepartmentId,\n /** Points to [[showcase.showcase.employee.EmployeeRow.id]] */\n managerId: Option[EmployeeId] = None,\n email: String,\n firstName: String,\n lastName: String,\n salary: Option[BigDecimal] = None,\n hiredAt: Option[LocalDate] = None,\n metadata: Option[Json] = None,\n resume: Option[/* XML */ String] = None,\n photo: Option[Array[Byte]] = None,\n employeeUid: Option[UUID] = None,\n lastModified: Option[OffsetDateTime] = None,\n rowVersion: Option[/* ROWVERSION/TIMESTAMP */ Array[Byte]] = None,\n orgPath: Option[/* HIERARCHYID */ String] = None,\n /** Default: true */\n active: Defaulted[Option[Boolean]] = new UseDefault(),\n /** Default: CURRENT_TIMESTAMP */\n createdAt: Defaulted[Option[LocalDateTime]] = new UseDefault()\n) {\n def toRow(\n activeDefault: => Option[Boolean],\n createdAtDefault: => Option[LocalDateTime]\n ): EmployeeRow = {\n new EmployeeRow(\n id = id,\n departmentId = departmentId,\n managerId = managerId,\n email = email,\n firstName = firstName,\n lastName = lastName,\n salary = salary,\n hiredAt = hiredAt,\n active = active.getOrElse(activeDefault),\n createdAt = createdAt.getOrElse(createdAtDefault),\n metadata = metadata,\n resume = resume,\n photo = photo,\n employeeUid = employeeUid,\n lastModified = lastModified,\n rowVersion = rowVersion,\n orgPath = orgPath\n )\n }\n}", - "EmployeeId": "package showcase.showcase.employee\n\nimport dev.typr.foundations.SqlServerType\nimport dev.typr.foundations.SqlServerTypes\nimport dev.typr.foundations.scala.Bijection\n\n/** Type for the primary key of table `showcase.employee` */\ncase class EmployeeId(value: String) extends scala.AnyVal\n\nobject EmployeeId {\n given bijection: Bijection[EmployeeId, String] = Bijection.apply[EmployeeId, String](_.value)(EmployeeId.apply)\n\n given sqlServerType: SqlServerType[EmployeeId] = SqlServerTypes.nvarchar.bimap(EmployeeId.apply, _.value)\n}", - "EmployeeRepo": "package showcase.showcase.employee\n\nimport dev.typr.foundations.scala.DeleteBuilder\nimport dev.typr.foundations.scala.SelectBuilder\nimport dev.typr.foundations.scala.UpdateBuilder\nimport java.sql.Connection\n\ntrait EmployeeRepo {\n def delete: DeleteBuilder[EmployeeFields, EmployeeRow]\n\n def deleteById(id: EmployeeId)(using c: Connection): Boolean\n\n def deleteByIds(ids: Array[EmployeeId])(using c: Connection): Int\n\n def insert(unsaved: EmployeeRow)(using c: Connection): EmployeeRow\n\n def insert(unsaved: EmployeeRowUnsaved)(using c: Connection): EmployeeRow\n\n def select: SelectBuilder[EmployeeFields, EmployeeRow]\n\n def selectAll(using c: Connection): List[EmployeeRow]\n\n def selectById(id: EmployeeId)(using c: Connection): Option[EmployeeRow]\n\n def selectByIds(ids: Array[EmployeeId])(using c: Connection): List[EmployeeRow]\n\n def selectByIdsTracked(ids: Array[EmployeeId])(using c: Connection): Map[EmployeeId, EmployeeRow]\n\n def selectByUniqueEmail(email: String)(using c: Connection): Option[EmployeeRow]\n\n def update: UpdateBuilder[EmployeeFields, EmployeeRow]\n\n def update(row: EmployeeRow)(using c: Connection): Boolean\n\n def upsert(unsaved: EmployeeRow)(using c: Connection): EmployeeRow\n\n def upsertBatch(unsaved: Iterator[EmployeeRow])(using c: Connection): List[EmployeeRow]\n}", - "EmployeeRepoImpl": "package showcase.showcase.employee\n\nimport dev.typr.foundations.SqlServerTypes\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.DeleteBuilder\nimport dev.typr.foundations.scala.Dialect\nimport dev.typr.foundations.scala.Fragment\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport dev.typr.foundations.scala.SelectBuilder\nimport dev.typr.foundations.scala.UpdateBuilder\nimport java.sql.Connection\nimport scala.collection.mutable.ListBuffer\nimport showcase.showcase.department.DepartmentId\nimport dev.typr.foundations.scala.Fragment.sql\n\nclass EmployeeRepoImpl extends EmployeeRepo {\n override def delete: DeleteBuilder[EmployeeFields, EmployeeRow] = DeleteBuilder.of(\"[showcase].[employee]\", EmployeeFields.structure, Dialect.SQLSERVER)\n\n override def deleteById(id: EmployeeId)(using c: Connection): Boolean = sql\"delete from [showcase].[employee] where [id] = ${Fragment.encode(EmployeeId.sqlServerType, id)}\".update().runUnchecked(c) > 0\n\n override def deleteByIds(ids: Array[EmployeeId])(using c: Connection): Int = {\n val fragments: ListBuffer[Fragment] = ListBuffer()\n ids.foreach { id => fragments.addOne(Fragment.encode(EmployeeId.sqlServerType, id)): @scala.annotation.nowarn }\n return Fragment.interpolate(Fragment.lit(\"delete from [showcase].[employee] where [id] in (\"), Fragment.comma(fragments), Fragment.lit(\")\")).update().runUnchecked(c)\n }\n\n override def insert(unsaved: EmployeeRow)(using c: Connection): EmployeeRow = {\n sql\"\"\"insert into [showcase].[employee]([id], [department_id], [manager_id], [email], [first_name], [last_name], [salary], [hired_at], [active], [created_at], [metadata], [resume], [photo], [employee_uid], [last_modified], [row_version], [org_path])\n OUTPUT INSERTED.[id], INSERTED.[department_id], INSERTED.[manager_id], INSERTED.[email], INSERTED.[first_name], INSERTED.[last_name], INSERTED.[salary], INSERTED.[hired_at], INSERTED.[active], INSERTED.[created_at], INSERTED.[metadata], INSERTED.[resume], INSERTED.[photo], INSERTED.[employee_uid], INSERTED.[last_modified], INSERTED.[row_version], INSERTED.[org_path]\n values (${Fragment.encode(EmployeeId.sqlServerType, unsaved.id)}, ${Fragment.encode(DepartmentId.sqlServerType, unsaved.departmentId)}, ${Fragment.encode(EmployeeId.sqlServerType.nullable, unsaved.managerId)}, ${Fragment.encode(SqlServerTypes.nvarchar, unsaved.email)}, ${Fragment.encode(SqlServerTypes.nvarchar, unsaved.firstName)}, ${Fragment.encode(SqlServerTypes.nvarchar, unsaved.lastName)}, ${Fragment.encode(ScalaDbTypes.SqlServerTypes.decimal.nullable, unsaved.salary)}, ${Fragment.encode(SqlServerTypes.date.nullable, unsaved.hiredAt)}, ${Fragment.encode(ScalaDbTypes.SqlServerTypes.bit.nullable, unsaved.active)}, ${Fragment.encode(SqlServerTypes.datetime2.nullable, unsaved.createdAt)}, ${Fragment.encode(SqlServerTypes.json.nullable, unsaved.metadata)}, ${Fragment.encode(SqlServerTypes.xml.nullable, unsaved.resume)}, ${Fragment.encode(SqlServerTypes.varbinary.nullable, unsaved.photo)}, ${Fragment.encode(SqlServerTypes.uniqueidentifier.nullable, unsaved.employeeUid)}, ${Fragment.encode(SqlServerTypes.datetimeoffset.nullable, unsaved.lastModified)}, ${Fragment.encode(SqlServerTypes.rowversion.nullable, unsaved.rowVersion)}, ${Fragment.encode(SqlServerTypes.hierarchyid.nullable, unsaved.orgPath)})\n \"\"\"\n .updateReturning(EmployeeRow.`_rowParser`.exactlyOne()).runUnchecked(c)\n }\n\n override def insert(unsaved: EmployeeRowUnsaved)(using c: Connection): EmployeeRow = {\n val columns: ListBuffer[Fragment] = ListBuffer()\n val values: ListBuffer[Fragment] = ListBuffer()\n columns.addOne(Fragment.lit(\"[id]\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(EmployeeId.sqlServerType, unsaved.id)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"[department_id]\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(DepartmentId.sqlServerType, unsaved.departmentId)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"[manager_id]\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(EmployeeId.sqlServerType.nullable, unsaved.managerId)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"[email]\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(SqlServerTypes.nvarchar, unsaved.email)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"[first_name]\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(SqlServerTypes.nvarchar, unsaved.firstName)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"[last_name]\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(SqlServerTypes.nvarchar, unsaved.lastName)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"[salary]\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(ScalaDbTypes.SqlServerTypes.decimal.nullable, unsaved.salary)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"[hired_at]\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(SqlServerTypes.date.nullable, unsaved.hiredAt)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"[metadata]\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(SqlServerTypes.json.nullable, unsaved.metadata)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"[resume]\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(SqlServerTypes.xml.nullable, unsaved.resume)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"[photo]\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(SqlServerTypes.varbinary.nullable, unsaved.photo)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"[employee_uid]\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(SqlServerTypes.uniqueidentifier.nullable, unsaved.employeeUid)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"[last_modified]\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(SqlServerTypes.datetimeoffset.nullable, unsaved.lastModified)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"[row_version]\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(SqlServerTypes.rowversion.nullable, unsaved.rowVersion)}\"): @scala.annotation.nowarn\n columns.addOne(Fragment.lit(\"[org_path]\")): @scala.annotation.nowarn\n values.addOne(sql\"${Fragment.encode(SqlServerTypes.hierarchyid.nullable, unsaved.orgPath)}\"): @scala.annotation.nowarn\n unsaved.active.visit(\n { },\n value => { columns.addOne(Fragment.lit(\"[active]\")): @scala.annotation.nowarn; values.addOne(sql\"${Fragment.encode(ScalaDbTypes.SqlServerTypes.bit.nullable, value)}\"): @scala.annotation.nowarn }\n );\n unsaved.createdAt.visit(\n { },\n value => { columns.addOne(Fragment.lit(\"[created_at]\")): @scala.annotation.nowarn; values.addOne(sql\"${Fragment.encode(SqlServerTypes.datetime2.nullable, value)}\"): @scala.annotation.nowarn }\n );\n val q: Fragment = {\n sql\"\"\"insert into [showcase].[employee](${Fragment.comma(columns)})\n OUTPUT INSERTED.[id], INSERTED.[department_id], INSERTED.[manager_id], INSERTED.[email], INSERTED.[first_name], INSERTED.[last_name], INSERTED.[salary], INSERTED.[hired_at], INSERTED.[active], INSERTED.[created_at], INSERTED.[metadata], INSERTED.[resume], INSERTED.[photo], INSERTED.[employee_uid], INSERTED.[last_modified], INSERTED.[row_version], INSERTED.[org_path]\n values (${Fragment.comma(values)})\n \"\"\"\n }\n return q.updateReturning(EmployeeRow.`_rowParser`.exactlyOne()).runUnchecked(c)\n }\n\n override def select: SelectBuilder[EmployeeFields, EmployeeRow] = SelectBuilder.of(\"[showcase].[employee]\", EmployeeFields.structure, EmployeeRow.`_rowParser`, Dialect.SQLSERVER)\n\n override def selectAll(using c: Connection): List[EmployeeRow] = {\n sql\"\"\"select [id], [department_id], [manager_id], [email], [first_name], [last_name], [salary], [hired_at], [active], [created_at], [metadata], [resume], [photo], [employee_uid], [last_modified], [row_version], [org_path]\n from [showcase].[employee]\n \"\"\".query(EmployeeRow.`_rowParser`.all()).runUnchecked(c)\n }\n\n override def selectById(id: EmployeeId)(using c: Connection): Option[EmployeeRow] = {\n sql\"\"\"select [id], [department_id], [manager_id], [email], [first_name], [last_name], [salary], [hired_at], [active], [created_at], [metadata], [resume], [photo], [employee_uid], [last_modified], [row_version], [org_path]\n from [showcase].[employee]\n where [id] = ${Fragment.encode(EmployeeId.sqlServerType, id)}\"\"\".query(EmployeeRow.`_rowParser`.first()).runUnchecked(c)\n }\n\n override def selectByIds(ids: Array[EmployeeId])(using c: Connection): List[EmployeeRow] = {\n val fragments: ListBuffer[Fragment] = ListBuffer()\n ids.foreach { id => fragments.addOne(Fragment.encode(EmployeeId.sqlServerType, id)): @scala.annotation.nowarn }\n return Fragment.interpolate(Fragment.lit(\"select [id], [department_id], [manager_id], [email], [first_name], [last_name], [salary], [hired_at], [active], [created_at], [metadata], [resume], [photo], [employee_uid], [last_modified], [row_version], [org_path] from [showcase].[employee] where [id] in (\"), Fragment.comma(fragments), Fragment.lit(\")\")).query(EmployeeRow.`_rowParser`.all()).runUnchecked(c)\n }\n\n override def selectByIdsTracked(ids: Array[EmployeeId])(using c: Connection): Map[EmployeeId, EmployeeRow] = {\n val ret: scala.collection.mutable.Map[EmployeeId, EmployeeRow] = scala.collection.mutable.Map.empty[EmployeeId, EmployeeRow]\n selectByIds(ids)(using c).foreach(row => ret.put(row.id, row): @scala.annotation.nowarn)\n return ret.toMap\n }\n\n override def selectByUniqueEmail(email: String)(using c: Connection): Option[EmployeeRow] = {\n sql\"\"\"select [id], [department_id], [manager_id], [email], [first_name], [last_name], [salary], [hired_at], [active], [created_at], [metadata], [resume], [photo], [employee_uid], [last_modified], [row_version], [org_path]\n from [showcase].[employee]\n where [email] = ${Fragment.encode(SqlServerTypes.nvarchar, email)}\n \"\"\".query(EmployeeRow.`_rowParser`.first()).runUnchecked(c)\n }\n\n override def update: UpdateBuilder[EmployeeFields, EmployeeRow] = UpdateBuilder.of(\"[showcase].[employee]\", EmployeeFields.structure, EmployeeRow.`_rowParser`, Dialect.SQLSERVER)\n\n override def update(row: EmployeeRow)(using c: Connection): Boolean = {\n val id: EmployeeId = row.id\n return sql\"\"\"update [showcase].[employee]\n set [department_id] = ${Fragment.encode(DepartmentId.sqlServerType, row.departmentId)},\n [manager_id] = ${Fragment.encode(EmployeeId.sqlServerType.nullable, row.managerId)},\n [email] = ${Fragment.encode(SqlServerTypes.nvarchar, row.email)},\n [first_name] = ${Fragment.encode(SqlServerTypes.nvarchar, row.firstName)},\n [last_name] = ${Fragment.encode(SqlServerTypes.nvarchar, row.lastName)},\n [salary] = ${Fragment.encode(ScalaDbTypes.SqlServerTypes.decimal.nullable, row.salary)},\n [hired_at] = ${Fragment.encode(SqlServerTypes.date.nullable, row.hiredAt)},\n [active] = ${Fragment.encode(ScalaDbTypes.SqlServerTypes.bit.nullable, row.active)},\n [created_at] = ${Fragment.encode(SqlServerTypes.datetime2.nullable, row.createdAt)},\n [metadata] = ${Fragment.encode(SqlServerTypes.json.nullable, row.metadata)},\n [resume] = ${Fragment.encode(SqlServerTypes.xml.nullable, row.resume)},\n [photo] = ${Fragment.encode(SqlServerTypes.varbinary.nullable, row.photo)},\n [employee_uid] = ${Fragment.encode(SqlServerTypes.uniqueidentifier.nullable, row.employeeUid)},\n [last_modified] = ${Fragment.encode(SqlServerTypes.datetimeoffset.nullable, row.lastModified)},\n [row_version] = ${Fragment.encode(SqlServerTypes.rowversion.nullable, row.rowVersion)},\n [org_path] = ${Fragment.encode(SqlServerTypes.hierarchyid.nullable, row.orgPath)}\n where [id] = ${Fragment.encode(EmployeeId.sqlServerType, id)}\"\"\".update().runUnchecked(c) > 0\n }\n\n override def upsert(unsaved: EmployeeRow)(using c: Connection): EmployeeRow = {\n sql\"\"\"MERGE INTO [showcase].[employee] AS target\n USING (VALUES (${Fragment.encode(EmployeeId.sqlServerType, unsaved.id)}, ${Fragment.encode(DepartmentId.sqlServerType, unsaved.departmentId)}, ${Fragment.encode(EmployeeId.sqlServerType.nullable, unsaved.managerId)}, ${Fragment.encode(SqlServerTypes.nvarchar, unsaved.email)}, ${Fragment.encode(SqlServerTypes.nvarchar, unsaved.firstName)}, ${Fragment.encode(SqlServerTypes.nvarchar, unsaved.lastName)}, ${Fragment.encode(ScalaDbTypes.SqlServerTypes.decimal.nullable, unsaved.salary)}, ${Fragment.encode(SqlServerTypes.date.nullable, unsaved.hiredAt)}, ${Fragment.encode(ScalaDbTypes.SqlServerTypes.bit.nullable, unsaved.active)}, ${Fragment.encode(SqlServerTypes.datetime2.nullable, unsaved.createdAt)}, ${Fragment.encode(SqlServerTypes.json.nullable, unsaved.metadata)}, ${Fragment.encode(SqlServerTypes.xml.nullable, unsaved.resume)}, ${Fragment.encode(SqlServerTypes.varbinary.nullable, unsaved.photo)}, ${Fragment.encode(SqlServerTypes.uniqueidentifier.nullable, unsaved.employeeUid)}, ${Fragment.encode(SqlServerTypes.datetimeoffset.nullable, unsaved.lastModified)}, ${Fragment.encode(SqlServerTypes.rowversion.nullable, unsaved.rowVersion)}, ${Fragment.encode(SqlServerTypes.hierarchyid.nullable, unsaved.orgPath)})) AS source([id], [department_id], [manager_id], [email], [first_name], [last_name], [salary], [hired_at], [active], [created_at], [metadata], [resume], [photo], [employee_uid], [last_modified], [row_version], [org_path])\n ON target.[id] = source.[id]\n WHEN MATCHED THEN UPDATE SET [department_id] = source.[department_id],\n [manager_id] = source.[manager_id],\n [email] = source.[email],\n [first_name] = source.[first_name],\n [last_name] = source.[last_name],\n [salary] = source.[salary],\n [hired_at] = source.[hired_at],\n [active] = source.[active],\n [created_at] = source.[created_at],\n [metadata] = source.[metadata],\n [resume] = source.[resume],\n [photo] = source.[photo],\n [employee_uid] = source.[employee_uid],\n [last_modified] = source.[last_modified],\n [row_version] = source.[row_version],\n [org_path] = source.[org_path]\n WHEN NOT MATCHED THEN INSERT ([id], [department_id], [manager_id], [email], [first_name], [last_name], [salary], [hired_at], [active], [created_at], [metadata], [resume], [photo], [employee_uid], [last_modified], [row_version], [org_path]) VALUES (${Fragment.encode(EmployeeId.sqlServerType, unsaved.id)}, ${Fragment.encode(DepartmentId.sqlServerType, unsaved.departmentId)}, ${Fragment.encode(EmployeeId.sqlServerType.nullable, unsaved.managerId)}, ${Fragment.encode(SqlServerTypes.nvarchar, unsaved.email)}, ${Fragment.encode(SqlServerTypes.nvarchar, unsaved.firstName)}, ${Fragment.encode(SqlServerTypes.nvarchar, unsaved.lastName)}, ${Fragment.encode(ScalaDbTypes.SqlServerTypes.decimal.nullable, unsaved.salary)}, ${Fragment.encode(SqlServerTypes.date.nullable, unsaved.hiredAt)}, ${Fragment.encode(ScalaDbTypes.SqlServerTypes.bit.nullable, unsaved.active)}, ${Fragment.encode(SqlServerTypes.datetime2.nullable, unsaved.createdAt)}, ${Fragment.encode(SqlServerTypes.json.nullable, unsaved.metadata)}, ${Fragment.encode(SqlServerTypes.xml.nullable, unsaved.resume)}, ${Fragment.encode(SqlServerTypes.varbinary.nullable, unsaved.photo)}, ${Fragment.encode(SqlServerTypes.uniqueidentifier.nullable, unsaved.employeeUid)}, ${Fragment.encode(SqlServerTypes.datetimeoffset.nullable, unsaved.lastModified)}, ${Fragment.encode(SqlServerTypes.rowversion.nullable, unsaved.rowVersion)}, ${Fragment.encode(SqlServerTypes.hierarchyid.nullable, unsaved.orgPath)})\n OUTPUT INSERTED.[id], INSERTED.[department_id], INSERTED.[manager_id], INSERTED.[email], INSERTED.[first_name], INSERTED.[last_name], INSERTED.[salary], INSERTED.[hired_at], INSERTED.[active], INSERTED.[created_at], INSERTED.[metadata], INSERTED.[resume], INSERTED.[photo], INSERTED.[employee_uid], INSERTED.[last_modified], INSERTED.[row_version], INSERTED.[org_path];\"\"\"\n .updateReturning(EmployeeRow.`_rowParser`.exactlyOne())\n .runUnchecked(c)\n }\n\n override def upsertBatch(unsaved: Iterator[EmployeeRow])(using c: Connection): List[EmployeeRow] = {\n sql\"\"\"MERGE INTO [showcase].[employee] AS target\n USING (VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)) AS source([id], [department_id], [manager_id], [email], [first_name], [last_name], [salary], [hired_at], [active], [created_at], [metadata], [resume], [photo], [employee_uid], [last_modified], [row_version], [org_path])\n ON target.[id] = source.[id]\n WHEN MATCHED THEN UPDATE SET [department_id] = source.[department_id],\n [manager_id] = source.[manager_id],\n [email] = source.[email],\n [first_name] = source.[first_name],\n [last_name] = source.[last_name],\n [salary] = source.[salary],\n [hired_at] = source.[hired_at],\n [active] = source.[active],\n [created_at] = source.[created_at],\n [metadata] = source.[metadata],\n [resume] = source.[resume],\n [photo] = source.[photo],\n [employee_uid] = source.[employee_uid],\n [last_modified] = source.[last_modified],\n [row_version] = source.[row_version],\n [org_path] = source.[org_path]\n WHEN NOT MATCHED THEN INSERT ([id], [department_id], [manager_id], [email], [first_name], [last_name], [salary], [hired_at], [active], [created_at], [metadata], [resume], [photo], [employee_uid], [last_modified], [row_version], [org_path]) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n OUTPUT INSERTED.[id], INSERTED.[department_id], INSERTED.[manager_id], INSERTED.[email], INSERTED.[first_name], INSERTED.[last_name], INSERTED.[salary], INSERTED.[hired_at], INSERTED.[active], INSERTED.[created_at], INSERTED.[metadata], INSERTED.[resume], INSERTED.[photo], INSERTED.[employee_uid], INSERTED.[last_modified], INSERTED.[row_version], INSERTED.[org_path];\"\"\"\n .updateReturningEach(EmployeeRow.`_rowParser`, unsaved)\n .runUnchecked(c)\n }\n}", - "EmployeeRepoMock": "package showcase.showcase.employee\n\nimport dev.typr.foundations.scala.DeleteBuilder\nimport dev.typr.foundations.scala.DeleteBuilderMock\nimport dev.typr.foundations.scala.DeleteParams\nimport dev.typr.foundations.scala.SelectBuilder\nimport dev.typr.foundations.scala.SelectBuilderMock\nimport dev.typr.foundations.scala.SelectParams\nimport dev.typr.foundations.scala.UpdateBuilder\nimport dev.typr.foundations.scala.UpdateBuilderMock\nimport dev.typr.foundations.scala.UpdateParams\nimport java.lang.RuntimeException\nimport java.sql.Connection\n\ncase class EmployeeRepoMock(\n toRow: EmployeeRowUnsaved => EmployeeRow,\n map: scala.collection.mutable.Map[EmployeeId, EmployeeRow] = scala.collection.mutable.Map.empty[EmployeeId, EmployeeRow]\n) extends EmployeeRepo {\n override def delete: DeleteBuilder[EmployeeFields, EmployeeRow] = DeleteBuilderMock(EmployeeFields.structure, () => map.values.toList, DeleteParams.empty(), row => row.id, id => map.remove(id): @scala.annotation.nowarn)\n\n override def deleteById(id: EmployeeId)(using c: Connection): Boolean = map.remove(id).isDefined\n\n override def deleteByIds(ids: Array[EmployeeId])(using c: Connection): Int = {\n var count = 0\n ids.foreach { id => if (map.remove(id).isDefined) {\n count = count + 1\n } }\n return count\n }\n\n override def insert(unsaved: EmployeeRow)(using c: Connection): EmployeeRow = {\n if (map.contains(unsaved.id)) {\n throw new RuntimeException(s\"id ${unsaved.id} already exists\")\n }\n map.put(unsaved.id, unsaved): @scala.annotation.nowarn\n return unsaved\n }\n\n override def insert(unsaved: EmployeeRowUnsaved)(using c: Connection): EmployeeRow = insert(toRow(unsaved))(using c)\n\n override def select: SelectBuilder[EmployeeFields, EmployeeRow] = SelectBuilderMock(EmployeeFields.structure, () => map.values.toList, SelectParams.empty())\n\n override def selectAll(using c: Connection): List[EmployeeRow] = map.values.toList\n\n override def selectById(id: EmployeeId)(using c: Connection): Option[EmployeeRow] = map.get(id)\n\n override def selectByIds(ids: Array[EmployeeId])(using c: Connection): List[EmployeeRow] = ids.flatMap(map.get(_)).toList\n\n override def selectByIdsTracked(ids: Array[EmployeeId])(using c: Connection): Map[EmployeeId, EmployeeRow] = selectByIds(ids)(using c).map(x => (((row: EmployeeRow) => row.id).apply(x), x)).toMap\n\n override def selectByUniqueEmail(email: String)(using c: Connection): Option[EmployeeRow] = map.values.toList.find(v => (email == v.email))\n\n override def update: UpdateBuilder[EmployeeFields, EmployeeRow] = UpdateBuilderMock(EmployeeFields.structure, () => map.values.toList, UpdateParams.empty(), row => row)\n\n override def update(row: EmployeeRow)(using c: Connection): Boolean = {\n val shouldUpdate = map.get(row.id).filter(oldRow => (oldRow != row)).isDefined\n if (shouldUpdate) {\n map.put(row.id, row): @scala.annotation.nowarn\n }\n return shouldUpdate\n }\n\n override def upsert(unsaved: EmployeeRow)(using c: Connection): EmployeeRow = {\n map.put(unsaved.id, unsaved): @scala.annotation.nowarn\n return unsaved\n }\n\n override def upsertBatch(unsaved: Iterator[EmployeeRow])(using c: Connection): List[EmployeeRow] = {\n unsaved.map { row =>\n map.put(row.id, row): @scala.annotation.nowarn\n row\n }.toList\n }\n}", - "EmployeeFields": "package showcase.showcase.employee\n\nimport dev.typr.foundations.RowParser\nimport dev.typr.foundations.SqlServerTypes\nimport dev.typr.foundations.data.Json\nimport dev.typr.foundations.dsl.FieldsExpr0\nimport dev.typr.foundations.dsl.Path\nimport dev.typr.foundations.dsl.SqlExpr.FieldLike\nimport dev.typr.foundations.scala.ForeignKey\nimport dev.typr.foundations.scala.RelationStructure\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport dev.typr.foundations.scala.SqlExpr.Field\nimport dev.typr.foundations.scala.SqlExpr.IdField\nimport dev.typr.foundations.scala.SqlExpr.OptField\nimport java.time.LocalDate\nimport java.time.LocalDateTime\nimport java.time.OffsetDateTime\nimport java.util.UUID\nimport showcase.showcase.department.DepartmentFields\nimport showcase.showcase.department.DepartmentId\nimport showcase.showcase.department.DepartmentRow\n\ntrait EmployeeFields extends FieldsExpr0[EmployeeRow] {\n def id: IdField[EmployeeId, EmployeeRow]\n\n def departmentId: Field[DepartmentId, EmployeeRow]\n\n def managerId: OptField[EmployeeId, EmployeeRow]\n\n def email: Field[String, EmployeeRow]\n\n def firstName: Field[String, EmployeeRow]\n\n def lastName: Field[String, EmployeeRow]\n\n def salary: OptField[BigDecimal, EmployeeRow]\n\n def hiredAt: OptField[LocalDate, EmployeeRow]\n\n def active: OptField[Boolean, EmployeeRow]\n\n def createdAt: OptField[LocalDateTime, EmployeeRow]\n\n def metadata: OptField[Json, EmployeeRow]\n\n def resume: OptField[/* XML */ String, EmployeeRow]\n\n def photo: OptField[Array[Byte], EmployeeRow]\n\n def employeeUid: OptField[UUID, EmployeeRow]\n\n def lastModified: OptField[OffsetDateTime, EmployeeRow]\n\n def rowVersion: OptField[/* ROWVERSION/TIMESTAMP */ Array[Byte], EmployeeRow]\n\n def orgPath: OptField[/* HIERARCHYID */ String, EmployeeRow]\n\n def fkDepartment: ForeignKey[DepartmentFields, DepartmentRow] = ForeignKey.of[DepartmentFields, DepartmentRow](\"employee_department_fk\").withColumnPair[DepartmentId](departmentId, _.id)\n\n def fkEmployee: ForeignKey[EmployeeFields, EmployeeRow] = ForeignKey.of[EmployeeFields, EmployeeRow](\"employee_manager_fk\").withColumnPair[EmployeeId](managerId, _.id)\n\n override def columns: java.util.List[FieldLike[?, EmployeeRow]]\n\n override def rowParser: RowParser[EmployeeRow] = EmployeeRow._rowParser.underlying\n}\n\nobject EmployeeFields {\n case class Impl(val `_path`: java.util.List[Path]) extends EmployeeFields with RelationStructure[EmployeeFields, EmployeeRow] {\n\n override def id: IdField[EmployeeId, EmployeeRow] = {\n new IdField[EmployeeId, EmployeeRow](\n _path,\n \"id\",\n _.id,\n None,\n None,\n (row, value) => row.copy(id = value),\n EmployeeId.sqlServerType\n )\n }\n\n override def departmentId: Field[DepartmentId, EmployeeRow] = {\n new Field[DepartmentId, EmployeeRow](\n _path,\n \"department_id\",\n _.departmentId,\n None,\n None,\n (row, value) => row.copy(departmentId = value),\n DepartmentId.sqlServerType\n )\n }\n\n override def managerId: OptField[EmployeeId, EmployeeRow] = {\n new OptField[EmployeeId, EmployeeRow](\n _path,\n \"manager_id\",\n _.managerId,\n None,\n None,\n (row, value) => row.copy(managerId = value),\n EmployeeId.sqlServerType\n )\n }\n\n override def email: Field[String, EmployeeRow] = {\n new Field[String, EmployeeRow](\n _path,\n \"email\",\n _.email,\n None,\n None,\n (row, value) => row.copy(email = value),\n SqlServerTypes.nvarchar\n )\n }\n\n override def firstName: Field[String, EmployeeRow] = {\n new Field[String, EmployeeRow](\n _path,\n \"first_name\",\n _.firstName,\n None,\n None,\n (row, value) => row.copy(firstName = value),\n SqlServerTypes.nvarchar\n )\n }\n\n override def lastName: Field[String, EmployeeRow] = {\n new Field[String, EmployeeRow](\n _path,\n \"last_name\",\n _.lastName,\n None,\n None,\n (row, value) => row.copy(lastName = value),\n SqlServerTypes.nvarchar\n )\n }\n\n override def salary: OptField[BigDecimal, EmployeeRow] = {\n new OptField[BigDecimal, EmployeeRow](\n _path,\n \"salary\",\n _.salary,\n None,\n None,\n (row, value) => row.copy(salary = value),\n ScalaDbTypes.SqlServerTypes.decimal\n )\n }\n\n override def hiredAt: OptField[LocalDate, EmployeeRow] = {\n new OptField[LocalDate, EmployeeRow](\n _path,\n \"hired_at\",\n _.hiredAt,\n None,\n None,\n (row, value) => row.copy(hiredAt = value),\n SqlServerTypes.date\n )\n }\n\n override def active: OptField[Boolean, EmployeeRow] = {\n new OptField[Boolean, EmployeeRow](\n _path,\n \"active\",\n _.active,\n None,\n None,\n (row, value) => row.copy(active = value),\n ScalaDbTypes.SqlServerTypes.bit\n )\n }\n\n override def createdAt: OptField[LocalDateTime, EmployeeRow] = {\n new OptField[LocalDateTime, EmployeeRow](\n _path,\n \"created_at\",\n _.createdAt,\n None,\n None,\n (row, value) => row.copy(createdAt = value),\n SqlServerTypes.datetime2\n )\n }\n\n override def metadata: OptField[Json, EmployeeRow] = {\n new OptField[Json, EmployeeRow](\n _path,\n \"metadata\",\n _.metadata,\n None,\n None,\n (row, value) => row.copy(metadata = value),\n SqlServerTypes.json\n )\n }\n\n override def resume: OptField[String, EmployeeRow] = {\n new OptField[String, EmployeeRow](\n _path,\n \"resume\",\n _.resume,\n None,\n None,\n (row, value) => row.copy(resume = value),\n SqlServerTypes.xml\n )\n }\n\n override def photo: OptField[Array[Byte], EmployeeRow] = {\n new OptField[Array[Byte], EmployeeRow](\n _path,\n \"photo\",\n _.photo,\n None,\n None,\n (row, value) => row.copy(photo = value),\n SqlServerTypes.varbinary\n )\n }\n\n override def employeeUid: OptField[UUID, EmployeeRow] = {\n new OptField[UUID, EmployeeRow](\n _path,\n \"employee_uid\",\n _.employeeUid,\n None,\n None,\n (row, value) => row.copy(employeeUid = value),\n SqlServerTypes.uniqueidentifier\n )\n }\n\n override def lastModified: OptField[OffsetDateTime, EmployeeRow] = {\n new OptField[OffsetDateTime, EmployeeRow](\n _path,\n \"last_modified\",\n _.lastModified,\n None,\n None,\n (row, value) => row.copy(lastModified = value),\n SqlServerTypes.datetimeoffset\n )\n }\n\n override def rowVersion: OptField[Array[Byte], EmployeeRow] = {\n new OptField[Array[Byte], EmployeeRow](\n _path,\n \"row_version\",\n _.rowVersion,\n None,\n None,\n (row, value) => row.copy(rowVersion = value),\n SqlServerTypes.rowversion\n )\n }\n\n override def orgPath: OptField[String, EmployeeRow] = {\n new OptField[String, EmployeeRow](\n _path,\n \"org_path\",\n _.orgPath,\n None,\n None,\n (row, value) => row.copy(orgPath = value),\n SqlServerTypes.hierarchyid\n )\n }\n\n override def columns: java.util.List[FieldLike[?, EmployeeRow]] = java.util.List.of(this.id.underlying, this.departmentId.underlying, this.managerId.underlying, this.email.underlying, this.firstName.underlying, this.lastName.underlying, this.salary.underlying, this.hiredAt.underlying, this.active.underlying, this.createdAt.underlying, this.metadata.underlying, this.resume.underlying, this.photo.underlying, this.employeeUid.underlying, this.lastModified.underlying, this.rowVersion.underlying, this.orgPath.underlying)\n\n override def withPaths(`_path`: java.util.List[Path]): RelationStructure[EmployeeFields, EmployeeRow] = new Impl(`_path`)\n }\n\n def structure: Impl = new Impl(java.util.Collections.emptyList())\n}", - "DepartmentRow": "package showcase.showcase.department\n\nimport dev.typr.foundations.SqlServerTypes\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport showcase.showcase.company.CompanyId\n\n/** Table: showcase.department\n * Primary key: id\n */\ncase class DepartmentRow(\n id: DepartmentId,\n /** Points to [[showcase.showcase.company.CompanyRow.id]] */\n companyId: CompanyId,\n name: String,\n budget: Option[BigDecimal]\n)\n\nobject DepartmentRow {\n val `_rowParser`: RowParser[DepartmentRow] = RowParsers.of(DepartmentId.sqlServerType, CompanyId.sqlServerType, SqlServerTypes.nvarchar, ScalaDbTypes.SqlServerTypes.decimal.nullable)(DepartmentRow.apply)(row => Array[Any](row.id, row.companyId, row.name, row.budget))\n}", - "DepartmentId": "package showcase.showcase.department\n\nimport dev.typr.foundations.SqlServerType\nimport dev.typr.foundations.SqlServerTypes\nimport dev.typr.foundations.scala.Bijection\n\n/** Type for the primary key of table `showcase.department` */\ncase class DepartmentId(value: String) extends scala.AnyVal\n\nobject DepartmentId {\n given bijection: Bijection[DepartmentId, String] = Bijection.apply[DepartmentId, String](_.value)(DepartmentId.apply)\n\n given sqlServerType: SqlServerType[DepartmentId] = SqlServerTypes.nvarchar.bimap(DepartmentId.apply, _.value)\n}", - "DepartmentRepo": "package showcase.showcase.department\n\nimport dev.typr.foundations.scala.DeleteBuilder\nimport dev.typr.foundations.scala.SelectBuilder\nimport dev.typr.foundations.scala.UpdateBuilder\nimport java.sql.Connection\n\ntrait DepartmentRepo {\n def delete: DeleteBuilder[DepartmentFields, DepartmentRow]\n\n def deleteById(id: DepartmentId)(using c: Connection): Boolean\n\n def deleteByIds(ids: Array[DepartmentId])(using c: Connection): Int\n\n def insert(unsaved: DepartmentRow)(using c: Connection): DepartmentRow\n\n def select: SelectBuilder[DepartmentFields, DepartmentRow]\n\n def selectAll(using c: Connection): List[DepartmentRow]\n\n def selectById(id: DepartmentId)(using c: Connection): Option[DepartmentRow]\n\n def selectByIds(ids: Array[DepartmentId])(using c: Connection): List[DepartmentRow]\n\n def selectByIdsTracked(ids: Array[DepartmentId])(using c: Connection): Map[DepartmentId, DepartmentRow]\n\n def update: UpdateBuilder[DepartmentFields, DepartmentRow]\n\n def update(row: DepartmentRow)(using c: Connection): Boolean\n\n def upsert(unsaved: DepartmentRow)(using c: Connection): DepartmentRow\n\n def upsertBatch(unsaved: Iterator[DepartmentRow])(using c: Connection): List[DepartmentRow]\n}", - "DepartmentRepoMock": "package showcase.showcase.department\n\nimport dev.typr.foundations.scala.DeleteBuilder\nimport dev.typr.foundations.scala.DeleteBuilderMock\nimport dev.typr.foundations.scala.DeleteParams\nimport dev.typr.foundations.scala.SelectBuilder\nimport dev.typr.foundations.scala.SelectBuilderMock\nimport dev.typr.foundations.scala.SelectParams\nimport dev.typr.foundations.scala.UpdateBuilder\nimport dev.typr.foundations.scala.UpdateBuilderMock\nimport dev.typr.foundations.scala.UpdateParams\nimport java.lang.RuntimeException\nimport java.sql.Connection\n\ncase class DepartmentRepoMock(map: scala.collection.mutable.Map[DepartmentId, DepartmentRow] = scala.collection.mutable.Map.empty[DepartmentId, DepartmentRow]) extends DepartmentRepo {\n override def delete: DeleteBuilder[DepartmentFields, DepartmentRow] = DeleteBuilderMock(DepartmentFields.structure, () => map.values.toList, DeleteParams.empty(), row => row.id, id => map.remove(id): @scala.annotation.nowarn)\n\n override def deleteById(id: DepartmentId)(using c: Connection): Boolean = map.remove(id).isDefined\n\n override def deleteByIds(ids: Array[DepartmentId])(using c: Connection): Int = {\n var count = 0\n ids.foreach { id => if (map.remove(id).isDefined) {\n count = count + 1\n } }\n return count\n }\n\n override def insert(unsaved: DepartmentRow)(using c: Connection): DepartmentRow = {\n if (map.contains(unsaved.id)) {\n throw new RuntimeException(s\"id ${unsaved.id} already exists\")\n }\n map.put(unsaved.id, unsaved): @scala.annotation.nowarn\n return unsaved\n }\n\n override def select: SelectBuilder[DepartmentFields, DepartmentRow] = SelectBuilderMock(DepartmentFields.structure, () => map.values.toList, SelectParams.empty())\n\n override def selectAll(using c: Connection): List[DepartmentRow] = map.values.toList\n\n override def selectById(id: DepartmentId)(using c: Connection): Option[DepartmentRow] = map.get(id)\n\n override def selectByIds(ids: Array[DepartmentId])(using c: Connection): List[DepartmentRow] = ids.flatMap(map.get(_)).toList\n\n override def selectByIdsTracked(ids: Array[DepartmentId])(using c: Connection): Map[DepartmentId, DepartmentRow] = selectByIds(ids)(using c).map(x => (((row: DepartmentRow) => row.id).apply(x), x)).toMap\n\n override def update: UpdateBuilder[DepartmentFields, DepartmentRow] = UpdateBuilderMock(DepartmentFields.structure, () => map.values.toList, UpdateParams.empty(), row => row)\n\n override def update(row: DepartmentRow)(using c: Connection): Boolean = {\n val shouldUpdate = map.get(row.id).filter(oldRow => (oldRow != row)).isDefined\n if (shouldUpdate) {\n map.put(row.id, row): @scala.annotation.nowarn\n }\n return shouldUpdate\n }\n\n override def upsert(unsaved: DepartmentRow)(using c: Connection): DepartmentRow = {\n map.put(unsaved.id, unsaved): @scala.annotation.nowarn\n return unsaved\n }\n\n override def upsertBatch(unsaved: Iterator[DepartmentRow])(using c: Connection): List[DepartmentRow] = {\n unsaved.map { row =>\n map.put(row.id, row): @scala.annotation.nowarn\n row\n }.toList\n }\n}", - "ProjectAssignmentRow": "package showcase.showcase.project_assignment\n\nimport dev.typr.foundations.SqlServerTypes\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport java.time.LocalDate\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.employee.EmployeeId\nimport showcase.showcase.project.ProjectId\n\n/** Table: showcase.project_assignment\n * Composite primary key: employee_id, project_id\n */\ncase class ProjectAssignmentRow(\n /** Points to [[showcase.showcase.employee.EmployeeRow.id]] */\n employeeId: EmployeeId,\n /** Points to [[showcase.showcase.project.ProjectRow.id]] */\n projectId: ProjectId,\n role: String,\n /** Default: 0 */\n hoursAllocated: Option[Int],\n startDate: Option[LocalDate],\n endDate: Option[LocalDate]\n) {\n def compositeId: ProjectAssignmentId = new ProjectAssignmentId(employeeId, projectId)\n\n def id: ProjectAssignmentId = this.compositeId\n\n def toUnsavedRow(hoursAllocated: Defaulted[Option[Int]] = Defaulted.Provided(this.hoursAllocated)): ProjectAssignmentRowUnsaved = {\n new ProjectAssignmentRowUnsaved(\n employeeId,\n projectId,\n role,\n startDate,\n endDate,\n hoursAllocated\n )\n }\n}\n\nobject ProjectAssignmentRow {\n val `_rowParser`: RowParser[ProjectAssignmentRow] = RowParsers.of(EmployeeId.sqlServerType, ProjectId.sqlServerType, SqlServerTypes.nvarchar, ScalaDbTypes.SqlServerTypes.int_.nullable, SqlServerTypes.date.nullable, SqlServerTypes.date.nullable)(ProjectAssignmentRow.apply)(row => Array[Any](row.employeeId, row.projectId, row.role, row.hoursAllocated, row.startDate, row.endDate))\n\n def apply(\n compositeId: ProjectAssignmentId,\n role: String,\n hoursAllocated: Option[Int],\n startDate: Option[LocalDate],\n endDate: Option[LocalDate]\n ): ProjectAssignmentRow = {\n new ProjectAssignmentRow(\n compositeId.employeeId,\n compositeId.projectId,\n role,\n hoursAllocated,\n startDate,\n endDate\n )\n }\n}", - "ProjectAssignmentRowUnsaved": "package showcase.showcase.project_assignment\n\nimport java.time.LocalDate\nimport showcase.customtypes.Defaulted\nimport showcase.customtypes.Defaulted.UseDefault\nimport showcase.showcase.employee.EmployeeId\nimport showcase.showcase.project.ProjectId\n\n/** This class corresponds to a row in table `showcase.project_assignment` which has not been persisted yet */\ncase class ProjectAssignmentRowUnsaved(\n /** Points to [[showcase.showcase.employee.EmployeeRow.id]] */\n employeeId: EmployeeId,\n /** Points to [[showcase.showcase.project.ProjectRow.id]] */\n projectId: ProjectId,\n role: String,\n startDate: Option[LocalDate] = None,\n endDate: Option[LocalDate] = None,\n /** Default: 0 */\n hoursAllocated: Defaulted[Option[Int]] = new UseDefault()\n) {\n def toRow(hoursAllocatedDefault: => Option[Int]): ProjectAssignmentRow = {\n new ProjectAssignmentRow(\n employeeId = employeeId,\n projectId = projectId,\n role = role,\n hoursAllocated = hoursAllocated.getOrElse(hoursAllocatedDefault),\n startDate = startDate,\n endDate = endDate\n )\n }\n}", - "ProjectAssignmentId": "package showcase.showcase.project_assignment\n\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport showcase.showcase.employee.EmployeeId\nimport showcase.showcase.project.ProjectId\n\n/** Type for the composite primary key of table `showcase.project_assignment` */\ncase class ProjectAssignmentId(\n employeeId: EmployeeId,\n projectId: ProjectId\n)\n\nobject ProjectAssignmentId {\n val `_rowParser`: RowParser[ProjectAssignmentId] = RowParsers.of(EmployeeId.sqlServerType, ProjectId.sqlServerType)(ProjectAssignmentId.apply)(row => Array[Any](row.employeeId, row.projectId))\n}", - "ProjectAssignmentRepo": "package showcase.showcase.project_assignment\n\nimport dev.typr.foundations.scala.DeleteBuilder\nimport dev.typr.foundations.scala.SelectBuilder\nimport dev.typr.foundations.scala.UpdateBuilder\nimport java.sql.Connection\n\ntrait ProjectAssignmentRepo {\n def delete: DeleteBuilder[ProjectAssignmentFields, ProjectAssignmentRow]\n\n def deleteById(compositeId: ProjectAssignmentId)(using c: Connection): Boolean\n\n def deleteByIds(compositeIds: Array[ProjectAssignmentId])(using c: Connection): Int\n\n def insert(unsaved: ProjectAssignmentRow)(using c: Connection): ProjectAssignmentRow\n\n def insert(unsaved: ProjectAssignmentRowUnsaved)(using c: Connection): ProjectAssignmentRow\n\n def select: SelectBuilder[ProjectAssignmentFields, ProjectAssignmentRow]\n\n def selectAll(using c: Connection): List[ProjectAssignmentRow]\n\n def selectById(compositeId: ProjectAssignmentId)(using c: Connection): Option[ProjectAssignmentRow]\n\n def selectByIds(compositeIds: Array[ProjectAssignmentId])(using c: Connection): List[ProjectAssignmentRow]\n\n def selectByIdsTracked(compositeIds: Array[ProjectAssignmentId])(using c: Connection): Map[ProjectAssignmentId, ProjectAssignmentRow]\n\n def update: UpdateBuilder[ProjectAssignmentFields, ProjectAssignmentRow]\n\n def update(row: ProjectAssignmentRow)(using c: Connection): Boolean\n\n def upsert(unsaved: ProjectAssignmentRow)(using c: Connection): ProjectAssignmentRow\n\n def upsertBatch(unsaved: Iterator[ProjectAssignmentRow])(using c: Connection): List[ProjectAssignmentRow]\n}", - "ProjectRow": "package showcase.showcase.project\n\nimport dev.typr.foundations.SqlServerTypes\nimport dev.typr.foundations.data.Json\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport java.time.LocalDate\nimport java.time.LocalDateTime\nimport java.util.UUID\nimport showcase.customtypes.Defaulted\n\n/** Table: showcase.project\n * Primary key: id\n */\ncase class ProjectRow(\n id: ProjectId,\n name: String,\n description: Option[String],\n startDate: Option[LocalDate],\n endDate: Option[LocalDate],\n budget: Option[BigDecimal],\n /** Default: 'planning' */\n status: Option[String],\n /** Default: CURRENT_TIMESTAMP */\n createdAt: Option[LocalDateTime],\n projectUid: Option[UUID],\n metadata: Option[Json],\n xmlPlan: Option[/* XML */ String],\n attachments: Option[Array[Byte]],\n rowVersion: Option[/* ROWVERSION/TIMESTAMP */ Array[Byte]],\n totalBudget: Option[BigDecimal],\n orgPath: Option[/* HIERARCHYID */ String]\n) {\n def toUnsavedRow(\n status: Defaulted[Option[String]] = Defaulted.Provided(this.status),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.Provided(this.createdAt)\n ): ProjectRowUnsaved = {\n new ProjectRowUnsaved(\n id,\n name,\n description,\n startDate,\n endDate,\n budget,\n projectUid,\n metadata,\n xmlPlan,\n attachments,\n rowVersion,\n totalBudget,\n orgPath,\n status,\n createdAt\n )\n }\n}\n\nobject ProjectRow {\n val `_rowParser`: RowParser[ProjectRow] = RowParsers.of(ProjectId.sqlServerType, SqlServerTypes.nvarchar, SqlServerTypes.nvarchar.nullable, SqlServerTypes.date.nullable, SqlServerTypes.date.nullable, ScalaDbTypes.SqlServerTypes.decimal.nullable, SqlServerTypes.nvarchar.nullable, SqlServerTypes.datetime2.nullable, SqlServerTypes.uniqueidentifier.nullable, SqlServerTypes.json.nullable, SqlServerTypes.xml.nullable, SqlServerTypes.varbinary.nullable, SqlServerTypes.rowversion.nullable, ScalaDbTypes.SqlServerTypes.money.nullable, SqlServerTypes.hierarchyid.nullable)(ProjectRow.apply)(row => Array[Any](row.id, row.name, row.description, row.startDate, row.endDate, row.budget, row.status, row.createdAt, row.projectUid, row.metadata, row.xmlPlan, row.attachments, row.rowVersion, row.totalBudget, row.orgPath))\n}", - "ProjectId": "package showcase.showcase.project\n\nimport dev.typr.foundations.SqlServerType\nimport dev.typr.foundations.SqlServerTypes\nimport dev.typr.foundations.scala.Bijection\n\n/** Type for the primary key of table `showcase.project` */\ncase class ProjectId(value: String) extends scala.AnyVal\n\nobject ProjectId {\n given bijection: Bijection[ProjectId, String] = Bijection.apply[ProjectId, String](_.value)(ProjectId.apply)\n\n given sqlServerType: SqlServerType[ProjectId] = SqlServerTypes.nvarchar.bimap(ProjectId.apply, _.value)\n}", - "EmployeeSummaryViewRow": "package showcase.showcase.employee_summary\n\nimport dev.typr.foundations.SqlServerTypes\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport java.time.LocalDate\nimport showcase.showcase.company.CompanyId\nimport showcase.showcase.department.DepartmentId\nimport showcase.showcase.employee.EmployeeId\n\n/** View: showcase.employee_summary\n * Summary view of employees with their department and company information\n */\ncase class EmployeeSummaryViewRow(\n /** Points to [[showcase.showcase.employee.EmployeeRow.id]] */\n employeeId: EmployeeId,\n email: String,\n firstName: String,\n lastName: String,\n salary: Option[BigDecimal],\n hiredAt: Option[LocalDate],\n active: Option[Boolean],\n /** Points to [[showcase.showcase.department.DepartmentRow.id]] */\n departmentId: DepartmentId,\n departmentName: String,\n departmentBudget: Option[BigDecimal],\n /** Points to [[showcase.showcase.company.CompanyRow.id]] */\n companyId: CompanyId,\n companyName: String,\n managerId: Option[String],\n managerFirstName: Option[String],\n managerLastName: Option[String]\n)\n\nobject EmployeeSummaryViewRow {\n val `_rowParser`: RowParser[EmployeeSummaryViewRow] = RowParsers.of(EmployeeId.sqlServerType, SqlServerTypes.nvarchar, SqlServerTypes.nvarchar, SqlServerTypes.nvarchar, ScalaDbTypes.SqlServerTypes.decimal.nullable, SqlServerTypes.date.nullable, ScalaDbTypes.SqlServerTypes.bit.nullable, DepartmentId.sqlServerType, SqlServerTypes.nvarchar, ScalaDbTypes.SqlServerTypes.decimal.nullable, CompanyId.sqlServerType, SqlServerTypes.nvarchar, SqlServerTypes.nvarchar.nullable, SqlServerTypes.nvarchar.nullable, SqlServerTypes.nvarchar.nullable)(EmployeeSummaryViewRow.apply)(row => Array[Any](row.employeeId, row.email, row.firstName, row.lastName, row.salary, row.hiredAt, row.active, row.departmentId, row.departmentName, row.departmentBudget, row.companyId, row.companyName, row.managerId, row.managerFirstName, row.managerLastName))\n}", - "EmployeeSummaryViewRepo": "package showcase.showcase.employee_summary\n\nimport dev.typr.foundations.scala.SelectBuilder\nimport java.sql.Connection\n\ntrait EmployeeSummaryViewRepo {\n def select: SelectBuilder[EmployeeSummaryViewFields, EmployeeSummaryViewRow]\n\n def selectAll(using c: Connection): List[EmployeeSummaryViewRow]\n}", - "CustomerOrderRow": "package showcase.showcase.customer_order\n\nimport dev.typr.foundations.SqlServerTypes\nimport dev.typr.foundations.data.Json\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport java.time.LocalDateTime\nimport java.util.UUID\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.address.AddressId\nimport showcase.showcase.customer.CustomerId\n\n/** Table: showcase.customer_order\n * Primary key: id\n */\ncase class CustomerOrderRow(\n id: CustomerOrderId,\n /** Points to [[showcase.showcase.customer.CustomerRow.id]] */\n customerId: CustomerId,\n /** Points to [[showcase.showcase.address.AddressRow.id]] */\n shippingAddressId: Option[AddressId],\n /** Points to [[showcase.showcase.address.AddressRow.id]] */\n billingAddressId: Option[AddressId],\n /** Default: 'pending' */\n status: Option[String],\n subtotal: BigDecimal,\n /** Default: 0 */\n tax: Option[BigDecimal],\n /** Default: 0 */\n shipping: Option[BigDecimal],\n total: BigDecimal,\n notes: Option[String],\n /** Default: CURRENT_TIMESTAMP */\n createdAt: Option[LocalDateTime],\n shippedAt: Option[LocalDateTime],\n deliveredAt: Option[LocalDateTime],\n orderUid: Option[UUID],\n metadata: Option[Json],\n xmlInvoice: Option[/* XML */ String],\n receiptData: Option[Array[Byte]],\n rowVersion: Option[/* ROWVERSION/TIMESTAMP */ Array[Byte]],\n orderAmount: Option[BigDecimal]\n) {\n def toUnsavedRow(\n status: Defaulted[Option[String]] = Defaulted.Provided(this.status),\n tax: Defaulted[Option[BigDecimal]] = Defaulted.Provided(this.tax),\n shipping: Defaulted[Option[BigDecimal]] = Defaulted.Provided(this.shipping),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.Provided(this.createdAt)\n ): CustomerOrderRowUnsaved = {\n new CustomerOrderRowUnsaved(\n id,\n customerId,\n shippingAddressId,\n billingAddressId,\n subtotal,\n total,\n notes,\n shippedAt,\n deliveredAt,\n orderUid,\n metadata,\n xmlInvoice,\n receiptData,\n rowVersion,\n orderAmount,\n status,\n tax,\n shipping,\n createdAt\n )\n }\n}\n\nobject CustomerOrderRow {\n val `_rowParser`: RowParser[CustomerOrderRow] = RowParsers.of(CustomerOrderId.sqlServerType, CustomerId.sqlServerType, AddressId.sqlServerType.nullable, AddressId.sqlServerType.nullable, SqlServerTypes.nvarchar.nullable, ScalaDbTypes.SqlServerTypes.decimal, ScalaDbTypes.SqlServerTypes.decimal.nullable, ScalaDbTypes.SqlServerTypes.decimal.nullable, ScalaDbTypes.SqlServerTypes.decimal, SqlServerTypes.nvarchar.nullable, SqlServerTypes.datetime2.nullable, SqlServerTypes.datetime2.nullable, SqlServerTypes.datetime2.nullable, SqlServerTypes.uniqueidentifier.nullable, SqlServerTypes.json.nullable, SqlServerTypes.xml.nullable, SqlServerTypes.varbinary.nullable, SqlServerTypes.rowversion.nullable, ScalaDbTypes.SqlServerTypes.money.nullable)(CustomerOrderRow.apply)(row => Array[Any](row.id, row.customerId, row.shippingAddressId, row.billingAddressId, row.status, row.subtotal, row.tax, row.shipping, row.total, row.notes, row.createdAt, row.shippedAt, row.deliveredAt, row.orderUid, row.metadata, row.xmlInvoice, row.receiptData, row.rowVersion, row.orderAmount))\n}", - "CustomerOrderRepo": "package showcase.showcase.customer_order\n\nimport dev.typr.foundations.scala.DeleteBuilder\nimport dev.typr.foundations.scala.SelectBuilder\nimport dev.typr.foundations.scala.UpdateBuilder\nimport java.sql.Connection\n\ntrait CustomerOrderRepo {\n def delete: DeleteBuilder[CustomerOrderFields, CustomerOrderRow]\n\n def deleteById(id: CustomerOrderId)(using c: Connection): Boolean\n\n def deleteByIds(ids: Array[CustomerOrderId])(using c: Connection): Int\n\n def insert(unsaved: CustomerOrderRow)(using c: Connection): CustomerOrderRow\n\n def insert(unsaved: CustomerOrderRowUnsaved)(using c: Connection): CustomerOrderRow\n\n def select: SelectBuilder[CustomerOrderFields, CustomerOrderRow]\n\n def selectAll(using c: Connection): List[CustomerOrderRow]\n\n def selectById(id: CustomerOrderId)(using c: Connection): Option[CustomerOrderRow]\n\n def selectByIds(ids: Array[CustomerOrderId])(using c: Connection): List[CustomerOrderRow]\n\n def selectByIdsTracked(ids: Array[CustomerOrderId])(using c: Connection): Map[CustomerOrderId, CustomerOrderRow]\n\n def update: UpdateBuilder[CustomerOrderFields, CustomerOrderRow]\n\n def update(row: CustomerOrderRow)(using c: Connection): Boolean\n\n def upsert(unsaved: CustomerOrderRow)(using c: Connection): CustomerOrderRow\n\n def upsertBatch(unsaved: Iterator[CustomerOrderRow])(using c: Connection): List[CustomerOrderRow]\n}", - "OrderItemRow": "package showcase.showcase.order_item\n\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.customer_order.CustomerOrderId\nimport showcase.showcase.product.ProductId\n\n/** Table: showcase.order_item\n * Composite primary key: order_id, product_id\n */\ncase class OrderItemRow(\n /** Points to [[showcase.showcase.customer_order.CustomerOrderRow.id]] */\n orderId: CustomerOrderId,\n /** Points to [[showcase.showcase.product.ProductRow.id]] */\n productId: ProductId,\n quantity: Int,\n unitPrice: BigDecimal,\n /** Default: 0 */\n discount: Option[BigDecimal]\n) {\n def compositeId: OrderItemId = new OrderItemId(orderId, productId)\n\n def id: OrderItemId = this.compositeId\n\n def toUnsavedRow(discount: Defaulted[Option[BigDecimal]] = Defaulted.Provided(this.discount)): OrderItemRowUnsaved = {\n new OrderItemRowUnsaved(\n orderId,\n productId,\n quantity,\n unitPrice,\n discount\n )\n }\n}\n\nobject OrderItemRow {\n val `_rowParser`: RowParser[OrderItemRow] = RowParsers.of(CustomerOrderId.sqlServerType, ProductId.sqlServerType, ScalaDbTypes.SqlServerTypes.int_, ScalaDbTypes.SqlServerTypes.decimal, ScalaDbTypes.SqlServerTypes.decimal.nullable)(OrderItemRow.apply)(row => Array[Any](row.orderId, row.productId, row.quantity, row.unitPrice, row.discount))\n\n def apply(\n compositeId: OrderItemId,\n quantity: Int,\n unitPrice: BigDecimal,\n discount: Option[BigDecimal]\n ): OrderItemRow = {\n new OrderItemRow(\n compositeId.orderId,\n compositeId.productId,\n quantity,\n unitPrice,\n discount\n )\n }\n}", - "OrderItemId": "package showcase.showcase.order_item\n\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport showcase.showcase.customer_order.CustomerOrderId\nimport showcase.showcase.product.ProductId\n\n/** Type for the composite primary key of table `showcase.order_item` */\ncase class OrderItemId(\n orderId: CustomerOrderId,\n productId: ProductId\n)\n\nobject OrderItemId {\n val `_rowParser`: RowParser[OrderItemId] = RowParsers.of(CustomerOrderId.sqlServerType, ProductId.sqlServerType)(OrderItemId.apply)(row => Array[Any](row.orderId, row.productId))\n}", - "ProductRow": "package showcase.showcase.product\n\nimport dev.typr.foundations.SqlServerTypes\nimport dev.typr.foundations.data.Json\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport java.time.LocalDateTime\nimport java.util.UUID\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.category.CategoryId\n\n/** Table: showcase.product\n * Primary key: id\n */\ncase class ProductRow(\n id: ProductId,\n /** Points to [[showcase.showcase.category.CategoryRow.id]] */\n categoryId: Option[CategoryId],\n name: String,\n sku: String,\n price: BigDecimal,\n cost: Option[BigDecimal],\n /** Default: true */\n inStock: Option[Boolean],\n /** Default: 0 */\n quantity: Option[Int],\n weight: Option[BigDecimal],\n /** Default: CURRENT_TIMESTAMP */\n createdAt: Option[LocalDateTime],\n attributes: Option[Json],\n specifications: Option[/* XML */ String],\n descriptionLong: Option[String],\n thumbnail: Option[Array[Byte]],\n productUid: Option[UUID],\n listPrice: Option[BigDecimal]\n) {\n def toUnsavedRow(\n inStock: Defaulted[Option[Boolean]] = Defaulted.Provided(this.inStock),\n quantity: Defaulted[Option[Int]] = Defaulted.Provided(this.quantity),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.Provided(this.createdAt)\n ): ProductRowUnsaved = {\n new ProductRowUnsaved(\n id,\n categoryId,\n name,\n sku,\n price,\n cost,\n weight,\n attributes,\n specifications,\n descriptionLong,\n thumbnail,\n productUid,\n listPrice,\n inStock,\n quantity,\n createdAt\n )\n }\n}\n\nobject ProductRow {\n val `_rowParser`: RowParser[ProductRow] = RowParsers.of(ProductId.sqlServerType, CategoryId.sqlServerType.nullable, SqlServerTypes.nvarchar, SqlServerTypes.nvarchar, ScalaDbTypes.SqlServerTypes.decimal, ScalaDbTypes.SqlServerTypes.decimal.nullable, ScalaDbTypes.SqlServerTypes.bit.nullable, ScalaDbTypes.SqlServerTypes.int_.nullable, ScalaDbTypes.SqlServerTypes.decimal.nullable, SqlServerTypes.datetime2.nullable, SqlServerTypes.json.nullable, SqlServerTypes.xml.nullable, SqlServerTypes.nvarchar.nullable, SqlServerTypes.varbinary.nullable, SqlServerTypes.uniqueidentifier.nullable, ScalaDbTypes.SqlServerTypes.money.nullable)(ProductRow.apply)(row => Array[Any](row.id, row.categoryId, row.name, row.sku, row.price, row.cost, row.inStock, row.quantity, row.weight, row.createdAt, row.attributes, row.specifications, row.descriptionLong, row.thumbnail, row.productUid, row.listPrice))\n}", - "ProductId": "package showcase.showcase.product\n\nimport dev.typr.foundations.SqlServerType\nimport dev.typr.foundations.SqlServerTypes\nimport dev.typr.foundations.scala.Bijection\n\n/** Type for the primary key of table `showcase.product` */\ncase class ProductId(value: String) extends scala.AnyVal\n\nobject ProductId {\n given bijection: Bijection[ProductId, String] = Bijection.apply[ProductId, String](_.value)(ProductId.apply)\n\n given sqlServerType: SqlServerType[ProductId] = SqlServerTypes.nvarchar.bimap(ProductId.apply, _.value)\n}", - "CategoryRow": "package showcase.showcase.category\n\nimport dev.typr.foundations.SqlServerTypes\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\n\n/** Table: showcase.category\n * Primary key: id\n */\ncase class CategoryRow(\n id: CategoryId,\n /** Points to [[showcase.showcase.category.CategoryRow.id]] */\n parentId: Option[CategoryId],\n name: String,\n description: Option[String]\n)\n\nobject CategoryRow {\n val `_rowParser`: RowParser[CategoryRow] = RowParsers.of(CategoryId.sqlServerType, CategoryId.sqlServerType.nullable, SqlServerTypes.nvarchar, SqlServerTypes.nvarchar.nullable)(CategoryRow.apply)(row => Array[Any](row.id, row.parentId, row.name, row.description))\n}", - "CategoryId": "package showcase.showcase.category\n\nimport dev.typr.foundations.SqlServerType\nimport dev.typr.foundations.SqlServerTypes\nimport dev.typr.foundations.scala.Bijection\n\n/** Type for the primary key of table `showcase.category` */\ncase class CategoryId(value: String) extends scala.AnyVal\n\nobject CategoryId {\n given bijection: Bijection[CategoryId, String] = Bijection.apply[CategoryId, String](_.value)(CategoryId.apply)\n\n given sqlServerType: SqlServerType[CategoryId] = SqlServerTypes.nvarchar.bimap(CategoryId.apply, _.value)\n}", - "AddressRow": "package showcase.showcase.address\n\nimport com.microsoft.sqlserver.jdbc.Geography\nimport com.microsoft.sqlserver.jdbc.Geometry\nimport dev.typr.foundations.SqlServerTypes\nimport dev.typr.foundations.scala.DbTypeOps\nimport dev.typr.foundations.scala.RowParser\nimport dev.typr.foundations.scala.RowParsers\nimport dev.typr.foundations.scala.ScalaDbTypes\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.customer.CustomerId\n\n/** Table: showcase.address\n * Primary key: id\n */\ncase class AddressRow(\n id: AddressId,\n /** Points to [[showcase.showcase.customer.CustomerRow.id]] */\n customerId: CustomerId,\n addressType: String,\n street: String,\n city: String,\n state: Option[String],\n postalCode: Option[String],\n country: String,\n /** Default: false */\n isDefault: Option[Boolean],\n location: Option[Geography],\n deliveryZone: Option[Geometry]\n) {\n def toUnsavedRow(isDefault: Defaulted[Option[Boolean]] = Defaulted.Provided(this.isDefault)): AddressRowUnsaved = {\n new AddressRowUnsaved(\n id,\n customerId,\n addressType,\n street,\n city,\n state,\n postalCode,\n country,\n location,\n deliveryZone,\n isDefault\n )\n }\n}\n\nobject AddressRow {\n val `_rowParser`: RowParser[AddressRow] = RowParsers.of(AddressId.sqlServerType, CustomerId.sqlServerType, SqlServerTypes.nvarchar, SqlServerTypes.nvarchar, SqlServerTypes.nvarchar, SqlServerTypes.nvarchar.nullable, SqlServerTypes.nvarchar.nullable, SqlServerTypes.nvarchar, ScalaDbTypes.SqlServerTypes.bit.nullable, SqlServerTypes.geography.nullable, SqlServerTypes.geometry.nullable)(AddressRow.apply)(row => Array[Any](row.id, row.customerId, row.addressType, row.street, row.city, row.state, row.postalCode, row.country, row.isDefault, row.location, row.deliveryZone))\n}", - "AddressId": "package showcase.showcase.address\n\nimport dev.typr.foundations.SqlServerType\nimport dev.typr.foundations.SqlServerTypes\nimport dev.typr.foundations.scala.Bijection\n\n/** Type for the primary key of table `showcase.address` */\ncase class AddressId(value: String) extends scala.AnyVal\n\nobject AddressId {\n given bijection: Bijection[AddressId, String] = Bijection.apply[AddressId, String](_.value)(AddressId.apply)\n\n given sqlServerType: SqlServerType[AddressId] = SqlServerTypes.nvarchar.bimap(AddressId.apply, _.value)\n}", - "Defaulted": "package showcase.customtypes\n\n\n\n/** This signals a value where if you don't provide it, postgres will generate it for you */\nsealed trait Defaulted[T] {\n def fold[U](\n onDefault: => U,\n onProvided: T => U\n ): U\n\n def getOrElse(onDefault: => T): T\n\n def visit(\n onDefault: => Unit,\n onProvided: T => Unit\n ): Unit\n}\n\nobject Defaulted {\n case class Provided[T](value: T) extends Defaulted[T] {\n override def fold[U](\n onDefault: => U,\n onProvided: T => U\n ): U = onProvided(value)\n\n override def getOrElse(onDefault: => T): T = value\n\n override def visit(\n onDefault: => Unit,\n onProvided: T => Unit\n ): Unit = onProvided(value)\n }\n\n case class UseDefault[T]() extends Defaulted[T] {\n override def fold[U](\n onDefault: => U,\n onProvided: T => U\n ): U = onDefault\n\n override def getOrElse(onDefault: => T): T = onDefault\n\n override def visit(\n onDefault: => Unit,\n onProvided: T => Unit\n ): Unit = onDefault\n }\n}", - "TestInsert": "package showcase\n\nimport com.microsoft.sqlserver.jdbc.Geography\nimport com.microsoft.sqlserver.jdbc.Geometry\nimport dev.typr.foundations.data.Json\nimport java.sql.Connection\nimport java.time.LocalDate\nimport java.time.LocalDateTime\nimport java.time.OffsetDateTime\nimport java.util.UUID\nimport scala.util.Random\nimport showcase.customtypes.Defaulted\nimport showcase.showcase.address.AddressId\nimport showcase.showcase.address.AddressRepoImpl\nimport showcase.showcase.address.AddressRow\nimport showcase.showcase.address.AddressRowUnsaved\nimport showcase.showcase.audit_log.AuditLogId\nimport showcase.showcase.audit_log.AuditLogRepoImpl\nimport showcase.showcase.audit_log.AuditLogRow\nimport showcase.showcase.audit_log.AuditLogRowUnsaved\nimport showcase.showcase.category.CategoryId\nimport showcase.showcase.category.CategoryRepoImpl\nimport showcase.showcase.category.CategoryRow\nimport showcase.showcase.company.CompanyId\nimport showcase.showcase.company.CompanyRepoImpl\nimport showcase.showcase.company.CompanyRow\nimport showcase.showcase.company.CompanyRowUnsaved\nimport showcase.showcase.customer.CustomerId\nimport showcase.showcase.customer.CustomerRepoImpl\nimport showcase.showcase.customer.CustomerRow\nimport showcase.showcase.customer.CustomerRowUnsaved\nimport showcase.showcase.customer_order.CustomerOrderId\nimport showcase.showcase.customer_order.CustomerOrderRepoImpl\nimport showcase.showcase.customer_order.CustomerOrderRow\nimport showcase.showcase.customer_order.CustomerOrderRowUnsaved\nimport showcase.showcase.department.DepartmentId\nimport showcase.showcase.department.DepartmentRepoImpl\nimport showcase.showcase.department.DepartmentRow\nimport showcase.showcase.employee.EmployeeId\nimport showcase.showcase.employee.EmployeeRepoImpl\nimport showcase.showcase.employee.EmployeeRow\nimport showcase.showcase.employee.EmployeeRowUnsaved\nimport showcase.showcase.order_item.OrderItemRepoImpl\nimport showcase.showcase.order_item.OrderItemRow\nimport showcase.showcase.order_item.OrderItemRowUnsaved\nimport showcase.showcase.product.ProductId\nimport showcase.showcase.product.ProductRepoImpl\nimport showcase.showcase.product.ProductRow\nimport showcase.showcase.product.ProductRowUnsaved\nimport showcase.showcase.project.ProjectId\nimport showcase.showcase.project.ProjectRepoImpl\nimport showcase.showcase.project.ProjectRow\nimport showcase.showcase.project.ProjectRowUnsaved\nimport showcase.showcase.project_assignment.ProjectAssignmentRepoImpl\nimport showcase.showcase.project_assignment.ProjectAssignmentRow\nimport showcase.showcase.project_assignment.ProjectAssignmentRowUnsaved\n\n/** Methods to generate random data for `Ident(TestInsert)` */\ncase class TestInsert(random: Random) {\n def showcaseAddress(\n customerId: CustomerId,\n id: AddressId = AddressId(random.alphanumeric.take(20).mkString),\n addressType: String = random.alphanumeric.take(20).mkString,\n street: String = random.alphanumeric.take(20).mkString,\n city: String = random.alphanumeric.take(20).mkString,\n state: Option[String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n postalCode: Option[String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n country: String = random.alphanumeric.take(20).mkString,\n location: Option[Geography] = None,\n deliveryZone: Option[Geometry] = None,\n isDefault: Defaulted[Option[Boolean]] = Defaulted.UseDefault()\n )(using c: Connection): AddressRow = {\n (new AddressRepoImpl()).insert(new AddressRowUnsaved(\n id = id,\n customerId = customerId,\n addressType = addressType,\n street = street,\n city = city,\n state = state,\n postalCode = postalCode,\n country = country,\n location = location,\n deliveryZone = deliveryZone,\n isDefault = isDefault\n ))(using c)\n }\n\n def showcaseAuditLog(\n id: AuditLogId = AuditLogId(random.alphanumeric.take(20).mkString),\n tableName: String = random.alphanumeric.take(20).mkString,\n recordId: String = random.alphanumeric.take(20).mkString,\n action: String = random.alphanumeric.take(20).mkString,\n oldValues: Option[String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n newValues: Option[String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n changedBy: Option[EmployeeId] = None,\n changedAt: Defaulted[Option[LocalDateTime]] = Defaulted.UseDefault()\n )(using c: Connection): AuditLogRow = {\n (new AuditLogRepoImpl()).insert(new AuditLogRowUnsaved(\n id = id,\n tableName = tableName,\n recordId = recordId,\n action = action,\n oldValues = oldValues,\n newValues = newValues,\n changedBy = changedBy,\n changedAt = changedAt\n ))(using c)\n }\n\n def showcaseCategory(\n id: CategoryId = CategoryId(random.alphanumeric.take(20).mkString),\n parentId: Option[CategoryId] = None,\n name: String = random.alphanumeric.take(20).mkString,\n description: Option[String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString)\n )(using c: Connection): CategoryRow = {\n (new CategoryRepoImpl()).insert(new CategoryRow(\n id = id,\n parentId = parentId,\n name = name,\n description = description\n ))(using c)\n }\n\n def showcaseCompany(\n id: CompanyId = CompanyId(random.alphanumeric.take(20).mkString),\n name: String = random.alphanumeric.take(20).mkString,\n foundedYear: Option[Int] = if (random.nextBoolean()) None else Some(random.nextInt()),\n active: Defaulted[Option[Boolean]] = Defaulted.UseDefault(),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.UseDefault()\n )(using c: Connection): CompanyRow = {\n (new CompanyRepoImpl()).insert(new CompanyRowUnsaved(\n id = id,\n name = name,\n foundedYear = foundedYear,\n active = active,\n createdAt = createdAt\n ))(using c)\n }\n\n def showcaseCustomer(\n id: CustomerId = CustomerId(random.alphanumeric.take(20).mkString),\n email: String = random.alphanumeric.take(20).mkString,\n firstName: String = random.alphanumeric.take(20).mkString,\n lastName: String = random.alphanumeric.take(20).mkString,\n phone: Option[String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n preferences: Option[Json] = None,\n avatar: Option[Array[Byte]] = None,\n customerUid: Option[UUID] = if (random.nextBoolean()) None else Some(UUID.nameUUIDFromBytes{val bs = Array.ofDim[Byte](16); random.nextBytes(bs); bs}),\n creditLimit: Option[BigDecimal] = if (random.nextBoolean()) None else Some(BigDecimal.decimal(random.nextDouble())),\n verified: Defaulted[Option[Boolean]] = Defaulted.UseDefault(),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.UseDefault()\n )(using c: Connection): CustomerRow = {\n (new CustomerRepoImpl()).insert(new CustomerRowUnsaved(\n id = id,\n email = email,\n firstName = firstName,\n lastName = lastName,\n phone = phone,\n preferences = preferences,\n avatar = avatar,\n customerUid = customerUid,\n creditLimit = creditLimit,\n verified = verified,\n createdAt = createdAt\n ))(using c)\n }\n\n def showcaseCustomerOrder(\n customerId: CustomerId,\n id: CustomerOrderId = CustomerOrderId(random.alphanumeric.take(20).mkString),\n shippingAddressId: Option[AddressId] = None,\n billingAddressId: Option[AddressId] = None,\n subtotal: BigDecimal = BigDecimal.decimal(random.nextDouble()),\n total: BigDecimal = BigDecimal.decimal(random.nextDouble()),\n notes: Option[String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n shippedAt: Option[LocalDateTime] = None,\n deliveredAt: Option[LocalDateTime] = None,\n orderUid: Option[UUID] = if (random.nextBoolean()) None else Some(UUID.nameUUIDFromBytes{val bs = Array.ofDim[Byte](16); random.nextBytes(bs); bs}),\n metadata: Option[Json] = None,\n xmlInvoice: Option[/* XML */ String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n receiptData: Option[Array[Byte]] = None,\n rowVersion: Option[/* ROWVERSION/TIMESTAMP */ Array[Byte]] = None,\n orderAmount: Option[BigDecimal] = if (random.nextBoolean()) None else Some(BigDecimal.decimal(random.nextDouble())),\n status: Defaulted[Option[String]] = Defaulted.UseDefault(),\n tax: Defaulted[Option[BigDecimal]] = Defaulted.UseDefault(),\n shipping: Defaulted[Option[BigDecimal]] = Defaulted.UseDefault(),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.UseDefault()\n )(using c: Connection): CustomerOrderRow = {\n (new CustomerOrderRepoImpl()).insert(new CustomerOrderRowUnsaved(\n id = id,\n customerId = customerId,\n shippingAddressId = shippingAddressId,\n billingAddressId = billingAddressId,\n subtotal = subtotal,\n total = total,\n notes = notes,\n shippedAt = shippedAt,\n deliveredAt = deliveredAt,\n orderUid = orderUid,\n metadata = metadata,\n xmlInvoice = xmlInvoice,\n receiptData = receiptData,\n rowVersion = rowVersion,\n orderAmount = orderAmount,\n status = status,\n tax = tax,\n shipping = shipping,\n createdAt = createdAt\n ))(using c)\n }\n\n def showcaseDepartment(\n companyId: CompanyId,\n id: DepartmentId = DepartmentId(random.alphanumeric.take(20).mkString),\n name: String = random.alphanumeric.take(20).mkString,\n budget: Option[BigDecimal] = if (random.nextBoolean()) None else Some(BigDecimal.decimal(random.nextDouble()))\n )(using c: Connection): DepartmentRow = {\n (new DepartmentRepoImpl()).insert(new DepartmentRow(\n id = id,\n companyId = companyId,\n name = name,\n budget = budget\n ))(using c)\n }\n\n def showcaseEmployee(\n departmentId: DepartmentId,\n id: EmployeeId = EmployeeId(random.alphanumeric.take(20).mkString),\n managerId: Option[EmployeeId] = None,\n email: String = random.alphanumeric.take(20).mkString,\n firstName: String = random.alphanumeric.take(20).mkString,\n lastName: String = random.alphanumeric.take(20).mkString,\n salary: Option[BigDecimal] = if (random.nextBoolean()) None else Some(BigDecimal.decimal(random.nextDouble())),\n hiredAt: Option[LocalDate] = None,\n metadata: Option[Json] = None,\n resume: Option[/* XML */ String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n photo: Option[Array[Byte]] = None,\n employeeUid: Option[UUID] = if (random.nextBoolean()) None else Some(UUID.nameUUIDFromBytes{val bs = Array.ofDim[Byte](16); random.nextBytes(bs); bs}),\n lastModified: Option[OffsetDateTime] = None,\n rowVersion: Option[/* ROWVERSION/TIMESTAMP */ Array[Byte]] = None,\n orgPath: Option[/* HIERARCHYID */ String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n active: Defaulted[Option[Boolean]] = Defaulted.UseDefault(),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.UseDefault()\n )(using c: Connection): EmployeeRow = {\n (new EmployeeRepoImpl()).insert(new EmployeeRowUnsaved(\n id = id,\n departmentId = departmentId,\n managerId = managerId,\n email = email,\n firstName = firstName,\n lastName = lastName,\n salary = salary,\n hiredAt = hiredAt,\n metadata = metadata,\n resume = resume,\n photo = photo,\n employeeUid = employeeUid,\n lastModified = lastModified,\n rowVersion = rowVersion,\n orgPath = orgPath,\n active = active,\n createdAt = createdAt\n ))(using c)\n }\n\n def showcaseOrderItem(\n orderId: CustomerOrderId,\n productId: ProductId,\n quantity: Int = random.nextInt(),\n unitPrice: BigDecimal = BigDecimal.decimal(random.nextDouble()),\n discount: Defaulted[Option[BigDecimal]] = Defaulted.UseDefault()\n )(using c: Connection): OrderItemRow = {\n (new OrderItemRepoImpl()).insert(new OrderItemRowUnsaved(\n orderId = orderId,\n productId = productId,\n quantity = quantity,\n unitPrice = unitPrice,\n discount = discount\n ))(using c)\n }\n\n def showcaseProduct(\n id: ProductId = ProductId(random.alphanumeric.take(20).mkString),\n categoryId: Option[CategoryId] = None,\n name: String = random.alphanumeric.take(20).mkString,\n sku: String = random.alphanumeric.take(20).mkString,\n price: BigDecimal = BigDecimal.decimal(random.nextDouble()),\n cost: Option[BigDecimal] = if (random.nextBoolean()) None else Some(BigDecimal.decimal(random.nextDouble())),\n weight: Option[BigDecimal] = if (random.nextBoolean()) None else Some(BigDecimal.decimal(random.nextDouble())),\n attributes: Option[Json] = None,\n specifications: Option[/* XML */ String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n descriptionLong: Option[String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n thumbnail: Option[Array[Byte]] = None,\n productUid: Option[UUID] = if (random.nextBoolean()) None else Some(UUID.nameUUIDFromBytes{val bs = Array.ofDim[Byte](16); random.nextBytes(bs); bs}),\n listPrice: Option[BigDecimal] = if (random.nextBoolean()) None else Some(BigDecimal.decimal(random.nextDouble())),\n inStock: Defaulted[Option[Boolean]] = Defaulted.UseDefault(),\n quantity: Defaulted[Option[Int]] = Defaulted.UseDefault(),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.UseDefault()\n )(using c: Connection): ProductRow = {\n (new ProductRepoImpl()).insert(new ProductRowUnsaved(\n id = id,\n categoryId = categoryId,\n name = name,\n sku = sku,\n price = price,\n cost = cost,\n weight = weight,\n attributes = attributes,\n specifications = specifications,\n descriptionLong = descriptionLong,\n thumbnail = thumbnail,\n productUid = productUid,\n listPrice = listPrice,\n inStock = inStock,\n quantity = quantity,\n createdAt = createdAt\n ))(using c)\n }\n\n def showcaseProject(\n id: ProjectId = ProjectId(random.alphanumeric.take(20).mkString),\n name: String = random.alphanumeric.take(20).mkString,\n description: Option[String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n startDate: Option[LocalDate] = None,\n endDate: Option[LocalDate] = None,\n budget: Option[BigDecimal] = if (random.nextBoolean()) None else Some(BigDecimal.decimal(random.nextDouble())),\n projectUid: Option[UUID] = if (random.nextBoolean()) None else Some(UUID.nameUUIDFromBytes{val bs = Array.ofDim[Byte](16); random.nextBytes(bs); bs}),\n metadata: Option[Json] = None,\n xmlPlan: Option[/* XML */ String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n attachments: Option[Array[Byte]] = None,\n rowVersion: Option[/* ROWVERSION/TIMESTAMP */ Array[Byte]] = None,\n totalBudget: Option[BigDecimal] = if (random.nextBoolean()) None else Some(BigDecimal.decimal(random.nextDouble())),\n orgPath: Option[/* HIERARCHYID */ String] = if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString),\n status: Defaulted[Option[String]] = Defaulted.UseDefault(),\n createdAt: Defaulted[Option[LocalDateTime]] = Defaulted.UseDefault()\n )(using c: Connection): ProjectRow = {\n (new ProjectRepoImpl()).insert(new ProjectRowUnsaved(\n id = id,\n name = name,\n description = description,\n startDate = startDate,\n endDate = endDate,\n budget = budget,\n projectUid = projectUid,\n metadata = metadata,\n xmlPlan = xmlPlan,\n attachments = attachments,\n rowVersion = rowVersion,\n totalBudget = totalBudget,\n orgPath = orgPath,\n status = status,\n createdAt = createdAt\n ))(using c)\n }\n\n def showcaseProjectAssignment(\n employeeId: EmployeeId,\n projectId: ProjectId,\n role: String = random.alphanumeric.take(20).mkString,\n startDate: Option[LocalDate] = None,\n endDate: Option[LocalDate] = None,\n hoursAllocated: Defaulted[Option[Int]] = Defaulted.UseDefault()\n )(using c: Connection): ProjectAssignmentRow = {\n (new ProjectAssignmentRepoImpl()).insert(new ProjectAssignmentRowUnsaved(\n employeeId = employeeId,\n projectId = projectId,\n role = role,\n startDate = startDate,\n endDate = endDate,\n hoursAllocated = hoursAllocated\n ))(using c)\n }\n}" - } - } -}; - -/** - * Get a code sample for the given database, language, and file name. - * Returns null if the sample doesn't exist for that combination. - */ -export function getCodeSample(database, language, fileName) { - return codeSamples[database]?.[language]?.[fileName] ?? null; -} - -/** - * Check if a code sample exists for the given combination. - */ -export function hasCodeSample(database, language, fileName) { - return getCodeSample(database, language, fileName) !== null; -} - -/** - * Get all available samples for a file name across all database/language combinations. - * Returns an object with { database: { language: content } } structure. - */ -export function getAllSamplesForFile(fileName) { - const result = {}; - for (const db of DATABASES) { - for (const lang of LANGUAGES) { - const sample = getCodeSample(db, lang, fileName); - if (sample) { - if (!result[db]) result[db] = {}; - result[db][lang] = sample; - } - } - } - return result; -} diff --git a/site/src/data/showcaseFiles.js b/site/src/data/showcaseFiles.js index 4291b1abf5..efcb6ad29e 100644 --- a/site/src/data/showcaseFiles.js +++ b/site/src/data/showcaseFiles.js @@ -61,7 +61,7 @@ const LANG_EXTENSIONS = { scala: '.scala', }; -export const DATABASES = ['postgres', 'mariadb', 'duckdb', 'oracle', 'sqlserver', 'db2']; +export const DATABASES = ['postgres', 'mariadb', 'duckdb', 'oracle', 'sqlserver', 'db2', 'sqlite']; export const LANGUAGES = ['java', 'kotlin', 'scala']; export const DATABASE_LABELS = { @@ -71,6 +71,7 @@ export const DATABASE_LABELS = { oracle: 'Oracle', sqlserver: 'SQL Server', db2: 'DB2', + sqlite: 'SQLite', }; export const LANGUAGE_LABELS = { diff --git a/site/src/pages/index.js b/site/src/pages/index.js index cda3f41d62..627b803513 100644 --- a/site/src/pages/index.js +++ b/site/src/pages/index.js @@ -235,7 +235,7 @@ function HeroSection() {
Boundaries
-
PostgreSQL · MariaDB · Oracle · SQL Server · DuckDB · DB2 · OpenAPI · Avro/Kafka · gRPC
+
PostgreSQL · MariaDB · Oracle · SQL Server · DuckDB · DB2 · SQLite · OpenAPI · Avro/Kafka · gRPC
Method
@@ -854,8 +854,8 @@ function BoundariesSection() { n: "01", title: "Databases", tagline: "Schemas in. Repos out.", - desc: "Six engines: PostgreSQL, MariaDB, Oracle, SQL Server, DuckDB, DB2. Row types, ID types, repositories, type‑safe DSL queries. Full DDL fidelity — composite types, arrays, enums, domains, defaults.", - tags: ["6 engines", "DDL fidelity", "Type‑safe DSL"], + desc: "Seven engines: PostgreSQL, MariaDB, Oracle, SQL Server, DuckDB, DB2, SQLite. Row types, ID types, repositories, type‑safe DSL queries. Full DDL fidelity — composite types, arrays, enums, domains, defaults.", + tags: ["7 engines", "DDL fidelity", "Type‑safe DSL"], to: "/typr/boundaries/databases/", }, { @@ -988,7 +988,7 @@ function StackSection() { { title: "Boundaries", items: [ - "PostgreSQL", "MariaDB", "Oracle", "SQL Server", "DuckDB", "DB2", + "PostgreSQL", "MariaDB", "Oracle", "SQL Server", "DuckDB", "DB2", "SQLite", "OpenAPI", "Kafka / Avro", ], soon: ["gRPC / Protobuf", "GraphQL"], diff --git a/sql-init/sqlite/00-schema.sql b/sql-init/sqlite/00-schema.sql new file mode 100644 index 0000000000..c2577275b1 --- /dev/null +++ b/sql-init/sqlite/00-schema.sql @@ -0,0 +1,205 @@ +-- SQLite test schema for Typr +-- Exercises every type affinity, plus PK/FK/composite/unique/precision tables. +-- +-- SQLite notes: +-- - All values use one of five storage classes (NULL, INTEGER, REAL, TEXT, BLOB). +-- - Declared column types map to one of five "affinities" via substring match. +-- - DATE/TIME/TIMESTAMP have no native storage class; we use ISO-8601 TEXT to +-- match the foundations SqliteTypes default codecs. +-- - FOREIGN KEYS are off by default on each connection (PRAGMA foreign_keys=ON). +-- - RETURNING is supported (SQLite >= 3.35). + +-- ==================== Table covering all canonical affinities ==================== +CREATE TABLE all_scalar_types ( + id INTEGER PRIMARY KEY, + -- INTEGER affinity, with concrete Java mappings via SqliteTypes + col_tinyint TINYINT, + col_smallint SMALLINT, + col_int INT, + col_integer INTEGER, + col_bigint BIGINT, + col_boolean BOOLEAN, + -- REAL affinity + col_real REAL, + col_double DOUBLE, + col_float FLOAT, + -- NUMERIC affinity + col_decimal DECIMAL(10, 2), + col_numeric NUMERIC, + -- TEXT affinity + col_text TEXT, + col_varchar VARCHAR(100), + col_char CHAR(5), + col_clob CLOB, + -- BLOB affinity + col_blob BLOB, + col_binary BINARY, + -- Date/time (stored as ISO-8601 TEXT) + col_date DATE, + col_time TIME, + col_datetime DATETIME, + col_timestamp TIMESTAMP, + -- Convenience types backed by TEXT + col_uuid UUID, + col_json JSON, + -- NOT NULL marker + col_not_null TEXT NOT NULL +); + +-- ==================== Customers / Products / Orders / Order items ==================== +CREATE TABLE customers ( + customer_id INTEGER PRIMARY KEY AUTOINCREMENT, + name TEXT NOT NULL, + email TEXT, + created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP +); + +CREATE TABLE products ( + product_id INTEGER PRIMARY KEY AUTOINCREMENT, + sku VARCHAR(50) NOT NULL UNIQUE, + name TEXT NOT NULL, + price DECIMAL(10, 2) NOT NULL, + metadata JSON +); + +CREATE TABLE orders ( + order_id INTEGER PRIMARY KEY AUTOINCREMENT, + customer_id INTEGER NOT NULL REFERENCES customers(customer_id), + order_date DATE NOT NULL, + total_amount DECIMAL(12, 2), + status TEXT NOT NULL DEFAULT 'pending' +); + +CREATE TABLE order_items ( + order_id INTEGER NOT NULL REFERENCES orders(order_id), + product_id INTEGER NOT NULL REFERENCES products(product_id), + quantity INTEGER NOT NULL DEFAULT 1, + unit_price DECIMAL(10, 2) NOT NULL, + PRIMARY KEY (order_id, product_id) +); + +-- ==================== Composite primary key + composite foreign key ==================== +CREATE TABLE departments ( + dept_code VARCHAR(10) NOT NULL, + dept_region VARCHAR(10) NOT NULL, + dept_name TEXT NOT NULL, + budget DECIMAL(15, 2), + PRIMARY KEY (dept_code, dept_region) +); + +CREATE TABLE employees ( + emp_number INTEGER NOT NULL, + emp_suffix VARCHAR(5) NOT NULL, + dept_code VARCHAR(10) NOT NULL, + dept_region VARCHAR(10) NOT NULL, + emp_name TEXT NOT NULL, + salary DECIMAL(10, 2), + hire_date DATE NOT NULL DEFAULT CURRENT_DATE, + PRIMARY KEY (emp_number, emp_suffix), + FOREIGN KEY (dept_code, dept_region) REFERENCES departments(dept_code, dept_region) +); + +-- ==================== UNIQUE constraint (not a PK) ==================== +CREATE TABLE users ( + user_id INTEGER PRIMARY KEY AUTOINCREMENT, + username VARCHAR(50) NOT NULL UNIQUE, + email VARCHAR(120) NOT NULL, + UNIQUE (email) +); + +-- ==================== Views ==================== +CREATE VIEW customer_orders AS +SELECT + c.customer_id, + c.name AS customer_name, + c.email, + o.order_id, + o.order_date, + o.total_amount, + o.status +FROM customers c +LEFT JOIN orders o ON c.customer_id = o.customer_id; + +CREATE VIEW order_details AS +SELECT + o.order_id, + o.order_date, + c.name AS customer_name, + p.name AS product_name, + oi.quantity, + oi.unit_price, + (oi.quantity * oi.unit_price) AS line_total +FROM orders o +JOIN customers c ON o.customer_id = c.customer_id +JOIN order_items oi ON o.order_id = oi.order_id +JOIN products p ON oi.product_id = p.product_id; + +-- ==================== Sample data ==================== +INSERT INTO all_scalar_types (id, col_tinyint, col_smallint, col_int, col_integer, col_bigint, + col_boolean, col_text, col_date, col_not_null) +VALUES (1, 42, 1000, 100000, 100000, 10000000000, 1, 'hello', '2025-01-01', 'required'); + +INSERT INTO customers (customer_id, name, email) VALUES +(1, 'John Doe', 'john@example.com'), +(2, 'Jane Smith', 'jane@example.com'); + +INSERT INTO products (product_id, sku, name, price) VALUES +(1, 'PROD-001', 'Widget A', 29.99), +(2, 'PROD-002', 'Widget B', 49.99); + +INSERT INTO orders (order_id, customer_id, order_date, total_amount, status) VALUES +(1, 1, '2025-01-15', 79.98, 'completed'), +(2, 2, '2025-01-16', 29.99, 'pending'); + +INSERT INTO order_items (order_id, product_id, quantity, unit_price) VALUES +(1, 1, 1, 29.99), +(1, 2, 1, 49.99), +(2, 1, 1, 29.99); + +INSERT INTO departments (dept_code, dept_region, dept_name, budget) VALUES +('IT', 'US-WEST', 'Information Technology', 1000000.00), +('HR', 'US-EAST', 'Human Resources', 500000.00); + +INSERT INTO employees (emp_number, emp_suffix, dept_code, dept_region, emp_name, salary) VALUES +(1001, 'A', 'IT', 'US-WEST', 'Alice Johnson', 95000.00), +(1002, 'B', 'HR', 'US-EAST', 'Bob Smith', 75000.00); + +INSERT INTO users (user_id, username, email) VALUES +(1, 'jdoe', 'jdoe@example.com'), +(2, 'jsmith','jsmith@example.com'); + +-- ============================================================================ +-- PRECISION TYPES TEST TABLES +-- These test precise wrapper-type generation. The precision_types selector +-- in typr.yaml restricts wrapper generation to these tables. +-- ============================================================================ + +CREATE TABLE precision_types ( + id INTEGER PRIMARY KEY, + string10 VARCHAR(10) NOT NULL, + string20 VARCHAR(20) NOT NULL, + string50 VARCHAR(50) NOT NULL, + string100 VARCHAR(100) NOT NULL, + string255 VARCHAR(255) NOT NULL, + decimal5_2 DECIMAL(5,2) NOT NULL, + decimal10_2 DECIMAL(10,2) NOT NULL, + decimal18_4 DECIMAL(18,4) NOT NULL, + decimal5_0 DECIMAL(5,0) NOT NULL, + decimal10_0 DECIMAL(10,0) NOT NULL, + decimal18_0 DECIMAL(18,0) NOT NULL +); + +CREATE TABLE precision_types_null ( + id INTEGER PRIMARY KEY, + string10 VARCHAR(10), + string20 VARCHAR(20), + string50 VARCHAR(50), + string100 VARCHAR(100), + string255 VARCHAR(255), + decimal5_2 DECIMAL(5,2), + decimal10_2 DECIMAL(10,2), + decimal18_4 DECIMAL(18,4), + decimal5_0 DECIMAL(5,0), + decimal10_0 DECIMAL(10,0), + decimal18_0 DECIMAL(18,0) +); diff --git a/sql-scripts/sqlite/all_scalar_types_search.sql b/sql-scripts/sqlite/all_scalar_types_search.sql new file mode 100644 index 0000000000..636a9f1a56 --- /dev/null +++ b/sql-scripts/sqlite/all_scalar_types_search.sql @@ -0,0 +1,22 @@ +-- Filter the all_scalar_types table by a handful of columns. +-- Tests: a parameter for each affinity (INTEGER, REAL, TEXT, DATE). + +SELECT + id, + col_tinyint, + col_smallint, + col_integer, + col_bigint, + col_real, + col_double, + col_decimal, + col_text, + col_date, + col_uuid, + col_json +FROM all_scalar_types +WHERE + (:"min_id?" IS NULL OR id >= :min_id) + AND (:"text_pattern?" IS NULL OR col_text LIKE :text_pattern) + AND (:"after_date?" IS NULL OR col_date >= :after_date) +ORDER BY id; diff --git a/sql-scripts/sqlite/customer_search.sql b/sql-scripts/sqlite/customer_search.sql new file mode 100644 index 0000000000..b99de88705 --- /dev/null +++ b/sql-scripts/sqlite/customer_search.sql @@ -0,0 +1,15 @@ +-- Customer search with multiple optional filters. +-- Tests: optional parameters, LIKE patterns, complex WHERE, ORDER BY/LIMIT. + +SELECT + customer_id, + name, + email, + created_at +FROM customers +WHERE + (:"name_pattern?" IS NULL OR name LIKE :name_pattern) + AND (:"email_pattern?" IS NULL OR email LIKE :email_pattern) + AND (:"created_after?" IS NULL OR created_at >= :created_after) +ORDER BY created_at DESC, customer_id +LIMIT :"max_results!"; diff --git a/sql-scripts/sqlite/delete_old_orders.sql b/sql-scripts/sqlite/delete_old_orders.sql new file mode 100644 index 0000000000..db6f981c8b --- /dev/null +++ b/sql-scripts/sqlite/delete_old_orders.sql @@ -0,0 +1,10 @@ +-- Delete completed orders older than a cutoff date. +-- Tests: DELETE statement with required date param, no result columns. +-- +-- SQLite stores DATE as ISO-8601 TEXT, so sqlglot can't infer that +-- order_date < :cutoff_date wants a LocalDate. We pin the type +-- explicitly with the `:name:Type!` annotation — same opt-in pattern +-- as the other dialects use for parameters not otherwise resolvable +-- from schema lineage. +DELETE FROM orders +WHERE status = 'completed' AND order_date < :"cutoff_date:LocalDate!"; diff --git a/sql-scripts/sqlite/order_summary_by_customer.sql b/sql-scripts/sqlite/order_summary_by_customer.sql new file mode 100644 index 0000000000..3860442515 --- /dev/null +++ b/sql-scripts/sqlite/order_summary_by_customer.sql @@ -0,0 +1,15 @@ +-- Summary stats per customer over an order date range. +-- Tests: GROUP BY, aggregates with NULL-aware results, JOIN, date params. + +SELECT + c.customer_id, + c.name AS customer_name, + COUNT(o.order_id) AS order_count, + COALESCE(SUM(o.total_amount), 0) AS total_revenue, + MAX(o.order_date) AS last_order_date +FROM customers c +LEFT JOIN orders o ON c.customer_id = o.customer_id +WHERE o.order_date IS NULL + OR (o.order_date >= :"from_date!" AND o.order_date <= :"to_date!") +GROUP BY c.customer_id, c.name +ORDER BY total_revenue DESC, c.customer_id; diff --git a/sql-scripts/sqlite/product_details_with_sales.sql b/sql-scripts/sqlite/product_details_with_sales.sql new file mode 100644 index 0000000000..e7b46504c4 --- /dev/null +++ b/sql-scripts/sqlite/product_details_with_sales.sql @@ -0,0 +1,15 @@ +-- Product details enriched with cumulative sales numbers. +-- Tests: subquery in SELECT, joining on FK, ordering by computed column. + +SELECT + p.product_id, + p.sku, + p.name AS product_name, + p.price, + COALESCE(SUM(oi.quantity), 0) AS total_units_sold, + COALESCE(SUM(oi.quantity * oi.unit_price), 0) AS total_revenue +FROM products p +LEFT JOIN order_items oi ON p.product_id = oi.product_id +WHERE (:"min_price?" IS NULL OR p.price >= :min_price) +GROUP BY p.product_id, p.sku, p.name, p.price +ORDER BY total_revenue DESC, p.product_id; diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/DefaultedDeserializer.java b/testers/sqlite/java/generated-and-checked-in/testdb/DefaultedDeserializer.java new file mode 100644 index 0000000000..04af0bf2ff --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/DefaultedDeserializer.java @@ -0,0 +1,76 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonToken; +import com.fasterxml.jackson.databind.BeanProperty; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.deser.ContextualDeserializer; +import java.io.IOException; +import java.lang.Class; +import java.lang.Object; +import java.lang.RuntimeException; +import testdb.customtypes.Defaulted; +import testdb.customtypes.Defaulted.Provided; +import testdb.customtypes.Defaulted.UseDefault; + +/** Jackson deserializer for Defaulted types */ +public class DefaultedDeserializer extends JsonDeserializer> implements ContextualDeserializer { + JavaType valueType; + + Class defaultedClass; + + public DefaultedDeserializer( + JavaType valueType, + Class defaultedClass + ) { + this.valueType = valueType; + this.defaultedClass = defaultedClass; + } + + @Override + public JsonDeserializer createContextual( + DeserializationContext ctxt, + BeanProperty property + ) { + JavaType contextType = ctxt.getContextualType(); + JavaType type = (contextType == null && property != null + ? property.getType() + : contextType); + if (type != null && type.containedTypeCount() > 0) { + return new DefaultedDeserializer(type.containedType(0), type.getRawClass()); + }; + throw new RuntimeException("unexpected"); + } + + @Override + public Defaulted deserialize( + JsonParser p, + DeserializationContext ctxt + ) throws IOException { + if (p.currentToken() == JsonToken.VALUE_STRING) { + String text = p.getText(); + if ("defaulted".equals(text)) { + return new UseDefault(); + } + throw new IOException("Expected 'defaulted' but got: " + text); + } + if (p.currentToken() == JsonToken.START_OBJECT) { + p.nextToken(); + if (p.currentToken() == JsonToken.FIELD_NAME && "provided".equals(p.currentName())) { + p.nextToken(); + Object value = ctxt.readValue(p, valueType); + p.nextToken(); + return new Provided(value); + } + + }; + throw new IOException("Expected 'provided' field but got: " + p.currentName()); + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/DefaultedSerializer.java b/testers/sqlite/java/generated-and-checked-in/testdb/DefaultedSerializer.java new file mode 100644 index 0000000000..030515b769 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/DefaultedSerializer.java @@ -0,0 +1,36 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; +import java.io.IOException; +import testdb.customtypes.Defaulted; +import testdb.customtypes.Defaulted.Provided; +import testdb.customtypes.Defaulted.UseDefault; + +/** Jackson serializer for Defaulted types */ +public class DefaultedSerializer extends JsonSerializer> { + @Override + public void serialize( + Defaulted value, + JsonGenerator gen, + SerializerProvider serializers + ) throws IOException { + switch (value) { + case null -> gen.writeNull(); + case UseDefault u -> gen.writeString("defaulted"); + case Provided p -> { + gen.writeStartObject(); + gen.writeFieldName("provided"); + serializers.defaultSerializeValue(p.value(), gen); + gen.writeEndObject(); + } + default -> throw new IOException("Unknown Defaulted subtype: " + value.getClass().getName()); + }; + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/TestInsert.java b/testers/sqlite/java/generated-and-checked-in/testdb/TestInsert.java new file mode 100644 index 0000000000..41b99ae376 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/TestInsert.java @@ -0,0 +1,113 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb; + +import dev.typr.dsl.Inserter; +import dev.typr.foundations.Connection; +import dev.typr.foundations.data.Json; +import dev.typr.foundations.internal.RandomHelper; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.util.Optional; +import java.util.Random; +import testdb.all_scalar_types.AllScalarTypesId; +import testdb.all_scalar_types.AllScalarTypesRepoImpl; +import testdb.all_scalar_types.AllScalarTypesRow; +import testdb.customers.CustomersId; +import testdb.customers.CustomersRepoImpl; +import testdb.customers.CustomersRow; +import testdb.customers.CustomersRowUnsaved; +import testdb.customtypes.Defaulted.UseDefault; +import testdb.departments.DepartmentsId; +import testdb.departments.DepartmentsRepoImpl; +import testdb.departments.DepartmentsRow; +import testdb.employees.EmployeesRepoImpl; +import testdb.employees.EmployeesRow; +import testdb.employees.EmployeesRowUnsaved; +import testdb.order_items.OrderItemsRepoImpl; +import testdb.order_items.OrderItemsRow; +import testdb.order_items.OrderItemsRowUnsaved; +import testdb.orders.OrdersId; +import testdb.orders.OrdersRepoImpl; +import testdb.orders.OrdersRow; +import testdb.orders.OrdersRowUnsaved; +import testdb.precisetypes.Decimal10_2; +import testdb.precisetypes.Decimal18_4; +import testdb.precisetypes.Decimal5_2; +import testdb.precisetypes.Int10; +import testdb.precisetypes.Int18; +import testdb.precisetypes.Int5; +import testdb.precisetypes.String10; +import testdb.precisetypes.String100; +import testdb.precisetypes.String20; +import testdb.precisetypes.String255; +import testdb.precisetypes.String50; +import testdb.precision_types.PrecisionTypesId; +import testdb.precision_types.PrecisionTypesRepoImpl; +import testdb.precision_types.PrecisionTypesRow; +import testdb.precision_types_null.PrecisionTypesNullId; +import testdb.precision_types_null.PrecisionTypesNullRepoImpl; +import testdb.precision_types_null.PrecisionTypesNullRow; +import testdb.products.ProductsId; +import testdb.products.ProductsRepoImpl; +import testdb.products.ProductsRow; +import testdb.userdefined.Email; +import testdb.users.UsersId; +import testdb.users.UsersRepoImpl; +import testdb.users.UsersRow; + +/** Methods to generate random data for `Ident(TestInsert)` */ +public record TestInsert(Random random) { + public TestInsert withRandom(Random random) { + return new TestInsert(random); + } + + public Inserter AllScalarTypes() { + return Inserter.of(new AllScalarTypesRow(new AllScalarTypesId(random.nextLong()), (random.nextBoolean() ? Optional.empty() : Optional.of((byte) (random.nextInt(Byte.MAX_VALUE)))), (random.nextBoolean() ? Optional.empty() : Optional.of((short) (random.nextInt(Short.MAX_VALUE)))), (random.nextBoolean() ? Optional.empty() : Optional.of(random.nextInt())), (random.nextBoolean() ? Optional.empty() : Optional.of(random.nextLong())), (random.nextBoolean() ? Optional.empty() : Optional.of(random.nextLong())), (random.nextBoolean() ? Optional.empty() : Optional.of(random.nextBoolean())), (random.nextBoolean() ? Optional.empty() : Optional.of(random.nextDouble())), (random.nextBoolean() ? Optional.empty() : Optional.of(random.nextDouble())), (random.nextBoolean() ? Optional.empty() : Optional.of(random.nextFloat())), (random.nextBoolean() ? Optional.empty() : Optional.of(BigDecimal.valueOf(random.nextDouble()))), (random.nextBoolean() ? Optional.empty() : Optional.of(BigDecimal.valueOf(random.nextDouble()))), (random.nextBoolean() ? Optional.empty() : Optional.of(RandomHelper.alphanumeric(random, 20))), (random.nextBoolean() ? Optional.empty() : Optional.of(RandomHelper.alphanumeric(random, 20))), (random.nextBoolean() ? Optional.empty() : Optional.of(RandomHelper.alphanumeric(random, 5))), (random.nextBoolean() ? Optional.empty() : Optional.of(RandomHelper.alphanumeric(random, 20))), Optional.empty(), Optional.empty(), (random.nextBoolean() ? Optional.empty() : Optional.of(LocalDate.ofEpochDay((long) (random.nextInt(30000))))), (random.nextBoolean() ? Optional.empty() : Optional.of(LocalTime.ofSecondOfDay((long) (random.nextInt(24 * 60 * 60))))), (random.nextBoolean() ? Optional.empty() : Optional.of(LocalDateTime.of(LocalDate.ofEpochDay((long) (random.nextInt(30000))), LocalTime.ofSecondOfDay((long) (random.nextInt(24 * 60 * 60)))))), (random.nextBoolean() ? Optional.empty() : Optional.of(LocalDateTime.of(LocalDate.ofEpochDay((long) (random.nextInt(30000))), LocalTime.ofSecondOfDay((long) (random.nextInt(24 * 60 * 60)))))), (random.nextBoolean() ? Optional.empty() : Optional.of(RandomHelper.randomUUID(random))), (random.nextBoolean() ? Optional.empty() : Optional.of(new Json("{}"))), RandomHelper.alphanumeric(random, 20)), (AllScalarTypesRow row, Connection c) -> (new AllScalarTypesRepoImpl()).insert(row, c)); + } + + public Inserter Customers() { + return Inserter.of(new CustomersRowUnsaved(new CustomersId(random.nextLong()), RandomHelper.alphanumeric(random, 20), (random.nextBoolean() ? Optional.empty() : Optional.of(new Email(RandomHelper.alphanumeric(random, 20)))), new UseDefault()), (CustomersRowUnsaved row, Connection c) -> (new CustomersRepoImpl()).insert(row, c)); + } + + public Inserter Departments() { + return Inserter.of(new DepartmentsRow(RandomHelper.alphanumeric(random, 10), RandomHelper.alphanumeric(random, 10), RandomHelper.alphanumeric(random, 20), (random.nextBoolean() ? Optional.empty() : Optional.of(BigDecimal.valueOf(random.nextDouble())))), (DepartmentsRow row, Connection c) -> (new DepartmentsRepoImpl()).insert(row, c)); + } + + public Inserter Employees(DepartmentsId DepartmentsId) { + return Inserter.of(new EmployeesRowUnsaved(random.nextLong(), RandomHelper.alphanumeric(random, 5), DepartmentsId.deptCode(), DepartmentsId.deptRegion(), RandomHelper.alphanumeric(random, 20), (random.nextBoolean() ? Optional.empty() : Optional.of(BigDecimal.valueOf(random.nextDouble()))), new UseDefault()), (EmployeesRowUnsaved row, Connection c) -> (new EmployeesRepoImpl()).insert(row, c)); + } + + public Inserter OrderItems( + OrdersId orderId, + ProductsId productId + ) { + return Inserter.of(new OrderItemsRowUnsaved(orderId, productId, BigDecimal.valueOf(random.nextDouble()), new UseDefault()), (OrderItemsRowUnsaved row, Connection c) -> (new OrderItemsRepoImpl()).insert(row, c)); + } + + public Inserter Orders(CustomersId customerId) { + return Inserter.of(new OrdersRowUnsaved(new OrdersId(random.nextLong()), customerId, LocalDate.ofEpochDay((long) (random.nextInt(30000))), (random.nextBoolean() ? Optional.empty() : Optional.of(BigDecimal.valueOf(random.nextDouble()))), new UseDefault()), (OrdersRowUnsaved row, Connection c) -> (new OrdersRepoImpl()).insert(row, c)); + } + + public Inserter PrecisionTypes() { + return Inserter.of(new PrecisionTypesRow(new PrecisionTypesId(random.nextLong()), String10.truncate(RandomHelper.alphanumeric(random, 10)), String20.truncate(RandomHelper.alphanumeric(random, 20)), String50.truncate(RandomHelper.alphanumeric(random, 20)), String100.truncate(RandomHelper.alphanumeric(random, 20)), String255.truncate(RandomHelper.alphanumeric(random, 20)), Decimal5_2.unsafeForce(BigDecimal.valueOf((long) (Math.abs(random.nextInt()) % 1000)).add(BigDecimal.valueOf((long) (Math.abs(random.nextInt()) % 100)).movePointLeft(2))), Decimal10_2.unsafeForce(BigDecimal.valueOf((long) (Math.abs(random.nextInt()) % 1000000)).add(BigDecimal.valueOf((long) (Math.abs(random.nextInt()) % 100)).movePointLeft(2))), Decimal18_4.unsafeForce(BigDecimal.valueOf((long) (Math.abs(random.nextInt()) % 1000000)).add(BigDecimal.valueOf((long) (Math.abs(random.nextInt()) % 10000)).movePointLeft(4))), Int5.unsafeForce(BigInteger.valueOf((long) (Math.abs(random.nextInt()) % 100000))), Int10.unsafeForce(BigInteger.valueOf((long) (Math.abs(random.nextInt()) % 1000000000))), Int18.unsafeForce(BigInteger.valueOf((long) (Math.abs(random.nextInt()) % 1000000000)))), (PrecisionTypesRow row, Connection c) -> (new PrecisionTypesRepoImpl()).insert(row, c)); + } + + public Inserter PrecisionTypesNull() { + return Inserter.of(new PrecisionTypesNullRow(new PrecisionTypesNullId(random.nextLong()), (random.nextBoolean() ? Optional.empty() : Optional.of(String10.truncate(RandomHelper.alphanumeric(random, 10)))), (random.nextBoolean() ? Optional.empty() : Optional.of(String20.truncate(RandomHelper.alphanumeric(random, 20)))), (random.nextBoolean() ? Optional.empty() : Optional.of(String50.truncate(RandomHelper.alphanumeric(random, 20)))), (random.nextBoolean() ? Optional.empty() : Optional.of(String100.truncate(RandomHelper.alphanumeric(random, 20)))), (random.nextBoolean() ? Optional.empty() : Optional.of(String255.truncate(RandomHelper.alphanumeric(random, 20)))), (random.nextBoolean() ? Optional.empty() : Optional.of(Decimal5_2.unsafeForce(BigDecimal.valueOf((long) (Math.abs(random.nextInt()) % 1000)).add(BigDecimal.valueOf((long) (Math.abs(random.nextInt()) % 100)).movePointLeft(2))))), (random.nextBoolean() ? Optional.empty() : Optional.of(Decimal10_2.unsafeForce(BigDecimal.valueOf((long) (Math.abs(random.nextInt()) % 1000000)).add(BigDecimal.valueOf((long) (Math.abs(random.nextInt()) % 100)).movePointLeft(2))))), (random.nextBoolean() ? Optional.empty() : Optional.of(Decimal18_4.unsafeForce(BigDecimal.valueOf((long) (Math.abs(random.nextInt()) % 1000000)).add(BigDecimal.valueOf((long) (Math.abs(random.nextInt()) % 10000)).movePointLeft(4))))), (random.nextBoolean() ? Optional.empty() : Optional.of(Int5.unsafeForce(BigInteger.valueOf((long) (Math.abs(random.nextInt()) % 100000))))), (random.nextBoolean() ? Optional.empty() : Optional.of(Int10.unsafeForce(BigInteger.valueOf((long) (Math.abs(random.nextInt()) % 1000000000))))), (random.nextBoolean() ? Optional.empty() : Optional.of(Int18.unsafeForce(BigInteger.valueOf((long) (Math.abs(random.nextInt()) % 1000000000)))))), (PrecisionTypesNullRow row, Connection c) -> (new PrecisionTypesNullRepoImpl()).insert(row, c)); + } + + public Inserter Products() { + return Inserter.of(new ProductsRow(new ProductsId(random.nextLong()), RandomHelper.alphanumeric(random, 20), RandomHelper.alphanumeric(random, 20), BigDecimal.valueOf(random.nextDouble()), (random.nextBoolean() ? Optional.empty() : Optional.of(new Json("{}")))), (ProductsRow row, Connection c) -> (new ProductsRepoImpl()).insert(row, c)); + } + + public Inserter Users() { + return Inserter.of(new UsersRow(new UsersId(random.nextLong()), RandomHelper.alphanumeric(random, 20), new Email(RandomHelper.alphanumeric(random, 20))), (UsersRow row, Connection c) -> (new UsersRepoImpl()).insert(row, c)); + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/all_scalar_types/AllScalarTypesFields.java b/testers/sqlite/java/generated-and-checked-in/testdb/all_scalar_types/AllScalarTypesFields.java new file mode 100644 index 0000000000..71afb6f79b --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/all_scalar_types/AllScalarTypesFields.java @@ -0,0 +1,281 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.all_scalar_types; + +import dev.typr.dsl.FieldsBase; +import dev.typr.dsl.Path; +import dev.typr.dsl.RelationStructure; +import dev.typr.dsl.SqlExpr; +import dev.typr.dsl.SqlExpr.Field; +import dev.typr.dsl.SqlExpr.FieldLike; +import dev.typr.dsl.SqlExpr.IdField; +import dev.typr.dsl.SqlExpr.OptField; +import dev.typr.dsl.TupleExpr.TupleExpr25; +import dev.typr.foundations.RowCodec; +import dev.typr.foundations.SqliteTypes; +import dev.typr.foundations.data.Json; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.util.List; +import java.util.Optional; +import java.util.UUID; + +public class AllScalarTypesFields extends TupleExpr25 implements RelationStructure, FieldsBase { + List _path; + + public AllScalarTypesFields(List _path) { + this._path = _path; + } + + public static AllScalarTypesFields structure = new AllScalarTypesFields(java.util.Collections.emptyList()); + + public IdField id() { + return new IdField(_path, "id", AllScalarTypesRow::id, Optional.empty(), Optional.empty(), (row, value) -> row.withId(value), AllScalarTypesId.sqliteType); + } + + public OptField colTinyint() { + return new OptField(_path, "col_tinyint", AllScalarTypesRow::colTinyint, Optional.empty(), Optional.empty(), (row, value) -> row.withColTinyint(value), SqliteTypes.tinyint); + } + + public OptField colSmallint() { + return new OptField(_path, "col_smallint", AllScalarTypesRow::colSmallint, Optional.empty(), Optional.empty(), (row, value) -> row.withColSmallint(value), SqliteTypes.smallint); + } + + public OptField colInt() { + return new OptField(_path, "col_int", AllScalarTypesRow::colInt, Optional.empty(), Optional.empty(), (row, value) -> row.withColInt(value), SqliteTypes.int_); + } + + public OptField colInteger() { + return new OptField(_path, "col_integer", AllScalarTypesRow::colInteger, Optional.empty(), Optional.empty(), (row, value) -> row.withColInteger(value), SqliteTypes.integer); + } + + public OptField colBigint() { + return new OptField(_path, "col_bigint", AllScalarTypesRow::colBigint, Optional.empty(), Optional.empty(), (row, value) -> row.withColBigint(value), SqliteTypes.bigint); + } + + public OptField colBoolean() { + return new OptField(_path, "col_boolean", AllScalarTypesRow::colBoolean, Optional.empty(), Optional.empty(), (row, value) -> row.withColBoolean(value), SqliteTypes.boolean_); + } + + public OptField colReal() { + return new OptField(_path, "col_real", AllScalarTypesRow::colReal, Optional.empty(), Optional.empty(), (row, value) -> row.withColReal(value), SqliteTypes.real); + } + + public OptField colDouble() { + return new OptField(_path, "col_double", AllScalarTypesRow::colDouble, Optional.empty(), Optional.empty(), (row, value) -> row.withColDouble(value), SqliteTypes.double_); + } + + public OptField colFloat() { + return new OptField(_path, "col_float", AllScalarTypesRow::colFloat, Optional.empty(), Optional.empty(), (row, value) -> row.withColFloat(value), SqliteTypes.float_); + } + + public OptField colDecimal() { + return new OptField(_path, "col_decimal", AllScalarTypesRow::colDecimal, Optional.empty(), Optional.empty(), (row, value) -> row.withColDecimal(value), SqliteTypes.numeric); + } + + public OptField colNumeric() { + return new OptField(_path, "col_numeric", AllScalarTypesRow::colNumeric, Optional.empty(), Optional.empty(), (row, value) -> row.withColNumeric(value), SqliteTypes.numeric); + } + + public OptField colText() { + return new OptField(_path, "col_text", AllScalarTypesRow::colText, Optional.empty(), Optional.empty(), (row, value) -> row.withColText(value), SqliteTypes.text); + } + + public OptField colVarchar() { + return new OptField(_path, "col_varchar", AllScalarTypesRow::colVarchar, Optional.empty(), Optional.empty(), (row, value) -> row.withColVarchar(value), SqliteTypes.varchar); + } + + public OptField colChar() { + return new OptField(_path, "col_char", AllScalarTypesRow::colChar, Optional.empty(), Optional.empty(), (row, value) -> row.withColChar(value), SqliteTypes.char_); + } + + public OptField colClob() { + return new OptField(_path, "col_clob", AllScalarTypesRow::colClob, Optional.empty(), Optional.empty(), (row, value) -> row.withColClob(value), SqliteTypes.clob); + } + + public OptField colBlob() { + return new OptField(_path, "col_blob", AllScalarTypesRow::colBlob, Optional.empty(), Optional.empty(), (row, value) -> row.withColBlob(value), SqliteTypes.blob); + } + + public OptField colBinary() { + return new OptField(_path, "col_binary", AllScalarTypesRow::colBinary, Optional.empty(), Optional.empty(), (row, value) -> row.withColBinary(value), SqliteTypes.binary); + } + + public OptField colDate() { + return new OptField(_path, "col_date", AllScalarTypesRow::colDate, Optional.empty(), Optional.empty(), (row, value) -> row.withColDate(value), SqliteTypes.date); + } + + public OptField colTime() { + return new OptField(_path, "col_time", AllScalarTypesRow::colTime, Optional.empty(), Optional.empty(), (row, value) -> row.withColTime(value), SqliteTypes.time); + } + + public OptField colDatetime() { + return new OptField(_path, "col_datetime", AllScalarTypesRow::colDatetime, Optional.empty(), Optional.empty(), (row, value) -> row.withColDatetime(value), SqliteTypes.timestamp); + } + + public OptField colTimestamp() { + return new OptField(_path, "col_timestamp", AllScalarTypesRow::colTimestamp, Optional.empty(), Optional.empty(), (row, value) -> row.withColTimestamp(value), SqliteTypes.timestamp); + } + + public OptField colUuid() { + return new OptField(_path, "col_uuid", AllScalarTypesRow::colUuid, Optional.empty(), Optional.empty(), (row, value) -> row.withColUuid(value), SqliteTypes.uuid); + } + + public OptField colJson() { + return new OptField(_path, "col_json", AllScalarTypesRow::colJson, Optional.empty(), Optional.empty(), (row, value) -> row.withColJson(value), SqliteTypes.json); + } + + public Field colNotNull() { + return new Field(_path, "col_not_null", AllScalarTypesRow::colNotNull, Optional.empty(), Optional.empty(), (row, value) -> row.withColNotNull(value), SqliteTypes.text); + } + + @Override + public List _path() { + return _path; + } + + @Override + public List> columns() { + return java.util.List.of(this.id(), this.colTinyint(), this.colSmallint(), this.colInt(), this.colInteger(), this.colBigint(), this.colBoolean(), this.colReal(), this.colDouble(), this.colFloat(), this.colDecimal(), this.colNumeric(), this.colText(), this.colVarchar(), this.colChar(), this.colClob(), this.colBlob(), this.colBinary(), this.colDate(), this.colTime(), this.colDatetime(), this.colTimestamp(), this.colUuid(), this.colJson(), this.colNotNull()); + } + + @Override + public RowCodec rowCodec() { + return AllScalarTypesRow.rowCodec; + } + + @Override + public RelationStructure withPaths(List _path) { + return new AllScalarTypesFields(_path); + } + + @Override + public SqlExpr _1() { + return id(); + } + + @Override + public SqlExpr _2() { + return colTinyint(); + } + + @Override + public SqlExpr _3() { + return colSmallint(); + } + + @Override + public SqlExpr _4() { + return colInt(); + } + + @Override + public SqlExpr _5() { + return colInteger(); + } + + @Override + public SqlExpr _6() { + return colBigint(); + } + + @Override + public SqlExpr _7() { + return colBoolean(); + } + + @Override + public SqlExpr _8() { + return colReal(); + } + + @Override + public SqlExpr _9() { + return colDouble(); + } + + @Override + public SqlExpr _10() { + return colFloat(); + } + + @Override + public SqlExpr _11() { + return colDecimal(); + } + + @Override + public SqlExpr _12() { + return colNumeric(); + } + + @Override + public SqlExpr _13() { + return colText(); + } + + @Override + public SqlExpr _14() { + return colVarchar(); + } + + @Override + public SqlExpr _15() { + return colChar(); + } + + @Override + public SqlExpr _16() { + return colClob(); + } + + @Override + public SqlExpr _17() { + return colBlob(); + } + + @Override + public SqlExpr _18() { + return colBinary(); + } + + @Override + public SqlExpr _19() { + return colDate(); + } + + @Override + public SqlExpr _20() { + return colTime(); + } + + @Override + public SqlExpr _21() { + return colDatetime(); + } + + @Override + public SqlExpr _22() { + return colTimestamp(); + } + + @Override + public SqlExpr _23() { + return colUuid(); + } + + @Override + public SqlExpr _24() { + return colJson(); + } + + @Override + public SqlExpr _25() { + return colNotNull(); + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/all_scalar_types/AllScalarTypesId.java b/testers/sqlite/java/generated-and-checked-in/testdb/all_scalar_types/AllScalarTypesId.java new file mode 100644 index 0000000000..24cf3be68d --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/all_scalar_types/AllScalarTypesId.java @@ -0,0 +1,29 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.all_scalar_types; + +import com.fasterxml.jackson.annotation.JsonValue; +import dev.typr.foundations.Bijection; +import dev.typr.foundations.SqliteType; +import dev.typr.foundations.SqliteTypes; + +/** Type for the primary key of table `all_scalar_types` */ +public record AllScalarTypesId(@JsonValue Long value) { + public AllScalarTypesId withValue(Long value) { + return new AllScalarTypesId(value); + } + + @Override + public java.lang.String toString() { + return value.toString(); + } + + static public Bijection bijection = + Bijection.of(AllScalarTypesId::value, AllScalarTypesId::new); + + static public SqliteType sqliteType = + SqliteTypes.integer.to(Bijection.of(AllScalarTypesId::new, AllScalarTypesId::value)); +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/all_scalar_types/AllScalarTypesRepo.java b/testers/sqlite/java/generated-and-checked-in/testdb/all_scalar_types/AllScalarTypesRepo.java new file mode 100644 index 0000000000..d3f2877ce0 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/all_scalar_types/AllScalarTypesRepo.java @@ -0,0 +1,71 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.all_scalar_types; + +import dev.typr.dsl.DeleteBuilder; +import dev.typr.dsl.SelectBuilder; +import dev.typr.dsl.UpdateBuilder; +import dev.typr.foundations.Connection; +import dev.typr.foundations.ConnectionRead; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +public interface AllScalarTypesRepo { + DeleteBuilder delete(); + + Boolean deleteById( + AllScalarTypesId id, + Connection c + ); + + Integer deleteByIds( + List ids, + Connection c + ); + + AllScalarTypesRow insert( + AllScalarTypesRow unsaved, + Connection c + ); + + SelectBuilder select(); + + List selectAll(ConnectionRead c); + + Optional selectById( + AllScalarTypesId id, + ConnectionRead c + ); + + List selectByIds( + List ids, + ConnectionRead c + ); + + Map selectByIdsTracked( + List ids, + ConnectionRead c + ); + + UpdateBuilder update(); + + Boolean update( + AllScalarTypesRow row, + Connection c + ); + + AllScalarTypesRow upsert( + AllScalarTypesRow unsaved, + Connection c + ); + + List upsertBatch( + Iterator unsaved, + Connection c + ); +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/all_scalar_types/AllScalarTypesRepoImpl.java b/testers/sqlite/java/generated-and-checked-in/testdb/all_scalar_types/AllScalarTypesRepoImpl.java new file mode 100644 index 0000000000..07990e8a79 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/all_scalar_types/AllScalarTypesRepoImpl.java @@ -0,0 +1,128 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.all_scalar_types; + +import dev.typr.dsl.DeleteBuilder; +import dev.typr.dsl.Dialect; +import dev.typr.dsl.SelectBuilder; +import dev.typr.dsl.UpdateBuilder; +import dev.typr.foundations.Connection; +import dev.typr.foundations.ConnectionRead; +import dev.typr.foundations.Fragment; +import dev.typr.foundations.SqliteTypes; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import static dev.typr.foundations.Fragment.concat; + +public class AllScalarTypesRepoImpl implements AllScalarTypesRepo { + @Override + public DeleteBuilder delete() { + return DeleteBuilder.of("\"all_scalar_types\"", AllScalarTypesFields.structure, Dialect.SQLITE); + } + + @Override + public Boolean deleteById( + AllScalarTypesId id, + Connection c + ) { + return concat(Fragment.of("delete from \"all_scalar_types\" where \"id\" = "), Fragment.encode(AllScalarTypesId.sqliteType, id), Fragment.of("")).update().run(c) > 0; + } + + @Override + public Integer deleteByIds( + List ids, + Connection c + ) { + ArrayList fragments = new ArrayList<>(); + for (var id : ids) { fragments.add(Fragment.encode(AllScalarTypesId.sqliteType, id)); }; + return Fragment.concat(Fragment.of("delete from \"all_scalar_types\" where \"id\" in ("), Fragment.comma(fragments), Fragment.of(")")).update().run(c); + } + + @Override + public AllScalarTypesRow insert( + AllScalarTypesRow unsaved, + Connection c + ) { + return concat(Fragment.of("insert into \"all_scalar_types\"(\"id\", \"col_tinyint\", \"col_smallint\", \"col_int\", \"col_integer\", \"col_bigint\", \"col_boolean\", \"col_real\", \"col_double\", \"col_float\", \"col_decimal\", \"col_numeric\", \"col_text\", \"col_varchar\", \"col_char\", \"col_clob\", \"col_blob\", \"col_binary\", \"col_date\", \"col_time\", \"col_datetime\", \"col_timestamp\", \"col_uuid\", \"col_json\", \"col_not_null\")\nvalues ("), Fragment.encode(AllScalarTypesId.sqliteType, unsaved.id()), Fragment.of(", "), Fragment.encode(SqliteTypes.tinyint.opt(), unsaved.colTinyint()), Fragment.of(", "), Fragment.encode(SqliteTypes.smallint.opt(), unsaved.colSmallint()), Fragment.of(", "), Fragment.encode(SqliteTypes.int_.opt(), unsaved.colInt()), Fragment.of(", "), Fragment.encode(SqliteTypes.integer.opt(), unsaved.colInteger()), Fragment.of(", "), Fragment.encode(SqliteTypes.bigint.opt(), unsaved.colBigint()), Fragment.of(", "), Fragment.encode(SqliteTypes.boolean_.opt(), unsaved.colBoolean()), Fragment.of(", "), Fragment.encode(SqliteTypes.real.opt(), unsaved.colReal()), Fragment.of(", "), Fragment.encode(SqliteTypes.double_.opt(), unsaved.colDouble()), Fragment.of(", "), Fragment.encode(SqliteTypes.float_.opt(), unsaved.colFloat()), Fragment.of(", "), Fragment.encode(SqliteTypes.numeric.opt(), unsaved.colDecimal()), Fragment.of(", "), Fragment.encode(SqliteTypes.numeric.opt(), unsaved.colNumeric()), Fragment.of(", "), Fragment.encode(SqliteTypes.text.opt(), unsaved.colText()), Fragment.of(", "), Fragment.encode(SqliteTypes.varchar.opt(), unsaved.colVarchar()), Fragment.of(", "), Fragment.encode(SqliteTypes.char_.opt(), unsaved.colChar()), Fragment.of(", "), Fragment.encode(SqliteTypes.clob.opt(), unsaved.colClob()), Fragment.of(", "), Fragment.encode(SqliteTypes.blob.opt(), unsaved.colBlob()), Fragment.of(", "), Fragment.encode(SqliteTypes.binary.opt(), unsaved.colBinary()), Fragment.of(", "), Fragment.encode(SqliteTypes.date.opt(), unsaved.colDate()), Fragment.of(", "), Fragment.encode(SqliteTypes.time.opt(), unsaved.colTime()), Fragment.of(", "), Fragment.encode(SqliteTypes.timestamp.opt(), unsaved.colDatetime()), Fragment.of(", "), Fragment.encode(SqliteTypes.timestamp.opt(), unsaved.colTimestamp()), Fragment.of(", "), Fragment.encode(SqliteTypes.uuid.opt(), unsaved.colUuid()), Fragment.of(", "), Fragment.encode(SqliteTypes.json.opt(), unsaved.colJson()), Fragment.of(", "), Fragment.encode(SqliteTypes.text, unsaved.colNotNull()), Fragment.of(")\nRETURNING \"id\", \"col_tinyint\", \"col_smallint\", \"col_int\", \"col_integer\", \"col_bigint\", \"col_boolean\", \"col_real\", \"col_double\", \"col_float\", \"col_decimal\", \"col_numeric\", \"col_text\", \"col_varchar\", \"col_char\", \"col_clob\", \"col_blob\", \"col_binary\", \"col_date\", \"col_time\", \"col_datetime\", \"col_timestamp\", \"col_uuid\", \"col_json\", \"col_not_null\"\n")) + .updateReturning(AllScalarTypesRow.rowCodec.exactlyOne()).run(c); + } + + @Override + public SelectBuilder select() { + return SelectBuilder.of("\"all_scalar_types\"", AllScalarTypesFields.structure, AllScalarTypesRow.rowCodec, Dialect.SQLITE); + } + + @Override + public List selectAll(ConnectionRead c) { + return concat(Fragment.of("select \"id\", \"col_tinyint\", \"col_smallint\", \"col_int\", \"col_integer\", \"col_bigint\", \"col_boolean\", \"col_real\", \"col_double\", \"col_float\", \"col_decimal\", \"col_numeric\", \"col_text\", \"col_varchar\", \"col_char\", \"col_clob\", \"col_blob\", \"col_binary\", \"col_date\", \"col_time\", \"col_datetime\", \"col_timestamp\", \"col_uuid\", \"col_json\", \"col_not_null\"\nfrom \"all_scalar_types\"\n")).query(AllScalarTypesRow.rowCodec.all()).run(c); + } + + @Override + public Optional selectById( + AllScalarTypesId id, + ConnectionRead c + ) { + return concat(Fragment.of("select \"id\", \"col_tinyint\", \"col_smallint\", \"col_int\", \"col_integer\", \"col_bigint\", \"col_boolean\", \"col_real\", \"col_double\", \"col_float\", \"col_decimal\", \"col_numeric\", \"col_text\", \"col_varchar\", \"col_char\", \"col_clob\", \"col_blob\", \"col_binary\", \"col_date\", \"col_time\", \"col_datetime\", \"col_timestamp\", \"col_uuid\", \"col_json\", \"col_not_null\"\nfrom \"all_scalar_types\"\nwhere \"id\" = "), Fragment.encode(AllScalarTypesId.sqliteType, id), Fragment.of("")).query(AllScalarTypesRow.rowCodec.first()).run(c); + } + + @Override + public List selectByIds( + List ids, + ConnectionRead c + ) { + ArrayList fragments = new ArrayList<>(); + for (var id : ids) { fragments.add(Fragment.encode(AllScalarTypesId.sqliteType, id)); }; + return Fragment.concat(Fragment.of("select \"id\", \"col_tinyint\", \"col_smallint\", \"col_int\", \"col_integer\", \"col_bigint\", \"col_boolean\", \"col_real\", \"col_double\", \"col_float\", \"col_decimal\", \"col_numeric\", \"col_text\", \"col_varchar\", \"col_char\", \"col_clob\", \"col_blob\", \"col_binary\", \"col_date\", \"col_time\", \"col_datetime\", \"col_timestamp\", \"col_uuid\", \"col_json\", \"col_not_null\" from \"all_scalar_types\" where \"id\" in ("), Fragment.comma(fragments), Fragment.of(")")).query(AllScalarTypesRow.rowCodec.all()).run(c); + } + + @Override + public Map selectByIdsTracked( + List ids, + ConnectionRead c + ) { + HashMap ret = new HashMap(); + selectByIds(ids, c).forEach(row -> ret.put(row.id(), row)); + return ret; + } + + @Override + public UpdateBuilder update() { + return UpdateBuilder.of("\"all_scalar_types\"", AllScalarTypesFields.structure, AllScalarTypesRow.rowCodec, Dialect.SQLITE); + } + + @Override + public Boolean update( + AllScalarTypesRow row, + Connection c + ) { + AllScalarTypesId id = row.id();; + return concat(Fragment.of("update \"all_scalar_types\"\nset \"col_tinyint\" = "), Fragment.encode(SqliteTypes.tinyint.opt(), row.colTinyint()), Fragment.of(",\n\"col_smallint\" = "), Fragment.encode(SqliteTypes.smallint.opt(), row.colSmallint()), Fragment.of(",\n\"col_int\" = "), Fragment.encode(SqliteTypes.int_.opt(), row.colInt()), Fragment.of(",\n\"col_integer\" = "), Fragment.encode(SqliteTypes.integer.opt(), row.colInteger()), Fragment.of(",\n\"col_bigint\" = "), Fragment.encode(SqliteTypes.bigint.opt(), row.colBigint()), Fragment.of(",\n\"col_boolean\" = "), Fragment.encode(SqliteTypes.boolean_.opt(), row.colBoolean()), Fragment.of(",\n\"col_real\" = "), Fragment.encode(SqliteTypes.real.opt(), row.colReal()), Fragment.of(",\n\"col_double\" = "), Fragment.encode(SqliteTypes.double_.opt(), row.colDouble()), Fragment.of(",\n\"col_float\" = "), Fragment.encode(SqliteTypes.float_.opt(), row.colFloat()), Fragment.of(",\n\"col_decimal\" = "), Fragment.encode(SqliteTypes.numeric.opt(), row.colDecimal()), Fragment.of(",\n\"col_numeric\" = "), Fragment.encode(SqliteTypes.numeric.opt(), row.colNumeric()), Fragment.of(",\n\"col_text\" = "), Fragment.encode(SqliteTypes.text.opt(), row.colText()), Fragment.of(",\n\"col_varchar\" = "), Fragment.encode(SqliteTypes.varchar.opt(), row.colVarchar()), Fragment.of(",\n\"col_char\" = "), Fragment.encode(SqliteTypes.char_.opt(), row.colChar()), Fragment.of(",\n\"col_clob\" = "), Fragment.encode(SqliteTypes.clob.opt(), row.colClob()), Fragment.of(",\n\"col_blob\" = "), Fragment.encode(SqliteTypes.blob.opt(), row.colBlob()), Fragment.of(",\n\"col_binary\" = "), Fragment.encode(SqliteTypes.binary.opt(), row.colBinary()), Fragment.of(",\n\"col_date\" = "), Fragment.encode(SqliteTypes.date.opt(), row.colDate()), Fragment.of(",\n\"col_time\" = "), Fragment.encode(SqliteTypes.time.opt(), row.colTime()), Fragment.of(",\n\"col_datetime\" = "), Fragment.encode(SqliteTypes.timestamp.opt(), row.colDatetime()), Fragment.of(",\n\"col_timestamp\" = "), Fragment.encode(SqliteTypes.timestamp.opt(), row.colTimestamp()), Fragment.of(",\n\"col_uuid\" = "), Fragment.encode(SqliteTypes.uuid.opt(), row.colUuid()), Fragment.of(",\n\"col_json\" = "), Fragment.encode(SqliteTypes.json.opt(), row.colJson()), Fragment.of(",\n\"col_not_null\" = "), Fragment.encode(SqliteTypes.text, row.colNotNull()), Fragment.of("\nwhere \"id\" = "), Fragment.encode(AllScalarTypesId.sqliteType, id), Fragment.of("")).update().run(c) > 0; + } + + @Override + public AllScalarTypesRow upsert( + AllScalarTypesRow unsaved, + Connection c + ) { + return concat(Fragment.of("INSERT INTO \"all_scalar_types\"(\"id\", \"col_tinyint\", \"col_smallint\", \"col_int\", \"col_integer\", \"col_bigint\", \"col_boolean\", \"col_real\", \"col_double\", \"col_float\", \"col_decimal\", \"col_numeric\", \"col_text\", \"col_varchar\", \"col_char\", \"col_clob\", \"col_blob\", \"col_binary\", \"col_date\", \"col_time\", \"col_datetime\", \"col_timestamp\", \"col_uuid\", \"col_json\", \"col_not_null\")\nVALUES ("), Fragment.encode(AllScalarTypesId.sqliteType, unsaved.id()), Fragment.of(", "), Fragment.encode(SqliteTypes.tinyint.opt(), unsaved.colTinyint()), Fragment.of(", "), Fragment.encode(SqliteTypes.smallint.opt(), unsaved.colSmallint()), Fragment.of(", "), Fragment.encode(SqliteTypes.int_.opt(), unsaved.colInt()), Fragment.of(", "), Fragment.encode(SqliteTypes.integer.opt(), unsaved.colInteger()), Fragment.of(", "), Fragment.encode(SqliteTypes.bigint.opt(), unsaved.colBigint()), Fragment.of(", "), Fragment.encode(SqliteTypes.boolean_.opt(), unsaved.colBoolean()), Fragment.of(", "), Fragment.encode(SqliteTypes.real.opt(), unsaved.colReal()), Fragment.of(", "), Fragment.encode(SqliteTypes.double_.opt(), unsaved.colDouble()), Fragment.of(", "), Fragment.encode(SqliteTypes.float_.opt(), unsaved.colFloat()), Fragment.of(", "), Fragment.encode(SqliteTypes.numeric.opt(), unsaved.colDecimal()), Fragment.of(", "), Fragment.encode(SqliteTypes.numeric.opt(), unsaved.colNumeric()), Fragment.of(", "), Fragment.encode(SqliteTypes.text.opt(), unsaved.colText()), Fragment.of(", "), Fragment.encode(SqliteTypes.varchar.opt(), unsaved.colVarchar()), Fragment.of(", "), Fragment.encode(SqliteTypes.char_.opt(), unsaved.colChar()), Fragment.of(", "), Fragment.encode(SqliteTypes.clob.opt(), unsaved.colClob()), Fragment.of(", "), Fragment.encode(SqliteTypes.blob.opt(), unsaved.colBlob()), Fragment.of(", "), Fragment.encode(SqliteTypes.binary.opt(), unsaved.colBinary()), Fragment.of(", "), Fragment.encode(SqliteTypes.date.opt(), unsaved.colDate()), Fragment.of(", "), Fragment.encode(SqliteTypes.time.opt(), unsaved.colTime()), Fragment.of(", "), Fragment.encode(SqliteTypes.timestamp.opt(), unsaved.colDatetime()), Fragment.of(", "), Fragment.encode(SqliteTypes.timestamp.opt(), unsaved.colTimestamp()), Fragment.of(", "), Fragment.encode(SqliteTypes.uuid.opt(), unsaved.colUuid()), Fragment.of(", "), Fragment.encode(SqliteTypes.json.opt(), unsaved.colJson()), Fragment.of(", "), Fragment.encode(SqliteTypes.text, unsaved.colNotNull()), Fragment.of(")\nON CONFLICT (\"id\")\nDO UPDATE SET\n \"col_tinyint\" = EXCLUDED.\"col_tinyint\",\n\"col_smallint\" = EXCLUDED.\"col_smallint\",\n\"col_int\" = EXCLUDED.\"col_int\",\n\"col_integer\" = EXCLUDED.\"col_integer\",\n\"col_bigint\" = EXCLUDED.\"col_bigint\",\n\"col_boolean\" = EXCLUDED.\"col_boolean\",\n\"col_real\" = EXCLUDED.\"col_real\",\n\"col_double\" = EXCLUDED.\"col_double\",\n\"col_float\" = EXCLUDED.\"col_float\",\n\"col_decimal\" = EXCLUDED.\"col_decimal\",\n\"col_numeric\" = EXCLUDED.\"col_numeric\",\n\"col_text\" = EXCLUDED.\"col_text\",\n\"col_varchar\" = EXCLUDED.\"col_varchar\",\n\"col_char\" = EXCLUDED.\"col_char\",\n\"col_clob\" = EXCLUDED.\"col_clob\",\n\"col_blob\" = EXCLUDED.\"col_blob\",\n\"col_binary\" = EXCLUDED.\"col_binary\",\n\"col_date\" = EXCLUDED.\"col_date\",\n\"col_time\" = EXCLUDED.\"col_time\",\n\"col_datetime\" = EXCLUDED.\"col_datetime\",\n\"col_timestamp\" = EXCLUDED.\"col_timestamp\",\n\"col_uuid\" = EXCLUDED.\"col_uuid\",\n\"col_json\" = EXCLUDED.\"col_json\",\n\"col_not_null\" = EXCLUDED.\"col_not_null\"\nRETURNING \"id\", \"col_tinyint\", \"col_smallint\", \"col_int\", \"col_integer\", \"col_bigint\", \"col_boolean\", \"col_real\", \"col_double\", \"col_float\", \"col_decimal\", \"col_numeric\", \"col_text\", \"col_varchar\", \"col_char\", \"col_clob\", \"col_blob\", \"col_binary\", \"col_date\", \"col_time\", \"col_datetime\", \"col_timestamp\", \"col_uuid\", \"col_json\", \"col_not_null\"")) + .updateReturning(AllScalarTypesRow.rowCodec.exactlyOne()) + .run(c); + } + + @Override + public List upsertBatch( + Iterator unsaved, + Connection c + ) { + return concat(Fragment.of("INSERT INTO \"all_scalar_types\"(\"id\", \"col_tinyint\", \"col_smallint\", \"col_int\", \"col_integer\", \"col_bigint\", \"col_boolean\", \"col_real\", \"col_double\", \"col_float\", \"col_decimal\", \"col_numeric\", \"col_text\", \"col_varchar\", \"col_char\", \"col_clob\", \"col_blob\", \"col_binary\", \"col_date\", \"col_time\", \"col_datetime\", \"col_timestamp\", \"col_uuid\", \"col_json\", \"col_not_null\")\nVALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\nON CONFLICT (\"id\")\nDO UPDATE SET\n \"col_tinyint\" = EXCLUDED.\"col_tinyint\",\n\"col_smallint\" = EXCLUDED.\"col_smallint\",\n\"col_int\" = EXCLUDED.\"col_int\",\n\"col_integer\" = EXCLUDED.\"col_integer\",\n\"col_bigint\" = EXCLUDED.\"col_bigint\",\n\"col_boolean\" = EXCLUDED.\"col_boolean\",\n\"col_real\" = EXCLUDED.\"col_real\",\n\"col_double\" = EXCLUDED.\"col_double\",\n\"col_float\" = EXCLUDED.\"col_float\",\n\"col_decimal\" = EXCLUDED.\"col_decimal\",\n\"col_numeric\" = EXCLUDED.\"col_numeric\",\n\"col_text\" = EXCLUDED.\"col_text\",\n\"col_varchar\" = EXCLUDED.\"col_varchar\",\n\"col_char\" = EXCLUDED.\"col_char\",\n\"col_clob\" = EXCLUDED.\"col_clob\",\n\"col_blob\" = EXCLUDED.\"col_blob\",\n\"col_binary\" = EXCLUDED.\"col_binary\",\n\"col_date\" = EXCLUDED.\"col_date\",\n\"col_time\" = EXCLUDED.\"col_time\",\n\"col_datetime\" = EXCLUDED.\"col_datetime\",\n\"col_timestamp\" = EXCLUDED.\"col_timestamp\",\n\"col_uuid\" = EXCLUDED.\"col_uuid\",\n\"col_json\" = EXCLUDED.\"col_json\",\n\"col_not_null\" = EXCLUDED.\"col_not_null\"\nRETURNING \"id\", \"col_tinyint\", \"col_smallint\", \"col_int\", \"col_integer\", \"col_bigint\", \"col_boolean\", \"col_real\", \"col_double\", \"col_float\", \"col_decimal\", \"col_numeric\", \"col_text\", \"col_varchar\", \"col_char\", \"col_clob\", \"col_blob\", \"col_binary\", \"col_date\", \"col_time\", \"col_datetime\", \"col_timestamp\", \"col_uuid\", \"col_json\", \"col_not_null\"")) + .updateReturningEach(AllScalarTypesRow.rowCodec, unsaved) + .run(c); + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/all_scalar_types/AllScalarTypesRepoMock.java b/testers/sqlite/java/generated-and-checked-in/testdb/all_scalar_types/AllScalarTypesRepoMock.java new file mode 100644 index 0000000000..e5681e80fc --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/all_scalar_types/AllScalarTypesRepoMock.java @@ -0,0 +1,157 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.all_scalar_types; + +import dev.typr.dsl.DeleteBuilder; +import dev.typr.dsl.DeleteBuilderMock; +import dev.typr.dsl.DeleteParams; +import dev.typr.dsl.SelectBuilder; +import dev.typr.dsl.SelectBuilderMock; +import dev.typr.dsl.SelectParams; +import dev.typr.dsl.UpdateBuilder; +import dev.typr.dsl.UpdateBuilderMock; +import dev.typr.dsl.UpdateParams; +import dev.typr.foundations.Connection; +import dev.typr.foundations.ConnectionRead; +import java.lang.RuntimeException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.function.Function; +import java.util.stream.Collectors; + +public record AllScalarTypesRepoMock(HashMap map) implements AllScalarTypesRepo { + public AllScalarTypesRepoMock() { + this(new HashMap()); + } + + public AllScalarTypesRepoMock withMap(HashMap map) { + return new AllScalarTypesRepoMock(map); + } + + @Override + public DeleteBuilder delete() { + return new DeleteBuilderMock<>(AllScalarTypesFields.structure, () -> new ArrayList<>(map.values()), DeleteParams.empty(), row -> row.id(), id -> map.remove(id)); + } + + @Override + public Boolean deleteById( + AllScalarTypesId id, + Connection c + ) { + return Optional.ofNullable(map.remove(id)).isPresent(); + } + + @Override + public Integer deleteByIds( + List ids, + Connection c + ) { + var count = 0; + for (var id : ids) { + if (Optional.ofNullable(map.remove(id)).isPresent()) { + count = count + 1;; + } + }; + return count; + } + + @Override + public AllScalarTypesRow insert( + AllScalarTypesRow unsaved, + Connection c + ) { + if (map.containsKey(unsaved.id())) { + throw new RuntimeException("id " + unsaved.id() + " already exists"); + } + map.put(unsaved.id(), unsaved); + return unsaved; + } + + @Override + public SelectBuilder select() { + return new SelectBuilderMock<>(AllScalarTypesFields.structure, () -> new ArrayList<>(map.values()), SelectParams.empty()); + } + + @Override + public List selectAll(ConnectionRead c) { + return new ArrayList<>(map.values()); + } + + @Override + public Optional selectById( + AllScalarTypesId id, + ConnectionRead c + ) { + return Optional.ofNullable(map.get(id)); + } + + @Override + public List selectByIds( + List ids, + ConnectionRead c + ) { + var result = new ArrayList(); + for (var id : ids) { + var opt = Optional.ofNullable(map.get(id)); + if (opt.isPresent()) { + result.add(opt.get()); + } + }; + return result; + } + + @Override + public Map selectByIdsTracked( + List ids, + ConnectionRead c + ) { + return selectByIds(ids, c).stream().collect(Collectors.toMap((AllScalarTypesRow row) -> row.id(), Function.identity())); + } + + @Override + public UpdateBuilder update() { + return new UpdateBuilderMock<>(AllScalarTypesFields.structure, () -> new ArrayList<>(map.values()), UpdateParams.empty(), row -> row); + } + + @Override + public Boolean update( + AllScalarTypesRow row, + Connection c + ) { + var shouldUpdate = Optional.ofNullable(map.get(row.id())).filter(oldRow -> !oldRow.equals(row)).isPresent(); + if (shouldUpdate) { + map.put(row.id(), row);; + } + return shouldUpdate; + } + + @Override + public AllScalarTypesRow upsert( + AllScalarTypesRow unsaved, + Connection c + ) { + map.put(unsaved.id(), unsaved); + return unsaved; + } + + @Override + public List upsertBatch( + Iterator unsaved, + Connection c + ) { + var result = new ArrayList(); + while (unsaved.hasNext()) { + var row = unsaved.next(); + map.put(row.id(), row); + result.add(row); + }; + return result; + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/all_scalar_types/AllScalarTypesRow.java b/testers/sqlite/java/generated-and-checked-in/testdb/all_scalar_types/AllScalarTypesRow.java new file mode 100644 index 0000000000..e70a6732c6 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/all_scalar_types/AllScalarTypesRow.java @@ -0,0 +1,277 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.all_scalar_types; + +import com.fasterxml.jackson.annotation.JsonProperty; +import dev.typr.dsl.RowCodecs; +import dev.typr.foundations.RowCodec; +import dev.typr.foundations.SqliteTypes; +import dev.typr.foundations.Tuple.Tuple25; +import dev.typr.foundations.data.Json; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.util.Optional; +import java.util.UUID; + +/** Table: all_scalar_types + * Primary key: id + */ +public record AllScalarTypesRow( + AllScalarTypesId id, + @JsonProperty("col_tinyint") Optional colTinyint, + @JsonProperty("col_smallint") Optional colSmallint, + @JsonProperty("col_int") Optional colInt, + @JsonProperty("col_integer") Optional colInteger, + @JsonProperty("col_bigint") Optional colBigint, + @JsonProperty("col_boolean") Optional colBoolean, + @JsonProperty("col_real") Optional colReal, + @JsonProperty("col_double") Optional colDouble, + @JsonProperty("col_float") Optional colFloat, + @JsonProperty("col_decimal") Optional colDecimal, + @JsonProperty("col_numeric") Optional colNumeric, + @JsonProperty("col_text") Optional colText, + @JsonProperty("col_varchar") Optional colVarchar, + @JsonProperty("col_char") Optional colChar, + @JsonProperty("col_clob") Optional colClob, + @JsonProperty("col_blob") Optional colBlob, + @JsonProperty("col_binary") Optional colBinary, + @JsonProperty("col_date") Optional colDate, + @JsonProperty("col_time") Optional colTime, + @JsonProperty("col_datetime") Optional colDatetime, + @JsonProperty("col_timestamp") Optional colTimestamp, + @JsonProperty("col_uuid") Optional colUuid, + @JsonProperty("col_json") Optional colJson, + @JsonProperty("col_not_null") String colNotNull +) implements Tuple25, Optional, Optional, Optional, Optional, Optional, Optional, Optional, Optional, Optional, Optional, Optional, Optional, Optional, Optional, Optional, Optional, Optional, Optional, Optional, Optional, Optional, Optional, String> { + public AllScalarTypesRow withId(AllScalarTypesId id) { + return new AllScalarTypesRow(id, colTinyint, colSmallint, colInt, colInteger, colBigint, colBoolean, colReal, colDouble, colFloat, colDecimal, colNumeric, colText, colVarchar, colChar, colClob, colBlob, colBinary, colDate, colTime, colDatetime, colTimestamp, colUuid, colJson, colNotNull); + } + + public AllScalarTypesRow withColTinyint(Optional colTinyint) { + return new AllScalarTypesRow(id, colTinyint, colSmallint, colInt, colInteger, colBigint, colBoolean, colReal, colDouble, colFloat, colDecimal, colNumeric, colText, colVarchar, colChar, colClob, colBlob, colBinary, colDate, colTime, colDatetime, colTimestamp, colUuid, colJson, colNotNull); + } + + public AllScalarTypesRow withColSmallint(Optional colSmallint) { + return new AllScalarTypesRow(id, colTinyint, colSmallint, colInt, colInteger, colBigint, colBoolean, colReal, colDouble, colFloat, colDecimal, colNumeric, colText, colVarchar, colChar, colClob, colBlob, colBinary, colDate, colTime, colDatetime, colTimestamp, colUuid, colJson, colNotNull); + } + + public AllScalarTypesRow withColInt(Optional colInt) { + return new AllScalarTypesRow(id, colTinyint, colSmallint, colInt, colInteger, colBigint, colBoolean, colReal, colDouble, colFloat, colDecimal, colNumeric, colText, colVarchar, colChar, colClob, colBlob, colBinary, colDate, colTime, colDatetime, colTimestamp, colUuid, colJson, colNotNull); + } + + public AllScalarTypesRow withColInteger(Optional colInteger) { + return new AllScalarTypesRow(id, colTinyint, colSmallint, colInt, colInteger, colBigint, colBoolean, colReal, colDouble, colFloat, colDecimal, colNumeric, colText, colVarchar, colChar, colClob, colBlob, colBinary, colDate, colTime, colDatetime, colTimestamp, colUuid, colJson, colNotNull); + } + + public AllScalarTypesRow withColBigint(Optional colBigint) { + return new AllScalarTypesRow(id, colTinyint, colSmallint, colInt, colInteger, colBigint, colBoolean, colReal, colDouble, colFloat, colDecimal, colNumeric, colText, colVarchar, colChar, colClob, colBlob, colBinary, colDate, colTime, colDatetime, colTimestamp, colUuid, colJson, colNotNull); + } + + public AllScalarTypesRow withColBoolean(Optional colBoolean) { + return new AllScalarTypesRow(id, colTinyint, colSmallint, colInt, colInteger, colBigint, colBoolean, colReal, colDouble, colFloat, colDecimal, colNumeric, colText, colVarchar, colChar, colClob, colBlob, colBinary, colDate, colTime, colDatetime, colTimestamp, colUuid, colJson, colNotNull); + } + + public AllScalarTypesRow withColReal(Optional colReal) { + return new AllScalarTypesRow(id, colTinyint, colSmallint, colInt, colInteger, colBigint, colBoolean, colReal, colDouble, colFloat, colDecimal, colNumeric, colText, colVarchar, colChar, colClob, colBlob, colBinary, colDate, colTime, colDatetime, colTimestamp, colUuid, colJson, colNotNull); + } + + public AllScalarTypesRow withColDouble(Optional colDouble) { + return new AllScalarTypesRow(id, colTinyint, colSmallint, colInt, colInteger, colBigint, colBoolean, colReal, colDouble, colFloat, colDecimal, colNumeric, colText, colVarchar, colChar, colClob, colBlob, colBinary, colDate, colTime, colDatetime, colTimestamp, colUuid, colJson, colNotNull); + } + + public AllScalarTypesRow withColFloat(Optional colFloat) { + return new AllScalarTypesRow(id, colTinyint, colSmallint, colInt, colInteger, colBigint, colBoolean, colReal, colDouble, colFloat, colDecimal, colNumeric, colText, colVarchar, colChar, colClob, colBlob, colBinary, colDate, colTime, colDatetime, colTimestamp, colUuid, colJson, colNotNull); + } + + public AllScalarTypesRow withColDecimal(Optional colDecimal) { + return new AllScalarTypesRow(id, colTinyint, colSmallint, colInt, colInteger, colBigint, colBoolean, colReal, colDouble, colFloat, colDecimal, colNumeric, colText, colVarchar, colChar, colClob, colBlob, colBinary, colDate, colTime, colDatetime, colTimestamp, colUuid, colJson, colNotNull); + } + + public AllScalarTypesRow withColNumeric(Optional colNumeric) { + return new AllScalarTypesRow(id, colTinyint, colSmallint, colInt, colInteger, colBigint, colBoolean, colReal, colDouble, colFloat, colDecimal, colNumeric, colText, colVarchar, colChar, colClob, colBlob, colBinary, colDate, colTime, colDatetime, colTimestamp, colUuid, colJson, colNotNull); + } + + public AllScalarTypesRow withColText(Optional colText) { + return new AllScalarTypesRow(id, colTinyint, colSmallint, colInt, colInteger, colBigint, colBoolean, colReal, colDouble, colFloat, colDecimal, colNumeric, colText, colVarchar, colChar, colClob, colBlob, colBinary, colDate, colTime, colDatetime, colTimestamp, colUuid, colJson, colNotNull); + } + + public AllScalarTypesRow withColVarchar(Optional colVarchar) { + return new AllScalarTypesRow(id, colTinyint, colSmallint, colInt, colInteger, colBigint, colBoolean, colReal, colDouble, colFloat, colDecimal, colNumeric, colText, colVarchar, colChar, colClob, colBlob, colBinary, colDate, colTime, colDatetime, colTimestamp, colUuid, colJson, colNotNull); + } + + public AllScalarTypesRow withColChar(Optional colChar) { + return new AllScalarTypesRow(id, colTinyint, colSmallint, colInt, colInteger, colBigint, colBoolean, colReal, colDouble, colFloat, colDecimal, colNumeric, colText, colVarchar, colChar, colClob, colBlob, colBinary, colDate, colTime, colDatetime, colTimestamp, colUuid, colJson, colNotNull); + } + + public AllScalarTypesRow withColClob(Optional colClob) { + return new AllScalarTypesRow(id, colTinyint, colSmallint, colInt, colInteger, colBigint, colBoolean, colReal, colDouble, colFloat, colDecimal, colNumeric, colText, colVarchar, colChar, colClob, colBlob, colBinary, colDate, colTime, colDatetime, colTimestamp, colUuid, colJson, colNotNull); + } + + public AllScalarTypesRow withColBlob(Optional colBlob) { + return new AllScalarTypesRow(id, colTinyint, colSmallint, colInt, colInteger, colBigint, colBoolean, colReal, colDouble, colFloat, colDecimal, colNumeric, colText, colVarchar, colChar, colClob, colBlob, colBinary, colDate, colTime, colDatetime, colTimestamp, colUuid, colJson, colNotNull); + } + + public AllScalarTypesRow withColBinary(Optional colBinary) { + return new AllScalarTypesRow(id, colTinyint, colSmallint, colInt, colInteger, colBigint, colBoolean, colReal, colDouble, colFloat, colDecimal, colNumeric, colText, colVarchar, colChar, colClob, colBlob, colBinary, colDate, colTime, colDatetime, colTimestamp, colUuid, colJson, colNotNull); + } + + public AllScalarTypesRow withColDate(Optional colDate) { + return new AllScalarTypesRow(id, colTinyint, colSmallint, colInt, colInteger, colBigint, colBoolean, colReal, colDouble, colFloat, colDecimal, colNumeric, colText, colVarchar, colChar, colClob, colBlob, colBinary, colDate, colTime, colDatetime, colTimestamp, colUuid, colJson, colNotNull); + } + + public AllScalarTypesRow withColTime(Optional colTime) { + return new AllScalarTypesRow(id, colTinyint, colSmallint, colInt, colInteger, colBigint, colBoolean, colReal, colDouble, colFloat, colDecimal, colNumeric, colText, colVarchar, colChar, colClob, colBlob, colBinary, colDate, colTime, colDatetime, colTimestamp, colUuid, colJson, colNotNull); + } + + public AllScalarTypesRow withColDatetime(Optional colDatetime) { + return new AllScalarTypesRow(id, colTinyint, colSmallint, colInt, colInteger, colBigint, colBoolean, colReal, colDouble, colFloat, colDecimal, colNumeric, colText, colVarchar, colChar, colClob, colBlob, colBinary, colDate, colTime, colDatetime, colTimestamp, colUuid, colJson, colNotNull); + } + + public AllScalarTypesRow withColTimestamp(Optional colTimestamp) { + return new AllScalarTypesRow(id, colTinyint, colSmallint, colInt, colInteger, colBigint, colBoolean, colReal, colDouble, colFloat, colDecimal, colNumeric, colText, colVarchar, colChar, colClob, colBlob, colBinary, colDate, colTime, colDatetime, colTimestamp, colUuid, colJson, colNotNull); + } + + public AllScalarTypesRow withColUuid(Optional colUuid) { + return new AllScalarTypesRow(id, colTinyint, colSmallint, colInt, colInteger, colBigint, colBoolean, colReal, colDouble, colFloat, colDecimal, colNumeric, colText, colVarchar, colChar, colClob, colBlob, colBinary, colDate, colTime, colDatetime, colTimestamp, colUuid, colJson, colNotNull); + } + + public AllScalarTypesRow withColJson(Optional colJson) { + return new AllScalarTypesRow(id, colTinyint, colSmallint, colInt, colInteger, colBigint, colBoolean, colReal, colDouble, colFloat, colDecimal, colNumeric, colText, colVarchar, colChar, colClob, colBlob, colBinary, colDate, colTime, colDatetime, colTimestamp, colUuid, colJson, colNotNull); + } + + public AllScalarTypesRow withColNotNull(String colNotNull) { + return new AllScalarTypesRow(id, colTinyint, colSmallint, colInt, colInteger, colBigint, colBoolean, colReal, colDouble, colFloat, colDecimal, colNumeric, colText, colVarchar, colChar, colClob, colBlob, colBinary, colDate, colTime, colDatetime, colTimestamp, colUuid, colJson, colNotNull); + } + + public static RowCodec rowCodec = RowCodecs.of(AllScalarTypesId.sqliteType, SqliteTypes.tinyint.opt(), SqliteTypes.smallint.opt(), SqliteTypes.int_.opt(), SqliteTypes.integer.opt(), SqliteTypes.bigint.opt(), SqliteTypes.boolean_.opt(), SqliteTypes.real.opt(), SqliteTypes.double_.opt(), SqliteTypes.float_.opt(), SqliteTypes.numeric.opt(), SqliteTypes.numeric.opt(), SqliteTypes.text.opt(), SqliteTypes.varchar.opt(), SqliteTypes.char_.opt(), SqliteTypes.clob.opt(), SqliteTypes.blob.opt(), SqliteTypes.binary.opt(), SqliteTypes.date.opt(), SqliteTypes.time.opt(), SqliteTypes.timestamp.opt(), SqliteTypes.timestamp.opt(), SqliteTypes.uuid.opt(), SqliteTypes.json.opt(), SqliteTypes.text, AllScalarTypesRow::new, row -> new Object[]{row.id(), row.colTinyint(), row.colSmallint(), row.colInt(), row.colInteger(), row.colBigint(), row.colBoolean(), row.colReal(), row.colDouble(), row.colFloat(), row.colDecimal(), row.colNumeric(), row.colText(), row.colVarchar(), row.colChar(), row.colClob(), row.colBlob(), row.colBinary(), row.colDate(), row.colTime(), row.colDatetime(), row.colTimestamp(), row.colUuid(), row.colJson(), row.colNotNull()}); + + @Override + public AllScalarTypesId _1() { + return id; + } + + @Override + public Optional _10() { + return colFloat; + } + + @Override + public Optional _11() { + return colDecimal; + } + + @Override + public Optional _12() { + return colNumeric; + } + + @Override + public Optional _13() { + return colText; + } + + @Override + public Optional _14() { + return colVarchar; + } + + @Override + public Optional _15() { + return colChar; + } + + @Override + public Optional _16() { + return colClob; + } + + @Override + public Optional _17() { + return colBlob; + } + + @Override + public Optional _18() { + return colBinary; + } + + @Override + public Optional _19() { + return colDate; + } + + @Override + public Optional _2() { + return colTinyint; + } + + @Override + public Optional _20() { + return colTime; + } + + @Override + public Optional _21() { + return colDatetime; + } + + @Override + public Optional _22() { + return colTimestamp; + } + + @Override + public Optional _23() { + return colUuid; + } + + @Override + public Optional _24() { + return colJson; + } + + @Override + public String _25() { + return colNotNull; + } + + @Override + public Optional _3() { + return colSmallint; + } + + @Override + public Optional _4() { + return colInt; + } + + @Override + public Optional _5() { + return colInteger; + } + + @Override + public Optional _6() { + return colBigint; + } + + @Override + public Optional _7() { + return colBoolean; + } + + @Override + public Optional _8() { + return colReal; + } + + @Override + public Optional _9() { + return colDouble; + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/all_scalar_types_search/AllScalarTypesSearchSqlRepo.java b/testers/sqlite/java/generated-and-checked-in/testdb/all_scalar_types_search/AllScalarTypesSearchSqlRepo.java new file mode 100644 index 0000000000..30777062f4 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/all_scalar_types_search/AllScalarTypesSearchSqlRepo.java @@ -0,0 +1,20 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.all_scalar_types_search; + +import dev.typr.foundations.ConnectionRead; +import java.time.LocalDate; +import java.util.List; +import java.util.Optional; + +public interface AllScalarTypesSearchSqlRepo { + List apply( + Optional minId, + Optional textPattern, + Optional afterDate, + ConnectionRead c + ); +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/all_scalar_types_search/AllScalarTypesSearchSqlRepoImpl.java b/testers/sqlite/java/generated-and-checked-in/testdb/all_scalar_types_search/AllScalarTypesSearchSqlRepoImpl.java new file mode 100644 index 0000000000..cfff536c3b --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/all_scalar_types_search/AllScalarTypesSearchSqlRepoImpl.java @@ -0,0 +1,26 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.all_scalar_types_search; + +import dev.typr.foundations.ConnectionRead; +import dev.typr.foundations.Fragment; +import dev.typr.foundations.SqliteTypes; +import java.time.LocalDate; +import java.util.List; +import java.util.Optional; +import static dev.typr.foundations.Fragment.concat; + +public class AllScalarTypesSearchSqlRepoImpl implements AllScalarTypesSearchSqlRepo { + @Override + public List apply( + Optional minId, + Optional textPattern, + Optional afterDate, + ConnectionRead c + ) { + return concat(Fragment.of("-- Filter the all_scalar_types table by a handful of columns.\n-- Tests: a parameter for each affinity (INTEGER, REAL, TEXT, DATE).\n\nSELECT\n id,\n col_tinyint,\n col_smallint,\n col_integer,\n col_bigint,\n col_real,\n col_double,\n col_decimal,\n col_text,\n col_date,\n col_uuid,\n col_json\nFROM all_scalar_types\nWHERE\n ("), Fragment.encode(SqliteTypes.integer.opt(), minId), Fragment.of(" IS NULL OR id >= "), Fragment.encode(SqliteTypes.integer.opt(), minId), Fragment.of(")\n AND ("), Fragment.encode(SqliteTypes.text.opt(), textPattern), Fragment.of(" IS NULL OR col_text LIKE "), Fragment.encode(SqliteTypes.text.opt(), textPattern), Fragment.of(")\n AND ("), Fragment.encode(SqliteTypes.date.opt(), afterDate), Fragment.of(" IS NULL OR col_date >= "), Fragment.encode(SqliteTypes.date.opt(), afterDate), Fragment.of(")\nORDER BY id")).query(AllScalarTypesSearchSqlRow.rowCodec.all()).run(c); + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/all_scalar_types_search/AllScalarTypesSearchSqlRow.java b/testers/sqlite/java/generated-and-checked-in/testdb/all_scalar_types_search/AllScalarTypesSearchSqlRow.java new file mode 100644 index 0000000000..35b81303d7 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/all_scalar_types_search/AllScalarTypesSearchSqlRow.java @@ -0,0 +1,168 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.all_scalar_types_search; + +import com.fasterxml.jackson.annotation.JsonProperty; +import dev.typr.dsl.RowCodecs; +import dev.typr.foundations.RowCodec; +import dev.typr.foundations.SqliteTypes; +import dev.typr.foundations.Tuple.Tuple12; +import dev.typr.foundations.data.Json; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.Optional; +import java.util.UUID; +import testdb.all_scalar_types.AllScalarTypesId; + +/** SQL file: all_scalar_types_search.sql */ +public record AllScalarTypesSearchSqlRow( + /** Points to {@link testdb.all_scalar_types.AllScalarTypesRow#id()} */ + AllScalarTypesId id, + /** Points to {@link testdb.all_scalar_types.AllScalarTypesRow#colTinyint()} */ + @JsonProperty("col_tinyint") Optional colTinyint, + /** Points to {@link testdb.all_scalar_types.AllScalarTypesRow#colSmallint()} */ + @JsonProperty("col_smallint") Optional colSmallint, + /** Points to {@link testdb.all_scalar_types.AllScalarTypesRow#colInteger()} */ + @JsonProperty("col_integer") Optional colInteger, + /** Points to {@link testdb.all_scalar_types.AllScalarTypesRow#colBigint()} */ + @JsonProperty("col_bigint") Optional colBigint, + /** Points to {@link testdb.all_scalar_types.AllScalarTypesRow#colReal()} */ + @JsonProperty("col_real") Optional colReal, + /** Points to {@link testdb.all_scalar_types.AllScalarTypesRow#colDouble()} */ + @JsonProperty("col_double") Optional colDouble, + /** Points to {@link testdb.all_scalar_types.AllScalarTypesRow#colDecimal()} */ + @JsonProperty("col_decimal") Optional colDecimal, + /** Points to {@link testdb.all_scalar_types.AllScalarTypesRow#colText()} */ + @JsonProperty("col_text") Optional colText, + /** Points to {@link testdb.all_scalar_types.AllScalarTypesRow#colDate()} */ + @JsonProperty("col_date") Optional colDate, + /** Points to {@link testdb.all_scalar_types.AllScalarTypesRow#colUuid()} */ + @JsonProperty("col_uuid") Optional colUuid, + /** Points to {@link testdb.all_scalar_types.AllScalarTypesRow#colJson()} */ + @JsonProperty("col_json") Optional colJson +) implements Tuple12, Optional, Optional, Optional, Optional, Optional, Optional, Optional, Optional, Optional, Optional> { + /** Points to {@link testdb.all_scalar_types.AllScalarTypesRow#id()} */ + public AllScalarTypesSearchSqlRow withId(AllScalarTypesId id) { + return new AllScalarTypesSearchSqlRow(id, colTinyint, colSmallint, colInteger, colBigint, colReal, colDouble, colDecimal, colText, colDate, colUuid, colJson); + } + + /** Points to {@link testdb.all_scalar_types.AllScalarTypesRow#colTinyint()} */ + public AllScalarTypesSearchSqlRow withColTinyint(Optional colTinyint) { + return new AllScalarTypesSearchSqlRow(id, colTinyint, colSmallint, colInteger, colBigint, colReal, colDouble, colDecimal, colText, colDate, colUuid, colJson); + } + + /** Points to {@link testdb.all_scalar_types.AllScalarTypesRow#colSmallint()} */ + public AllScalarTypesSearchSqlRow withColSmallint(Optional colSmallint) { + return new AllScalarTypesSearchSqlRow(id, colTinyint, colSmallint, colInteger, colBigint, colReal, colDouble, colDecimal, colText, colDate, colUuid, colJson); + } + + /** Points to {@link testdb.all_scalar_types.AllScalarTypesRow#colInteger()} */ + public AllScalarTypesSearchSqlRow withColInteger(Optional colInteger) { + return new AllScalarTypesSearchSqlRow(id, colTinyint, colSmallint, colInteger, colBigint, colReal, colDouble, colDecimal, colText, colDate, colUuid, colJson); + } + + /** Points to {@link testdb.all_scalar_types.AllScalarTypesRow#colBigint()} */ + public AllScalarTypesSearchSqlRow withColBigint(Optional colBigint) { + return new AllScalarTypesSearchSqlRow(id, colTinyint, colSmallint, colInteger, colBigint, colReal, colDouble, colDecimal, colText, colDate, colUuid, colJson); + } + + /** Points to {@link testdb.all_scalar_types.AllScalarTypesRow#colReal()} */ + public AllScalarTypesSearchSqlRow withColReal(Optional colReal) { + return new AllScalarTypesSearchSqlRow(id, colTinyint, colSmallint, colInteger, colBigint, colReal, colDouble, colDecimal, colText, colDate, colUuid, colJson); + } + + /** Points to {@link testdb.all_scalar_types.AllScalarTypesRow#colDouble()} */ + public AllScalarTypesSearchSqlRow withColDouble(Optional colDouble) { + return new AllScalarTypesSearchSqlRow(id, colTinyint, colSmallint, colInteger, colBigint, colReal, colDouble, colDecimal, colText, colDate, colUuid, colJson); + } + + /** Points to {@link testdb.all_scalar_types.AllScalarTypesRow#colDecimal()} */ + public AllScalarTypesSearchSqlRow withColDecimal(Optional colDecimal) { + return new AllScalarTypesSearchSqlRow(id, colTinyint, colSmallint, colInteger, colBigint, colReal, colDouble, colDecimal, colText, colDate, colUuid, colJson); + } + + /** Points to {@link testdb.all_scalar_types.AllScalarTypesRow#colText()} */ + public AllScalarTypesSearchSqlRow withColText(Optional colText) { + return new AllScalarTypesSearchSqlRow(id, colTinyint, colSmallint, colInteger, colBigint, colReal, colDouble, colDecimal, colText, colDate, colUuid, colJson); + } + + /** Points to {@link testdb.all_scalar_types.AllScalarTypesRow#colDate()} */ + public AllScalarTypesSearchSqlRow withColDate(Optional colDate) { + return new AllScalarTypesSearchSqlRow(id, colTinyint, colSmallint, colInteger, colBigint, colReal, colDouble, colDecimal, colText, colDate, colUuid, colJson); + } + + /** Points to {@link testdb.all_scalar_types.AllScalarTypesRow#colUuid()} */ + public AllScalarTypesSearchSqlRow withColUuid(Optional colUuid) { + return new AllScalarTypesSearchSqlRow(id, colTinyint, colSmallint, colInteger, colBigint, colReal, colDouble, colDecimal, colText, colDate, colUuid, colJson); + } + + /** Points to {@link testdb.all_scalar_types.AllScalarTypesRow#colJson()} */ + public AllScalarTypesSearchSqlRow withColJson(Optional colJson) { + return new AllScalarTypesSearchSqlRow(id, colTinyint, colSmallint, colInteger, colBigint, colReal, colDouble, colDecimal, colText, colDate, colUuid, colJson); + } + + public static RowCodec rowCodec = RowCodecs.of(AllScalarTypesId.sqliteType, SqliteTypes.tinyint.opt(), SqliteTypes.smallint.opt(), SqliteTypes.integer.opt(), SqliteTypes.bigint.opt(), SqliteTypes.real.opt(), SqliteTypes.double_.opt(), SqliteTypes.numeric.opt(), SqliteTypes.text.opt(), SqliteTypes.date.opt(), SqliteTypes.uuid.opt(), SqliteTypes.json.opt(), AllScalarTypesSearchSqlRow::new, row -> new Object[]{row.id(), row.colTinyint(), row.colSmallint(), row.colInteger(), row.colBigint(), row.colReal(), row.colDouble(), row.colDecimal(), row.colText(), row.colDate(), row.colUuid(), row.colJson()}); + + @Override + public AllScalarTypesId _1() { + return id; + } + + @Override + public Optional _10() { + return colDate; + } + + @Override + public Optional _11() { + return colUuid; + } + + @Override + public Optional _12() { + return colJson; + } + + @Override + public Optional _2() { + return colTinyint; + } + + @Override + public Optional _3() { + return colSmallint; + } + + @Override + public Optional _4() { + return colInteger; + } + + @Override + public Optional _5() { + return colBigint; + } + + @Override + public Optional _6() { + return colReal; + } + + @Override + public Optional _7() { + return colDouble; + } + + @Override + public Optional _8() { + return colDecimal; + } + + @Override + public Optional _9() { + return colText; + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/bridge/Customer.java b/testers/sqlite/java/generated-and-checked-in/testdb/bridge/Customer.java new file mode 100644 index 0000000000..12680f0a92 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/bridge/Customer.java @@ -0,0 +1,27 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.bridge; + +import java.util.Optional; + +/** Bridge composite type: Customer */ +public record Customer( + Optional created_at, + String customer_id, + Optional email +) { + public Customer withCreated_at(Optional created_at) { + return new Customer(created_at, customer_id, email); + } + + public Customer withCustomer_id(String customer_id) { + return new Customer(created_at, customer_id, email); + } + + public Customer withEmail(Optional email) { + return new Customer(created_at, customer_id, email); + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/customer_orders/CustomerOrdersViewFields.java b/testers/sqlite/java/generated-and-checked-in/testdb/customer_orders/CustomerOrdersViewFields.java new file mode 100644 index 0000000000..8fc043c711 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/customer_orders/CustomerOrdersViewFields.java @@ -0,0 +1,116 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.customer_orders; + +import dev.typr.dsl.FieldsBase; +import dev.typr.dsl.Path; +import dev.typr.dsl.RelationStructure; +import dev.typr.dsl.SqlExpr; +import dev.typr.dsl.SqlExpr.FieldLike; +import dev.typr.dsl.SqlExpr.OptField; +import dev.typr.dsl.TupleExpr.TupleExpr7; +import dev.typr.foundations.RowCodec; +import dev.typr.foundations.SqliteTypes; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.List; +import java.util.Optional; +import testdb.customers.CustomersId; +import testdb.orders.OrdersId; +import testdb.userdefined.Email; + +public class CustomerOrdersViewFields extends TupleExpr7 implements RelationStructure, FieldsBase { + List _path; + + public CustomerOrdersViewFields(List _path) { + this._path = _path; + } + + public static CustomerOrdersViewFields structure = new CustomerOrdersViewFields(java.util.Collections.emptyList()); + + public OptField customerId() { + return new OptField(_path, "customer_id", CustomerOrdersViewRow::customerId, Optional.empty(), Optional.empty(), (row, value) -> row.withCustomerId(value), CustomersId.sqliteType); + } + + public OptField customerName() { + return new OptField(_path, "customer_name", CustomerOrdersViewRow::customerName, Optional.empty(), Optional.empty(), (row, value) -> row.withCustomerName(value), SqliteTypes.text); + } + + public OptField email() { + return new OptField(_path, "email", CustomerOrdersViewRow::email, Optional.empty(), Optional.empty(), (row, value) -> row.withEmail(value), Email.sqliteType); + } + + public OptField orderId() { + return new OptField(_path, "order_id", CustomerOrdersViewRow::orderId, Optional.empty(), Optional.empty(), (row, value) -> row.withOrderId(value), OrdersId.sqliteType); + } + + public OptField orderDate() { + return new OptField(_path, "order_date", CustomerOrdersViewRow::orderDate, Optional.empty(), Optional.empty(), (row, value) -> row.withOrderDate(value), SqliteTypes.date); + } + + public OptField totalAmount() { + return new OptField(_path, "total_amount", CustomerOrdersViewRow::totalAmount, Optional.empty(), Optional.empty(), (row, value) -> row.withTotalAmount(value), SqliteTypes.numeric); + } + + public OptField status() { + return new OptField(_path, "status", CustomerOrdersViewRow::status, Optional.empty(), Optional.empty(), (row, value) -> row.withStatus(value), SqliteTypes.text); + } + + @Override + public List _path() { + return _path; + } + + @Override + public List> columns() { + return java.util.List.of(this.customerId(), this.customerName(), this.email(), this.orderId(), this.orderDate(), this.totalAmount(), this.status()); + } + + @Override + public RowCodec rowCodec() { + return CustomerOrdersViewRow.rowCodec; + } + + @Override + public RelationStructure withPaths(List _path) { + return new CustomerOrdersViewFields(_path); + } + + @Override + public SqlExpr _1() { + return customerId(); + } + + @Override + public SqlExpr _2() { + return customerName(); + } + + @Override + public SqlExpr _3() { + return email(); + } + + @Override + public SqlExpr _4() { + return orderId(); + } + + @Override + public SqlExpr _5() { + return orderDate(); + } + + @Override + public SqlExpr _6() { + return totalAmount(); + } + + @Override + public SqlExpr _7() { + return status(); + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/customer_orders/CustomerOrdersViewRepo.java b/testers/sqlite/java/generated-and-checked-in/testdb/customer_orders/CustomerOrdersViewRepo.java new file mode 100644 index 0000000000..c5d583eaa6 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/customer_orders/CustomerOrdersViewRepo.java @@ -0,0 +1,16 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.customer_orders; + +import dev.typr.dsl.SelectBuilder; +import dev.typr.foundations.ConnectionRead; +import java.util.List; + +public interface CustomerOrdersViewRepo { + SelectBuilder select(); + + List selectAll(ConnectionRead c); +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/customer_orders/CustomerOrdersViewRepoImpl.java b/testers/sqlite/java/generated-and-checked-in/testdb/customer_orders/CustomerOrdersViewRepoImpl.java new file mode 100644 index 0000000000..06ba12d62b --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/customer_orders/CustomerOrdersViewRepoImpl.java @@ -0,0 +1,25 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.customer_orders; + +import dev.typr.dsl.Dialect; +import dev.typr.dsl.SelectBuilder; +import dev.typr.foundations.ConnectionRead; +import dev.typr.foundations.Fragment; +import java.util.List; +import static dev.typr.foundations.Fragment.concat; + +public class CustomerOrdersViewRepoImpl implements CustomerOrdersViewRepo { + @Override + public SelectBuilder select() { + return SelectBuilder.of("\"customer_orders\"", CustomerOrdersViewFields.structure, CustomerOrdersViewRow.rowCodec, Dialect.SQLITE); + } + + @Override + public List selectAll(ConnectionRead c) { + return concat(Fragment.of("select \"customer_id\", \"customer_name\", \"email\", \"order_id\", \"order_date\", \"total_amount\", \"status\"\nfrom \"customer_orders\"\n")).query(CustomerOrdersViewRow.rowCodec.all()).run(c); + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/customer_orders/CustomerOrdersViewRow.java b/testers/sqlite/java/generated-and-checked-in/testdb/customer_orders/CustomerOrdersViewRow.java new file mode 100644 index 0000000000..6c4dc1fd8d --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/customer_orders/CustomerOrdersViewRow.java @@ -0,0 +1,108 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.customer_orders; + +import com.fasterxml.jackson.annotation.JsonProperty; +import dev.typr.dsl.RowCodecs; +import dev.typr.foundations.RowCodec; +import dev.typr.foundations.SqliteTypes; +import dev.typr.foundations.Tuple.Tuple7; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.Optional; +import testdb.customers.CustomersId; +import testdb.orders.OrdersId; +import testdb.userdefined.Email; + +/** View: customer_orders */ +public record CustomerOrdersViewRow( + /** Points to {@link testdb.customers.CustomersRow#customerId()} */ + @JsonProperty("customer_id") Optional customerId, + /** Points to {@link testdb.customers.CustomersRow#customerName()} */ + @JsonProperty("customer_name") Optional customerName, + /** Points to {@link testdb.customers.CustomersRow#email()} */ + Optional email, + /** Points to {@link testdb.orders.OrdersRow#orderId()} */ + @JsonProperty("order_id") Optional orderId, + /** Points to {@link testdb.orders.OrdersRow#orderDate()} */ + @JsonProperty("order_date") Optional orderDate, + /** Points to {@link testdb.orders.OrdersRow#totalAmount()} */ + @JsonProperty("total_amount") Optional totalAmount, + /** Points to {@link testdb.orders.OrdersRow#status()} */ + Optional status +) implements Tuple7, Optional, Optional, Optional, Optional, Optional, Optional> { + /** Points to {@link testdb.customers.CustomersRow#customerId()} */ + public CustomerOrdersViewRow withCustomerId(Optional customerId) { + return new CustomerOrdersViewRow(customerId, customerName, email, orderId, orderDate, totalAmount, status); + } + + /** Points to {@link testdb.customers.CustomersRow#customerName()} */ + public CustomerOrdersViewRow withCustomerName(Optional customerName) { + return new CustomerOrdersViewRow(customerId, customerName, email, orderId, orderDate, totalAmount, status); + } + + /** Points to {@link testdb.customers.CustomersRow#email()} */ + public CustomerOrdersViewRow withEmail(Optional email) { + return new CustomerOrdersViewRow(customerId, customerName, email, orderId, orderDate, totalAmount, status); + } + + /** Points to {@link testdb.orders.OrdersRow#orderId()} */ + public CustomerOrdersViewRow withOrderId(Optional orderId) { + return new CustomerOrdersViewRow(customerId, customerName, email, orderId, orderDate, totalAmount, status); + } + + /** Points to {@link testdb.orders.OrdersRow#orderDate()} */ + public CustomerOrdersViewRow withOrderDate(Optional orderDate) { + return new CustomerOrdersViewRow(customerId, customerName, email, orderId, orderDate, totalAmount, status); + } + + /** Points to {@link testdb.orders.OrdersRow#totalAmount()} */ + public CustomerOrdersViewRow withTotalAmount(Optional totalAmount) { + return new CustomerOrdersViewRow(customerId, customerName, email, orderId, orderDate, totalAmount, status); + } + + /** Points to {@link testdb.orders.OrdersRow#status()} */ + public CustomerOrdersViewRow withStatus(Optional status) { + return new CustomerOrdersViewRow(customerId, customerName, email, orderId, orderDate, totalAmount, status); + } + + public static RowCodec rowCodec = RowCodecs.of(CustomersId.sqliteType.opt(), SqliteTypes.text.opt(), Email.sqliteType.opt(), OrdersId.sqliteType.opt(), SqliteTypes.date.opt(), SqliteTypes.numeric.opt(), SqliteTypes.text.opt(), CustomerOrdersViewRow::new, row -> new Object[]{row.customerId(), row.customerName(), row.email(), row.orderId(), row.orderDate(), row.totalAmount(), row.status()}); + + @Override + public Optional _1() { + return customerId; + } + + @Override + public Optional _2() { + return customerName; + } + + @Override + public Optional _3() { + return email; + } + + @Override + public Optional _4() { + return orderId; + } + + @Override + public Optional _5() { + return orderDate; + } + + @Override + public Optional _6() { + return totalAmount; + } + + @Override + public Optional _7() { + return status; + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/customer_search/CustomerSearchSqlRepo.java b/testers/sqlite/java/generated-and-checked-in/testdb/customer_search/CustomerSearchSqlRepo.java new file mode 100644 index 0000000000..dfbba73723 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/customer_search/CustomerSearchSqlRepo.java @@ -0,0 +1,21 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.customer_search; + +import dev.typr.foundations.ConnectionRead; +import java.time.LocalDateTime; +import java.util.List; +import java.util.Optional; + +public interface CustomerSearchSqlRepo { + List apply( + Optional namePattern, + Optional emailPattern, + Optional createdAfter, + Long maxResults, + ConnectionRead c + ); +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/customer_search/CustomerSearchSqlRepoImpl.java b/testers/sqlite/java/generated-and-checked-in/testdb/customer_search/CustomerSearchSqlRepoImpl.java new file mode 100644 index 0000000000..112dcb8506 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/customer_search/CustomerSearchSqlRepoImpl.java @@ -0,0 +1,27 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.customer_search; + +import dev.typr.foundations.ConnectionRead; +import dev.typr.foundations.Fragment; +import dev.typr.foundations.SqliteTypes; +import java.time.LocalDateTime; +import java.util.List; +import java.util.Optional; +import static dev.typr.foundations.Fragment.concat; + +public class CustomerSearchSqlRepoImpl implements CustomerSearchSqlRepo { + @Override + public List apply( + Optional namePattern, + Optional emailPattern, + Optional createdAfter, + Long maxResults, + ConnectionRead c + ) { + return concat(Fragment.of("-- Customer search with multiple optional filters.\n-- Tests: optional parameters, LIKE patterns, complex WHERE, ORDER BY/LIMIT.\n\nSELECT\n customer_id,\n name,\n email,\n created_at\nFROM customers\nWHERE\n ("), Fragment.encode(SqliteTypes.text.opt(), namePattern), Fragment.of(" IS NULL OR name LIKE "), Fragment.encode(SqliteTypes.text.opt(), namePattern), Fragment.of(")\n AND ("), Fragment.encode(SqliteTypes.text.opt(), emailPattern), Fragment.of(" IS NULL OR email LIKE "), Fragment.encode(SqliteTypes.text.opt(), emailPattern), Fragment.of(")\n AND ("), Fragment.encode(SqliteTypes.timestamp.opt(), createdAfter), Fragment.of(" IS NULL OR created_at >= "), Fragment.encode(SqliteTypes.timestamp.opt(), createdAfter), Fragment.of(")\nORDER BY created_at DESC, customer_id\nLIMIT "), Fragment.encode(SqliteTypes.bigint, maxResults), Fragment.of("")).query(CustomerSearchSqlRow.rowCodec.all()).run(c); + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/customer_search/CustomerSearchSqlRow.java b/testers/sqlite/java/generated-and-checked-in/testdb/customer_search/CustomerSearchSqlRow.java new file mode 100644 index 0000000000..8ae6d529d4 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/customer_search/CustomerSearchSqlRow.java @@ -0,0 +1,70 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.customer_search; + +import com.fasterxml.jackson.annotation.JsonProperty; +import dev.typr.dsl.RowCodecs; +import dev.typr.foundations.RowCodec; +import dev.typr.foundations.SqliteTypes; +import dev.typr.foundations.Tuple.Tuple4; +import java.time.LocalDateTime; +import java.util.Optional; +import testdb.customers.CustomersId; +import testdb.userdefined.Email; + +/** SQL file: customer_search.sql */ +public record CustomerSearchSqlRow( + /** Points to {@link testdb.customers.CustomersRow#customerId()} */ + @JsonProperty("customer_id") CustomersId customerId, + /** Points to {@link testdb.customers.CustomersRow#name()} */ + String name, + /** Points to {@link testdb.customers.CustomersRow#email()} */ + Optional email, + /** Points to {@link testdb.customers.CustomersRow#createdAt()} */ + @JsonProperty("created_at") LocalDateTime createdAt +) implements Tuple4, LocalDateTime> { + /** Points to {@link testdb.customers.CustomersRow#customerId()} */ + public CustomerSearchSqlRow withCustomerId(CustomersId customerId) { + return new CustomerSearchSqlRow(customerId, name, email, createdAt); + } + + /** Points to {@link testdb.customers.CustomersRow#name()} */ + public CustomerSearchSqlRow withName(String name) { + return new CustomerSearchSqlRow(customerId, name, email, createdAt); + } + + /** Points to {@link testdb.customers.CustomersRow#email()} */ + public CustomerSearchSqlRow withEmail(Optional email) { + return new CustomerSearchSqlRow(customerId, name, email, createdAt); + } + + /** Points to {@link testdb.customers.CustomersRow#createdAt()} */ + public CustomerSearchSqlRow withCreatedAt(LocalDateTime createdAt) { + return new CustomerSearchSqlRow(customerId, name, email, createdAt); + } + + public static RowCodec rowCodec = RowCodecs.of(CustomersId.sqliteType, SqliteTypes.text, Email.sqliteType.opt(), SqliteTypes.timestamp, CustomerSearchSqlRow::new, row -> new Object[]{row.customerId(), row.name(), row.email(), row.createdAt()}); + + @Override + public CustomersId _1() { + return customerId; + } + + @Override + public String _2() { + return name; + } + + @Override + public Optional _3() { + return email; + } + + @Override + public LocalDateTime _4() { + return createdAt; + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/customers/CustomersFields.java b/testers/sqlite/java/generated-and-checked-in/testdb/customers/CustomersFields.java new file mode 100644 index 0000000000..12e267480d --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/customers/CustomersFields.java @@ -0,0 +1,88 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.customers; + +import dev.typr.dsl.FieldsBase; +import dev.typr.dsl.Path; +import dev.typr.dsl.RelationStructure; +import dev.typr.dsl.SqlExpr; +import dev.typr.dsl.SqlExpr.Field; +import dev.typr.dsl.SqlExpr.FieldLike; +import dev.typr.dsl.SqlExpr.IdField; +import dev.typr.dsl.SqlExpr.OptField; +import dev.typr.dsl.TupleExpr.TupleExpr4; +import dev.typr.foundations.RowCodec; +import dev.typr.foundations.SqliteTypes; +import java.time.LocalDateTime; +import java.util.List; +import java.util.Optional; +import testdb.userdefined.Email; + +public class CustomersFields extends TupleExpr4 implements RelationStructure, FieldsBase { + List _path; + + public CustomersFields(List _path) { + this._path = _path; + } + + public static CustomersFields structure = new CustomersFields(java.util.Collections.emptyList()); + + public IdField customerId() { + return new IdField(_path, "customer_id", CustomersRow::customerId, Optional.empty(), Optional.empty(), (row, value) -> row.withCustomerId(value), CustomersId.sqliteType); + } + + public Field name() { + return new Field(_path, "name", CustomersRow::name, Optional.empty(), Optional.empty(), (row, value) -> row.withName(value), SqliteTypes.text); + } + + public OptField email() { + return new OptField(_path, "email", CustomersRow::email, Optional.empty(), Optional.empty(), (row, value) -> row.withEmail(value), Email.sqliteType); + } + + public Field createdAt() { + return new Field(_path, "created_at", CustomersRow::createdAt, Optional.empty(), Optional.empty(), (row, value) -> row.withCreatedAt(value), SqliteTypes.timestamp); + } + + @Override + public List _path() { + return _path; + } + + @Override + public List> columns() { + return java.util.List.of(this.customerId(), this.name(), this.email(), this.createdAt()); + } + + @Override + public RowCodec rowCodec() { + return CustomersRow.rowCodec; + } + + @Override + public RelationStructure withPaths(List _path) { + return new CustomersFields(_path); + } + + @Override + public SqlExpr _1() { + return customerId(); + } + + @Override + public SqlExpr _2() { + return name(); + } + + @Override + public SqlExpr _3() { + return email(); + } + + @Override + public SqlExpr _4() { + return createdAt(); + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/customers/CustomersId.java b/testers/sqlite/java/generated-and-checked-in/testdb/customers/CustomersId.java new file mode 100644 index 0000000000..b05b41d460 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/customers/CustomersId.java @@ -0,0 +1,29 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.customers; + +import com.fasterxml.jackson.annotation.JsonValue; +import dev.typr.foundations.Bijection; +import dev.typr.foundations.SqliteType; +import dev.typr.foundations.SqliteTypes; + +/** Type for the primary key of table `customers` */ +public record CustomersId(@JsonValue Long value) { + public CustomersId withValue(Long value) { + return new CustomersId(value); + } + + @Override + public java.lang.String toString() { + return value.toString(); + } + + static public Bijection bijection = + Bijection.of(CustomersId::value, CustomersId::new); + + static public SqliteType sqliteType = + SqliteTypes.integer.to(Bijection.of(CustomersId::new, CustomersId::value)); +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/customers/CustomersRepo.java b/testers/sqlite/java/generated-and-checked-in/testdb/customers/CustomersRepo.java new file mode 100644 index 0000000000..a70ba9d80c --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/customers/CustomersRepo.java @@ -0,0 +1,76 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.customers; + +import dev.typr.dsl.DeleteBuilder; +import dev.typr.dsl.SelectBuilder; +import dev.typr.dsl.UpdateBuilder; +import dev.typr.foundations.Connection; +import dev.typr.foundations.ConnectionRead; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +public interface CustomersRepo { + DeleteBuilder delete(); + + Boolean deleteById( + CustomersId customerId, + Connection c + ); + + Integer deleteByIds( + List customerIds, + Connection c + ); + + CustomersRow insert( + CustomersRow unsaved, + Connection c + ); + + CustomersRow insert( + CustomersRowUnsaved unsaved, + Connection c + ); + + SelectBuilder select(); + + List selectAll(ConnectionRead c); + + Optional selectById( + CustomersId customerId, + ConnectionRead c + ); + + List selectByIds( + List customerIds, + ConnectionRead c + ); + + Map selectByIdsTracked( + List customerIds, + ConnectionRead c + ); + + UpdateBuilder update(); + + Boolean update( + CustomersRow row, + Connection c + ); + + CustomersRow upsert( + CustomersRow unsaved, + Connection c + ); + + List upsertBatch( + Iterator unsaved, + Connection c + ); +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/customers/CustomersRepoImpl.java b/testers/sqlite/java/generated-and-checked-in/testdb/customers/CustomersRepoImpl.java new file mode 100644 index 0000000000..56333f2751 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/customers/CustomersRepoImpl.java @@ -0,0 +1,155 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.customers; + +import dev.typr.dsl.DeleteBuilder; +import dev.typr.dsl.Dialect; +import dev.typr.dsl.SelectBuilder; +import dev.typr.dsl.UpdateBuilder; +import dev.typr.foundations.Connection; +import dev.typr.foundations.ConnectionRead; +import dev.typr.foundations.Fragment; +import dev.typr.foundations.SqliteTypes; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import testdb.userdefined.Email; +import static dev.typr.foundations.Fragment.concat; + +public class CustomersRepoImpl implements CustomersRepo { + @Override + public DeleteBuilder delete() { + return DeleteBuilder.of("\"customers\"", CustomersFields.structure, Dialect.SQLITE); + } + + @Override + public Boolean deleteById( + CustomersId customerId, + Connection c + ) { + return concat(Fragment.of("delete from \"customers\" where \"customer_id\" = "), Fragment.encode(CustomersId.sqliteType, customerId), Fragment.of("")).update().run(c) > 0; + } + + @Override + public Integer deleteByIds( + List customerIds, + Connection c + ) { + ArrayList fragments = new ArrayList<>(); + for (var id : customerIds) { fragments.add(Fragment.encode(CustomersId.sqliteType, id)); }; + return Fragment.concat(Fragment.of("delete from \"customers\" where \"customer_id\" in ("), Fragment.comma(fragments), Fragment.of(")")).update().run(c); + } + + @Override + public CustomersRow insert( + CustomersRow unsaved, + Connection c + ) { + return concat(Fragment.of("insert into \"customers\"(\"customer_id\", \"name\", \"email\", \"created_at\")\nvalues ("), Fragment.encode(CustomersId.sqliteType, unsaved.customerId()), Fragment.of(", "), Fragment.encode(SqliteTypes.text, unsaved.name()), Fragment.of(", "), Fragment.encode(Email.sqliteType.opt(), unsaved.email()), Fragment.of(", "), Fragment.encode(SqliteTypes.timestamp, unsaved.createdAt()), Fragment.of(")\nRETURNING \"customer_id\", \"name\", \"email\", \"created_at\"\n")) + .updateReturning(CustomersRow.rowCodec.exactlyOne()).run(c); + } + + @Override + public CustomersRow insert( + CustomersRowUnsaved unsaved, + Connection c + ) { + ArrayList columns = new ArrayList<>();; + ArrayList values = new ArrayList<>();; + columns.add(Fragment.of("\"customer_id\"")); + values.add(concat(Fragment.encode(CustomersId.sqliteType, unsaved.customerId()), Fragment.of(""))); + columns.add(Fragment.of("\"name\"")); + values.add(concat(Fragment.encode(SqliteTypes.text, unsaved.name()), Fragment.of(""))); + columns.add(Fragment.of("\"email\"")); + values.add(concat(Fragment.encode(Email.sqliteType.opt(), unsaved.email()), Fragment.of(""))); + unsaved.createdAt().visit( + () -> { + + }, + value -> { + columns.add(Fragment.of("\"created_at\"")); + values.add(concat(Fragment.encode(SqliteTypes.timestamp, value), Fragment.of(""))); + } + );; + Fragment q = concat(Fragment.of("insert into \"customers\"("), Fragment.comma(columns), Fragment.of(")\nvalues ("), Fragment.comma(values), Fragment.of(")\nRETURNING \"customer_id\", \"name\", \"email\", \"created_at\"\n"));; + return q.updateReturning(CustomersRow.rowCodec.exactlyOne()).run(c); + } + + @Override + public SelectBuilder select() { + return SelectBuilder.of("\"customers\"", CustomersFields.structure, CustomersRow.rowCodec, Dialect.SQLITE); + } + + @Override + public List selectAll(ConnectionRead c) { + return concat(Fragment.of("select \"customer_id\", \"name\", \"email\", \"created_at\"\nfrom \"customers\"\n")).query(CustomersRow.rowCodec.all()).run(c); + } + + @Override + public Optional selectById( + CustomersId customerId, + ConnectionRead c + ) { + return concat(Fragment.of("select \"customer_id\", \"name\", \"email\", \"created_at\"\nfrom \"customers\"\nwhere \"customer_id\" = "), Fragment.encode(CustomersId.sqliteType, customerId), Fragment.of("")).query(CustomersRow.rowCodec.first()).run(c); + } + + @Override + public List selectByIds( + List customerIds, + ConnectionRead c + ) { + ArrayList fragments = new ArrayList<>(); + for (var id : customerIds) { fragments.add(Fragment.encode(CustomersId.sqliteType, id)); }; + return Fragment.concat(Fragment.of("select \"customer_id\", \"name\", \"email\", \"created_at\" from \"customers\" where \"customer_id\" in ("), Fragment.comma(fragments), Fragment.of(")")).query(CustomersRow.rowCodec.all()).run(c); + } + + @Override + public Map selectByIdsTracked( + List customerIds, + ConnectionRead c + ) { + HashMap ret = new HashMap(); + selectByIds(customerIds, c).forEach(row -> ret.put(row.customerId(), row)); + return ret; + } + + @Override + public UpdateBuilder update() { + return UpdateBuilder.of("\"customers\"", CustomersFields.structure, CustomersRow.rowCodec, Dialect.SQLITE); + } + + @Override + public Boolean update( + CustomersRow row, + Connection c + ) { + CustomersId customerId = row.customerId();; + return concat(Fragment.of("update \"customers\"\nset \"name\" = "), Fragment.encode(SqliteTypes.text, row.name()), Fragment.of(",\n\"email\" = "), Fragment.encode(Email.sqliteType.opt(), row.email()), Fragment.of(",\n\"created_at\" = "), Fragment.encode(SqliteTypes.timestamp, row.createdAt()), Fragment.of("\nwhere \"customer_id\" = "), Fragment.encode(CustomersId.sqliteType, customerId), Fragment.of("")).update().run(c) > 0; + } + + @Override + public CustomersRow upsert( + CustomersRow unsaved, + Connection c + ) { + return concat(Fragment.of("INSERT INTO \"customers\"(\"customer_id\", \"name\", \"email\", \"created_at\")\nVALUES ("), Fragment.encode(CustomersId.sqliteType, unsaved.customerId()), Fragment.of(", "), Fragment.encode(SqliteTypes.text, unsaved.name()), Fragment.of(", "), Fragment.encode(Email.sqliteType.opt(), unsaved.email()), Fragment.of(", "), Fragment.encode(SqliteTypes.timestamp, unsaved.createdAt()), Fragment.of(")\nON CONFLICT (\"customer_id\")\nDO UPDATE SET\n \"name\" = EXCLUDED.\"name\",\n\"email\" = EXCLUDED.\"email\",\n\"created_at\" = EXCLUDED.\"created_at\"\nRETURNING \"customer_id\", \"name\", \"email\", \"created_at\"")) + .updateReturning(CustomersRow.rowCodec.exactlyOne()) + .run(c); + } + + @Override + public List upsertBatch( + Iterator unsaved, + Connection c + ) { + return concat(Fragment.of("INSERT INTO \"customers\"(\"customer_id\", \"name\", \"email\", \"created_at\")\nVALUES (?, ?, ?, ?)\nON CONFLICT (\"customer_id\")\nDO UPDATE SET\n \"name\" = EXCLUDED.\"name\",\n\"email\" = EXCLUDED.\"email\",\n\"created_at\" = EXCLUDED.\"created_at\"\nRETURNING \"customer_id\", \"name\", \"email\", \"created_at\"")) + .updateReturningEach(CustomersRow.rowCodec, unsaved) + .run(c); + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/customers/CustomersRepoMock.java b/testers/sqlite/java/generated-and-checked-in/testdb/customers/CustomersRepoMock.java new file mode 100644 index 0000000000..6e4520cea4 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/customers/CustomersRepoMock.java @@ -0,0 +1,172 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.customers; + +import dev.typr.dsl.DeleteBuilder; +import dev.typr.dsl.DeleteBuilderMock; +import dev.typr.dsl.DeleteParams; +import dev.typr.dsl.SelectBuilder; +import dev.typr.dsl.SelectBuilderMock; +import dev.typr.dsl.SelectParams; +import dev.typr.dsl.UpdateBuilder; +import dev.typr.dsl.UpdateBuilderMock; +import dev.typr.dsl.UpdateParams; +import dev.typr.foundations.Connection; +import dev.typr.foundations.ConnectionRead; +import java.lang.RuntimeException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.function.Function; +import java.util.stream.Collectors; + +public record CustomersRepoMock( + java.util.function.Function toRow, + HashMap map +) implements CustomersRepo { + public CustomersRepoMock(java.util.function.Function toRow) { + this(toRow, new HashMap()); + } + + public CustomersRepoMock withToRow(java.util.function.Function toRow) { + return new CustomersRepoMock(toRow, map); + } + + public CustomersRepoMock withMap(HashMap map) { + return new CustomersRepoMock(toRow, map); + } + + @Override + public DeleteBuilder delete() { + return new DeleteBuilderMock<>(CustomersFields.structure, () -> new ArrayList<>(map.values()), DeleteParams.empty(), row -> row.customerId(), id -> map.remove(id)); + } + + @Override + public Boolean deleteById( + CustomersId customerId, + Connection c + ) { + return Optional.ofNullable(map.remove(customerId)).isPresent(); + } + + @Override + public Integer deleteByIds( + List customerIds, + Connection c + ) { + var count = 0; + for (var id : customerIds) { + if (Optional.ofNullable(map.remove(id)).isPresent()) { + count = count + 1;; + } + }; + return count; + } + + @Override + public CustomersRow insert( + CustomersRow unsaved, + Connection c + ) { + if (map.containsKey(unsaved.customerId())) { + throw new RuntimeException("id " + unsaved.customerId() + " already exists"); + } + map.put(unsaved.customerId(), unsaved); + return unsaved; + } + + @Override + public CustomersRow insert( + CustomersRowUnsaved unsaved, + Connection c + ) { + return insert(toRow.apply(unsaved), c); + } + + @Override + public SelectBuilder select() { + return new SelectBuilderMock<>(CustomersFields.structure, () -> new ArrayList<>(map.values()), SelectParams.empty()); + } + + @Override + public List selectAll(ConnectionRead c) { + return new ArrayList<>(map.values()); + } + + @Override + public Optional selectById( + CustomersId customerId, + ConnectionRead c + ) { + return Optional.ofNullable(map.get(customerId)); + } + + @Override + public List selectByIds( + List customerIds, + ConnectionRead c + ) { + var result = new ArrayList(); + for (var id : customerIds) { + var opt = Optional.ofNullable(map.get(id)); + if (opt.isPresent()) { + result.add(opt.get()); + } + }; + return result; + } + + @Override + public Map selectByIdsTracked( + List customerIds, + ConnectionRead c + ) { + return selectByIds(customerIds, c).stream().collect(Collectors.toMap((CustomersRow row) -> row.customerId(), Function.identity())); + } + + @Override + public UpdateBuilder update() { + return new UpdateBuilderMock<>(CustomersFields.structure, () -> new ArrayList<>(map.values()), UpdateParams.empty(), row -> row); + } + + @Override + public Boolean update( + CustomersRow row, + Connection c + ) { + var shouldUpdate = Optional.ofNullable(map.get(row.customerId())).filter(oldRow -> !oldRow.equals(row)).isPresent(); + if (shouldUpdate) { + map.put(row.customerId(), row);; + } + return shouldUpdate; + } + + @Override + public CustomersRow upsert( + CustomersRow unsaved, + Connection c + ) { + map.put(unsaved.customerId(), unsaved); + return unsaved; + } + + @Override + public List upsertBatch( + Iterator unsaved, + Connection c + ) { + var result = new ArrayList(); + while (unsaved.hasNext()) { + var row = unsaved.next(); + map.put(row.customerId(), row); + result.add(row); + }; + return result; + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/customers/CustomersRow.java b/testers/sqlite/java/generated-and-checked-in/testdb/customers/CustomersRow.java new file mode 100644 index 0000000000..0173ec4c6f --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/customers/CustomersRow.java @@ -0,0 +1,74 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.customers; + +import com.fasterxml.jackson.annotation.JsonProperty; +import dev.typr.dsl.RowCodecs; +import dev.typr.foundations.RowCodec; +import dev.typr.foundations.SqliteTypes; +import dev.typr.foundations.Tuple.Tuple4; +import java.time.LocalDateTime; +import java.util.Optional; +import testdb.customtypes.Defaulted; +import testdb.userdefined.Email; + +/** Table: customers + * Primary key: customer_id + */ +public record CustomersRow( + @JsonProperty("customer_id") CustomersId customerId, + String name, + Optional email, + /** Default: CURRENT_TIMESTAMP */ + @JsonProperty("created_at") LocalDateTime createdAt +) implements Tuple4, LocalDateTime> { + public CustomersRow withCustomerId(CustomersId customerId) { + return new CustomersRow(customerId, name, email, createdAt); + } + + public CustomersRow withName(String name) { + return new CustomersRow(customerId, name, email, createdAt); + } + + public CustomersRow withEmail(Optional email) { + return new CustomersRow(customerId, name, email, createdAt); + } + + /** Default: CURRENT_TIMESTAMP */ + public CustomersRow withCreatedAt(LocalDateTime createdAt) { + return new CustomersRow(customerId, name, email, createdAt); + } + + public static RowCodec rowCodec = RowCodecs.of(CustomersId.sqliteType, SqliteTypes.text, Email.sqliteType.opt(), SqliteTypes.timestamp, CustomersRow::new, row -> new Object[]{row.customerId(), row.name(), row.email(), row.createdAt()}); + + @Override + public CustomersId _1() { + return customerId; + } + + @Override + public String _2() { + return name; + } + + @Override + public Optional _3() { + return email; + } + + @Override + public LocalDateTime _4() { + return createdAt; + } + + public CustomersId id() { + return customerId; + } + + public CustomersRowUnsaved toUnsavedRow(Defaulted createdAt) { + return new CustomersRowUnsaved(customerId, name, email, createdAt); + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/customers/CustomersRowUnsaved.java b/testers/sqlite/java/generated-and-checked-in/testdb/customers/CustomersRowUnsaved.java new file mode 100644 index 0000000000..1a60f5d56f --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/customers/CustomersRowUnsaved.java @@ -0,0 +1,50 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.customers; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.time.LocalDateTime; +import java.util.Optional; +import testdb.customtypes.Defaulted; +import testdb.customtypes.Defaulted.UseDefault; +import testdb.userdefined.Email; + +/** This class corresponds to a row in table `customers` which has not been persisted yet */ +public record CustomersRowUnsaved( + @JsonProperty("customer_id") CustomersId customerId, + String name, + Optional email, + /** Default: CURRENT_TIMESTAMP */ + @JsonProperty("created_at") Defaulted createdAt +) { + public CustomersRowUnsaved( + @JsonProperty("customer_id") CustomersId customerId, + String name + ) { + this(customerId, name, Optional.empty(), new UseDefault<>()); + } + + public CustomersRowUnsaved withCustomerId(CustomersId customerId) { + return new CustomersRowUnsaved(customerId, name, email, createdAt); + } + + public CustomersRowUnsaved withName(String name) { + return new CustomersRowUnsaved(customerId, name, email, createdAt); + } + + public CustomersRowUnsaved withEmail(Optional email) { + return new CustomersRowUnsaved(customerId, name, email, createdAt); + } + + /** Default: CURRENT_TIMESTAMP */ + public CustomersRowUnsaved withCreatedAt(Defaulted createdAt) { + return new CustomersRowUnsaved(customerId, name, email, createdAt); + } + + public CustomersRow toRow(java.util.function.Supplier createdAtDefault) { + return new CustomersRow(customerId, name, email, createdAt.getOrElse(createdAtDefault)); + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/customtypes/Defaulted.java b/testers/sqlite/java/generated-and-checked-in/testdb/customtypes/Defaulted.java new file mode 100644 index 0000000000..84a4b09be0 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/customtypes/Defaulted.java @@ -0,0 +1,78 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.customtypes; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import testdb.DefaultedDeserializer; +import testdb.DefaultedSerializer; + +/** This signals a value where if you don't provide it, postgres will generate it for you */ +@JsonSerialize(using = DefaultedSerializer.class) +@JsonDeserialize(using = DefaultedDeserializer.class) +public sealed interface Defaulted permits Defaulted.Provided, Defaulted.UseDefault { + record Provided(T value) implements Defaulted { + public Provided withValue(T value) { + return new Provided<>(value); + } + + @Override + public U fold( + java.util.function.Supplier onDefault, + java.util.function.Function onProvided + ) { + return onProvided.apply(value); + } + + @Override + public T getOrElse(java.util.function.Supplier onDefault) { + return value; + } + + @Override + public void visit( + java.lang.Runnable onDefault, + java.util.function.Consumer onProvided + ) { + onProvided.accept(value); + } + } + + record UseDefault() implements Defaulted { + @Override + public U fold( + java.util.function.Supplier onDefault, + java.util.function.Function onProvided + ) { + return onDefault.get(); + } + + @Override + public T getOrElse(java.util.function.Supplier onDefault) { + return onDefault.get(); + } + + @Override + public void visit( + java.lang.Runnable onDefault, + java.util.function.Consumer onProvided + ) { + onDefault.run(); + } + } + + U fold( + java.util.function.Supplier onDefault, + java.util.function.Function onProvided + ); + + T getOrElse(java.util.function.Supplier onDefault); + + void visit( + java.lang.Runnable onDefault, + java.util.function.Consumer onProvided + ); +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/delete_old_orders/DeleteOldOrdersSqlRepo.java b/testers/sqlite/java/generated-and-checked-in/testdb/delete_old_orders/DeleteOldOrdersSqlRepo.java new file mode 100644 index 0000000000..209069a925 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/delete_old_orders/DeleteOldOrdersSqlRepo.java @@ -0,0 +1,16 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.delete_old_orders; + +import dev.typr.foundations.Connection; +import java.time.LocalDate; + +public interface DeleteOldOrdersSqlRepo { + Integer apply( + LocalDate cutoffDate, + Connection c + ); +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/delete_old_orders/DeleteOldOrdersSqlRepoImpl.java b/testers/sqlite/java/generated-and-checked-in/testdb/delete_old_orders/DeleteOldOrdersSqlRepoImpl.java new file mode 100644 index 0000000000..b34a991302 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/delete_old_orders/DeleteOldOrdersSqlRepoImpl.java @@ -0,0 +1,22 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.delete_old_orders; + +import dev.typr.foundations.Connection; +import dev.typr.foundations.Fragment; +import dev.typr.foundations.SqliteTypes; +import java.time.LocalDate; +import static dev.typr.foundations.Fragment.concat; + +public class DeleteOldOrdersSqlRepoImpl implements DeleteOldOrdersSqlRepo { + @Override + public Integer apply( + LocalDate cutoffDate, + Connection c + ) { + return concat(Fragment.of("-- Delete completed orders older than a cutoff date.\n-- Tests: DELETE statement with required date param, no result columns.\n--\n-- SQLite stores DATE as ISO-8601 TEXT, so sqlglot can't infer that\n-- order_date < :cutoff_date wants a LocalDate. We pin the type\n-- explicitly with the `:name:Type!` annotation — same opt-in pattern\n-- as the other dialects use for parameters not otherwise resolvable\n-- from schema lineage.\nDELETE FROM orders\nWHERE status = 'completed' AND order_date < "), Fragment.encode(SqliteTypes.date, cutoffDate), Fragment.of("")).update().run(c); + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/departments/DepartmentsFields.java b/testers/sqlite/java/generated-and-checked-in/testdb/departments/DepartmentsFields.java new file mode 100644 index 0000000000..c98bcc9ae9 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/departments/DepartmentsFields.java @@ -0,0 +1,96 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.departments; + +import dev.typr.dsl.FieldsBase; +import dev.typr.dsl.Path; +import dev.typr.dsl.RelationStructure; +import dev.typr.dsl.SqlExpr; +import dev.typr.dsl.SqlExpr.Field; +import dev.typr.dsl.SqlExpr.FieldLike; +import dev.typr.dsl.SqlExpr.IdField; +import dev.typr.dsl.SqlExpr.OptField; +import dev.typr.dsl.TupleExpr; +import dev.typr.dsl.TupleExpr.TupleExpr4; +import dev.typr.foundations.RowCodec; +import dev.typr.foundations.SqliteTypes; +import java.math.BigDecimal; +import java.util.List; +import java.util.Optional; + +public class DepartmentsFields extends TupleExpr4 implements RelationStructure, FieldsBase { + List _path; + + public DepartmentsFields(List _path) { + this._path = _path; + } + + public static DepartmentsFields structure = new DepartmentsFields(java.util.Collections.emptyList()); + + public IdField deptCode() { + return new IdField(_path, "dept_code", DepartmentsRow::deptCode, Optional.empty(), Optional.empty(), (row, value) -> row.withDeptCode(value), SqliteTypes.varchar); + } + + public IdField deptRegion() { + return new IdField(_path, "dept_region", DepartmentsRow::deptRegion, Optional.empty(), Optional.empty(), (row, value) -> row.withDeptRegion(value), SqliteTypes.varchar); + } + + public Field deptName() { + return new Field(_path, "dept_name", DepartmentsRow::deptName, Optional.empty(), Optional.empty(), (row, value) -> row.withDeptName(value), SqliteTypes.text); + } + + public OptField budget() { + return new OptField(_path, "budget", DepartmentsRow::budget, Optional.empty(), Optional.empty(), (row, value) -> row.withBudget(value), SqliteTypes.numeric); + } + + @Override + public List _path() { + return _path; + } + + public SqlExpr compositeIdIs(DepartmentsId compositeId) { + return SqlExpr.all(deptCode().isEqual(compositeId.deptCode()), deptRegion().isEqual(compositeId.deptRegion())); + } + + public SqlExpr compositeIdIn(List compositeIds) { + return TupleExpr.of(deptCode(), deptRegion()).among(compositeIds); + } + + @Override + public List> columns() { + return java.util.List.of(this.deptCode(), this.deptRegion(), this.deptName(), this.budget()); + } + + @Override + public RowCodec rowCodec() { + return DepartmentsRow.rowCodec; + } + + @Override + public RelationStructure withPaths(List _path) { + return new DepartmentsFields(_path); + } + + @Override + public SqlExpr _1() { + return deptCode(); + } + + @Override + public SqlExpr _2() { + return deptRegion(); + } + + @Override + public SqlExpr _3() { + return deptName(); + } + + @Override + public SqlExpr _4() { + return budget(); + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/departments/DepartmentsId.java b/testers/sqlite/java/generated-and-checked-in/testdb/departments/DepartmentsId.java new file mode 100644 index 0000000000..b8bc61557b --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/departments/DepartmentsId.java @@ -0,0 +1,38 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.departments; + +import com.fasterxml.jackson.annotation.JsonProperty; +import dev.typr.dsl.RowCodecs; +import dev.typr.foundations.RowCodec; +import dev.typr.foundations.SqliteTypes; +import dev.typr.foundations.Tuple.Tuple2; + +/** Type for the composite primary key of table `departments` */ +public record DepartmentsId( + @JsonProperty("dept_code") String deptCode, + @JsonProperty("dept_region") String deptRegion +) implements Tuple2 { + public DepartmentsId withDeptCode(String deptCode) { + return new DepartmentsId(deptCode, deptRegion); + } + + public DepartmentsId withDeptRegion(String deptRegion) { + return new DepartmentsId(deptCode, deptRegion); + } + + public static RowCodec rowCodec = RowCodecs.of(SqliteTypes.varchar, SqliteTypes.varchar, DepartmentsId::new, row -> new Object[]{row.deptCode(), row.deptRegion()}); + + @Override + public String _1() { + return deptCode; + } + + @Override + public String _2() { + return deptRegion; + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/departments/DepartmentsRepo.java b/testers/sqlite/java/generated-and-checked-in/testdb/departments/DepartmentsRepo.java new file mode 100644 index 0000000000..bdbe6e5b08 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/departments/DepartmentsRepo.java @@ -0,0 +1,71 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.departments; + +import dev.typr.dsl.DeleteBuilder; +import dev.typr.dsl.SelectBuilder; +import dev.typr.dsl.UpdateBuilder; +import dev.typr.foundations.Connection; +import dev.typr.foundations.ConnectionRead; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +public interface DepartmentsRepo { + DeleteBuilder delete(); + + Boolean deleteById( + DepartmentsId compositeId, + Connection c + ); + + Integer deleteByIds( + List compositeIds, + Connection c + ); + + DepartmentsRow insert( + DepartmentsRow unsaved, + Connection c + ); + + SelectBuilder select(); + + List selectAll(ConnectionRead c); + + Optional selectById( + DepartmentsId compositeId, + ConnectionRead c + ); + + List selectByIds( + List compositeIds, + ConnectionRead c + ); + + Map selectByIdsTracked( + List compositeIds, + ConnectionRead c + ); + + UpdateBuilder update(); + + Boolean update( + DepartmentsRow row, + Connection c + ); + + DepartmentsRow upsert( + DepartmentsRow unsaved, + Connection c + ); + + List upsertBatch( + Iterator unsaved, + Connection c + ); +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/departments/DepartmentsRepoImpl.java b/testers/sqlite/java/generated-and-checked-in/testdb/departments/DepartmentsRepoImpl.java new file mode 100644 index 0000000000..003e250d0d --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/departments/DepartmentsRepoImpl.java @@ -0,0 +1,128 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.departments; + +import dev.typr.dsl.DeleteBuilder; +import dev.typr.dsl.Dialect; +import dev.typr.dsl.SelectBuilder; +import dev.typr.dsl.UpdateBuilder; +import dev.typr.foundations.Connection; +import dev.typr.foundations.ConnectionRead; +import dev.typr.foundations.Fragment; +import dev.typr.foundations.SqliteTypes; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import static dev.typr.foundations.Fragment.concat; + +public class DepartmentsRepoImpl implements DepartmentsRepo { + @Override + public DeleteBuilder delete() { + return DeleteBuilder.of("\"departments\"", DepartmentsFields.structure, Dialect.SQLITE); + } + + @Override + public Boolean deleteById( + DepartmentsId compositeId, + Connection c + ) { + return concat(Fragment.of("delete from \"departments\" where \"dept_code\" = "), Fragment.encode(SqliteTypes.varchar, compositeId.deptCode()), Fragment.of(" AND \"dept_region\" = "), Fragment.encode(SqliteTypes.varchar, compositeId.deptRegion()), Fragment.of("")).update().run(c) > 0; + } + + @Override + public Integer deleteByIds( + List compositeIds, + Connection c + ) { + ArrayList fragments = new ArrayList<>(); + for (var id : compositeIds) { fragments.add(Fragment.concat(Fragment.of("("), Fragment.encode(SqliteTypes.varchar, id.deptCode()), Fragment.of(", "), Fragment.encode(SqliteTypes.varchar, id.deptRegion()), Fragment.of(")"))); }; + return Fragment.concat(Fragment.of("delete from \"departments\" where (\"dept_code\", \"dept_region\") in ("), Fragment.comma(fragments), Fragment.of(")")).update().run(c); + } + + @Override + public DepartmentsRow insert( + DepartmentsRow unsaved, + Connection c + ) { + return concat(Fragment.of("insert into \"departments\"(\"dept_code\", \"dept_region\", \"dept_name\", \"budget\")\nvalues ("), Fragment.encode(SqliteTypes.varchar, unsaved.deptCode()), Fragment.of(", "), Fragment.encode(SqliteTypes.varchar, unsaved.deptRegion()), Fragment.of(", "), Fragment.encode(SqliteTypes.text, unsaved.deptName()), Fragment.of(", "), Fragment.encode(SqliteTypes.numeric.opt(), unsaved.budget()), Fragment.of(")\nRETURNING \"dept_code\", \"dept_region\", \"dept_name\", \"budget\"\n")) + .updateReturning(DepartmentsRow.rowCodec.exactlyOne()).run(c); + } + + @Override + public SelectBuilder select() { + return SelectBuilder.of("\"departments\"", DepartmentsFields.structure, DepartmentsRow.rowCodec, Dialect.SQLITE); + } + + @Override + public List selectAll(ConnectionRead c) { + return concat(Fragment.of("select \"dept_code\", \"dept_region\", \"dept_name\", \"budget\"\nfrom \"departments\"\n")).query(DepartmentsRow.rowCodec.all()).run(c); + } + + @Override + public Optional selectById( + DepartmentsId compositeId, + ConnectionRead c + ) { + return concat(Fragment.of("select \"dept_code\", \"dept_region\", \"dept_name\", \"budget\"\nfrom \"departments\"\nwhere \"dept_code\" = "), Fragment.encode(SqliteTypes.varchar, compositeId.deptCode()), Fragment.of(" AND \"dept_region\" = "), Fragment.encode(SqliteTypes.varchar, compositeId.deptRegion()), Fragment.of("")).query(DepartmentsRow.rowCodec.first()).run(c); + } + + @Override + public List selectByIds( + List compositeIds, + ConnectionRead c + ) { + ArrayList fragments = new ArrayList<>(); + for (var id : compositeIds) { fragments.add(Fragment.concat(Fragment.of("("), Fragment.encode(SqliteTypes.varchar, id.deptCode()), Fragment.of(", "), Fragment.encode(SqliteTypes.varchar, id.deptRegion()), Fragment.of(")"))); }; + return Fragment.concat(Fragment.of("select \"dept_code\", \"dept_region\", \"dept_name\", \"budget\" from \"departments\" where (\"dept_code\", \"dept_region\") in ("), Fragment.comma(fragments), Fragment.of(")")).query(DepartmentsRow.rowCodec.all()).run(c); + } + + @Override + public Map selectByIdsTracked( + List compositeIds, + ConnectionRead c + ) { + HashMap ret = new HashMap(); + selectByIds(compositeIds, c).forEach(row -> ret.put(row.compositeId(), row)); + return ret; + } + + @Override + public UpdateBuilder update() { + return UpdateBuilder.of("\"departments\"", DepartmentsFields.structure, DepartmentsRow.rowCodec, Dialect.SQLITE); + } + + @Override + public Boolean update( + DepartmentsRow row, + Connection c + ) { + DepartmentsId compositeId = row.compositeId();; + return concat(Fragment.of("update \"departments\"\nset \"dept_name\" = "), Fragment.encode(SqliteTypes.text, row.deptName()), Fragment.of(",\n\"budget\" = "), Fragment.encode(SqliteTypes.numeric.opt(), row.budget()), Fragment.of("\nwhere \"dept_code\" = "), Fragment.encode(SqliteTypes.varchar, compositeId.deptCode()), Fragment.of(" AND \"dept_region\" = "), Fragment.encode(SqliteTypes.varchar, compositeId.deptRegion()), Fragment.of("")).update().run(c) > 0; + } + + @Override + public DepartmentsRow upsert( + DepartmentsRow unsaved, + Connection c + ) { + return concat(Fragment.of("INSERT INTO \"departments\"(\"dept_code\", \"dept_region\", \"dept_name\", \"budget\")\nVALUES ("), Fragment.encode(SqliteTypes.varchar, unsaved.deptCode()), Fragment.of(", "), Fragment.encode(SqliteTypes.varchar, unsaved.deptRegion()), Fragment.of(", "), Fragment.encode(SqliteTypes.text, unsaved.deptName()), Fragment.of(", "), Fragment.encode(SqliteTypes.numeric.opt(), unsaved.budget()), Fragment.of(")\nON CONFLICT (\"dept_code\", \"dept_region\")\nDO UPDATE SET\n \"dept_name\" = EXCLUDED.\"dept_name\",\n\"budget\" = EXCLUDED.\"budget\"\nRETURNING \"dept_code\", \"dept_region\", \"dept_name\", \"budget\"")) + .updateReturning(DepartmentsRow.rowCodec.exactlyOne()) + .run(c); + } + + @Override + public List upsertBatch( + Iterator unsaved, + Connection c + ) { + return concat(Fragment.of("INSERT INTO \"departments\"(\"dept_code\", \"dept_region\", \"dept_name\", \"budget\")\nVALUES (?, ?, ?, ?)\nON CONFLICT (\"dept_code\", \"dept_region\")\nDO UPDATE SET\n \"dept_name\" = EXCLUDED.\"dept_name\",\n\"budget\" = EXCLUDED.\"budget\"\nRETURNING \"dept_code\", \"dept_region\", \"dept_name\", \"budget\"")) + .updateReturningEach(DepartmentsRow.rowCodec, unsaved) + .run(c); + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/departments/DepartmentsRepoMock.java b/testers/sqlite/java/generated-and-checked-in/testdb/departments/DepartmentsRepoMock.java new file mode 100644 index 0000000000..78c185ddfc --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/departments/DepartmentsRepoMock.java @@ -0,0 +1,157 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.departments; + +import dev.typr.dsl.DeleteBuilder; +import dev.typr.dsl.DeleteBuilderMock; +import dev.typr.dsl.DeleteParams; +import dev.typr.dsl.SelectBuilder; +import dev.typr.dsl.SelectBuilderMock; +import dev.typr.dsl.SelectParams; +import dev.typr.dsl.UpdateBuilder; +import dev.typr.dsl.UpdateBuilderMock; +import dev.typr.dsl.UpdateParams; +import dev.typr.foundations.Connection; +import dev.typr.foundations.ConnectionRead; +import java.lang.RuntimeException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.function.Function; +import java.util.stream.Collectors; + +public record DepartmentsRepoMock(HashMap map) implements DepartmentsRepo { + public DepartmentsRepoMock() { + this(new HashMap()); + } + + public DepartmentsRepoMock withMap(HashMap map) { + return new DepartmentsRepoMock(map); + } + + @Override + public DeleteBuilder delete() { + return new DeleteBuilderMock<>(DepartmentsFields.structure, () -> new ArrayList<>(map.values()), DeleteParams.empty(), row -> row.compositeId(), id -> map.remove(id)); + } + + @Override + public Boolean deleteById( + DepartmentsId compositeId, + Connection c + ) { + return Optional.ofNullable(map.remove(compositeId)).isPresent(); + } + + @Override + public Integer deleteByIds( + List compositeIds, + Connection c + ) { + var count = 0; + for (var id : compositeIds) { + if (Optional.ofNullable(map.remove(id)).isPresent()) { + count = count + 1;; + } + }; + return count; + } + + @Override + public DepartmentsRow insert( + DepartmentsRow unsaved, + Connection c + ) { + if (map.containsKey(unsaved.compositeId())) { + throw new RuntimeException("id " + unsaved.compositeId() + " already exists"); + } + map.put(unsaved.compositeId(), unsaved); + return unsaved; + } + + @Override + public SelectBuilder select() { + return new SelectBuilderMock<>(DepartmentsFields.structure, () -> new ArrayList<>(map.values()), SelectParams.empty()); + } + + @Override + public List selectAll(ConnectionRead c) { + return new ArrayList<>(map.values()); + } + + @Override + public Optional selectById( + DepartmentsId compositeId, + ConnectionRead c + ) { + return Optional.ofNullable(map.get(compositeId)); + } + + @Override + public List selectByIds( + List compositeIds, + ConnectionRead c + ) { + var result = new ArrayList(); + for (var id : compositeIds) { + var opt = Optional.ofNullable(map.get(id)); + if (opt.isPresent()) { + result.add(opt.get()); + } + }; + return result; + } + + @Override + public Map selectByIdsTracked( + List compositeIds, + ConnectionRead c + ) { + return selectByIds(compositeIds, c).stream().collect(Collectors.toMap((DepartmentsRow row) -> row.compositeId(), Function.identity())); + } + + @Override + public UpdateBuilder update() { + return new UpdateBuilderMock<>(DepartmentsFields.structure, () -> new ArrayList<>(map.values()), UpdateParams.empty(), row -> row); + } + + @Override + public Boolean update( + DepartmentsRow row, + Connection c + ) { + var shouldUpdate = Optional.ofNullable(map.get(row.compositeId())).filter(oldRow -> !oldRow.equals(row)).isPresent(); + if (shouldUpdate) { + map.put(row.compositeId(), row);; + } + return shouldUpdate; + } + + @Override + public DepartmentsRow upsert( + DepartmentsRow unsaved, + Connection c + ) { + map.put(unsaved.compositeId(), unsaved); + return unsaved; + } + + @Override + public List upsertBatch( + Iterator unsaved, + Connection c + ) { + var result = new ArrayList(); + while (unsaved.hasNext()) { + var row = unsaved.next(); + map.put(row.compositeId(), row); + result.add(row); + }; + return result; + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/departments/DepartmentsRow.java b/testers/sqlite/java/generated-and-checked-in/testdb/departments/DepartmentsRow.java new file mode 100644 index 0000000000..68f3d813ce --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/departments/DepartmentsRow.java @@ -0,0 +1,78 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.departments; + +import com.fasterxml.jackson.annotation.JsonProperty; +import dev.typr.dsl.RowCodecs; +import dev.typr.foundations.RowCodec; +import dev.typr.foundations.SqliteTypes; +import dev.typr.foundations.Tuple.Tuple4; +import java.math.BigDecimal; +import java.util.Optional; + +/** Table: departments + * Composite primary key: dept_code, dept_region + */ +public record DepartmentsRow( + @JsonProperty("dept_code") String deptCode, + @JsonProperty("dept_region") String deptRegion, + @JsonProperty("dept_name") String deptName, + Optional budget +) implements Tuple4> { + public DepartmentsRow withDeptCode(String deptCode) { + return new DepartmentsRow(deptCode, deptRegion, deptName, budget); + } + + public DepartmentsRow withDeptRegion(String deptRegion) { + return new DepartmentsRow(deptCode, deptRegion, deptName, budget); + } + + public DepartmentsRow withDeptName(String deptName) { + return new DepartmentsRow(deptCode, deptRegion, deptName, budget); + } + + public DepartmentsRow withBudget(Optional budget) { + return new DepartmentsRow(deptCode, deptRegion, deptName, budget); + } + + public static RowCodec rowCodec = RowCodecs.of(SqliteTypes.varchar, SqliteTypes.varchar, SqliteTypes.text, SqliteTypes.numeric.opt(), DepartmentsRow::new, row -> new Object[]{row.deptCode(), row.deptRegion(), row.deptName(), row.budget()}); + + static public DepartmentsRow apply( + DepartmentsId compositeId, + String deptName, + Optional budget + ) { + return new DepartmentsRow(compositeId.deptCode(), compositeId.deptRegion(), deptName, budget); + } + + @Override + public String _1() { + return deptCode; + } + + @Override + public String _2() { + return deptRegion; + } + + @Override + public String _3() { + return deptName; + } + + @Override + public Optional _4() { + return budget; + } + + public DepartmentsId compositeId() { + return new DepartmentsId(deptCode, deptRegion); + } + + public DepartmentsId id() { + return this.compositeId(); + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/employees/EmployeesFields.java b/testers/sqlite/java/generated-and-checked-in/testdb/employees/EmployeesFields.java new file mode 100644 index 0000000000..658e7a43a3 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/employees/EmployeesFields.java @@ -0,0 +1,140 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.employees; + +import dev.typr.dsl.FieldsBase; +import dev.typr.dsl.ForeignKey; +import dev.typr.dsl.Path; +import dev.typr.dsl.RelationStructure; +import dev.typr.dsl.SqlExpr; +import dev.typr.dsl.SqlExpr.Field; +import dev.typr.dsl.SqlExpr.FieldLike; +import dev.typr.dsl.SqlExpr.IdField; +import dev.typr.dsl.SqlExpr.OptField; +import dev.typr.dsl.TupleExpr; +import dev.typr.dsl.TupleExpr.TupleExpr7; +import dev.typr.foundations.RowCodec; +import dev.typr.foundations.SqliteTypes; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.List; +import java.util.Optional; +import testdb.departments.DepartmentsFields; +import testdb.departments.DepartmentsId; +import testdb.departments.DepartmentsRow; + +public class EmployeesFields extends TupleExpr7 implements RelationStructure, FieldsBase { + List _path; + + public EmployeesFields(List _path) { + this._path = _path; + } + + public static EmployeesFields structure = new EmployeesFields(java.util.Collections.emptyList()); + + public IdField empNumber() { + return new IdField(_path, "emp_number", EmployeesRow::empNumber, Optional.empty(), Optional.empty(), (row, value) -> row.withEmpNumber(value), SqliteTypes.integer); + } + + public IdField empSuffix() { + return new IdField(_path, "emp_suffix", EmployeesRow::empSuffix, Optional.empty(), Optional.empty(), (row, value) -> row.withEmpSuffix(value), SqliteTypes.varchar); + } + + public Field deptCode() { + return new Field(_path, "dept_code", EmployeesRow::deptCode, Optional.empty(), Optional.empty(), (row, value) -> row.withDeptCode(value), SqliteTypes.varchar); + } + + public Field deptRegion() { + return new Field(_path, "dept_region", EmployeesRow::deptRegion, Optional.empty(), Optional.empty(), (row, value) -> row.withDeptRegion(value), SqliteTypes.varchar); + } + + public Field empName() { + return new Field(_path, "emp_name", EmployeesRow::empName, Optional.empty(), Optional.empty(), (row, value) -> row.withEmpName(value), SqliteTypes.text); + } + + public OptField salary() { + return new OptField(_path, "salary", EmployeesRow::salary, Optional.empty(), Optional.empty(), (row, value) -> row.withSalary(value), SqliteTypes.numeric); + } + + public Field hireDate() { + return new Field(_path, "hire_date", EmployeesRow::hireDate, Optional.empty(), Optional.empty(), (row, value) -> row.withHireDate(value), SqliteTypes.date); + } + + @Override + public List _path() { + return _path; + } + + public ForeignKey fkDepartments() { + return ForeignKey.of("employees_fk_0").withColumnPair(deptCode(), DepartmentsFields::deptCode).withColumnPair(deptRegion(), DepartmentsFields::deptRegion); + } + + public SqlExpr extractIdentDepartmentsIdIs(DepartmentsId id) { + return SqlExpr.all(deptCode().isEqual(id.deptCode()), deptRegion().isEqual(id.deptRegion())); + } + + public SqlExpr extractIdentDepartmentsIdIn(List ids) { + return TupleExpr.of(deptCode(), deptRegion()).among(ids); + } + + public SqlExpr compositeIdIs(EmployeesId compositeId) { + return SqlExpr.all(empNumber().isEqual(compositeId.empNumber()), empSuffix().isEqual(compositeId.empSuffix())); + } + + public SqlExpr compositeIdIn(List compositeIds) { + return TupleExpr.of(empNumber(), empSuffix()).among(compositeIds); + } + + @Override + public List> columns() { + return java.util.List.of(this.empNumber(), this.empSuffix(), this.deptCode(), this.deptRegion(), this.empName(), this.salary(), this.hireDate()); + } + + @Override + public RowCodec rowCodec() { + return EmployeesRow.rowCodec; + } + + @Override + public RelationStructure withPaths(List _path) { + return new EmployeesFields(_path); + } + + @Override + public SqlExpr _1() { + return empNumber(); + } + + @Override + public SqlExpr _2() { + return empSuffix(); + } + + @Override + public SqlExpr _3() { + return deptCode(); + } + + @Override + public SqlExpr _4() { + return deptRegion(); + } + + @Override + public SqlExpr _5() { + return empName(); + } + + @Override + public SqlExpr _6() { + return salary(); + } + + @Override + public SqlExpr _7() { + return hireDate(); + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/employees/EmployeesId.java b/testers/sqlite/java/generated-and-checked-in/testdb/employees/EmployeesId.java new file mode 100644 index 0000000000..fff45b8363 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/employees/EmployeesId.java @@ -0,0 +1,38 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.employees; + +import com.fasterxml.jackson.annotation.JsonProperty; +import dev.typr.dsl.RowCodecs; +import dev.typr.foundations.RowCodec; +import dev.typr.foundations.SqliteTypes; +import dev.typr.foundations.Tuple.Tuple2; + +/** Type for the composite primary key of table `employees` */ +public record EmployeesId( + @JsonProperty("emp_number") Long empNumber, + @JsonProperty("emp_suffix") String empSuffix +) implements Tuple2 { + public EmployeesId withEmpNumber(Long empNumber) { + return new EmployeesId(empNumber, empSuffix); + } + + public EmployeesId withEmpSuffix(String empSuffix) { + return new EmployeesId(empNumber, empSuffix); + } + + public static RowCodec rowCodec = RowCodecs.of(SqliteTypes.integer, SqliteTypes.varchar, EmployeesId::new, row -> new Object[]{row.empNumber(), row.empSuffix()}); + + @Override + public Long _1() { + return empNumber; + } + + @Override + public String _2() { + return empSuffix; + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/employees/EmployeesRepo.java b/testers/sqlite/java/generated-and-checked-in/testdb/employees/EmployeesRepo.java new file mode 100644 index 0000000000..22f284d6f2 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/employees/EmployeesRepo.java @@ -0,0 +1,76 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.employees; + +import dev.typr.dsl.DeleteBuilder; +import dev.typr.dsl.SelectBuilder; +import dev.typr.dsl.UpdateBuilder; +import dev.typr.foundations.Connection; +import dev.typr.foundations.ConnectionRead; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +public interface EmployeesRepo { + DeleteBuilder delete(); + + Boolean deleteById( + EmployeesId compositeId, + Connection c + ); + + Integer deleteByIds( + List compositeIds, + Connection c + ); + + EmployeesRow insert( + EmployeesRow unsaved, + Connection c + ); + + EmployeesRow insert( + EmployeesRowUnsaved unsaved, + Connection c + ); + + SelectBuilder select(); + + List selectAll(ConnectionRead c); + + Optional selectById( + EmployeesId compositeId, + ConnectionRead c + ); + + List selectByIds( + List compositeIds, + ConnectionRead c + ); + + Map selectByIdsTracked( + List compositeIds, + ConnectionRead c + ); + + UpdateBuilder update(); + + Boolean update( + EmployeesRow row, + Connection c + ); + + EmployeesRow upsert( + EmployeesRow unsaved, + Connection c + ); + + List upsertBatch( + Iterator unsaved, + Connection c + ); +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/employees/EmployeesRepoImpl.java b/testers/sqlite/java/generated-and-checked-in/testdb/employees/EmployeesRepoImpl.java new file mode 100644 index 0000000000..131d1b8df8 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/employees/EmployeesRepoImpl.java @@ -0,0 +1,160 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.employees; + +import dev.typr.dsl.DeleteBuilder; +import dev.typr.dsl.Dialect; +import dev.typr.dsl.SelectBuilder; +import dev.typr.dsl.UpdateBuilder; +import dev.typr.foundations.Connection; +import dev.typr.foundations.ConnectionRead; +import dev.typr.foundations.Fragment; +import dev.typr.foundations.SqliteTypes; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import static dev.typr.foundations.Fragment.concat; + +public class EmployeesRepoImpl implements EmployeesRepo { + @Override + public DeleteBuilder delete() { + return DeleteBuilder.of("\"employees\"", EmployeesFields.structure, Dialect.SQLITE); + } + + @Override + public Boolean deleteById( + EmployeesId compositeId, + Connection c + ) { + return concat(Fragment.of("delete from \"employees\" where \"emp_number\" = "), Fragment.encode(SqliteTypes.integer, compositeId.empNumber()), Fragment.of(" AND \"emp_suffix\" = "), Fragment.encode(SqliteTypes.varchar, compositeId.empSuffix()), Fragment.of("")).update().run(c) > 0; + } + + @Override + public Integer deleteByIds( + List compositeIds, + Connection c + ) { + ArrayList fragments = new ArrayList<>(); + for (var id : compositeIds) { fragments.add(Fragment.concat(Fragment.of("("), Fragment.encode(SqliteTypes.integer, id.empNumber()), Fragment.of(", "), Fragment.encode(SqliteTypes.varchar, id.empSuffix()), Fragment.of(")"))); }; + return Fragment.concat(Fragment.of("delete from \"employees\" where (\"emp_number\", \"emp_suffix\") in ("), Fragment.comma(fragments), Fragment.of(")")).update().run(c); + } + + @Override + public EmployeesRow insert( + EmployeesRow unsaved, + Connection c + ) { + return concat(Fragment.of("insert into \"employees\"(\"emp_number\", \"emp_suffix\", \"dept_code\", \"dept_region\", \"emp_name\", \"salary\", \"hire_date\")\nvalues ("), Fragment.encode(SqliteTypes.integer, unsaved.empNumber()), Fragment.of(", "), Fragment.encode(SqliteTypes.varchar, unsaved.empSuffix()), Fragment.of(", "), Fragment.encode(SqliteTypes.varchar, unsaved.deptCode()), Fragment.of(", "), Fragment.encode(SqliteTypes.varchar, unsaved.deptRegion()), Fragment.of(", "), Fragment.encode(SqliteTypes.text, unsaved.empName()), Fragment.of(", "), Fragment.encode(SqliteTypes.numeric.opt(), unsaved.salary()), Fragment.of(", "), Fragment.encode(SqliteTypes.date, unsaved.hireDate()), Fragment.of(")\nRETURNING \"emp_number\", \"emp_suffix\", \"dept_code\", \"dept_region\", \"emp_name\", \"salary\", \"hire_date\"\n")) + .updateReturning(EmployeesRow.rowCodec.exactlyOne()).run(c); + } + + @Override + public EmployeesRow insert( + EmployeesRowUnsaved unsaved, + Connection c + ) { + ArrayList columns = new ArrayList<>();; + ArrayList values = new ArrayList<>();; + columns.add(Fragment.of("\"emp_number\"")); + values.add(concat(Fragment.encode(SqliteTypes.integer, unsaved.empNumber()), Fragment.of(""))); + columns.add(Fragment.of("\"emp_suffix\"")); + values.add(concat(Fragment.encode(SqliteTypes.varchar, unsaved.empSuffix()), Fragment.of(""))); + columns.add(Fragment.of("\"dept_code\"")); + values.add(concat(Fragment.encode(SqliteTypes.varchar, unsaved.deptCode()), Fragment.of(""))); + columns.add(Fragment.of("\"dept_region\"")); + values.add(concat(Fragment.encode(SqliteTypes.varchar, unsaved.deptRegion()), Fragment.of(""))); + columns.add(Fragment.of("\"emp_name\"")); + values.add(concat(Fragment.encode(SqliteTypes.text, unsaved.empName()), Fragment.of(""))); + columns.add(Fragment.of("\"salary\"")); + values.add(concat(Fragment.encode(SqliteTypes.numeric.opt(), unsaved.salary()), Fragment.of(""))); + unsaved.hireDate().visit( + () -> { + + }, + value -> { + columns.add(Fragment.of("\"hire_date\"")); + values.add(concat(Fragment.encode(SqliteTypes.date, value), Fragment.of(""))); + } + );; + Fragment q = concat(Fragment.of("insert into \"employees\"("), Fragment.comma(columns), Fragment.of(")\nvalues ("), Fragment.comma(values), Fragment.of(")\nRETURNING \"emp_number\", \"emp_suffix\", \"dept_code\", \"dept_region\", \"emp_name\", \"salary\", \"hire_date\"\n"));; + return q.updateReturning(EmployeesRow.rowCodec.exactlyOne()).run(c); + } + + @Override + public SelectBuilder select() { + return SelectBuilder.of("\"employees\"", EmployeesFields.structure, EmployeesRow.rowCodec, Dialect.SQLITE); + } + + @Override + public List selectAll(ConnectionRead c) { + return concat(Fragment.of("select \"emp_number\", \"emp_suffix\", \"dept_code\", \"dept_region\", \"emp_name\", \"salary\", \"hire_date\"\nfrom \"employees\"\n")).query(EmployeesRow.rowCodec.all()).run(c); + } + + @Override + public Optional selectById( + EmployeesId compositeId, + ConnectionRead c + ) { + return concat(Fragment.of("select \"emp_number\", \"emp_suffix\", \"dept_code\", \"dept_region\", \"emp_name\", \"salary\", \"hire_date\"\nfrom \"employees\"\nwhere \"emp_number\" = "), Fragment.encode(SqliteTypes.integer, compositeId.empNumber()), Fragment.of(" AND \"emp_suffix\" = "), Fragment.encode(SqliteTypes.varchar, compositeId.empSuffix()), Fragment.of("")).query(EmployeesRow.rowCodec.first()).run(c); + } + + @Override + public List selectByIds( + List compositeIds, + ConnectionRead c + ) { + ArrayList fragments = new ArrayList<>(); + for (var id : compositeIds) { fragments.add(Fragment.concat(Fragment.of("("), Fragment.encode(SqliteTypes.integer, id.empNumber()), Fragment.of(", "), Fragment.encode(SqliteTypes.varchar, id.empSuffix()), Fragment.of(")"))); }; + return Fragment.concat(Fragment.of("select \"emp_number\", \"emp_suffix\", \"dept_code\", \"dept_region\", \"emp_name\", \"salary\", \"hire_date\" from \"employees\" where (\"emp_number\", \"emp_suffix\") in ("), Fragment.comma(fragments), Fragment.of(")")).query(EmployeesRow.rowCodec.all()).run(c); + } + + @Override + public Map selectByIdsTracked( + List compositeIds, + ConnectionRead c + ) { + HashMap ret = new HashMap(); + selectByIds(compositeIds, c).forEach(row -> ret.put(row.compositeId(), row)); + return ret; + } + + @Override + public UpdateBuilder update() { + return UpdateBuilder.of("\"employees\"", EmployeesFields.structure, EmployeesRow.rowCodec, Dialect.SQLITE); + } + + @Override + public Boolean update( + EmployeesRow row, + Connection c + ) { + EmployeesId compositeId = row.compositeId();; + return concat(Fragment.of("update \"employees\"\nset \"dept_code\" = "), Fragment.encode(SqliteTypes.varchar, row.deptCode()), Fragment.of(",\n\"dept_region\" = "), Fragment.encode(SqliteTypes.varchar, row.deptRegion()), Fragment.of(",\n\"emp_name\" = "), Fragment.encode(SqliteTypes.text, row.empName()), Fragment.of(",\n\"salary\" = "), Fragment.encode(SqliteTypes.numeric.opt(), row.salary()), Fragment.of(",\n\"hire_date\" = "), Fragment.encode(SqliteTypes.date, row.hireDate()), Fragment.of("\nwhere \"emp_number\" = "), Fragment.encode(SqliteTypes.integer, compositeId.empNumber()), Fragment.of(" AND \"emp_suffix\" = "), Fragment.encode(SqliteTypes.varchar, compositeId.empSuffix()), Fragment.of("")).update().run(c) > 0; + } + + @Override + public EmployeesRow upsert( + EmployeesRow unsaved, + Connection c + ) { + return concat(Fragment.of("INSERT INTO \"employees\"(\"emp_number\", \"emp_suffix\", \"dept_code\", \"dept_region\", \"emp_name\", \"salary\", \"hire_date\")\nVALUES ("), Fragment.encode(SqliteTypes.integer, unsaved.empNumber()), Fragment.of(", "), Fragment.encode(SqliteTypes.varchar, unsaved.empSuffix()), Fragment.of(", "), Fragment.encode(SqliteTypes.varchar, unsaved.deptCode()), Fragment.of(", "), Fragment.encode(SqliteTypes.varchar, unsaved.deptRegion()), Fragment.of(", "), Fragment.encode(SqliteTypes.text, unsaved.empName()), Fragment.of(", "), Fragment.encode(SqliteTypes.numeric.opt(), unsaved.salary()), Fragment.of(", "), Fragment.encode(SqliteTypes.date, unsaved.hireDate()), Fragment.of(")\nON CONFLICT (\"emp_number\", \"emp_suffix\")\nDO UPDATE SET\n \"dept_code\" = EXCLUDED.\"dept_code\",\n\"dept_region\" = EXCLUDED.\"dept_region\",\n\"emp_name\" = EXCLUDED.\"emp_name\",\n\"salary\" = EXCLUDED.\"salary\",\n\"hire_date\" = EXCLUDED.\"hire_date\"\nRETURNING \"emp_number\", \"emp_suffix\", \"dept_code\", \"dept_region\", \"emp_name\", \"salary\", \"hire_date\"")) + .updateReturning(EmployeesRow.rowCodec.exactlyOne()) + .run(c); + } + + @Override + public List upsertBatch( + Iterator unsaved, + Connection c + ) { + return concat(Fragment.of("INSERT INTO \"employees\"(\"emp_number\", \"emp_suffix\", \"dept_code\", \"dept_region\", \"emp_name\", \"salary\", \"hire_date\")\nVALUES (?, ?, ?, ?, ?, ?, ?)\nON CONFLICT (\"emp_number\", \"emp_suffix\")\nDO UPDATE SET\n \"dept_code\" = EXCLUDED.\"dept_code\",\n\"dept_region\" = EXCLUDED.\"dept_region\",\n\"emp_name\" = EXCLUDED.\"emp_name\",\n\"salary\" = EXCLUDED.\"salary\",\n\"hire_date\" = EXCLUDED.\"hire_date\"\nRETURNING \"emp_number\", \"emp_suffix\", \"dept_code\", \"dept_region\", \"emp_name\", \"salary\", \"hire_date\"")) + .updateReturningEach(EmployeesRow.rowCodec, unsaved) + .run(c); + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/employees/EmployeesRepoMock.java b/testers/sqlite/java/generated-and-checked-in/testdb/employees/EmployeesRepoMock.java new file mode 100644 index 0000000000..debd682027 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/employees/EmployeesRepoMock.java @@ -0,0 +1,172 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.employees; + +import dev.typr.dsl.DeleteBuilder; +import dev.typr.dsl.DeleteBuilderMock; +import dev.typr.dsl.DeleteParams; +import dev.typr.dsl.SelectBuilder; +import dev.typr.dsl.SelectBuilderMock; +import dev.typr.dsl.SelectParams; +import dev.typr.dsl.UpdateBuilder; +import dev.typr.dsl.UpdateBuilderMock; +import dev.typr.dsl.UpdateParams; +import dev.typr.foundations.Connection; +import dev.typr.foundations.ConnectionRead; +import java.lang.RuntimeException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.function.Function; +import java.util.stream.Collectors; + +public record EmployeesRepoMock( + java.util.function.Function toRow, + HashMap map +) implements EmployeesRepo { + public EmployeesRepoMock(java.util.function.Function toRow) { + this(toRow, new HashMap()); + } + + public EmployeesRepoMock withToRow(java.util.function.Function toRow) { + return new EmployeesRepoMock(toRow, map); + } + + public EmployeesRepoMock withMap(HashMap map) { + return new EmployeesRepoMock(toRow, map); + } + + @Override + public DeleteBuilder delete() { + return new DeleteBuilderMock<>(EmployeesFields.structure, () -> new ArrayList<>(map.values()), DeleteParams.empty(), row -> row.compositeId(), id -> map.remove(id)); + } + + @Override + public Boolean deleteById( + EmployeesId compositeId, + Connection c + ) { + return Optional.ofNullable(map.remove(compositeId)).isPresent(); + } + + @Override + public Integer deleteByIds( + List compositeIds, + Connection c + ) { + var count = 0; + for (var id : compositeIds) { + if (Optional.ofNullable(map.remove(id)).isPresent()) { + count = count + 1;; + } + }; + return count; + } + + @Override + public EmployeesRow insert( + EmployeesRow unsaved, + Connection c + ) { + if (map.containsKey(unsaved.compositeId())) { + throw new RuntimeException("id " + unsaved.compositeId() + " already exists"); + } + map.put(unsaved.compositeId(), unsaved); + return unsaved; + } + + @Override + public EmployeesRow insert( + EmployeesRowUnsaved unsaved, + Connection c + ) { + return insert(toRow.apply(unsaved), c); + } + + @Override + public SelectBuilder select() { + return new SelectBuilderMock<>(EmployeesFields.structure, () -> new ArrayList<>(map.values()), SelectParams.empty()); + } + + @Override + public List selectAll(ConnectionRead c) { + return new ArrayList<>(map.values()); + } + + @Override + public Optional selectById( + EmployeesId compositeId, + ConnectionRead c + ) { + return Optional.ofNullable(map.get(compositeId)); + } + + @Override + public List selectByIds( + List compositeIds, + ConnectionRead c + ) { + var result = new ArrayList(); + for (var id : compositeIds) { + var opt = Optional.ofNullable(map.get(id)); + if (opt.isPresent()) { + result.add(opt.get()); + } + }; + return result; + } + + @Override + public Map selectByIdsTracked( + List compositeIds, + ConnectionRead c + ) { + return selectByIds(compositeIds, c).stream().collect(Collectors.toMap((EmployeesRow row) -> row.compositeId(), Function.identity())); + } + + @Override + public UpdateBuilder update() { + return new UpdateBuilderMock<>(EmployeesFields.structure, () -> new ArrayList<>(map.values()), UpdateParams.empty(), row -> row); + } + + @Override + public Boolean update( + EmployeesRow row, + Connection c + ) { + var shouldUpdate = Optional.ofNullable(map.get(row.compositeId())).filter(oldRow -> !oldRow.equals(row)).isPresent(); + if (shouldUpdate) { + map.put(row.compositeId(), row);; + } + return shouldUpdate; + } + + @Override + public EmployeesRow upsert( + EmployeesRow unsaved, + Connection c + ) { + map.put(unsaved.compositeId(), unsaved); + return unsaved; + } + + @Override + public List upsertBatch( + Iterator unsaved, + Connection c + ) { + var result = new ArrayList(); + while (unsaved.hasNext()) { + var row = unsaved.next(); + map.put(row.compositeId(), row); + result.add(row); + }; + return result; + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/employees/EmployeesRow.java b/testers/sqlite/java/generated-and-checked-in/testdb/employees/EmployeesRow.java new file mode 100644 index 0000000000..307de5972d --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/employees/EmployeesRow.java @@ -0,0 +1,128 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.employees; + +import com.fasterxml.jackson.annotation.JsonProperty; +import dev.typr.dsl.RowCodecs; +import dev.typr.foundations.RowCodec; +import dev.typr.foundations.SqliteTypes; +import dev.typr.foundations.Tuple.Tuple7; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.Optional; +import testdb.customtypes.Defaulted; +import testdb.departments.DepartmentsId; + +/** Table: employees + * Composite primary key: emp_number, emp_suffix + */ +public record EmployeesRow( + @JsonProperty("emp_number") Long empNumber, + @JsonProperty("emp_suffix") String empSuffix, + /** Points to {@link testdb.departments.DepartmentsRow#deptCode()} */ + @JsonProperty("dept_code") String deptCode, + /** Points to {@link testdb.departments.DepartmentsRow#deptRegion()} */ + @JsonProperty("dept_region") String deptRegion, + @JsonProperty("emp_name") String empName, + Optional salary, + /** Default: CURRENT_DATE */ + @JsonProperty("hire_date") LocalDate hireDate +) implements Tuple7, LocalDate> { + public EmployeesRow withEmpNumber(Long empNumber) { + return new EmployeesRow(empNumber, empSuffix, deptCode, deptRegion, empName, salary, hireDate); + } + + public EmployeesRow withEmpSuffix(String empSuffix) { + return new EmployeesRow(empNumber, empSuffix, deptCode, deptRegion, empName, salary, hireDate); + } + + /** Points to {@link testdb.departments.DepartmentsRow#deptCode()} */ + public EmployeesRow withDeptCode(String deptCode) { + return new EmployeesRow(empNumber, empSuffix, deptCode, deptRegion, empName, salary, hireDate); + } + + /** Points to {@link testdb.departments.DepartmentsRow#deptRegion()} */ + public EmployeesRow withDeptRegion(String deptRegion) { + return new EmployeesRow(empNumber, empSuffix, deptCode, deptRegion, empName, salary, hireDate); + } + + public EmployeesRow withEmpName(String empName) { + return new EmployeesRow(empNumber, empSuffix, deptCode, deptRegion, empName, salary, hireDate); + } + + public EmployeesRow withSalary(Optional salary) { + return new EmployeesRow(empNumber, empSuffix, deptCode, deptRegion, empName, salary, hireDate); + } + + /** Default: CURRENT_DATE */ + public EmployeesRow withHireDate(LocalDate hireDate) { + return new EmployeesRow(empNumber, empSuffix, deptCode, deptRegion, empName, salary, hireDate); + } + + public static RowCodec rowCodec = RowCodecs.of(SqliteTypes.integer, SqliteTypes.varchar, SqliteTypes.varchar, SqliteTypes.varchar, SqliteTypes.text, SqliteTypes.numeric.opt(), SqliteTypes.date, EmployeesRow::new, row -> new Object[]{row.empNumber(), row.empSuffix(), row.deptCode(), row.deptRegion(), row.empName(), row.salary(), row.hireDate()}); + + static public EmployeesRow apply( + EmployeesId compositeId, + String deptCode, + String deptRegion, + String empName, + Optional salary, + LocalDate hireDate + ) { + return new EmployeesRow(compositeId.empNumber(), compositeId.empSuffix(), deptCode, deptRegion, empName, salary, hireDate); + } + + @Override + public Long _1() { + return empNumber; + } + + @Override + public String _2() { + return empSuffix; + } + + @Override + public String _3() { + return deptCode; + } + + @Override + public String _4() { + return deptRegion; + } + + @Override + public String _5() { + return empName; + } + + @Override + public Optional _6() { + return salary; + } + + @Override + public LocalDate _7() { + return hireDate; + } + + public EmployeesId compositeId() { + return new EmployeesId(empNumber, empSuffix); + } + + public DepartmentsId extractDepartmentsId() { + return new DepartmentsId(deptCode, deptRegion); + } + + public EmployeesId id() { + return this.compositeId(); + } + + public EmployeesRowUnsaved toUnsavedRow(Defaulted hireDate) { + return new EmployeesRowUnsaved(empNumber, empSuffix, deptCode, deptRegion, empName, salary, hireDate); + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/employees/EmployeesRowUnsaved.java b/testers/sqlite/java/generated-and-checked-in/testdb/employees/EmployeesRowUnsaved.java new file mode 100644 index 0000000000..03f6b8b4e8 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/employees/EmployeesRowUnsaved.java @@ -0,0 +1,74 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.employees; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.Optional; +import testdb.customtypes.Defaulted; +import testdb.customtypes.Defaulted.UseDefault; + +/** This class corresponds to a row in table `employees` which has not been persisted yet */ +public record EmployeesRowUnsaved( + @JsonProperty("emp_number") Long empNumber, + @JsonProperty("emp_suffix") String empSuffix, + /** Points to {@link testdb.departments.DepartmentsRow#deptCode()} */ + @JsonProperty("dept_code") String deptCode, + /** Points to {@link testdb.departments.DepartmentsRow#deptRegion()} */ + @JsonProperty("dept_region") String deptRegion, + @JsonProperty("emp_name") String empName, + Optional salary, + /** Default: CURRENT_DATE */ + @JsonProperty("hire_date") Defaulted hireDate +) { + public EmployeesRowUnsaved( + @JsonProperty("emp_number") Long empNumber, + @JsonProperty("emp_suffix") String empSuffix, + /** Points to {@link testdb.departments.DepartmentsRow#deptCode()} */ + @JsonProperty("dept_code") String deptCode, + /** Points to {@link testdb.departments.DepartmentsRow#deptRegion()} */ + @JsonProperty("dept_region") String deptRegion, + @JsonProperty("emp_name") String empName + ) { + this(empNumber, empSuffix, deptCode, deptRegion, empName, Optional.empty(), new UseDefault<>()); + } + + public EmployeesRowUnsaved withEmpNumber(Long empNumber) { + return new EmployeesRowUnsaved(empNumber, empSuffix, deptCode, deptRegion, empName, salary, hireDate); + } + + public EmployeesRowUnsaved withEmpSuffix(String empSuffix) { + return new EmployeesRowUnsaved(empNumber, empSuffix, deptCode, deptRegion, empName, salary, hireDate); + } + + /** Points to {@link testdb.departments.DepartmentsRow#deptCode()} */ + public EmployeesRowUnsaved withDeptCode(String deptCode) { + return new EmployeesRowUnsaved(empNumber, empSuffix, deptCode, deptRegion, empName, salary, hireDate); + } + + /** Points to {@link testdb.departments.DepartmentsRow#deptRegion()} */ + public EmployeesRowUnsaved withDeptRegion(String deptRegion) { + return new EmployeesRowUnsaved(empNumber, empSuffix, deptCode, deptRegion, empName, salary, hireDate); + } + + public EmployeesRowUnsaved withEmpName(String empName) { + return new EmployeesRowUnsaved(empNumber, empSuffix, deptCode, deptRegion, empName, salary, hireDate); + } + + public EmployeesRowUnsaved withSalary(Optional salary) { + return new EmployeesRowUnsaved(empNumber, empSuffix, deptCode, deptRegion, empName, salary, hireDate); + } + + /** Default: CURRENT_DATE */ + public EmployeesRowUnsaved withHireDate(Defaulted hireDate) { + return new EmployeesRowUnsaved(empNumber, empSuffix, deptCode, deptRegion, empName, salary, hireDate); + } + + public EmployeesRow toRow(java.util.function.Supplier hireDateDefault) { + return new EmployeesRow(empNumber, empSuffix, deptCode, deptRegion, empName, salary, hireDate.getOrElse(hireDateDefault)); + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/order_details/OrderDetailsViewFields.java b/testers/sqlite/java/generated-and-checked-in/testdb/order_details/OrderDetailsViewFields.java new file mode 100644 index 0000000000..f81b188b85 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/order_details/OrderDetailsViewFields.java @@ -0,0 +1,114 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.order_details; + +import dev.typr.dsl.FieldsBase; +import dev.typr.dsl.Path; +import dev.typr.dsl.RelationStructure; +import dev.typr.dsl.SqlExpr; +import dev.typr.dsl.SqlExpr.FieldLike; +import dev.typr.dsl.SqlExpr.OptField; +import dev.typr.dsl.TupleExpr.TupleExpr7; +import dev.typr.foundations.RowCodec; +import dev.typr.foundations.SqliteTypes; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.List; +import java.util.Optional; +import testdb.orders.OrdersId; + +public class OrderDetailsViewFields extends TupleExpr7 implements RelationStructure, FieldsBase { + List _path; + + public OrderDetailsViewFields(List _path) { + this._path = _path; + } + + public static OrderDetailsViewFields structure = new OrderDetailsViewFields(java.util.Collections.emptyList()); + + public OptField orderId() { + return new OptField(_path, "order_id", OrderDetailsViewRow::orderId, Optional.empty(), Optional.empty(), (row, value) -> row.withOrderId(value), OrdersId.sqliteType); + } + + public OptField orderDate() { + return new OptField(_path, "order_date", OrderDetailsViewRow::orderDate, Optional.empty(), Optional.empty(), (row, value) -> row.withOrderDate(value), SqliteTypes.date); + } + + public OptField customerName() { + return new OptField(_path, "customer_name", OrderDetailsViewRow::customerName, Optional.empty(), Optional.empty(), (row, value) -> row.withCustomerName(value), SqliteTypes.text); + } + + public OptField productName() { + return new OptField(_path, "product_name", OrderDetailsViewRow::productName, Optional.empty(), Optional.empty(), (row, value) -> row.withProductName(value), SqliteTypes.text); + } + + public OptField quantity() { + return new OptField(_path, "quantity", OrderDetailsViewRow::quantity, Optional.empty(), Optional.empty(), (row, value) -> row.withQuantity(value), SqliteTypes.integer); + } + + public OptField unitPrice() { + return new OptField(_path, "unit_price", OrderDetailsViewRow::unitPrice, Optional.empty(), Optional.empty(), (row, value) -> row.withUnitPrice(value), SqliteTypes.numeric); + } + + public OptField lineTotal() { + return new OptField(_path, "line_total", OrderDetailsViewRow::lineTotal, Optional.empty(), Optional.empty(), (row, value) -> row.withLineTotal(value), SqliteTypes.text); + } + + @Override + public List _path() { + return _path; + } + + @Override + public List> columns() { + return java.util.List.of(this.orderId(), this.orderDate(), this.customerName(), this.productName(), this.quantity(), this.unitPrice(), this.lineTotal()); + } + + @Override + public RowCodec rowCodec() { + return OrderDetailsViewRow.rowCodec; + } + + @Override + public RelationStructure withPaths(List _path) { + return new OrderDetailsViewFields(_path); + } + + @Override + public SqlExpr _1() { + return orderId(); + } + + @Override + public SqlExpr _2() { + return orderDate(); + } + + @Override + public SqlExpr _3() { + return customerName(); + } + + @Override + public SqlExpr _4() { + return productName(); + } + + @Override + public SqlExpr _5() { + return quantity(); + } + + @Override + public SqlExpr _6() { + return unitPrice(); + } + + @Override + public SqlExpr _7() { + return lineTotal(); + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/order_details/OrderDetailsViewRepo.java b/testers/sqlite/java/generated-and-checked-in/testdb/order_details/OrderDetailsViewRepo.java new file mode 100644 index 0000000000..c4b9f78b7a --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/order_details/OrderDetailsViewRepo.java @@ -0,0 +1,16 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.order_details; + +import dev.typr.dsl.SelectBuilder; +import dev.typr.foundations.ConnectionRead; +import java.util.List; + +public interface OrderDetailsViewRepo { + SelectBuilder select(); + + List selectAll(ConnectionRead c); +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/order_details/OrderDetailsViewRepoImpl.java b/testers/sqlite/java/generated-and-checked-in/testdb/order_details/OrderDetailsViewRepoImpl.java new file mode 100644 index 0000000000..2028e344d3 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/order_details/OrderDetailsViewRepoImpl.java @@ -0,0 +1,25 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.order_details; + +import dev.typr.dsl.Dialect; +import dev.typr.dsl.SelectBuilder; +import dev.typr.foundations.ConnectionRead; +import dev.typr.foundations.Fragment; +import java.util.List; +import static dev.typr.foundations.Fragment.concat; + +public class OrderDetailsViewRepoImpl implements OrderDetailsViewRepo { + @Override + public SelectBuilder select() { + return SelectBuilder.of("\"order_details\"", OrderDetailsViewFields.structure, OrderDetailsViewRow.rowCodec, Dialect.SQLITE); + } + + @Override + public List selectAll(ConnectionRead c) { + return concat(Fragment.of("select \"order_id\", \"order_date\", \"customer_name\", \"product_name\", \"quantity\", \"unit_price\", \"line_total\"\nfrom \"order_details\"\n")).query(OrderDetailsViewRow.rowCodec.all()).run(c); + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/order_details/OrderDetailsViewRow.java b/testers/sqlite/java/generated-and-checked-in/testdb/order_details/OrderDetailsViewRow.java new file mode 100644 index 0000000000..6932718d89 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/order_details/OrderDetailsViewRow.java @@ -0,0 +1,104 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.order_details; + +import com.fasterxml.jackson.annotation.JsonProperty; +import dev.typr.dsl.RowCodecs; +import dev.typr.foundations.RowCodec; +import dev.typr.foundations.SqliteTypes; +import dev.typr.foundations.Tuple.Tuple7; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.Optional; +import testdb.orders.OrdersId; + +/** View: order_details */ +public record OrderDetailsViewRow( + /** Points to {@link testdb.orders.OrdersRow#orderId()} */ + @JsonProperty("order_id") Optional orderId, + /** Points to {@link testdb.orders.OrdersRow#orderDate()} */ + @JsonProperty("order_date") Optional orderDate, + /** Points to {@link testdb.customers.CustomersRow#customerName()} */ + @JsonProperty("customer_name") Optional customerName, + /** Points to {@link testdb.products.ProductsRow#productName()} */ + @JsonProperty("product_name") Optional productName, + /** Points to {@link testdb.order_items.OrderItemsRow#quantity()} */ + Optional quantity, + /** Points to {@link testdb.order_items.OrderItemsRow#unitPrice()} */ + @JsonProperty("unit_price") Optional unitPrice, + @JsonProperty("line_total") Optional lineTotal +) implements Tuple7, Optional, Optional, Optional, Optional, Optional, Optional> { + /** Points to {@link testdb.orders.OrdersRow#orderId()} */ + public OrderDetailsViewRow withOrderId(Optional orderId) { + return new OrderDetailsViewRow(orderId, orderDate, customerName, productName, quantity, unitPrice, lineTotal); + } + + /** Points to {@link testdb.orders.OrdersRow#orderDate()} */ + public OrderDetailsViewRow withOrderDate(Optional orderDate) { + return new OrderDetailsViewRow(orderId, orderDate, customerName, productName, quantity, unitPrice, lineTotal); + } + + /** Points to {@link testdb.customers.CustomersRow#customerName()} */ + public OrderDetailsViewRow withCustomerName(Optional customerName) { + return new OrderDetailsViewRow(orderId, orderDate, customerName, productName, quantity, unitPrice, lineTotal); + } + + /** Points to {@link testdb.products.ProductsRow#productName()} */ + public OrderDetailsViewRow withProductName(Optional productName) { + return new OrderDetailsViewRow(orderId, orderDate, customerName, productName, quantity, unitPrice, lineTotal); + } + + /** Points to {@link testdb.order_items.OrderItemsRow#quantity()} */ + public OrderDetailsViewRow withQuantity(Optional quantity) { + return new OrderDetailsViewRow(orderId, orderDate, customerName, productName, quantity, unitPrice, lineTotal); + } + + /** Points to {@link testdb.order_items.OrderItemsRow#unitPrice()} */ + public OrderDetailsViewRow withUnitPrice(Optional unitPrice) { + return new OrderDetailsViewRow(orderId, orderDate, customerName, productName, quantity, unitPrice, lineTotal); + } + + public OrderDetailsViewRow withLineTotal(Optional lineTotal) { + return new OrderDetailsViewRow(orderId, orderDate, customerName, productName, quantity, unitPrice, lineTotal); + } + + public static RowCodec rowCodec = RowCodecs.of(OrdersId.sqliteType.opt(), SqliteTypes.date.opt(), SqliteTypes.text.opt(), SqliteTypes.text.opt(), SqliteTypes.integer.opt(), SqliteTypes.numeric.opt(), SqliteTypes.text.opt(), OrderDetailsViewRow::new, row -> new Object[]{row.orderId(), row.orderDate(), row.customerName(), row.productName(), row.quantity(), row.unitPrice(), row.lineTotal()}); + + @Override + public Optional _1() { + return orderId; + } + + @Override + public Optional _2() { + return orderDate; + } + + @Override + public Optional _3() { + return customerName; + } + + @Override + public Optional _4() { + return productName; + } + + @Override + public Optional _5() { + return quantity; + } + + @Override + public Optional _6() { + return unitPrice; + } + + @Override + public Optional _7() { + return lineTotal; + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/order_items/OrderItemsFields.java b/testers/sqlite/java/generated-and-checked-in/testdb/order_items/OrderItemsFields.java new file mode 100644 index 0000000000..5bdb3db10b --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/order_items/OrderItemsFields.java @@ -0,0 +1,110 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.order_items; + +import dev.typr.dsl.FieldsBase; +import dev.typr.dsl.ForeignKey; +import dev.typr.dsl.Path; +import dev.typr.dsl.RelationStructure; +import dev.typr.dsl.SqlExpr; +import dev.typr.dsl.SqlExpr.Field; +import dev.typr.dsl.SqlExpr.FieldLike; +import dev.typr.dsl.SqlExpr.IdField; +import dev.typr.dsl.TupleExpr; +import dev.typr.dsl.TupleExpr.TupleExpr4; +import dev.typr.foundations.RowCodec; +import dev.typr.foundations.SqliteTypes; +import java.math.BigDecimal; +import java.util.List; +import java.util.Optional; +import testdb.orders.OrdersFields; +import testdb.orders.OrdersId; +import testdb.orders.OrdersRow; +import testdb.products.ProductsFields; +import testdb.products.ProductsId; +import testdb.products.ProductsRow; + +public class OrderItemsFields extends TupleExpr4 implements RelationStructure, FieldsBase { + List _path; + + public OrderItemsFields(List _path) { + this._path = _path; + } + + public static OrderItemsFields structure = new OrderItemsFields(java.util.Collections.emptyList()); + + public IdField orderId() { + return new IdField(_path, "order_id", OrderItemsRow::orderId, Optional.empty(), Optional.empty(), (row, value) -> row.withOrderId(value), OrdersId.sqliteType); + } + + public IdField productId() { + return new IdField(_path, "product_id", OrderItemsRow::productId, Optional.empty(), Optional.empty(), (row, value) -> row.withProductId(value), ProductsId.sqliteType); + } + + public Field quantity() { + return new Field(_path, "quantity", OrderItemsRow::quantity, Optional.empty(), Optional.empty(), (row, value) -> row.withQuantity(value), SqliteTypes.integer); + } + + public Field unitPrice() { + return new Field(_path, "unit_price", OrderItemsRow::unitPrice, Optional.empty(), Optional.empty(), (row, value) -> row.withUnitPrice(value), SqliteTypes.numeric); + } + + @Override + public List _path() { + return _path; + } + + public ForeignKey fkProducts() { + return ForeignKey.of("order_items_fk_0").withColumnPair(productId(), ProductsFields::productId); + } + + public ForeignKey fkOrders() { + return ForeignKey.of("order_items_fk_1").withColumnPair(orderId(), OrdersFields::orderId); + } + + public SqlExpr compositeIdIs(OrderItemsId compositeId) { + return SqlExpr.all(orderId().isEqual(compositeId.orderId()), productId().isEqual(compositeId.productId())); + } + + public SqlExpr compositeIdIn(List compositeIds) { + return TupleExpr.of(orderId(), productId()).among(compositeIds); + } + + @Override + public List> columns() { + return java.util.List.of(this.orderId(), this.productId(), this.quantity(), this.unitPrice()); + } + + @Override + public RowCodec rowCodec() { + return OrderItemsRow.rowCodec; + } + + @Override + public RelationStructure withPaths(List _path) { + return new OrderItemsFields(_path); + } + + @Override + public SqlExpr _1() { + return orderId(); + } + + @Override + public SqlExpr _2() { + return productId(); + } + + @Override + public SqlExpr _3() { + return quantity(); + } + + @Override + public SqlExpr _4() { + return unitPrice(); + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/order_items/OrderItemsId.java b/testers/sqlite/java/generated-and-checked-in/testdb/order_items/OrderItemsId.java new file mode 100644 index 0000000000..913c0cbbdc --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/order_items/OrderItemsId.java @@ -0,0 +1,39 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.order_items; + +import com.fasterxml.jackson.annotation.JsonProperty; +import dev.typr.dsl.RowCodecs; +import dev.typr.foundations.RowCodec; +import dev.typr.foundations.Tuple.Tuple2; +import testdb.orders.OrdersId; +import testdb.products.ProductsId; + +/** Type for the composite primary key of table `order_items` */ +public record OrderItemsId( + @JsonProperty("order_id") OrdersId orderId, + @JsonProperty("product_id") ProductsId productId +) implements Tuple2 { + public OrderItemsId withOrderId(OrdersId orderId) { + return new OrderItemsId(orderId, productId); + } + + public OrderItemsId withProductId(ProductsId productId) { + return new OrderItemsId(orderId, productId); + } + + public static RowCodec rowCodec = RowCodecs.of(OrdersId.sqliteType, ProductsId.sqliteType, OrderItemsId::new, row -> new Object[]{row.orderId(), row.productId()}); + + @Override + public OrdersId _1() { + return orderId; + } + + @Override + public ProductsId _2() { + return productId; + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/order_items/OrderItemsRepo.java b/testers/sqlite/java/generated-and-checked-in/testdb/order_items/OrderItemsRepo.java new file mode 100644 index 0000000000..489c4678d0 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/order_items/OrderItemsRepo.java @@ -0,0 +1,76 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.order_items; + +import dev.typr.dsl.DeleteBuilder; +import dev.typr.dsl.SelectBuilder; +import dev.typr.dsl.UpdateBuilder; +import dev.typr.foundations.Connection; +import dev.typr.foundations.ConnectionRead; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +public interface OrderItemsRepo { + DeleteBuilder delete(); + + Boolean deleteById( + OrderItemsId compositeId, + Connection c + ); + + Integer deleteByIds( + List compositeIds, + Connection c + ); + + OrderItemsRow insert( + OrderItemsRow unsaved, + Connection c + ); + + OrderItemsRow insert( + OrderItemsRowUnsaved unsaved, + Connection c + ); + + SelectBuilder select(); + + List selectAll(ConnectionRead c); + + Optional selectById( + OrderItemsId compositeId, + ConnectionRead c + ); + + List selectByIds( + List compositeIds, + ConnectionRead c + ); + + Map selectByIdsTracked( + List compositeIds, + ConnectionRead c + ); + + UpdateBuilder update(); + + Boolean update( + OrderItemsRow row, + Connection c + ); + + OrderItemsRow upsert( + OrderItemsRow unsaved, + Connection c + ); + + List upsertBatch( + Iterator unsaved, + Connection c + ); +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/order_items/OrderItemsRepoImpl.java b/testers/sqlite/java/generated-and-checked-in/testdb/order_items/OrderItemsRepoImpl.java new file mode 100644 index 0000000000..5e14b06f45 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/order_items/OrderItemsRepoImpl.java @@ -0,0 +1,156 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.order_items; + +import dev.typr.dsl.DeleteBuilder; +import dev.typr.dsl.Dialect; +import dev.typr.dsl.SelectBuilder; +import dev.typr.dsl.UpdateBuilder; +import dev.typr.foundations.Connection; +import dev.typr.foundations.ConnectionRead; +import dev.typr.foundations.Fragment; +import dev.typr.foundations.SqliteTypes; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import testdb.orders.OrdersId; +import testdb.products.ProductsId; +import static dev.typr.foundations.Fragment.concat; + +public class OrderItemsRepoImpl implements OrderItemsRepo { + @Override + public DeleteBuilder delete() { + return DeleteBuilder.of("\"order_items\"", OrderItemsFields.structure, Dialect.SQLITE); + } + + @Override + public Boolean deleteById( + OrderItemsId compositeId, + Connection c + ) { + return concat(Fragment.of("delete from \"order_items\" where \"order_id\" = "), Fragment.encode(OrdersId.sqliteType, compositeId.orderId()), Fragment.of(" AND \"product_id\" = "), Fragment.encode(ProductsId.sqliteType, compositeId.productId()), Fragment.of("")).update().run(c) > 0; + } + + @Override + public Integer deleteByIds( + List compositeIds, + Connection c + ) { + ArrayList fragments = new ArrayList<>(); + for (var id : compositeIds) { fragments.add(Fragment.concat(Fragment.of("("), Fragment.encode(OrdersId.sqliteType, id.orderId()), Fragment.of(", "), Fragment.encode(ProductsId.sqliteType, id.productId()), Fragment.of(")"))); }; + return Fragment.concat(Fragment.of("delete from \"order_items\" where (\"order_id\", \"product_id\") in ("), Fragment.comma(fragments), Fragment.of(")")).update().run(c); + } + + @Override + public OrderItemsRow insert( + OrderItemsRow unsaved, + Connection c + ) { + return concat(Fragment.of("insert into \"order_items\"(\"order_id\", \"product_id\", \"quantity\", \"unit_price\")\nvalues ("), Fragment.encode(OrdersId.sqliteType, unsaved.orderId()), Fragment.of(", "), Fragment.encode(ProductsId.sqliteType, unsaved.productId()), Fragment.of(", "), Fragment.encode(SqliteTypes.integer, unsaved.quantity()), Fragment.of(", "), Fragment.encode(SqliteTypes.numeric, unsaved.unitPrice()), Fragment.of(")\nRETURNING \"order_id\", \"product_id\", \"quantity\", \"unit_price\"\n")) + .updateReturning(OrderItemsRow.rowCodec.exactlyOne()).run(c); + } + + @Override + public OrderItemsRow insert( + OrderItemsRowUnsaved unsaved, + Connection c + ) { + ArrayList columns = new ArrayList<>();; + ArrayList values = new ArrayList<>();; + columns.add(Fragment.of("\"order_id\"")); + values.add(concat(Fragment.encode(OrdersId.sqliteType, unsaved.orderId()), Fragment.of(""))); + columns.add(Fragment.of("\"product_id\"")); + values.add(concat(Fragment.encode(ProductsId.sqliteType, unsaved.productId()), Fragment.of(""))); + columns.add(Fragment.of("\"unit_price\"")); + values.add(concat(Fragment.encode(SqliteTypes.numeric, unsaved.unitPrice()), Fragment.of(""))); + unsaved.quantity().visit( + () -> { + + }, + value -> { + columns.add(Fragment.of("\"quantity\"")); + values.add(concat(Fragment.encode(SqliteTypes.integer, value), Fragment.of(""))); + } + );; + Fragment q = concat(Fragment.of("insert into \"order_items\"("), Fragment.comma(columns), Fragment.of(")\nvalues ("), Fragment.comma(values), Fragment.of(")\nRETURNING \"order_id\", \"product_id\", \"quantity\", \"unit_price\"\n"));; + return q.updateReturning(OrderItemsRow.rowCodec.exactlyOne()).run(c); + } + + @Override + public SelectBuilder select() { + return SelectBuilder.of("\"order_items\"", OrderItemsFields.structure, OrderItemsRow.rowCodec, Dialect.SQLITE); + } + + @Override + public List selectAll(ConnectionRead c) { + return concat(Fragment.of("select \"order_id\", \"product_id\", \"quantity\", \"unit_price\"\nfrom \"order_items\"\n")).query(OrderItemsRow.rowCodec.all()).run(c); + } + + @Override + public Optional selectById( + OrderItemsId compositeId, + ConnectionRead c + ) { + return concat(Fragment.of("select \"order_id\", \"product_id\", \"quantity\", \"unit_price\"\nfrom \"order_items\"\nwhere \"order_id\" = "), Fragment.encode(OrdersId.sqliteType, compositeId.orderId()), Fragment.of(" AND \"product_id\" = "), Fragment.encode(ProductsId.sqliteType, compositeId.productId()), Fragment.of("")).query(OrderItemsRow.rowCodec.first()).run(c); + } + + @Override + public List selectByIds( + List compositeIds, + ConnectionRead c + ) { + ArrayList fragments = new ArrayList<>(); + for (var id : compositeIds) { fragments.add(Fragment.concat(Fragment.of("("), Fragment.encode(OrdersId.sqliteType, id.orderId()), Fragment.of(", "), Fragment.encode(ProductsId.sqliteType, id.productId()), Fragment.of(")"))); }; + return Fragment.concat(Fragment.of("select \"order_id\", \"product_id\", \"quantity\", \"unit_price\" from \"order_items\" where (\"order_id\", \"product_id\") in ("), Fragment.comma(fragments), Fragment.of(")")).query(OrderItemsRow.rowCodec.all()).run(c); + } + + @Override + public Map selectByIdsTracked( + List compositeIds, + ConnectionRead c + ) { + HashMap ret = new HashMap(); + selectByIds(compositeIds, c).forEach(row -> ret.put(row.compositeId(), row)); + return ret; + } + + @Override + public UpdateBuilder update() { + return UpdateBuilder.of("\"order_items\"", OrderItemsFields.structure, OrderItemsRow.rowCodec, Dialect.SQLITE); + } + + @Override + public Boolean update( + OrderItemsRow row, + Connection c + ) { + OrderItemsId compositeId = row.compositeId();; + return concat(Fragment.of("update \"order_items\"\nset \"quantity\" = "), Fragment.encode(SqliteTypes.integer, row.quantity()), Fragment.of(",\n\"unit_price\" = "), Fragment.encode(SqliteTypes.numeric, row.unitPrice()), Fragment.of("\nwhere \"order_id\" = "), Fragment.encode(OrdersId.sqliteType, compositeId.orderId()), Fragment.of(" AND \"product_id\" = "), Fragment.encode(ProductsId.sqliteType, compositeId.productId()), Fragment.of("")).update().run(c) > 0; + } + + @Override + public OrderItemsRow upsert( + OrderItemsRow unsaved, + Connection c + ) { + return concat(Fragment.of("INSERT INTO \"order_items\"(\"order_id\", \"product_id\", \"quantity\", \"unit_price\")\nVALUES ("), Fragment.encode(OrdersId.sqliteType, unsaved.orderId()), Fragment.of(", "), Fragment.encode(ProductsId.sqliteType, unsaved.productId()), Fragment.of(", "), Fragment.encode(SqliteTypes.integer, unsaved.quantity()), Fragment.of(", "), Fragment.encode(SqliteTypes.numeric, unsaved.unitPrice()), Fragment.of(")\nON CONFLICT (\"order_id\", \"product_id\")\nDO UPDATE SET\n \"quantity\" = EXCLUDED.\"quantity\",\n\"unit_price\" = EXCLUDED.\"unit_price\"\nRETURNING \"order_id\", \"product_id\", \"quantity\", \"unit_price\"")) + .updateReturning(OrderItemsRow.rowCodec.exactlyOne()) + .run(c); + } + + @Override + public List upsertBatch( + Iterator unsaved, + Connection c + ) { + return concat(Fragment.of("INSERT INTO \"order_items\"(\"order_id\", \"product_id\", \"quantity\", \"unit_price\")\nVALUES (?, ?, ?, ?)\nON CONFLICT (\"order_id\", \"product_id\")\nDO UPDATE SET\n \"quantity\" = EXCLUDED.\"quantity\",\n\"unit_price\" = EXCLUDED.\"unit_price\"\nRETURNING \"order_id\", \"product_id\", \"quantity\", \"unit_price\"")) + .updateReturningEach(OrderItemsRow.rowCodec, unsaved) + .run(c); + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/order_items/OrderItemsRepoMock.java b/testers/sqlite/java/generated-and-checked-in/testdb/order_items/OrderItemsRepoMock.java new file mode 100644 index 0000000000..c8cdeaf179 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/order_items/OrderItemsRepoMock.java @@ -0,0 +1,172 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.order_items; + +import dev.typr.dsl.DeleteBuilder; +import dev.typr.dsl.DeleteBuilderMock; +import dev.typr.dsl.DeleteParams; +import dev.typr.dsl.SelectBuilder; +import dev.typr.dsl.SelectBuilderMock; +import dev.typr.dsl.SelectParams; +import dev.typr.dsl.UpdateBuilder; +import dev.typr.dsl.UpdateBuilderMock; +import dev.typr.dsl.UpdateParams; +import dev.typr.foundations.Connection; +import dev.typr.foundations.ConnectionRead; +import java.lang.RuntimeException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.function.Function; +import java.util.stream.Collectors; + +public record OrderItemsRepoMock( + java.util.function.Function toRow, + HashMap map +) implements OrderItemsRepo { + public OrderItemsRepoMock(java.util.function.Function toRow) { + this(toRow, new HashMap()); + } + + public OrderItemsRepoMock withToRow(java.util.function.Function toRow) { + return new OrderItemsRepoMock(toRow, map); + } + + public OrderItemsRepoMock withMap(HashMap map) { + return new OrderItemsRepoMock(toRow, map); + } + + @Override + public DeleteBuilder delete() { + return new DeleteBuilderMock<>(OrderItemsFields.structure, () -> new ArrayList<>(map.values()), DeleteParams.empty(), row -> row.compositeId(), id -> map.remove(id)); + } + + @Override + public Boolean deleteById( + OrderItemsId compositeId, + Connection c + ) { + return Optional.ofNullable(map.remove(compositeId)).isPresent(); + } + + @Override + public Integer deleteByIds( + List compositeIds, + Connection c + ) { + var count = 0; + for (var id : compositeIds) { + if (Optional.ofNullable(map.remove(id)).isPresent()) { + count = count + 1;; + } + }; + return count; + } + + @Override + public OrderItemsRow insert( + OrderItemsRow unsaved, + Connection c + ) { + if (map.containsKey(unsaved.compositeId())) { + throw new RuntimeException("id " + unsaved.compositeId() + " already exists"); + } + map.put(unsaved.compositeId(), unsaved); + return unsaved; + } + + @Override + public OrderItemsRow insert( + OrderItemsRowUnsaved unsaved, + Connection c + ) { + return insert(toRow.apply(unsaved), c); + } + + @Override + public SelectBuilder select() { + return new SelectBuilderMock<>(OrderItemsFields.structure, () -> new ArrayList<>(map.values()), SelectParams.empty()); + } + + @Override + public List selectAll(ConnectionRead c) { + return new ArrayList<>(map.values()); + } + + @Override + public Optional selectById( + OrderItemsId compositeId, + ConnectionRead c + ) { + return Optional.ofNullable(map.get(compositeId)); + } + + @Override + public List selectByIds( + List compositeIds, + ConnectionRead c + ) { + var result = new ArrayList(); + for (var id : compositeIds) { + var opt = Optional.ofNullable(map.get(id)); + if (opt.isPresent()) { + result.add(opt.get()); + } + }; + return result; + } + + @Override + public Map selectByIdsTracked( + List compositeIds, + ConnectionRead c + ) { + return selectByIds(compositeIds, c).stream().collect(Collectors.toMap((OrderItemsRow row) -> row.compositeId(), Function.identity())); + } + + @Override + public UpdateBuilder update() { + return new UpdateBuilderMock<>(OrderItemsFields.structure, () -> new ArrayList<>(map.values()), UpdateParams.empty(), row -> row); + } + + @Override + public Boolean update( + OrderItemsRow row, + Connection c + ) { + var shouldUpdate = Optional.ofNullable(map.get(row.compositeId())).filter(oldRow -> !oldRow.equals(row)).isPresent(); + if (shouldUpdate) { + map.put(row.compositeId(), row);; + } + return shouldUpdate; + } + + @Override + public OrderItemsRow upsert( + OrderItemsRow unsaved, + Connection c + ) { + map.put(unsaved.compositeId(), unsaved); + return unsaved; + } + + @Override + public List upsertBatch( + Iterator unsaved, + Connection c + ) { + var result = new ArrayList(); + while (unsaved.hasNext()) { + var row = unsaved.next(); + map.put(row.compositeId(), row); + result.add(row); + }; + return result; + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/order_items/OrderItemsRow.java b/testers/sqlite/java/generated-and-checked-in/testdb/order_items/OrderItemsRow.java new file mode 100644 index 0000000000..020065f322 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/order_items/OrderItemsRow.java @@ -0,0 +1,90 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.order_items; + +import com.fasterxml.jackson.annotation.JsonProperty; +import dev.typr.dsl.RowCodecs; +import dev.typr.foundations.RowCodec; +import dev.typr.foundations.SqliteTypes; +import dev.typr.foundations.Tuple.Tuple4; +import java.math.BigDecimal; +import testdb.customtypes.Defaulted; +import testdb.orders.OrdersId; +import testdb.products.ProductsId; + +/** Table: order_items + * Composite primary key: order_id, product_id + */ +public record OrderItemsRow( + /** Points to {@link testdb.orders.OrdersRow#orderId()} */ + @JsonProperty("order_id") OrdersId orderId, + /** Points to {@link testdb.products.ProductsRow#productId()} */ + @JsonProperty("product_id") ProductsId productId, + /** Default: 1 */ + Long quantity, + @JsonProperty("unit_price") BigDecimal unitPrice +) implements Tuple4 { + /** Points to {@link testdb.orders.OrdersRow#orderId()} */ + public OrderItemsRow withOrderId(OrdersId orderId) { + return new OrderItemsRow(orderId, productId, quantity, unitPrice); + } + + /** Points to {@link testdb.products.ProductsRow#productId()} */ + public OrderItemsRow withProductId(ProductsId productId) { + return new OrderItemsRow(orderId, productId, quantity, unitPrice); + } + + /** Default: 1 */ + public OrderItemsRow withQuantity(Long quantity) { + return new OrderItemsRow(orderId, productId, quantity, unitPrice); + } + + public OrderItemsRow withUnitPrice(BigDecimal unitPrice) { + return new OrderItemsRow(orderId, productId, quantity, unitPrice); + } + + public static RowCodec rowCodec = RowCodecs.of(OrdersId.sqliteType, ProductsId.sqliteType, SqliteTypes.integer, SqliteTypes.numeric, OrderItemsRow::new, row -> new Object[]{row.orderId(), row.productId(), row.quantity(), row.unitPrice()}); + + static public OrderItemsRow apply( + OrderItemsId compositeId, + Long quantity, + BigDecimal unitPrice + ) { + return new OrderItemsRow(compositeId.orderId(), compositeId.productId(), quantity, unitPrice); + } + + @Override + public OrdersId _1() { + return orderId; + } + + @Override + public ProductsId _2() { + return productId; + } + + @Override + public Long _3() { + return quantity; + } + + @Override + public BigDecimal _4() { + return unitPrice; + } + + public OrderItemsId compositeId() { + return new OrderItemsId(orderId, productId); + } + + public OrderItemsId id() { + return this.compositeId(); + } + + public OrderItemsRowUnsaved toUnsavedRow(Defaulted quantity) { + return new OrderItemsRowUnsaved(orderId, productId, unitPrice, quantity); + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/order_items/OrderItemsRowUnsaved.java b/testers/sqlite/java/generated-and-checked-in/testdb/order_items/OrderItemsRowUnsaved.java new file mode 100644 index 0000000000..37338b9942 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/order_items/OrderItemsRowUnsaved.java @@ -0,0 +1,57 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.order_items; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.math.BigDecimal; +import testdb.customtypes.Defaulted; +import testdb.customtypes.Defaulted.UseDefault; +import testdb.orders.OrdersId; +import testdb.products.ProductsId; + +/** This class corresponds to a row in table `order_items` which has not been persisted yet */ +public record OrderItemsRowUnsaved( + /** Points to {@link testdb.orders.OrdersRow#orderId()} */ + @JsonProperty("order_id") OrdersId orderId, + /** Points to {@link testdb.products.ProductsRow#productId()} */ + @JsonProperty("product_id") ProductsId productId, + @JsonProperty("unit_price") BigDecimal unitPrice, + /** Default: 1 */ + Defaulted quantity +) { + public OrderItemsRowUnsaved( + /** Points to {@link testdb.orders.OrdersRow#orderId()} */ + @JsonProperty("order_id") OrdersId orderId, + /** Points to {@link testdb.products.ProductsRow#productId()} */ + @JsonProperty("product_id") ProductsId productId, + @JsonProperty("unit_price") BigDecimal unitPrice + ) { + this(orderId, productId, unitPrice, new UseDefault<>()); + } + + /** Points to {@link testdb.orders.OrdersRow#orderId()} */ + public OrderItemsRowUnsaved withOrderId(OrdersId orderId) { + return new OrderItemsRowUnsaved(orderId, productId, unitPrice, quantity); + } + + /** Points to {@link testdb.products.ProductsRow#productId()} */ + public OrderItemsRowUnsaved withProductId(ProductsId productId) { + return new OrderItemsRowUnsaved(orderId, productId, unitPrice, quantity); + } + + public OrderItemsRowUnsaved withUnitPrice(BigDecimal unitPrice) { + return new OrderItemsRowUnsaved(orderId, productId, unitPrice, quantity); + } + + /** Default: 1 */ + public OrderItemsRowUnsaved withQuantity(Defaulted quantity) { + return new OrderItemsRowUnsaved(orderId, productId, unitPrice, quantity); + } + + public OrderItemsRow toRow(java.util.function.Supplier quantityDefault) { + return new OrderItemsRow(orderId, productId, quantity.getOrElse(quantityDefault), unitPrice); + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/order_summary_by_customer/OrderSummaryByCustomerSqlRepo.java b/testers/sqlite/java/generated-and-checked-in/testdb/order_summary_by_customer/OrderSummaryByCustomerSqlRepo.java new file mode 100644 index 0000000000..31d3454863 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/order_summary_by_customer/OrderSummaryByCustomerSqlRepo.java @@ -0,0 +1,18 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.order_summary_by_customer; + +import dev.typr.foundations.ConnectionRead; +import java.time.LocalDate; +import java.util.List; + +public interface OrderSummaryByCustomerSqlRepo { + List apply( + LocalDate fromDate, + LocalDate toDate, + ConnectionRead c + ); +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/order_summary_by_customer/OrderSummaryByCustomerSqlRepoImpl.java b/testers/sqlite/java/generated-and-checked-in/testdb/order_summary_by_customer/OrderSummaryByCustomerSqlRepoImpl.java new file mode 100644 index 0000000000..875223470a --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/order_summary_by_customer/OrderSummaryByCustomerSqlRepoImpl.java @@ -0,0 +1,24 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.order_summary_by_customer; + +import dev.typr.foundations.ConnectionRead; +import dev.typr.foundations.Fragment; +import dev.typr.foundations.SqliteTypes; +import java.time.LocalDate; +import java.util.List; +import static dev.typr.foundations.Fragment.concat; + +public class OrderSummaryByCustomerSqlRepoImpl implements OrderSummaryByCustomerSqlRepo { + @Override + public List apply( + LocalDate fromDate, + LocalDate toDate, + ConnectionRead c + ) { + return concat(Fragment.of("-- Summary stats per customer over an order date range.\n-- Tests: GROUP BY, aggregates with NULL-aware results, JOIN, date params.\n\nSELECT\n c.customer_id,\n c.name AS customer_name,\n COUNT(o.order_id) AS order_count,\n COALESCE(SUM(o.total_amount), 0) AS total_revenue,\n MAX(o.order_date) AS last_order_date\nFROM customers c\nLEFT JOIN orders o ON c.customer_id = o.customer_id\nWHERE o.order_date IS NULL\n OR (o.order_date >= "), Fragment.encode(SqliteTypes.date, fromDate), Fragment.of(" AND o.order_date <= "), Fragment.encode(SqliteTypes.date, toDate), Fragment.of(")\nGROUP BY c.customer_id, c.name\nORDER BY total_revenue DESC, c.customer_id")).query(OrderSummaryByCustomerSqlRow.rowCodec.all()).run(c); + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/order_summary_by_customer/OrderSummaryByCustomerSqlRow.java b/testers/sqlite/java/generated-and-checked-in/testdb/order_summary_by_customer/OrderSummaryByCustomerSqlRow.java new file mode 100644 index 0000000000..d968353f26 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/order_summary_by_customer/OrderSummaryByCustomerSqlRow.java @@ -0,0 +1,82 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.order_summary_by_customer; + +import com.fasterxml.jackson.annotation.JsonProperty; +import dev.typr.dsl.RowCodecs; +import dev.typr.foundations.RowCodec; +import dev.typr.foundations.SqliteTypes; +import dev.typr.foundations.Tuple.Tuple5; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.Optional; +import testdb.customers.CustomersId; + +/** SQL file: order_summary_by_customer.sql */ +public record OrderSummaryByCustomerSqlRow( + /** Points to {@link testdb.customers.CustomersRow#customerId()} */ + @JsonProperty("customer_id") CustomersId customerId, + /** Points to {@link testdb.customers.CustomersRow#name()} */ + @JsonProperty("customer_name") String customerName, + /** Points to {@link testdb.orders.OrdersRow#orderId()} */ + @JsonProperty("order_count") Optional orderCount, + /** Points to {@link testdb.orders.OrdersRow#totalAmount()} */ + @JsonProperty("total_revenue") Optional totalRevenue, + /** Points to {@link testdb.orders.OrdersRow#orderDate()} */ + @JsonProperty("last_order_date") Optional lastOrderDate +) implements Tuple5, Optional, Optional> { + /** Points to {@link testdb.customers.CustomersRow#customerId()} */ + public OrderSummaryByCustomerSqlRow withCustomerId(CustomersId customerId) { + return new OrderSummaryByCustomerSqlRow(customerId, customerName, orderCount, totalRevenue, lastOrderDate); + } + + /** Points to {@link testdb.customers.CustomersRow#name()} */ + public OrderSummaryByCustomerSqlRow withCustomerName(String customerName) { + return new OrderSummaryByCustomerSqlRow(customerId, customerName, orderCount, totalRevenue, lastOrderDate); + } + + /** Points to {@link testdb.orders.OrdersRow#orderId()} */ + public OrderSummaryByCustomerSqlRow withOrderCount(Optional orderCount) { + return new OrderSummaryByCustomerSqlRow(customerId, customerName, orderCount, totalRevenue, lastOrderDate); + } + + /** Points to {@link testdb.orders.OrdersRow#totalAmount()} */ + public OrderSummaryByCustomerSqlRow withTotalRevenue(Optional totalRevenue) { + return new OrderSummaryByCustomerSqlRow(customerId, customerName, orderCount, totalRevenue, lastOrderDate); + } + + /** Points to {@link testdb.orders.OrdersRow#orderDate()} */ + public OrderSummaryByCustomerSqlRow withLastOrderDate(Optional lastOrderDate) { + return new OrderSummaryByCustomerSqlRow(customerId, customerName, orderCount, totalRevenue, lastOrderDate); + } + + public static RowCodec rowCodec = RowCodecs.of(CustomersId.sqliteType, SqliteTypes.text, SqliteTypes.bigint.opt(), SqliteTypes.numeric.opt(), SqliteTypes.date.opt(), OrderSummaryByCustomerSqlRow::new, row -> new Object[]{row.customerId(), row.customerName(), row.orderCount(), row.totalRevenue(), row.lastOrderDate()}); + + @Override + public CustomersId _1() { + return customerId; + } + + @Override + public String _2() { + return customerName; + } + + @Override + public Optional _3() { + return orderCount; + } + + @Override + public Optional _4() { + return totalRevenue; + } + + @Override + public Optional _5() { + return lastOrderDate; + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/orders/OrdersFields.java b/testers/sqlite/java/generated-and-checked-in/testdb/orders/OrdersFields.java new file mode 100644 index 0000000000..659be0b434 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/orders/OrdersFields.java @@ -0,0 +1,105 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.orders; + +import dev.typr.dsl.FieldsBase; +import dev.typr.dsl.ForeignKey; +import dev.typr.dsl.Path; +import dev.typr.dsl.RelationStructure; +import dev.typr.dsl.SqlExpr; +import dev.typr.dsl.SqlExpr.Field; +import dev.typr.dsl.SqlExpr.FieldLike; +import dev.typr.dsl.SqlExpr.IdField; +import dev.typr.dsl.SqlExpr.OptField; +import dev.typr.dsl.TupleExpr.TupleExpr5; +import dev.typr.foundations.RowCodec; +import dev.typr.foundations.SqliteTypes; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.List; +import java.util.Optional; +import testdb.customers.CustomersFields; +import testdb.customers.CustomersId; +import testdb.customers.CustomersRow; + +public class OrdersFields extends TupleExpr5 implements RelationStructure, FieldsBase { + List _path; + + public OrdersFields(List _path) { + this._path = _path; + } + + public static OrdersFields structure = new OrdersFields(java.util.Collections.emptyList()); + + public IdField orderId() { + return new IdField(_path, "order_id", OrdersRow::orderId, Optional.empty(), Optional.empty(), (row, value) -> row.withOrderId(value), OrdersId.sqliteType); + } + + public Field customerId() { + return new Field(_path, "customer_id", OrdersRow::customerId, Optional.empty(), Optional.empty(), (row, value) -> row.withCustomerId(value), CustomersId.sqliteType); + } + + public Field orderDate() { + return new Field(_path, "order_date", OrdersRow::orderDate, Optional.empty(), Optional.empty(), (row, value) -> row.withOrderDate(value), SqliteTypes.date); + } + + public OptField totalAmount() { + return new OptField(_path, "total_amount", OrdersRow::totalAmount, Optional.empty(), Optional.empty(), (row, value) -> row.withTotalAmount(value), SqliteTypes.numeric); + } + + public Field status() { + return new Field(_path, "status", OrdersRow::status, Optional.empty(), Optional.empty(), (row, value) -> row.withStatus(value), SqliteTypes.text); + } + + @Override + public List _path() { + return _path; + } + + public ForeignKey fkCustomers() { + return ForeignKey.of("orders_fk_0").withColumnPair(customerId(), CustomersFields::customerId); + } + + @Override + public List> columns() { + return java.util.List.of(this.orderId(), this.customerId(), this.orderDate(), this.totalAmount(), this.status()); + } + + @Override + public RowCodec rowCodec() { + return OrdersRow.rowCodec; + } + + @Override + public RelationStructure withPaths(List _path) { + return new OrdersFields(_path); + } + + @Override + public SqlExpr _1() { + return orderId(); + } + + @Override + public SqlExpr _2() { + return customerId(); + } + + @Override + public SqlExpr _3() { + return orderDate(); + } + + @Override + public SqlExpr _4() { + return totalAmount(); + } + + @Override + public SqlExpr _5() { + return status(); + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/orders/OrdersId.java b/testers/sqlite/java/generated-and-checked-in/testdb/orders/OrdersId.java new file mode 100644 index 0000000000..4b8886a755 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/orders/OrdersId.java @@ -0,0 +1,29 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.orders; + +import com.fasterxml.jackson.annotation.JsonValue; +import dev.typr.foundations.Bijection; +import dev.typr.foundations.SqliteType; +import dev.typr.foundations.SqliteTypes; + +/** Type for the primary key of table `orders` */ +public record OrdersId(@JsonValue Long value) { + public OrdersId withValue(Long value) { + return new OrdersId(value); + } + + @Override + public java.lang.String toString() { + return value.toString(); + } + + static public Bijection bijection = + Bijection.of(OrdersId::value, OrdersId::new); + + static public SqliteType sqliteType = + SqliteTypes.integer.to(Bijection.of(OrdersId::new, OrdersId::value)); +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/orders/OrdersRepo.java b/testers/sqlite/java/generated-and-checked-in/testdb/orders/OrdersRepo.java new file mode 100644 index 0000000000..dfe958636f --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/orders/OrdersRepo.java @@ -0,0 +1,76 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.orders; + +import dev.typr.dsl.DeleteBuilder; +import dev.typr.dsl.SelectBuilder; +import dev.typr.dsl.UpdateBuilder; +import dev.typr.foundations.Connection; +import dev.typr.foundations.ConnectionRead; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +public interface OrdersRepo { + DeleteBuilder delete(); + + Boolean deleteById( + OrdersId orderId, + Connection c + ); + + Integer deleteByIds( + List orderIds, + Connection c + ); + + OrdersRow insert( + OrdersRow unsaved, + Connection c + ); + + OrdersRow insert( + OrdersRowUnsaved unsaved, + Connection c + ); + + SelectBuilder select(); + + List selectAll(ConnectionRead c); + + Optional selectById( + OrdersId orderId, + ConnectionRead c + ); + + List selectByIds( + List orderIds, + ConnectionRead c + ); + + Map selectByIdsTracked( + List orderIds, + ConnectionRead c + ); + + UpdateBuilder update(); + + Boolean update( + OrdersRow row, + Connection c + ); + + OrdersRow upsert( + OrdersRow unsaved, + Connection c + ); + + List upsertBatch( + Iterator unsaved, + Connection c + ); +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/orders/OrdersRepoImpl.java b/testers/sqlite/java/generated-and-checked-in/testdb/orders/OrdersRepoImpl.java new file mode 100644 index 0000000000..cd48f4532b --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/orders/OrdersRepoImpl.java @@ -0,0 +1,157 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.orders; + +import dev.typr.dsl.DeleteBuilder; +import dev.typr.dsl.Dialect; +import dev.typr.dsl.SelectBuilder; +import dev.typr.dsl.UpdateBuilder; +import dev.typr.foundations.Connection; +import dev.typr.foundations.ConnectionRead; +import dev.typr.foundations.Fragment; +import dev.typr.foundations.SqliteTypes; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import testdb.customers.CustomersId; +import static dev.typr.foundations.Fragment.concat; + +public class OrdersRepoImpl implements OrdersRepo { + @Override + public DeleteBuilder delete() { + return DeleteBuilder.of("\"orders\"", OrdersFields.structure, Dialect.SQLITE); + } + + @Override + public Boolean deleteById( + OrdersId orderId, + Connection c + ) { + return concat(Fragment.of("delete from \"orders\" where \"order_id\" = "), Fragment.encode(OrdersId.sqliteType, orderId), Fragment.of("")).update().run(c) > 0; + } + + @Override + public Integer deleteByIds( + List orderIds, + Connection c + ) { + ArrayList fragments = new ArrayList<>(); + for (var id : orderIds) { fragments.add(Fragment.encode(OrdersId.sqliteType, id)); }; + return Fragment.concat(Fragment.of("delete from \"orders\" where \"order_id\" in ("), Fragment.comma(fragments), Fragment.of(")")).update().run(c); + } + + @Override + public OrdersRow insert( + OrdersRow unsaved, + Connection c + ) { + return concat(Fragment.of("insert into \"orders\"(\"order_id\", \"customer_id\", \"order_date\", \"total_amount\", \"status\")\nvalues ("), Fragment.encode(OrdersId.sqliteType, unsaved.orderId()), Fragment.of(", "), Fragment.encode(CustomersId.sqliteType, unsaved.customerId()), Fragment.of(", "), Fragment.encode(SqliteTypes.date, unsaved.orderDate()), Fragment.of(", "), Fragment.encode(SqliteTypes.numeric.opt(), unsaved.totalAmount()), Fragment.of(", "), Fragment.encode(SqliteTypes.text, unsaved.status()), Fragment.of(")\nRETURNING \"order_id\", \"customer_id\", \"order_date\", \"total_amount\", \"status\"\n")) + .updateReturning(OrdersRow.rowCodec.exactlyOne()).run(c); + } + + @Override + public OrdersRow insert( + OrdersRowUnsaved unsaved, + Connection c + ) { + ArrayList columns = new ArrayList<>();; + ArrayList values = new ArrayList<>();; + columns.add(Fragment.of("\"order_id\"")); + values.add(concat(Fragment.encode(OrdersId.sqliteType, unsaved.orderId()), Fragment.of(""))); + columns.add(Fragment.of("\"customer_id\"")); + values.add(concat(Fragment.encode(CustomersId.sqliteType, unsaved.customerId()), Fragment.of(""))); + columns.add(Fragment.of("\"order_date\"")); + values.add(concat(Fragment.encode(SqliteTypes.date, unsaved.orderDate()), Fragment.of(""))); + columns.add(Fragment.of("\"total_amount\"")); + values.add(concat(Fragment.encode(SqliteTypes.numeric.opt(), unsaved.totalAmount()), Fragment.of(""))); + unsaved.status().visit( + () -> { + + }, + value -> { + columns.add(Fragment.of("\"status\"")); + values.add(concat(Fragment.encode(SqliteTypes.text, value), Fragment.of(""))); + } + );; + Fragment q = concat(Fragment.of("insert into \"orders\"("), Fragment.comma(columns), Fragment.of(")\nvalues ("), Fragment.comma(values), Fragment.of(")\nRETURNING \"order_id\", \"customer_id\", \"order_date\", \"total_amount\", \"status\"\n"));; + return q.updateReturning(OrdersRow.rowCodec.exactlyOne()).run(c); + } + + @Override + public SelectBuilder select() { + return SelectBuilder.of("\"orders\"", OrdersFields.structure, OrdersRow.rowCodec, Dialect.SQLITE); + } + + @Override + public List selectAll(ConnectionRead c) { + return concat(Fragment.of("select \"order_id\", \"customer_id\", \"order_date\", \"total_amount\", \"status\"\nfrom \"orders\"\n")).query(OrdersRow.rowCodec.all()).run(c); + } + + @Override + public Optional selectById( + OrdersId orderId, + ConnectionRead c + ) { + return concat(Fragment.of("select \"order_id\", \"customer_id\", \"order_date\", \"total_amount\", \"status\"\nfrom \"orders\"\nwhere \"order_id\" = "), Fragment.encode(OrdersId.sqliteType, orderId), Fragment.of("")).query(OrdersRow.rowCodec.first()).run(c); + } + + @Override + public List selectByIds( + List orderIds, + ConnectionRead c + ) { + ArrayList fragments = new ArrayList<>(); + for (var id : orderIds) { fragments.add(Fragment.encode(OrdersId.sqliteType, id)); }; + return Fragment.concat(Fragment.of("select \"order_id\", \"customer_id\", \"order_date\", \"total_amount\", \"status\" from \"orders\" where \"order_id\" in ("), Fragment.comma(fragments), Fragment.of(")")).query(OrdersRow.rowCodec.all()).run(c); + } + + @Override + public Map selectByIdsTracked( + List orderIds, + ConnectionRead c + ) { + HashMap ret = new HashMap(); + selectByIds(orderIds, c).forEach(row -> ret.put(row.orderId(), row)); + return ret; + } + + @Override + public UpdateBuilder update() { + return UpdateBuilder.of("\"orders\"", OrdersFields.structure, OrdersRow.rowCodec, Dialect.SQLITE); + } + + @Override + public Boolean update( + OrdersRow row, + Connection c + ) { + OrdersId orderId = row.orderId();; + return concat(Fragment.of("update \"orders\"\nset \"customer_id\" = "), Fragment.encode(CustomersId.sqliteType, row.customerId()), Fragment.of(",\n\"order_date\" = "), Fragment.encode(SqliteTypes.date, row.orderDate()), Fragment.of(",\n\"total_amount\" = "), Fragment.encode(SqliteTypes.numeric.opt(), row.totalAmount()), Fragment.of(",\n\"status\" = "), Fragment.encode(SqliteTypes.text, row.status()), Fragment.of("\nwhere \"order_id\" = "), Fragment.encode(OrdersId.sqliteType, orderId), Fragment.of("")).update().run(c) > 0; + } + + @Override + public OrdersRow upsert( + OrdersRow unsaved, + Connection c + ) { + return concat(Fragment.of("INSERT INTO \"orders\"(\"order_id\", \"customer_id\", \"order_date\", \"total_amount\", \"status\")\nVALUES ("), Fragment.encode(OrdersId.sqliteType, unsaved.orderId()), Fragment.of(", "), Fragment.encode(CustomersId.sqliteType, unsaved.customerId()), Fragment.of(", "), Fragment.encode(SqliteTypes.date, unsaved.orderDate()), Fragment.of(", "), Fragment.encode(SqliteTypes.numeric.opt(), unsaved.totalAmount()), Fragment.of(", "), Fragment.encode(SqliteTypes.text, unsaved.status()), Fragment.of(")\nON CONFLICT (\"order_id\")\nDO UPDATE SET\n \"customer_id\" = EXCLUDED.\"customer_id\",\n\"order_date\" = EXCLUDED.\"order_date\",\n\"total_amount\" = EXCLUDED.\"total_amount\",\n\"status\" = EXCLUDED.\"status\"\nRETURNING \"order_id\", \"customer_id\", \"order_date\", \"total_amount\", \"status\"")) + .updateReturning(OrdersRow.rowCodec.exactlyOne()) + .run(c); + } + + @Override + public List upsertBatch( + Iterator unsaved, + Connection c + ) { + return concat(Fragment.of("INSERT INTO \"orders\"(\"order_id\", \"customer_id\", \"order_date\", \"total_amount\", \"status\")\nVALUES (?, ?, ?, ?, ?)\nON CONFLICT (\"order_id\")\nDO UPDATE SET\n \"customer_id\" = EXCLUDED.\"customer_id\",\n\"order_date\" = EXCLUDED.\"order_date\",\n\"total_amount\" = EXCLUDED.\"total_amount\",\n\"status\" = EXCLUDED.\"status\"\nRETURNING \"order_id\", \"customer_id\", \"order_date\", \"total_amount\", \"status\"")) + .updateReturningEach(OrdersRow.rowCodec, unsaved) + .run(c); + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/orders/OrdersRepoMock.java b/testers/sqlite/java/generated-and-checked-in/testdb/orders/OrdersRepoMock.java new file mode 100644 index 0000000000..66dcb4119d --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/orders/OrdersRepoMock.java @@ -0,0 +1,172 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.orders; + +import dev.typr.dsl.DeleteBuilder; +import dev.typr.dsl.DeleteBuilderMock; +import dev.typr.dsl.DeleteParams; +import dev.typr.dsl.SelectBuilder; +import dev.typr.dsl.SelectBuilderMock; +import dev.typr.dsl.SelectParams; +import dev.typr.dsl.UpdateBuilder; +import dev.typr.dsl.UpdateBuilderMock; +import dev.typr.dsl.UpdateParams; +import dev.typr.foundations.Connection; +import dev.typr.foundations.ConnectionRead; +import java.lang.RuntimeException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.function.Function; +import java.util.stream.Collectors; + +public record OrdersRepoMock( + java.util.function.Function toRow, + HashMap map +) implements OrdersRepo { + public OrdersRepoMock(java.util.function.Function toRow) { + this(toRow, new HashMap()); + } + + public OrdersRepoMock withToRow(java.util.function.Function toRow) { + return new OrdersRepoMock(toRow, map); + } + + public OrdersRepoMock withMap(HashMap map) { + return new OrdersRepoMock(toRow, map); + } + + @Override + public DeleteBuilder delete() { + return new DeleteBuilderMock<>(OrdersFields.structure, () -> new ArrayList<>(map.values()), DeleteParams.empty(), row -> row.orderId(), id -> map.remove(id)); + } + + @Override + public Boolean deleteById( + OrdersId orderId, + Connection c + ) { + return Optional.ofNullable(map.remove(orderId)).isPresent(); + } + + @Override + public Integer deleteByIds( + List orderIds, + Connection c + ) { + var count = 0; + for (var id : orderIds) { + if (Optional.ofNullable(map.remove(id)).isPresent()) { + count = count + 1;; + } + }; + return count; + } + + @Override + public OrdersRow insert( + OrdersRow unsaved, + Connection c + ) { + if (map.containsKey(unsaved.orderId())) { + throw new RuntimeException("id " + unsaved.orderId() + " already exists"); + } + map.put(unsaved.orderId(), unsaved); + return unsaved; + } + + @Override + public OrdersRow insert( + OrdersRowUnsaved unsaved, + Connection c + ) { + return insert(toRow.apply(unsaved), c); + } + + @Override + public SelectBuilder select() { + return new SelectBuilderMock<>(OrdersFields.structure, () -> new ArrayList<>(map.values()), SelectParams.empty()); + } + + @Override + public List selectAll(ConnectionRead c) { + return new ArrayList<>(map.values()); + } + + @Override + public Optional selectById( + OrdersId orderId, + ConnectionRead c + ) { + return Optional.ofNullable(map.get(orderId)); + } + + @Override + public List selectByIds( + List orderIds, + ConnectionRead c + ) { + var result = new ArrayList(); + for (var id : orderIds) { + var opt = Optional.ofNullable(map.get(id)); + if (opt.isPresent()) { + result.add(opt.get()); + } + }; + return result; + } + + @Override + public Map selectByIdsTracked( + List orderIds, + ConnectionRead c + ) { + return selectByIds(orderIds, c).stream().collect(Collectors.toMap((OrdersRow row) -> row.orderId(), Function.identity())); + } + + @Override + public UpdateBuilder update() { + return new UpdateBuilderMock<>(OrdersFields.structure, () -> new ArrayList<>(map.values()), UpdateParams.empty(), row -> row); + } + + @Override + public Boolean update( + OrdersRow row, + Connection c + ) { + var shouldUpdate = Optional.ofNullable(map.get(row.orderId())).filter(oldRow -> !oldRow.equals(row)).isPresent(); + if (shouldUpdate) { + map.put(row.orderId(), row);; + } + return shouldUpdate; + } + + @Override + public OrdersRow upsert( + OrdersRow unsaved, + Connection c + ) { + map.put(unsaved.orderId(), unsaved); + return unsaved; + } + + @Override + public List upsertBatch( + Iterator unsaved, + Connection c + ) { + var result = new ArrayList(); + while (unsaved.hasNext()) { + var row = unsaved.next(); + map.put(row.orderId(), row); + result.add(row); + }; + return result; + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/orders/OrdersRow.java b/testers/sqlite/java/generated-and-checked-in/testdb/orders/OrdersRow.java new file mode 100644 index 0000000000..15165b66e3 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/orders/OrdersRow.java @@ -0,0 +1,87 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.orders; + +import com.fasterxml.jackson.annotation.JsonProperty; +import dev.typr.dsl.RowCodecs; +import dev.typr.foundations.RowCodec; +import dev.typr.foundations.SqliteTypes; +import dev.typr.foundations.Tuple.Tuple5; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.Optional; +import testdb.customers.CustomersId; +import testdb.customtypes.Defaulted; + +/** Table: orders + * Primary key: order_id + */ +public record OrdersRow( + @JsonProperty("order_id") OrdersId orderId, + /** Points to {@link testdb.customers.CustomersRow#customerId()} */ + @JsonProperty("customer_id") CustomersId customerId, + @JsonProperty("order_date") LocalDate orderDate, + @JsonProperty("total_amount") Optional totalAmount, + /** Default: 'pending' */ + String status +) implements Tuple5, String> { + public OrdersRow withOrderId(OrdersId orderId) { + return new OrdersRow(orderId, customerId, orderDate, totalAmount, status); + } + + /** Points to {@link testdb.customers.CustomersRow#customerId()} */ + public OrdersRow withCustomerId(CustomersId customerId) { + return new OrdersRow(orderId, customerId, orderDate, totalAmount, status); + } + + public OrdersRow withOrderDate(LocalDate orderDate) { + return new OrdersRow(orderId, customerId, orderDate, totalAmount, status); + } + + public OrdersRow withTotalAmount(Optional totalAmount) { + return new OrdersRow(orderId, customerId, orderDate, totalAmount, status); + } + + /** Default: 'pending' */ + public OrdersRow withStatus(String status) { + return new OrdersRow(orderId, customerId, orderDate, totalAmount, status); + } + + public static RowCodec rowCodec = RowCodecs.of(OrdersId.sqliteType, CustomersId.sqliteType, SqliteTypes.date, SqliteTypes.numeric.opt(), SqliteTypes.text, OrdersRow::new, row -> new Object[]{row.orderId(), row.customerId(), row.orderDate(), row.totalAmount(), row.status()}); + + @Override + public OrdersId _1() { + return orderId; + } + + @Override + public CustomersId _2() { + return customerId; + } + + @Override + public LocalDate _3() { + return orderDate; + } + + @Override + public Optional _4() { + return totalAmount; + } + + @Override + public String _5() { + return status; + } + + public OrdersId id() { + return orderId; + } + + public OrdersRowUnsaved toUnsavedRow(Defaulted status) { + return new OrdersRowUnsaved(orderId, customerId, orderDate, totalAmount, status); + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/orders/OrdersRowUnsaved.java b/testers/sqlite/java/generated-and-checked-in/testdb/orders/OrdersRowUnsaved.java new file mode 100644 index 0000000000..ea30da357a --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/orders/OrdersRowUnsaved.java @@ -0,0 +1,60 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.orders; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.Optional; +import testdb.customers.CustomersId; +import testdb.customtypes.Defaulted; +import testdb.customtypes.Defaulted.UseDefault; + +/** This class corresponds to a row in table `orders` which has not been persisted yet */ +public record OrdersRowUnsaved( + @JsonProperty("order_id") OrdersId orderId, + /** Points to {@link testdb.customers.CustomersRow#customerId()} */ + @JsonProperty("customer_id") CustomersId customerId, + @JsonProperty("order_date") LocalDate orderDate, + @JsonProperty("total_amount") Optional totalAmount, + /** Default: 'pending' */ + Defaulted status +) { + public OrdersRowUnsaved( + @JsonProperty("order_id") OrdersId orderId, + /** Points to {@link testdb.customers.CustomersRow#customerId()} */ + @JsonProperty("customer_id") CustomersId customerId, + @JsonProperty("order_date") LocalDate orderDate + ) { + this(orderId, customerId, orderDate, Optional.empty(), new UseDefault<>()); + } + + public OrdersRowUnsaved withOrderId(OrdersId orderId) { + return new OrdersRowUnsaved(orderId, customerId, orderDate, totalAmount, status); + } + + /** Points to {@link testdb.customers.CustomersRow#customerId()} */ + public OrdersRowUnsaved withCustomerId(CustomersId customerId) { + return new OrdersRowUnsaved(orderId, customerId, orderDate, totalAmount, status); + } + + public OrdersRowUnsaved withOrderDate(LocalDate orderDate) { + return new OrdersRowUnsaved(orderId, customerId, orderDate, totalAmount, status); + } + + public OrdersRowUnsaved withTotalAmount(Optional totalAmount) { + return new OrdersRowUnsaved(orderId, customerId, orderDate, totalAmount, status); + } + + /** Default: 'pending' */ + public OrdersRowUnsaved withStatus(Defaulted status) { + return new OrdersRowUnsaved(orderId, customerId, orderDate, totalAmount, status); + } + + public OrdersRow toRow(java.util.function.Supplier statusDefault) { + return new OrdersRow(orderId, customerId, orderDate, totalAmount, status.getOrElse(statusDefault)); + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/precisetypes/Decimal10_2.java b/testers/sqlite/java/generated-and-checked-in/testdb/precisetypes/Decimal10_2.java new file mode 100644 index 0000000000..146e9811e1 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/precisetypes/Decimal10_2.java @@ -0,0 +1,101 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precisetypes; + +import com.fasterxml.jackson.annotation.JsonValue; +import dev.typr.foundations.Bijection; +import dev.typr.foundations.SqliteType; +import dev.typr.foundations.SqliteTypes; +import dev.typr.foundations.data.precise.DecimalN; +import java.lang.IllegalArgumentException; +import java.lang.Object; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.Optional; + +public record Decimal10_2(@JsonValue BigDecimal value) implements DecimalN { + @java.lang.Deprecated + public Decimal10_2 { + } + + public Decimal10_2 withValue(BigDecimal value) { + return new Decimal10_2(value); + } + + @Override + public java.lang.String toString() { + return value.toString(); + } + + static public Optional of(BigDecimal value) { + BigDecimal scaled = value.setScale(2, RoundingMode.HALF_UP); + return scaled.precision() <= 10 ? Optional.of(new Decimal10_2(scaled)) : Optional.empty(); + } + + static public Decimal10_2 unsafeForce(BigDecimal value) { + BigDecimal scaled = value.setScale(2, RoundingMode.HALF_UP); + if (scaled.precision() > 10) { throw new IllegalArgumentException("Value exceeds precision(10, 2)"); }; + return new Decimal10_2(scaled); + } + + static public Decimal10_2 of(Integer value) { + return new Decimal10_2(BigDecimal.valueOf((long) (value))); + } + + static public Optional of(Long value) { + return Decimal10_2.of(BigDecimal.valueOf(value)); + } + + static public Optional of(Double value) { + return Decimal10_2.of(BigDecimal.valueOf(value)); + } + + static public Decimal10_2 Zero = + new Decimal10_2(BigDecimal.ZERO); + + static public Bijection bijection = + Bijection.of(Decimal10_2::value, Decimal10_2::new); + + static public SqliteType sqliteType = + SqliteTypes.numeric.to(Bijection.of(Decimal10_2::new, Decimal10_2::value)); + + @Override + public BigDecimal decimalValue() { + return value; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (!(obj instanceof DecimalN other)) return false; + return decimalValue().compareTo(other.decimalValue()) == 0; + } + + @Override + public int hashCode() { + return decimalValue().stripTrailingZeros().hashCode(); + } + + @Override + public int precision() { + return 10; + } + + @Override + public int scale() { + return 2; + } + + @Override + public boolean semanticEquals(DecimalN other) { + return (other == null ? false : decimalValue().compareTo(other.decimalValue()) == 0); + } + + @Override + public int semanticHashCode() { + return decimalValue().stripTrailingZeros().hashCode(); + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/precisetypes/Decimal18_4.java b/testers/sqlite/java/generated-and-checked-in/testdb/precisetypes/Decimal18_4.java new file mode 100644 index 0000000000..3bc57283ce --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/precisetypes/Decimal18_4.java @@ -0,0 +1,101 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precisetypes; + +import com.fasterxml.jackson.annotation.JsonValue; +import dev.typr.foundations.Bijection; +import dev.typr.foundations.SqliteType; +import dev.typr.foundations.SqliteTypes; +import dev.typr.foundations.data.precise.DecimalN; +import java.lang.IllegalArgumentException; +import java.lang.Object; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.Optional; + +public record Decimal18_4(@JsonValue BigDecimal value) implements DecimalN { + @java.lang.Deprecated + public Decimal18_4 { + } + + public Decimal18_4 withValue(BigDecimal value) { + return new Decimal18_4(value); + } + + @Override + public java.lang.String toString() { + return value.toString(); + } + + static public Optional of(BigDecimal value) { + BigDecimal scaled = value.setScale(4, RoundingMode.HALF_UP); + return scaled.precision() <= 18 ? Optional.of(new Decimal18_4(scaled)) : Optional.empty(); + } + + static public Decimal18_4 unsafeForce(BigDecimal value) { + BigDecimal scaled = value.setScale(4, RoundingMode.HALF_UP); + if (scaled.precision() > 18) { throw new IllegalArgumentException("Value exceeds precision(18, 4)"); }; + return new Decimal18_4(scaled); + } + + static public Decimal18_4 of(Integer value) { + return new Decimal18_4(BigDecimal.valueOf((long) (value))); + } + + static public Optional of(Long value) { + return Decimal18_4.of(BigDecimal.valueOf(value)); + } + + static public Optional of(Double value) { + return Decimal18_4.of(BigDecimal.valueOf(value)); + } + + static public Decimal18_4 Zero = + new Decimal18_4(BigDecimal.ZERO); + + static public Bijection bijection = + Bijection.of(Decimal18_4::value, Decimal18_4::new); + + static public SqliteType sqliteType = + SqliteTypes.numeric.to(Bijection.of(Decimal18_4::new, Decimal18_4::value)); + + @Override + public BigDecimal decimalValue() { + return value; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (!(obj instanceof DecimalN other)) return false; + return decimalValue().compareTo(other.decimalValue()) == 0; + } + + @Override + public int hashCode() { + return decimalValue().stripTrailingZeros().hashCode(); + } + + @Override + public int precision() { + return 18; + } + + @Override + public int scale() { + return 4; + } + + @Override + public boolean semanticEquals(DecimalN other) { + return (other == null ? false : decimalValue().compareTo(other.decimalValue()) == 0); + } + + @Override + public int semanticHashCode() { + return decimalValue().stripTrailingZeros().hashCode(); + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/precisetypes/Decimal5_2.java b/testers/sqlite/java/generated-and-checked-in/testdb/precisetypes/Decimal5_2.java new file mode 100644 index 0000000000..2dfd258003 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/precisetypes/Decimal5_2.java @@ -0,0 +1,101 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precisetypes; + +import com.fasterxml.jackson.annotation.JsonValue; +import dev.typr.foundations.Bijection; +import dev.typr.foundations.SqliteType; +import dev.typr.foundations.SqliteTypes; +import dev.typr.foundations.data.precise.DecimalN; +import java.lang.IllegalArgumentException; +import java.lang.Object; +import java.math.BigDecimal; +import java.math.RoundingMode; +import java.util.Optional; + +public record Decimal5_2(@JsonValue BigDecimal value) implements DecimalN { + @java.lang.Deprecated + public Decimal5_2 { + } + + public Decimal5_2 withValue(BigDecimal value) { + return new Decimal5_2(value); + } + + @Override + public java.lang.String toString() { + return value.toString(); + } + + static public Optional of(BigDecimal value) { + BigDecimal scaled = value.setScale(2, RoundingMode.HALF_UP); + return scaled.precision() <= 5 ? Optional.of(new Decimal5_2(scaled)) : Optional.empty(); + } + + static public Decimal5_2 unsafeForce(BigDecimal value) { + BigDecimal scaled = value.setScale(2, RoundingMode.HALF_UP); + if (scaled.precision() > 5) { throw new IllegalArgumentException("Value exceeds precision(5, 2)"); }; + return new Decimal5_2(scaled); + } + + static public Decimal5_2 of(Integer value) { + return new Decimal5_2(BigDecimal.valueOf((long) (value))); + } + + static public Optional of(Long value) { + return Decimal5_2.of(BigDecimal.valueOf(value)); + } + + static public Optional of(Double value) { + return Decimal5_2.of(BigDecimal.valueOf(value)); + } + + static public Decimal5_2 Zero = + new Decimal5_2(BigDecimal.ZERO); + + static public Bijection bijection = + Bijection.of(Decimal5_2::value, Decimal5_2::new); + + static public SqliteType sqliteType = + SqliteTypes.numeric.to(Bijection.of(Decimal5_2::new, Decimal5_2::value)); + + @Override + public BigDecimal decimalValue() { + return value; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (!(obj instanceof DecimalN other)) return false; + return decimalValue().compareTo(other.decimalValue()) == 0; + } + + @Override + public int hashCode() { + return decimalValue().stripTrailingZeros().hashCode(); + } + + @Override + public int precision() { + return 5; + } + + @Override + public int scale() { + return 2; + } + + @Override + public boolean semanticEquals(DecimalN other) { + return (other == null ? false : decimalValue().compareTo(other.decimalValue()) == 0); + } + + @Override + public int semanticHashCode() { + return decimalValue().stripTrailingZeros().hashCode(); + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/precisetypes/Int10.java b/testers/sqlite/java/generated-and-checked-in/testdb/precisetypes/Int10.java new file mode 100644 index 0000000000..397ac3d6f2 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/precisetypes/Int10.java @@ -0,0 +1,97 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precisetypes; + +import com.fasterxml.jackson.annotation.JsonValue; +import dev.typr.foundations.Bijection; +import dev.typr.foundations.SqliteType; +import dev.typr.foundations.SqliteTypes; +import dev.typr.foundations.data.precise.DecimalN; +import java.lang.IllegalArgumentException; +import java.lang.Object; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.Optional; + +public record Int10(@JsonValue BigInteger value) implements DecimalN { + @java.lang.Deprecated + public Int10 { + } + + public Int10 withValue(BigInteger value) { + return new Int10(value); + } + + @Override + public java.lang.String toString() { + return value.toString(); + } + + static public Optional of(BigInteger value) { + return (value.bitLength() <= 40 ? Optional.of(new Int10(value)) : Optional.empty()); + } + + static public Int10 unsafeForce(BigInteger value) { + if (value.bitLength() > 40) { + throw new IllegalArgumentException("Value exceeds precision(10, 0)"); + } + return new Int10(value); + } + + static public Int10 of(Integer value) { + return new Int10(BigInteger.valueOf((long) (value))); + } + + static public Optional of(Long value) { + return Int10.of(BigInteger.valueOf(value)); + } + + static public Int10 Zero = + new Int10(BigInteger.ZERO); + + static public Bijection bijection = + Bijection.of(Int10::value, Int10::new); + + static public SqliteType sqliteType = + SqliteTypes.numeric.to(Bijection.of(bd -> new Int10(bd.toBigIntegerExact()), v -> new BigDecimal(v.value()))); + + @Override + public BigDecimal decimalValue() { + return new BigDecimal(value); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (!(obj instanceof DecimalN other)) return false; + return decimalValue().compareTo(other.decimalValue()) == 0; + } + + @Override + public int hashCode() { + return decimalValue().stripTrailingZeros().hashCode(); + } + + @Override + public int precision() { + return 10; + } + + @Override + public int scale() { + return 0; + } + + @Override + public boolean semanticEquals(DecimalN other) { + return (other == null ? false : decimalValue().compareTo(other.decimalValue()) == 0); + } + + @Override + public int semanticHashCode() { + return decimalValue().stripTrailingZeros().hashCode(); + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/precisetypes/Int18.java b/testers/sqlite/java/generated-and-checked-in/testdb/precisetypes/Int18.java new file mode 100644 index 0000000000..28010a314b --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/precisetypes/Int18.java @@ -0,0 +1,97 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precisetypes; + +import com.fasterxml.jackson.annotation.JsonValue; +import dev.typr.foundations.Bijection; +import dev.typr.foundations.SqliteType; +import dev.typr.foundations.SqliteTypes; +import dev.typr.foundations.data.precise.DecimalN; +import java.lang.IllegalArgumentException; +import java.lang.Object; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.Optional; + +public record Int18(@JsonValue BigInteger value) implements DecimalN { + @java.lang.Deprecated + public Int18 { + } + + public Int18 withValue(BigInteger value) { + return new Int18(value); + } + + @Override + public java.lang.String toString() { + return value.toString(); + } + + static public Optional of(BigInteger value) { + return (value.bitLength() <= 72 ? Optional.of(new Int18(value)) : Optional.empty()); + } + + static public Int18 unsafeForce(BigInteger value) { + if (value.bitLength() > 72) { + throw new IllegalArgumentException("Value exceeds precision(18, 0)"); + } + return new Int18(value); + } + + static public Int18 of(Integer value) { + return new Int18(BigInteger.valueOf((long) (value))); + } + + static public Optional of(Long value) { + return Int18.of(BigInteger.valueOf(value)); + } + + static public Int18 Zero = + new Int18(BigInteger.ZERO); + + static public Bijection bijection = + Bijection.of(Int18::value, Int18::new); + + static public SqliteType sqliteType = + SqliteTypes.numeric.to(Bijection.of(bd -> new Int18(bd.toBigIntegerExact()), v -> new BigDecimal(v.value()))); + + @Override + public BigDecimal decimalValue() { + return new BigDecimal(value); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (!(obj instanceof DecimalN other)) return false; + return decimalValue().compareTo(other.decimalValue()) == 0; + } + + @Override + public int hashCode() { + return decimalValue().stripTrailingZeros().hashCode(); + } + + @Override + public int precision() { + return 18; + } + + @Override + public int scale() { + return 0; + } + + @Override + public boolean semanticEquals(DecimalN other) { + return (other == null ? false : decimalValue().compareTo(other.decimalValue()) == 0); + } + + @Override + public int semanticHashCode() { + return decimalValue().stripTrailingZeros().hashCode(); + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/precisetypes/Int5.java b/testers/sqlite/java/generated-and-checked-in/testdb/precisetypes/Int5.java new file mode 100644 index 0000000000..fce9dad0ad --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/precisetypes/Int5.java @@ -0,0 +1,97 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precisetypes; + +import com.fasterxml.jackson.annotation.JsonValue; +import dev.typr.foundations.Bijection; +import dev.typr.foundations.SqliteType; +import dev.typr.foundations.SqliteTypes; +import dev.typr.foundations.data.precise.DecimalN; +import java.lang.IllegalArgumentException; +import java.lang.Object; +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.Optional; + +public record Int5(@JsonValue BigInteger value) implements DecimalN { + @java.lang.Deprecated + public Int5 { + } + + public Int5 withValue(BigInteger value) { + return new Int5(value); + } + + @Override + public java.lang.String toString() { + return value.toString(); + } + + static public Optional of(BigInteger value) { + return (value.bitLength() <= 20 ? Optional.of(new Int5(value)) : Optional.empty()); + } + + static public Int5 unsafeForce(BigInteger value) { + if (value.bitLength() > 20) { + throw new IllegalArgumentException("Value exceeds precision(5, 0)"); + } + return new Int5(value); + } + + static public Int5 of(Integer value) { + return new Int5(BigInteger.valueOf((long) (value))); + } + + static public Optional of(Long value) { + return Int5.of(BigInteger.valueOf(value)); + } + + static public Int5 Zero = + new Int5(BigInteger.ZERO); + + static public Bijection bijection = + Bijection.of(Int5::value, Int5::new); + + static public SqliteType sqliteType = + SqliteTypes.numeric.to(Bijection.of(bd -> new Int5(bd.toBigIntegerExact()), v -> new BigDecimal(v.value()))); + + @Override + public BigDecimal decimalValue() { + return new BigDecimal(value); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (!(obj instanceof DecimalN other)) return false; + return decimalValue().compareTo(other.decimalValue()) == 0; + } + + @Override + public int hashCode() { + return decimalValue().stripTrailingZeros().hashCode(); + } + + @Override + public int precision() { + return 5; + } + + @Override + public int scale() { + return 0; + } + + @Override + public boolean semanticEquals(DecimalN other) { + return (other == null ? false : decimalValue().compareTo(other.decimalValue()) == 0); + } + + @Override + public int semanticHashCode() { + return decimalValue().stripTrailingZeros().hashCode(); + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/precisetypes/String10.java b/testers/sqlite/java/generated-and-checked-in/testdb/precisetypes/String10.java new file mode 100644 index 0000000000..6bce794757 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/precisetypes/String10.java @@ -0,0 +1,83 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precisetypes; + +import com.fasterxml.jackson.annotation.JsonValue; +import dev.typr.foundations.Bijection; +import dev.typr.foundations.SqliteType; +import dev.typr.foundations.SqliteTypes; +import dev.typr.foundations.data.precise.StringN; +import java.lang.IllegalArgumentException; +import java.lang.Object; +import java.util.Optional; + +public record String10(@JsonValue String value) implements StringN { + @java.lang.Deprecated + public String10 { + } + + public String10 withValue(String value) { + return new String10(value); + } + + @Override + public java.lang.String toString() { + return value.toString(); + } + + static public Optional of(String value) { + return (value.length() <= 10 ? Optional.of(new String10(value)) : Optional.empty()); + } + + static public String10 unsafeForce(String value) { + if (value.length() > 10) { + throw new IllegalArgumentException("Value length ${value.length()} exceeds maximum 10"); + } + return new String10(value); + } + + static public String10 truncate(String value) { + return new String10((value.length() <= 10 ? value : value.substring(0, 10))); + } + + static public Bijection bijection = + Bijection.of(String10::value, String10::new); + + static public SqliteType sqliteType = + SqliteTypes.varchar.to(Bijection.of(String10::new, String10::value)); + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (!(obj instanceof StringN other)) return false; + return value.equals(other.rawValue()); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + @Override + public int maxLength() { + return 10; + } + + @Override + public String rawValue() { + return value; + } + + @Override + public boolean semanticEquals(StringN other) { + return (other == null ? false : value.equals(other.rawValue())); + } + + @Override + public int semanticHashCode() { + return value.hashCode(); + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/precisetypes/String100.java b/testers/sqlite/java/generated-and-checked-in/testdb/precisetypes/String100.java new file mode 100644 index 0000000000..927c8f2ab2 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/precisetypes/String100.java @@ -0,0 +1,83 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precisetypes; + +import com.fasterxml.jackson.annotation.JsonValue; +import dev.typr.foundations.Bijection; +import dev.typr.foundations.SqliteType; +import dev.typr.foundations.SqliteTypes; +import dev.typr.foundations.data.precise.StringN; +import java.lang.IllegalArgumentException; +import java.lang.Object; +import java.util.Optional; + +public record String100(@JsonValue String value) implements StringN { + @java.lang.Deprecated + public String100 { + } + + public String100 withValue(String value) { + return new String100(value); + } + + @Override + public java.lang.String toString() { + return value.toString(); + } + + static public Optional of(String value) { + return (value.length() <= 100 ? Optional.of(new String100(value)) : Optional.empty()); + } + + static public String100 unsafeForce(String value) { + if (value.length() > 100) { + throw new IllegalArgumentException("Value length ${value.length()} exceeds maximum 100"); + } + return new String100(value); + } + + static public String100 truncate(String value) { + return new String100((value.length() <= 100 ? value : value.substring(0, 100))); + } + + static public Bijection bijection = + Bijection.of(String100::value, String100::new); + + static public SqliteType sqliteType = + SqliteTypes.varchar.to(Bijection.of(String100::new, String100::value)); + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (!(obj instanceof StringN other)) return false; + return value.equals(other.rawValue()); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + @Override + public int maxLength() { + return 100; + } + + @Override + public String rawValue() { + return value; + } + + @Override + public boolean semanticEquals(StringN other) { + return (other == null ? false : value.equals(other.rawValue())); + } + + @Override + public int semanticHashCode() { + return value.hashCode(); + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/precisetypes/String20.java b/testers/sqlite/java/generated-and-checked-in/testdb/precisetypes/String20.java new file mode 100644 index 0000000000..f1ad2ce995 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/precisetypes/String20.java @@ -0,0 +1,83 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precisetypes; + +import com.fasterxml.jackson.annotation.JsonValue; +import dev.typr.foundations.Bijection; +import dev.typr.foundations.SqliteType; +import dev.typr.foundations.SqliteTypes; +import dev.typr.foundations.data.precise.StringN; +import java.lang.IllegalArgumentException; +import java.lang.Object; +import java.util.Optional; + +public record String20(@JsonValue String value) implements StringN { + @java.lang.Deprecated + public String20 { + } + + public String20 withValue(String value) { + return new String20(value); + } + + @Override + public java.lang.String toString() { + return value.toString(); + } + + static public Optional of(String value) { + return (value.length() <= 20 ? Optional.of(new String20(value)) : Optional.empty()); + } + + static public String20 unsafeForce(String value) { + if (value.length() > 20) { + throw new IllegalArgumentException("Value length ${value.length()} exceeds maximum 20"); + } + return new String20(value); + } + + static public String20 truncate(String value) { + return new String20((value.length() <= 20 ? value : value.substring(0, 20))); + } + + static public Bijection bijection = + Bijection.of(String20::value, String20::new); + + static public SqliteType sqliteType = + SqliteTypes.varchar.to(Bijection.of(String20::new, String20::value)); + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (!(obj instanceof StringN other)) return false; + return value.equals(other.rawValue()); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + @Override + public int maxLength() { + return 20; + } + + @Override + public String rawValue() { + return value; + } + + @Override + public boolean semanticEquals(StringN other) { + return (other == null ? false : value.equals(other.rawValue())); + } + + @Override + public int semanticHashCode() { + return value.hashCode(); + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/precisetypes/String255.java b/testers/sqlite/java/generated-and-checked-in/testdb/precisetypes/String255.java new file mode 100644 index 0000000000..9acd021534 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/precisetypes/String255.java @@ -0,0 +1,83 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precisetypes; + +import com.fasterxml.jackson.annotation.JsonValue; +import dev.typr.foundations.Bijection; +import dev.typr.foundations.SqliteType; +import dev.typr.foundations.SqliteTypes; +import dev.typr.foundations.data.precise.StringN; +import java.lang.IllegalArgumentException; +import java.lang.Object; +import java.util.Optional; + +public record String255(@JsonValue String value) implements StringN { + @java.lang.Deprecated + public String255 { + } + + public String255 withValue(String value) { + return new String255(value); + } + + @Override + public java.lang.String toString() { + return value.toString(); + } + + static public Optional of(String value) { + return (value.length() <= 255 ? Optional.of(new String255(value)) : Optional.empty()); + } + + static public String255 unsafeForce(String value) { + if (value.length() > 255) { + throw new IllegalArgumentException("Value length ${value.length()} exceeds maximum 255"); + } + return new String255(value); + } + + static public String255 truncate(String value) { + return new String255((value.length() <= 255 ? value : value.substring(0, 255))); + } + + static public Bijection bijection = + Bijection.of(String255::value, String255::new); + + static public SqliteType sqliteType = + SqliteTypes.varchar.to(Bijection.of(String255::new, String255::value)); + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (!(obj instanceof StringN other)) return false; + return value.equals(other.rawValue()); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + @Override + public int maxLength() { + return 255; + } + + @Override + public String rawValue() { + return value; + } + + @Override + public boolean semanticEquals(StringN other) { + return (other == null ? false : value.equals(other.rawValue())); + } + + @Override + public int semanticHashCode() { + return value.hashCode(); + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/precisetypes/String50.java b/testers/sqlite/java/generated-and-checked-in/testdb/precisetypes/String50.java new file mode 100644 index 0000000000..c71972e603 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/precisetypes/String50.java @@ -0,0 +1,83 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precisetypes; + +import com.fasterxml.jackson.annotation.JsonValue; +import dev.typr.foundations.Bijection; +import dev.typr.foundations.SqliteType; +import dev.typr.foundations.SqliteTypes; +import dev.typr.foundations.data.precise.StringN; +import java.lang.IllegalArgumentException; +import java.lang.Object; +import java.util.Optional; + +public record String50(@JsonValue String value) implements StringN { + @java.lang.Deprecated + public String50 { + } + + public String50 withValue(String value) { + return new String50(value); + } + + @Override + public java.lang.String toString() { + return value.toString(); + } + + static public Optional of(String value) { + return (value.length() <= 50 ? Optional.of(new String50(value)) : Optional.empty()); + } + + static public String50 unsafeForce(String value) { + if (value.length() > 50) { + throw new IllegalArgumentException("Value length ${value.length()} exceeds maximum 50"); + } + return new String50(value); + } + + static public String50 truncate(String value) { + return new String50((value.length() <= 50 ? value : value.substring(0, 50))); + } + + static public Bijection bijection = + Bijection.of(String50::value, String50::new); + + static public SqliteType sqliteType = + SqliteTypes.varchar.to(Bijection.of(String50::new, String50::value)); + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (!(obj instanceof StringN other)) return false; + return value.equals(other.rawValue()); + } + + @Override + public int hashCode() { + return value.hashCode(); + } + + @Override + public int maxLength() { + return 50; + } + + @Override + public String rawValue() { + return value; + } + + @Override + public boolean semanticEquals(StringN other) { + return (other == null ? false : value.equals(other.rawValue())); + } + + @Override + public int semanticHashCode() { + return value.hashCode(); + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/precision_types/PrecisionTypesFields.java b/testers/sqlite/java/generated-and-checked-in/testdb/precision_types/PrecisionTypesFields.java new file mode 100644 index 0000000000..fc76887232 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/precision_types/PrecisionTypesFields.java @@ -0,0 +1,167 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precision_types; + +import dev.typr.dsl.FieldsBase; +import dev.typr.dsl.Path; +import dev.typr.dsl.RelationStructure; +import dev.typr.dsl.SqlExpr; +import dev.typr.dsl.SqlExpr.Field; +import dev.typr.dsl.SqlExpr.FieldLike; +import dev.typr.dsl.SqlExpr.IdField; +import dev.typr.dsl.TupleExpr.TupleExpr12; +import dev.typr.foundations.RowCodec; +import java.util.List; +import java.util.Optional; +import testdb.precisetypes.Decimal10_2; +import testdb.precisetypes.Decimal18_4; +import testdb.precisetypes.Decimal5_2; +import testdb.precisetypes.Int10; +import testdb.precisetypes.Int18; +import testdb.precisetypes.Int5; +import testdb.precisetypes.String10; +import testdb.precisetypes.String100; +import testdb.precisetypes.String20; +import testdb.precisetypes.String255; +import testdb.precisetypes.String50; + +public class PrecisionTypesFields extends TupleExpr12 implements RelationStructure, FieldsBase { + List _path; + + public PrecisionTypesFields(List _path) { + this._path = _path; + } + + public static PrecisionTypesFields structure = new PrecisionTypesFields(java.util.Collections.emptyList()); + + public IdField id() { + return new IdField(_path, "id", PrecisionTypesRow::id, Optional.empty(), Optional.empty(), (row, value) -> row.withId(value), PrecisionTypesId.sqliteType); + } + + public Field string10() { + return new Field(_path, "string10", PrecisionTypesRow::string10, Optional.empty(), Optional.empty(), (row, value) -> row.withString10(value), String10.sqliteType); + } + + public Field string20() { + return new Field(_path, "string20", PrecisionTypesRow::string20, Optional.empty(), Optional.empty(), (row, value) -> row.withString20(value), String20.sqliteType); + } + + public Field string50() { + return new Field(_path, "string50", PrecisionTypesRow::string50, Optional.empty(), Optional.empty(), (row, value) -> row.withString50(value), String50.sqliteType); + } + + public Field string100() { + return new Field(_path, "string100", PrecisionTypesRow::string100, Optional.empty(), Optional.empty(), (row, value) -> row.withString100(value), String100.sqliteType); + } + + public Field string255() { + return new Field(_path, "string255", PrecisionTypesRow::string255, Optional.empty(), Optional.empty(), (row, value) -> row.withString255(value), String255.sqliteType); + } + + public Field decimal52() { + return new Field(_path, "decimal5_2", PrecisionTypesRow::decimal52, Optional.empty(), Optional.empty(), (row, value) -> row.withDecimal52(value), Decimal5_2.sqliteType); + } + + public Field decimal102() { + return new Field(_path, "decimal10_2", PrecisionTypesRow::decimal102, Optional.empty(), Optional.empty(), (row, value) -> row.withDecimal102(value), Decimal10_2.sqliteType); + } + + public Field decimal184() { + return new Field(_path, "decimal18_4", PrecisionTypesRow::decimal184, Optional.empty(), Optional.empty(), (row, value) -> row.withDecimal184(value), Decimal18_4.sqliteType); + } + + public Field decimal50() { + return new Field(_path, "decimal5_0", PrecisionTypesRow::decimal50, Optional.empty(), Optional.empty(), (row, value) -> row.withDecimal50(value), Int5.sqliteType); + } + + public Field decimal100() { + return new Field(_path, "decimal10_0", PrecisionTypesRow::decimal100, Optional.empty(), Optional.empty(), (row, value) -> row.withDecimal100(value), Int10.sqliteType); + } + + public Field decimal180() { + return new Field(_path, "decimal18_0", PrecisionTypesRow::decimal180, Optional.empty(), Optional.empty(), (row, value) -> row.withDecimal180(value), Int18.sqliteType); + } + + @Override + public List _path() { + return _path; + } + + @Override + public List> columns() { + return java.util.List.of(this.id(), this.string10(), this.string20(), this.string50(), this.string100(), this.string255(), this.decimal52(), this.decimal102(), this.decimal184(), this.decimal50(), this.decimal100(), this.decimal180()); + } + + @Override + public RowCodec rowCodec() { + return PrecisionTypesRow.rowCodec; + } + + @Override + public RelationStructure withPaths(List _path) { + return new PrecisionTypesFields(_path); + } + + @Override + public SqlExpr _1() { + return id(); + } + + @Override + public SqlExpr _2() { + return string10(); + } + + @Override + public SqlExpr _3() { + return string20(); + } + + @Override + public SqlExpr _4() { + return string50(); + } + + @Override + public SqlExpr _5() { + return string100(); + } + + @Override + public SqlExpr _6() { + return string255(); + } + + @Override + public SqlExpr _7() { + return decimal52(); + } + + @Override + public SqlExpr _8() { + return decimal102(); + } + + @Override + public SqlExpr _9() { + return decimal184(); + } + + @Override + public SqlExpr _10() { + return decimal50(); + } + + @Override + public SqlExpr _11() { + return decimal100(); + } + + @Override + public SqlExpr _12() { + return decimal180(); + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/precision_types/PrecisionTypesId.java b/testers/sqlite/java/generated-and-checked-in/testdb/precision_types/PrecisionTypesId.java new file mode 100644 index 0000000000..101c662fad --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/precision_types/PrecisionTypesId.java @@ -0,0 +1,29 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precision_types; + +import com.fasterxml.jackson.annotation.JsonValue; +import dev.typr.foundations.Bijection; +import dev.typr.foundations.SqliteType; +import dev.typr.foundations.SqliteTypes; + +/** Type for the primary key of table `precision_types` */ +public record PrecisionTypesId(@JsonValue Long value) { + public PrecisionTypesId withValue(Long value) { + return new PrecisionTypesId(value); + } + + @Override + public java.lang.String toString() { + return value.toString(); + } + + static public Bijection bijection = + Bijection.of(PrecisionTypesId::value, PrecisionTypesId::new); + + static public SqliteType sqliteType = + SqliteTypes.integer.to(Bijection.of(PrecisionTypesId::new, PrecisionTypesId::value)); +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/precision_types/PrecisionTypesRepo.java b/testers/sqlite/java/generated-and-checked-in/testdb/precision_types/PrecisionTypesRepo.java new file mode 100644 index 0000000000..c9c183854d --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/precision_types/PrecisionTypesRepo.java @@ -0,0 +1,71 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precision_types; + +import dev.typr.dsl.DeleteBuilder; +import dev.typr.dsl.SelectBuilder; +import dev.typr.dsl.UpdateBuilder; +import dev.typr.foundations.Connection; +import dev.typr.foundations.ConnectionRead; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +public interface PrecisionTypesRepo { + DeleteBuilder delete(); + + Boolean deleteById( + PrecisionTypesId id, + Connection c + ); + + Integer deleteByIds( + List ids, + Connection c + ); + + PrecisionTypesRow insert( + PrecisionTypesRow unsaved, + Connection c + ); + + SelectBuilder select(); + + List selectAll(ConnectionRead c); + + Optional selectById( + PrecisionTypesId id, + ConnectionRead c + ); + + List selectByIds( + List ids, + ConnectionRead c + ); + + Map selectByIdsTracked( + List ids, + ConnectionRead c + ); + + UpdateBuilder update(); + + Boolean update( + PrecisionTypesRow row, + Connection c + ); + + PrecisionTypesRow upsert( + PrecisionTypesRow unsaved, + Connection c + ); + + List upsertBatch( + Iterator unsaved, + Connection c + ); +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/precision_types/PrecisionTypesRepoImpl.java b/testers/sqlite/java/generated-and-checked-in/testdb/precision_types/PrecisionTypesRepoImpl.java new file mode 100644 index 0000000000..971f79290c --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/precision_types/PrecisionTypesRepoImpl.java @@ -0,0 +1,138 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precision_types; + +import dev.typr.dsl.DeleteBuilder; +import dev.typr.dsl.Dialect; +import dev.typr.dsl.SelectBuilder; +import dev.typr.dsl.UpdateBuilder; +import dev.typr.foundations.Connection; +import dev.typr.foundations.ConnectionRead; +import dev.typr.foundations.Fragment; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import testdb.precisetypes.Decimal10_2; +import testdb.precisetypes.Decimal18_4; +import testdb.precisetypes.Decimal5_2; +import testdb.precisetypes.Int10; +import testdb.precisetypes.Int18; +import testdb.precisetypes.Int5; +import testdb.precisetypes.String10; +import testdb.precisetypes.String100; +import testdb.precisetypes.String20; +import testdb.precisetypes.String255; +import testdb.precisetypes.String50; +import static dev.typr.foundations.Fragment.concat; + +public class PrecisionTypesRepoImpl implements PrecisionTypesRepo { + @Override + public DeleteBuilder delete() { + return DeleteBuilder.of("\"precision_types\"", PrecisionTypesFields.structure, Dialect.SQLITE); + } + + @Override + public Boolean deleteById( + PrecisionTypesId id, + Connection c + ) { + return concat(Fragment.of("delete from \"precision_types\" where \"id\" = "), Fragment.encode(PrecisionTypesId.sqliteType, id), Fragment.of("")).update().run(c) > 0; + } + + @Override + public Integer deleteByIds( + List ids, + Connection c + ) { + ArrayList fragments = new ArrayList<>(); + for (var id : ids) { fragments.add(Fragment.encode(PrecisionTypesId.sqliteType, id)); }; + return Fragment.concat(Fragment.of("delete from \"precision_types\" where \"id\" in ("), Fragment.comma(fragments), Fragment.of(")")).update().run(c); + } + + @Override + public PrecisionTypesRow insert( + PrecisionTypesRow unsaved, + Connection c + ) { + return concat(Fragment.of("insert into \"precision_types\"(\"id\", \"string10\", \"string20\", \"string50\", \"string100\", \"string255\", \"decimal5_2\", \"decimal10_2\", \"decimal18_4\", \"decimal5_0\", \"decimal10_0\", \"decimal18_0\")\nvalues ("), Fragment.encode(PrecisionTypesId.sqliteType, unsaved.id()), Fragment.of(", "), Fragment.encode(String10.sqliteType, unsaved.string10()), Fragment.of(", "), Fragment.encode(String20.sqliteType, unsaved.string20()), Fragment.of(", "), Fragment.encode(String50.sqliteType, unsaved.string50()), Fragment.of(", "), Fragment.encode(String100.sqliteType, unsaved.string100()), Fragment.of(", "), Fragment.encode(String255.sqliteType, unsaved.string255()), Fragment.of(", "), Fragment.encode(Decimal5_2.sqliteType, unsaved.decimal52()), Fragment.of(", "), Fragment.encode(Decimal10_2.sqliteType, unsaved.decimal102()), Fragment.of(", "), Fragment.encode(Decimal18_4.sqliteType, unsaved.decimal184()), Fragment.of(", "), Fragment.encode(Int5.sqliteType, unsaved.decimal50()), Fragment.of(", "), Fragment.encode(Int10.sqliteType, unsaved.decimal100()), Fragment.of(", "), Fragment.encode(Int18.sqliteType, unsaved.decimal180()), Fragment.of(")\nRETURNING \"id\", \"string10\", \"string20\", \"string50\", \"string100\", \"string255\", \"decimal5_2\", \"decimal10_2\", \"decimal18_4\", \"decimal5_0\", \"decimal10_0\", \"decimal18_0\"\n")) + .updateReturning(PrecisionTypesRow.rowCodec.exactlyOne()).run(c); + } + + @Override + public SelectBuilder select() { + return SelectBuilder.of("\"precision_types\"", PrecisionTypesFields.structure, PrecisionTypesRow.rowCodec, Dialect.SQLITE); + } + + @Override + public List selectAll(ConnectionRead c) { + return concat(Fragment.of("select \"id\", \"string10\", \"string20\", \"string50\", \"string100\", \"string255\", \"decimal5_2\", \"decimal10_2\", \"decimal18_4\", \"decimal5_0\", \"decimal10_0\", \"decimal18_0\"\nfrom \"precision_types\"\n")).query(PrecisionTypesRow.rowCodec.all()).run(c); + } + + @Override + public Optional selectById( + PrecisionTypesId id, + ConnectionRead c + ) { + return concat(Fragment.of("select \"id\", \"string10\", \"string20\", \"string50\", \"string100\", \"string255\", \"decimal5_2\", \"decimal10_2\", \"decimal18_4\", \"decimal5_0\", \"decimal10_0\", \"decimal18_0\"\nfrom \"precision_types\"\nwhere \"id\" = "), Fragment.encode(PrecisionTypesId.sqliteType, id), Fragment.of("")).query(PrecisionTypesRow.rowCodec.first()).run(c); + } + + @Override + public List selectByIds( + List ids, + ConnectionRead c + ) { + ArrayList fragments = new ArrayList<>(); + for (var id : ids) { fragments.add(Fragment.encode(PrecisionTypesId.sqliteType, id)); }; + return Fragment.concat(Fragment.of("select \"id\", \"string10\", \"string20\", \"string50\", \"string100\", \"string255\", \"decimal5_2\", \"decimal10_2\", \"decimal18_4\", \"decimal5_0\", \"decimal10_0\", \"decimal18_0\" from \"precision_types\" where \"id\" in ("), Fragment.comma(fragments), Fragment.of(")")).query(PrecisionTypesRow.rowCodec.all()).run(c); + } + + @Override + public Map selectByIdsTracked( + List ids, + ConnectionRead c + ) { + HashMap ret = new HashMap(); + selectByIds(ids, c).forEach(row -> ret.put(row.id(), row)); + return ret; + } + + @Override + public UpdateBuilder update() { + return UpdateBuilder.of("\"precision_types\"", PrecisionTypesFields.structure, PrecisionTypesRow.rowCodec, Dialect.SQLITE); + } + + @Override + public Boolean update( + PrecisionTypesRow row, + Connection c + ) { + PrecisionTypesId id = row.id();; + return concat(Fragment.of("update \"precision_types\"\nset \"string10\" = "), Fragment.encode(String10.sqliteType, row.string10()), Fragment.of(",\n\"string20\" = "), Fragment.encode(String20.sqliteType, row.string20()), Fragment.of(",\n\"string50\" = "), Fragment.encode(String50.sqliteType, row.string50()), Fragment.of(",\n\"string100\" = "), Fragment.encode(String100.sqliteType, row.string100()), Fragment.of(",\n\"string255\" = "), Fragment.encode(String255.sqliteType, row.string255()), Fragment.of(",\n\"decimal5_2\" = "), Fragment.encode(Decimal5_2.sqliteType, row.decimal52()), Fragment.of(",\n\"decimal10_2\" = "), Fragment.encode(Decimal10_2.sqliteType, row.decimal102()), Fragment.of(",\n\"decimal18_4\" = "), Fragment.encode(Decimal18_4.sqliteType, row.decimal184()), Fragment.of(",\n\"decimal5_0\" = "), Fragment.encode(Int5.sqliteType, row.decimal50()), Fragment.of(",\n\"decimal10_0\" = "), Fragment.encode(Int10.sqliteType, row.decimal100()), Fragment.of(",\n\"decimal18_0\" = "), Fragment.encode(Int18.sqliteType, row.decimal180()), Fragment.of("\nwhere \"id\" = "), Fragment.encode(PrecisionTypesId.sqliteType, id), Fragment.of("")).update().run(c) > 0; + } + + @Override + public PrecisionTypesRow upsert( + PrecisionTypesRow unsaved, + Connection c + ) { + return concat(Fragment.of("INSERT INTO \"precision_types\"(\"id\", \"string10\", \"string20\", \"string50\", \"string100\", \"string255\", \"decimal5_2\", \"decimal10_2\", \"decimal18_4\", \"decimal5_0\", \"decimal10_0\", \"decimal18_0\")\nVALUES ("), Fragment.encode(PrecisionTypesId.sqliteType, unsaved.id()), Fragment.of(", "), Fragment.encode(String10.sqliteType, unsaved.string10()), Fragment.of(", "), Fragment.encode(String20.sqliteType, unsaved.string20()), Fragment.of(", "), Fragment.encode(String50.sqliteType, unsaved.string50()), Fragment.of(", "), Fragment.encode(String100.sqliteType, unsaved.string100()), Fragment.of(", "), Fragment.encode(String255.sqliteType, unsaved.string255()), Fragment.of(", "), Fragment.encode(Decimal5_2.sqliteType, unsaved.decimal52()), Fragment.of(", "), Fragment.encode(Decimal10_2.sqliteType, unsaved.decimal102()), Fragment.of(", "), Fragment.encode(Decimal18_4.sqliteType, unsaved.decimal184()), Fragment.of(", "), Fragment.encode(Int5.sqliteType, unsaved.decimal50()), Fragment.of(", "), Fragment.encode(Int10.sqliteType, unsaved.decimal100()), Fragment.of(", "), Fragment.encode(Int18.sqliteType, unsaved.decimal180()), Fragment.of(")\nON CONFLICT (\"id\")\nDO UPDATE SET\n \"string10\" = EXCLUDED.\"string10\",\n\"string20\" = EXCLUDED.\"string20\",\n\"string50\" = EXCLUDED.\"string50\",\n\"string100\" = EXCLUDED.\"string100\",\n\"string255\" = EXCLUDED.\"string255\",\n\"decimal5_2\" = EXCLUDED.\"decimal5_2\",\n\"decimal10_2\" = EXCLUDED.\"decimal10_2\",\n\"decimal18_4\" = EXCLUDED.\"decimal18_4\",\n\"decimal5_0\" = EXCLUDED.\"decimal5_0\",\n\"decimal10_0\" = EXCLUDED.\"decimal10_0\",\n\"decimal18_0\" = EXCLUDED.\"decimal18_0\"\nRETURNING \"id\", \"string10\", \"string20\", \"string50\", \"string100\", \"string255\", \"decimal5_2\", \"decimal10_2\", \"decimal18_4\", \"decimal5_0\", \"decimal10_0\", \"decimal18_0\"")) + .updateReturning(PrecisionTypesRow.rowCodec.exactlyOne()) + .run(c); + } + + @Override + public List upsertBatch( + Iterator unsaved, + Connection c + ) { + return concat(Fragment.of("INSERT INTO \"precision_types\"(\"id\", \"string10\", \"string20\", \"string50\", \"string100\", \"string255\", \"decimal5_2\", \"decimal10_2\", \"decimal18_4\", \"decimal5_0\", \"decimal10_0\", \"decimal18_0\")\nVALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\nON CONFLICT (\"id\")\nDO UPDATE SET\n \"string10\" = EXCLUDED.\"string10\",\n\"string20\" = EXCLUDED.\"string20\",\n\"string50\" = EXCLUDED.\"string50\",\n\"string100\" = EXCLUDED.\"string100\",\n\"string255\" = EXCLUDED.\"string255\",\n\"decimal5_2\" = EXCLUDED.\"decimal5_2\",\n\"decimal10_2\" = EXCLUDED.\"decimal10_2\",\n\"decimal18_4\" = EXCLUDED.\"decimal18_4\",\n\"decimal5_0\" = EXCLUDED.\"decimal5_0\",\n\"decimal10_0\" = EXCLUDED.\"decimal10_0\",\n\"decimal18_0\" = EXCLUDED.\"decimal18_0\"\nRETURNING \"id\", \"string10\", \"string20\", \"string50\", \"string100\", \"string255\", \"decimal5_2\", \"decimal10_2\", \"decimal18_4\", \"decimal5_0\", \"decimal10_0\", \"decimal18_0\"")) + .updateReturningEach(PrecisionTypesRow.rowCodec, unsaved) + .run(c); + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/precision_types/PrecisionTypesRepoMock.java b/testers/sqlite/java/generated-and-checked-in/testdb/precision_types/PrecisionTypesRepoMock.java new file mode 100644 index 0000000000..edc4e3c2ac --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/precision_types/PrecisionTypesRepoMock.java @@ -0,0 +1,157 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precision_types; + +import dev.typr.dsl.DeleteBuilder; +import dev.typr.dsl.DeleteBuilderMock; +import dev.typr.dsl.DeleteParams; +import dev.typr.dsl.SelectBuilder; +import dev.typr.dsl.SelectBuilderMock; +import dev.typr.dsl.SelectParams; +import dev.typr.dsl.UpdateBuilder; +import dev.typr.dsl.UpdateBuilderMock; +import dev.typr.dsl.UpdateParams; +import dev.typr.foundations.Connection; +import dev.typr.foundations.ConnectionRead; +import java.lang.RuntimeException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.function.Function; +import java.util.stream.Collectors; + +public record PrecisionTypesRepoMock(HashMap map) implements PrecisionTypesRepo { + public PrecisionTypesRepoMock() { + this(new HashMap()); + } + + public PrecisionTypesRepoMock withMap(HashMap map) { + return new PrecisionTypesRepoMock(map); + } + + @Override + public DeleteBuilder delete() { + return new DeleteBuilderMock<>(PrecisionTypesFields.structure, () -> new ArrayList<>(map.values()), DeleteParams.empty(), row -> row.id(), id -> map.remove(id)); + } + + @Override + public Boolean deleteById( + PrecisionTypesId id, + Connection c + ) { + return Optional.ofNullable(map.remove(id)).isPresent(); + } + + @Override + public Integer deleteByIds( + List ids, + Connection c + ) { + var count = 0; + for (var id : ids) { + if (Optional.ofNullable(map.remove(id)).isPresent()) { + count = count + 1;; + } + }; + return count; + } + + @Override + public PrecisionTypesRow insert( + PrecisionTypesRow unsaved, + Connection c + ) { + if (map.containsKey(unsaved.id())) { + throw new RuntimeException("id " + unsaved.id() + " already exists"); + } + map.put(unsaved.id(), unsaved); + return unsaved; + } + + @Override + public SelectBuilder select() { + return new SelectBuilderMock<>(PrecisionTypesFields.structure, () -> new ArrayList<>(map.values()), SelectParams.empty()); + } + + @Override + public List selectAll(ConnectionRead c) { + return new ArrayList<>(map.values()); + } + + @Override + public Optional selectById( + PrecisionTypesId id, + ConnectionRead c + ) { + return Optional.ofNullable(map.get(id)); + } + + @Override + public List selectByIds( + List ids, + ConnectionRead c + ) { + var result = new ArrayList(); + for (var id : ids) { + var opt = Optional.ofNullable(map.get(id)); + if (opt.isPresent()) { + result.add(opt.get()); + } + }; + return result; + } + + @Override + public Map selectByIdsTracked( + List ids, + ConnectionRead c + ) { + return selectByIds(ids, c).stream().collect(Collectors.toMap((PrecisionTypesRow row) -> row.id(), Function.identity())); + } + + @Override + public UpdateBuilder update() { + return new UpdateBuilderMock<>(PrecisionTypesFields.structure, () -> new ArrayList<>(map.values()), UpdateParams.empty(), row -> row); + } + + @Override + public Boolean update( + PrecisionTypesRow row, + Connection c + ) { + var shouldUpdate = Optional.ofNullable(map.get(row.id())).filter(oldRow -> !oldRow.equals(row)).isPresent(); + if (shouldUpdate) { + map.put(row.id(), row);; + } + return shouldUpdate; + } + + @Override + public PrecisionTypesRow upsert( + PrecisionTypesRow unsaved, + Connection c + ) { + map.put(unsaved.id(), unsaved); + return unsaved; + } + + @Override + public List upsertBatch( + Iterator unsaved, + Connection c + ) { + var result = new ArrayList(); + while (unsaved.hasNext()) { + var row = unsaved.next(); + map.put(row.id(), row); + result.add(row); + }; + return result; + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/precision_types/PrecisionTypesRow.java b/testers/sqlite/java/generated-and-checked-in/testdb/precision_types/PrecisionTypesRow.java new file mode 100644 index 0000000000..f9f71589af --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/precision_types/PrecisionTypesRow.java @@ -0,0 +1,150 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precision_types; + +import com.fasterxml.jackson.annotation.JsonProperty; +import dev.typr.dsl.RowCodecs; +import dev.typr.foundations.RowCodec; +import dev.typr.foundations.Tuple.Tuple12; +import testdb.precisetypes.Decimal10_2; +import testdb.precisetypes.Decimal18_4; +import testdb.precisetypes.Decimal5_2; +import testdb.precisetypes.Int10; +import testdb.precisetypes.Int18; +import testdb.precisetypes.Int5; +import testdb.precisetypes.String10; +import testdb.precisetypes.String100; +import testdb.precisetypes.String20; +import testdb.precisetypes.String255; +import testdb.precisetypes.String50; + +/** Table: precision_types + * Primary key: id + */ +public record PrecisionTypesRow( + PrecisionTypesId id, + String10 string10, + String20 string20, + String50 string50, + String100 string100, + String255 string255, + @JsonProperty("decimal5_2") Decimal5_2 decimal52, + @JsonProperty("decimal10_2") Decimal10_2 decimal102, + @JsonProperty("decimal18_4") Decimal18_4 decimal184, + @JsonProperty("decimal5_0") Int5 decimal50, + @JsonProperty("decimal10_0") Int10 decimal100, + @JsonProperty("decimal18_0") Int18 decimal180 +) implements Tuple12 { + public PrecisionTypesRow withId(PrecisionTypesId id) { + return new PrecisionTypesRow(id, string10, string20, string50, string100, string255, decimal52, decimal102, decimal184, decimal50, decimal100, decimal180); + } + + public PrecisionTypesRow withString10(String10 string10) { + return new PrecisionTypesRow(id, string10, string20, string50, string100, string255, decimal52, decimal102, decimal184, decimal50, decimal100, decimal180); + } + + public PrecisionTypesRow withString20(String20 string20) { + return new PrecisionTypesRow(id, string10, string20, string50, string100, string255, decimal52, decimal102, decimal184, decimal50, decimal100, decimal180); + } + + public PrecisionTypesRow withString50(String50 string50) { + return new PrecisionTypesRow(id, string10, string20, string50, string100, string255, decimal52, decimal102, decimal184, decimal50, decimal100, decimal180); + } + + public PrecisionTypesRow withString100(String100 string100) { + return new PrecisionTypesRow(id, string10, string20, string50, string100, string255, decimal52, decimal102, decimal184, decimal50, decimal100, decimal180); + } + + public PrecisionTypesRow withString255(String255 string255) { + return new PrecisionTypesRow(id, string10, string20, string50, string100, string255, decimal52, decimal102, decimal184, decimal50, decimal100, decimal180); + } + + public PrecisionTypesRow withDecimal52(Decimal5_2 decimal52) { + return new PrecisionTypesRow(id, string10, string20, string50, string100, string255, decimal52, decimal102, decimal184, decimal50, decimal100, decimal180); + } + + public PrecisionTypesRow withDecimal102(Decimal10_2 decimal102) { + return new PrecisionTypesRow(id, string10, string20, string50, string100, string255, decimal52, decimal102, decimal184, decimal50, decimal100, decimal180); + } + + public PrecisionTypesRow withDecimal184(Decimal18_4 decimal184) { + return new PrecisionTypesRow(id, string10, string20, string50, string100, string255, decimal52, decimal102, decimal184, decimal50, decimal100, decimal180); + } + + public PrecisionTypesRow withDecimal50(Int5 decimal50) { + return new PrecisionTypesRow(id, string10, string20, string50, string100, string255, decimal52, decimal102, decimal184, decimal50, decimal100, decimal180); + } + + public PrecisionTypesRow withDecimal100(Int10 decimal100) { + return new PrecisionTypesRow(id, string10, string20, string50, string100, string255, decimal52, decimal102, decimal184, decimal50, decimal100, decimal180); + } + + public PrecisionTypesRow withDecimal180(Int18 decimal180) { + return new PrecisionTypesRow(id, string10, string20, string50, string100, string255, decimal52, decimal102, decimal184, decimal50, decimal100, decimal180); + } + + public static RowCodec rowCodec = RowCodecs.of(PrecisionTypesId.sqliteType, String10.sqliteType, String20.sqliteType, String50.sqliteType, String100.sqliteType, String255.sqliteType, Decimal5_2.sqliteType, Decimal10_2.sqliteType, Decimal18_4.sqliteType, Int5.sqliteType, Int10.sqliteType, Int18.sqliteType, PrecisionTypesRow::new, row -> new Object[]{row.id(), row.string10(), row.string20(), row.string50(), row.string100(), row.string255(), row.decimal52(), row.decimal102(), row.decimal184(), row.decimal50(), row.decimal100(), row.decimal180()}); + + @Override + public PrecisionTypesId _1() { + return id; + } + + @Override + public Int5 _10() { + return decimal50; + } + + @Override + public Int10 _11() { + return decimal100; + } + + @Override + public Int18 _12() { + return decimal180; + } + + @Override + public String10 _2() { + return string10; + } + + @Override + public String20 _3() { + return string20; + } + + @Override + public String50 _4() { + return string50; + } + + @Override + public String100 _5() { + return string100; + } + + @Override + public String255 _6() { + return string255; + } + + @Override + public Decimal5_2 _7() { + return decimal52; + } + + @Override + public Decimal10_2 _8() { + return decimal102; + } + + @Override + public Decimal18_4 _9() { + return decimal184; + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/precision_types_null/PrecisionTypesNullFields.java b/testers/sqlite/java/generated-and-checked-in/testdb/precision_types_null/PrecisionTypesNullFields.java new file mode 100644 index 0000000000..4bbcf9b223 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/precision_types_null/PrecisionTypesNullFields.java @@ -0,0 +1,167 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precision_types_null; + +import dev.typr.dsl.FieldsBase; +import dev.typr.dsl.Path; +import dev.typr.dsl.RelationStructure; +import dev.typr.dsl.SqlExpr; +import dev.typr.dsl.SqlExpr.FieldLike; +import dev.typr.dsl.SqlExpr.IdField; +import dev.typr.dsl.SqlExpr.OptField; +import dev.typr.dsl.TupleExpr.TupleExpr12; +import dev.typr.foundations.RowCodec; +import java.util.List; +import java.util.Optional; +import testdb.precisetypes.Decimal10_2; +import testdb.precisetypes.Decimal18_4; +import testdb.precisetypes.Decimal5_2; +import testdb.precisetypes.Int10; +import testdb.precisetypes.Int18; +import testdb.precisetypes.Int5; +import testdb.precisetypes.String10; +import testdb.precisetypes.String100; +import testdb.precisetypes.String20; +import testdb.precisetypes.String255; +import testdb.precisetypes.String50; + +public class PrecisionTypesNullFields extends TupleExpr12 implements RelationStructure, FieldsBase { + List _path; + + public PrecisionTypesNullFields(List _path) { + this._path = _path; + } + + public static PrecisionTypesNullFields structure = new PrecisionTypesNullFields(java.util.Collections.emptyList()); + + public IdField id() { + return new IdField(_path, "id", PrecisionTypesNullRow::id, Optional.empty(), Optional.empty(), (row, value) -> row.withId(value), PrecisionTypesNullId.sqliteType); + } + + public OptField string10() { + return new OptField(_path, "string10", PrecisionTypesNullRow::string10, Optional.empty(), Optional.empty(), (row, value) -> row.withString10(value), String10.sqliteType); + } + + public OptField string20() { + return new OptField(_path, "string20", PrecisionTypesNullRow::string20, Optional.empty(), Optional.empty(), (row, value) -> row.withString20(value), String20.sqliteType); + } + + public OptField string50() { + return new OptField(_path, "string50", PrecisionTypesNullRow::string50, Optional.empty(), Optional.empty(), (row, value) -> row.withString50(value), String50.sqliteType); + } + + public OptField string100() { + return new OptField(_path, "string100", PrecisionTypesNullRow::string100, Optional.empty(), Optional.empty(), (row, value) -> row.withString100(value), String100.sqliteType); + } + + public OptField string255() { + return new OptField(_path, "string255", PrecisionTypesNullRow::string255, Optional.empty(), Optional.empty(), (row, value) -> row.withString255(value), String255.sqliteType); + } + + public OptField decimal52() { + return new OptField(_path, "decimal5_2", PrecisionTypesNullRow::decimal52, Optional.empty(), Optional.empty(), (row, value) -> row.withDecimal52(value), Decimal5_2.sqliteType); + } + + public OptField decimal102() { + return new OptField(_path, "decimal10_2", PrecisionTypesNullRow::decimal102, Optional.empty(), Optional.empty(), (row, value) -> row.withDecimal102(value), Decimal10_2.sqliteType); + } + + public OptField decimal184() { + return new OptField(_path, "decimal18_4", PrecisionTypesNullRow::decimal184, Optional.empty(), Optional.empty(), (row, value) -> row.withDecimal184(value), Decimal18_4.sqliteType); + } + + public OptField decimal50() { + return new OptField(_path, "decimal5_0", PrecisionTypesNullRow::decimal50, Optional.empty(), Optional.empty(), (row, value) -> row.withDecimal50(value), Int5.sqliteType); + } + + public OptField decimal100() { + return new OptField(_path, "decimal10_0", PrecisionTypesNullRow::decimal100, Optional.empty(), Optional.empty(), (row, value) -> row.withDecimal100(value), Int10.sqliteType); + } + + public OptField decimal180() { + return new OptField(_path, "decimal18_0", PrecisionTypesNullRow::decimal180, Optional.empty(), Optional.empty(), (row, value) -> row.withDecimal180(value), Int18.sqliteType); + } + + @Override + public List _path() { + return _path; + } + + @Override + public List> columns() { + return java.util.List.of(this.id(), this.string10(), this.string20(), this.string50(), this.string100(), this.string255(), this.decimal52(), this.decimal102(), this.decimal184(), this.decimal50(), this.decimal100(), this.decimal180()); + } + + @Override + public RowCodec rowCodec() { + return PrecisionTypesNullRow.rowCodec; + } + + @Override + public RelationStructure withPaths(List _path) { + return new PrecisionTypesNullFields(_path); + } + + @Override + public SqlExpr _1() { + return id(); + } + + @Override + public SqlExpr _2() { + return string10(); + } + + @Override + public SqlExpr _3() { + return string20(); + } + + @Override + public SqlExpr _4() { + return string50(); + } + + @Override + public SqlExpr _5() { + return string100(); + } + + @Override + public SqlExpr _6() { + return string255(); + } + + @Override + public SqlExpr _7() { + return decimal52(); + } + + @Override + public SqlExpr _8() { + return decimal102(); + } + + @Override + public SqlExpr _9() { + return decimal184(); + } + + @Override + public SqlExpr _10() { + return decimal50(); + } + + @Override + public SqlExpr _11() { + return decimal100(); + } + + @Override + public SqlExpr _12() { + return decimal180(); + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/precision_types_null/PrecisionTypesNullId.java b/testers/sqlite/java/generated-and-checked-in/testdb/precision_types_null/PrecisionTypesNullId.java new file mode 100644 index 0000000000..ef5797d57d --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/precision_types_null/PrecisionTypesNullId.java @@ -0,0 +1,29 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precision_types_null; + +import com.fasterxml.jackson.annotation.JsonValue; +import dev.typr.foundations.Bijection; +import dev.typr.foundations.SqliteType; +import dev.typr.foundations.SqliteTypes; + +/** Type for the primary key of table `precision_types_null` */ +public record PrecisionTypesNullId(@JsonValue Long value) { + public PrecisionTypesNullId withValue(Long value) { + return new PrecisionTypesNullId(value); + } + + @Override + public java.lang.String toString() { + return value.toString(); + } + + static public Bijection bijection = + Bijection.of(PrecisionTypesNullId::value, PrecisionTypesNullId::new); + + static public SqliteType sqliteType = + SqliteTypes.integer.to(Bijection.of(PrecisionTypesNullId::new, PrecisionTypesNullId::value)); +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/precision_types_null/PrecisionTypesNullRepo.java b/testers/sqlite/java/generated-and-checked-in/testdb/precision_types_null/PrecisionTypesNullRepo.java new file mode 100644 index 0000000000..b214f26de4 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/precision_types_null/PrecisionTypesNullRepo.java @@ -0,0 +1,71 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precision_types_null; + +import dev.typr.dsl.DeleteBuilder; +import dev.typr.dsl.SelectBuilder; +import dev.typr.dsl.UpdateBuilder; +import dev.typr.foundations.Connection; +import dev.typr.foundations.ConnectionRead; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +public interface PrecisionTypesNullRepo { + DeleteBuilder delete(); + + Boolean deleteById( + PrecisionTypesNullId id, + Connection c + ); + + Integer deleteByIds( + List ids, + Connection c + ); + + PrecisionTypesNullRow insert( + PrecisionTypesNullRow unsaved, + Connection c + ); + + SelectBuilder select(); + + List selectAll(ConnectionRead c); + + Optional selectById( + PrecisionTypesNullId id, + ConnectionRead c + ); + + List selectByIds( + List ids, + ConnectionRead c + ); + + Map selectByIdsTracked( + List ids, + ConnectionRead c + ); + + UpdateBuilder update(); + + Boolean update( + PrecisionTypesNullRow row, + Connection c + ); + + PrecisionTypesNullRow upsert( + PrecisionTypesNullRow unsaved, + Connection c + ); + + List upsertBatch( + Iterator unsaved, + Connection c + ); +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/precision_types_null/PrecisionTypesNullRepoImpl.java b/testers/sqlite/java/generated-and-checked-in/testdb/precision_types_null/PrecisionTypesNullRepoImpl.java new file mode 100644 index 0000000000..068a2e87df --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/precision_types_null/PrecisionTypesNullRepoImpl.java @@ -0,0 +1,138 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precision_types_null; + +import dev.typr.dsl.DeleteBuilder; +import dev.typr.dsl.Dialect; +import dev.typr.dsl.SelectBuilder; +import dev.typr.dsl.UpdateBuilder; +import dev.typr.foundations.Connection; +import dev.typr.foundations.ConnectionRead; +import dev.typr.foundations.Fragment; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import testdb.precisetypes.Decimal10_2; +import testdb.precisetypes.Decimal18_4; +import testdb.precisetypes.Decimal5_2; +import testdb.precisetypes.Int10; +import testdb.precisetypes.Int18; +import testdb.precisetypes.Int5; +import testdb.precisetypes.String10; +import testdb.precisetypes.String100; +import testdb.precisetypes.String20; +import testdb.precisetypes.String255; +import testdb.precisetypes.String50; +import static dev.typr.foundations.Fragment.concat; + +public class PrecisionTypesNullRepoImpl implements PrecisionTypesNullRepo { + @Override + public DeleteBuilder delete() { + return DeleteBuilder.of("\"precision_types_null\"", PrecisionTypesNullFields.structure, Dialect.SQLITE); + } + + @Override + public Boolean deleteById( + PrecisionTypesNullId id, + Connection c + ) { + return concat(Fragment.of("delete from \"precision_types_null\" where \"id\" = "), Fragment.encode(PrecisionTypesNullId.sqliteType, id), Fragment.of("")).update().run(c) > 0; + } + + @Override + public Integer deleteByIds( + List ids, + Connection c + ) { + ArrayList fragments = new ArrayList<>(); + for (var id : ids) { fragments.add(Fragment.encode(PrecisionTypesNullId.sqliteType, id)); }; + return Fragment.concat(Fragment.of("delete from \"precision_types_null\" where \"id\" in ("), Fragment.comma(fragments), Fragment.of(")")).update().run(c); + } + + @Override + public PrecisionTypesNullRow insert( + PrecisionTypesNullRow unsaved, + Connection c + ) { + return concat(Fragment.of("insert into \"precision_types_null\"(\"id\", \"string10\", \"string20\", \"string50\", \"string100\", \"string255\", \"decimal5_2\", \"decimal10_2\", \"decimal18_4\", \"decimal5_0\", \"decimal10_0\", \"decimal18_0\")\nvalues ("), Fragment.encode(PrecisionTypesNullId.sqliteType, unsaved.id()), Fragment.of(", "), Fragment.encode(String10.sqliteType.opt(), unsaved.string10()), Fragment.of(", "), Fragment.encode(String20.sqliteType.opt(), unsaved.string20()), Fragment.of(", "), Fragment.encode(String50.sqliteType.opt(), unsaved.string50()), Fragment.of(", "), Fragment.encode(String100.sqliteType.opt(), unsaved.string100()), Fragment.of(", "), Fragment.encode(String255.sqliteType.opt(), unsaved.string255()), Fragment.of(", "), Fragment.encode(Decimal5_2.sqliteType.opt(), unsaved.decimal52()), Fragment.of(", "), Fragment.encode(Decimal10_2.sqliteType.opt(), unsaved.decimal102()), Fragment.of(", "), Fragment.encode(Decimal18_4.sqliteType.opt(), unsaved.decimal184()), Fragment.of(", "), Fragment.encode(Int5.sqliteType.opt(), unsaved.decimal50()), Fragment.of(", "), Fragment.encode(Int10.sqliteType.opt(), unsaved.decimal100()), Fragment.of(", "), Fragment.encode(Int18.sqliteType.opt(), unsaved.decimal180()), Fragment.of(")\nRETURNING \"id\", \"string10\", \"string20\", \"string50\", \"string100\", \"string255\", \"decimal5_2\", \"decimal10_2\", \"decimal18_4\", \"decimal5_0\", \"decimal10_0\", \"decimal18_0\"\n")) + .updateReturning(PrecisionTypesNullRow.rowCodec.exactlyOne()).run(c); + } + + @Override + public SelectBuilder select() { + return SelectBuilder.of("\"precision_types_null\"", PrecisionTypesNullFields.structure, PrecisionTypesNullRow.rowCodec, Dialect.SQLITE); + } + + @Override + public List selectAll(ConnectionRead c) { + return concat(Fragment.of("select \"id\", \"string10\", \"string20\", \"string50\", \"string100\", \"string255\", \"decimal5_2\", \"decimal10_2\", \"decimal18_4\", \"decimal5_0\", \"decimal10_0\", \"decimal18_0\"\nfrom \"precision_types_null\"\n")).query(PrecisionTypesNullRow.rowCodec.all()).run(c); + } + + @Override + public Optional selectById( + PrecisionTypesNullId id, + ConnectionRead c + ) { + return concat(Fragment.of("select \"id\", \"string10\", \"string20\", \"string50\", \"string100\", \"string255\", \"decimal5_2\", \"decimal10_2\", \"decimal18_4\", \"decimal5_0\", \"decimal10_0\", \"decimal18_0\"\nfrom \"precision_types_null\"\nwhere \"id\" = "), Fragment.encode(PrecisionTypesNullId.sqliteType, id), Fragment.of("")).query(PrecisionTypesNullRow.rowCodec.first()).run(c); + } + + @Override + public List selectByIds( + List ids, + ConnectionRead c + ) { + ArrayList fragments = new ArrayList<>(); + for (var id : ids) { fragments.add(Fragment.encode(PrecisionTypesNullId.sqliteType, id)); }; + return Fragment.concat(Fragment.of("select \"id\", \"string10\", \"string20\", \"string50\", \"string100\", \"string255\", \"decimal5_2\", \"decimal10_2\", \"decimal18_4\", \"decimal5_0\", \"decimal10_0\", \"decimal18_0\" from \"precision_types_null\" where \"id\" in ("), Fragment.comma(fragments), Fragment.of(")")).query(PrecisionTypesNullRow.rowCodec.all()).run(c); + } + + @Override + public Map selectByIdsTracked( + List ids, + ConnectionRead c + ) { + HashMap ret = new HashMap(); + selectByIds(ids, c).forEach(row -> ret.put(row.id(), row)); + return ret; + } + + @Override + public UpdateBuilder update() { + return UpdateBuilder.of("\"precision_types_null\"", PrecisionTypesNullFields.structure, PrecisionTypesNullRow.rowCodec, Dialect.SQLITE); + } + + @Override + public Boolean update( + PrecisionTypesNullRow row, + Connection c + ) { + PrecisionTypesNullId id = row.id();; + return concat(Fragment.of("update \"precision_types_null\"\nset \"string10\" = "), Fragment.encode(String10.sqliteType.opt(), row.string10()), Fragment.of(",\n\"string20\" = "), Fragment.encode(String20.sqliteType.opt(), row.string20()), Fragment.of(",\n\"string50\" = "), Fragment.encode(String50.sqliteType.opt(), row.string50()), Fragment.of(",\n\"string100\" = "), Fragment.encode(String100.sqliteType.opt(), row.string100()), Fragment.of(",\n\"string255\" = "), Fragment.encode(String255.sqliteType.opt(), row.string255()), Fragment.of(",\n\"decimal5_2\" = "), Fragment.encode(Decimal5_2.sqliteType.opt(), row.decimal52()), Fragment.of(",\n\"decimal10_2\" = "), Fragment.encode(Decimal10_2.sqliteType.opt(), row.decimal102()), Fragment.of(",\n\"decimal18_4\" = "), Fragment.encode(Decimal18_4.sqliteType.opt(), row.decimal184()), Fragment.of(",\n\"decimal5_0\" = "), Fragment.encode(Int5.sqliteType.opt(), row.decimal50()), Fragment.of(",\n\"decimal10_0\" = "), Fragment.encode(Int10.sqliteType.opt(), row.decimal100()), Fragment.of(",\n\"decimal18_0\" = "), Fragment.encode(Int18.sqliteType.opt(), row.decimal180()), Fragment.of("\nwhere \"id\" = "), Fragment.encode(PrecisionTypesNullId.sqliteType, id), Fragment.of("")).update().run(c) > 0; + } + + @Override + public PrecisionTypesNullRow upsert( + PrecisionTypesNullRow unsaved, + Connection c + ) { + return concat(Fragment.of("INSERT INTO \"precision_types_null\"(\"id\", \"string10\", \"string20\", \"string50\", \"string100\", \"string255\", \"decimal5_2\", \"decimal10_2\", \"decimal18_4\", \"decimal5_0\", \"decimal10_0\", \"decimal18_0\")\nVALUES ("), Fragment.encode(PrecisionTypesNullId.sqliteType, unsaved.id()), Fragment.of(", "), Fragment.encode(String10.sqliteType.opt(), unsaved.string10()), Fragment.of(", "), Fragment.encode(String20.sqliteType.opt(), unsaved.string20()), Fragment.of(", "), Fragment.encode(String50.sqliteType.opt(), unsaved.string50()), Fragment.of(", "), Fragment.encode(String100.sqliteType.opt(), unsaved.string100()), Fragment.of(", "), Fragment.encode(String255.sqliteType.opt(), unsaved.string255()), Fragment.of(", "), Fragment.encode(Decimal5_2.sqliteType.opt(), unsaved.decimal52()), Fragment.of(", "), Fragment.encode(Decimal10_2.sqliteType.opt(), unsaved.decimal102()), Fragment.of(", "), Fragment.encode(Decimal18_4.sqliteType.opt(), unsaved.decimal184()), Fragment.of(", "), Fragment.encode(Int5.sqliteType.opt(), unsaved.decimal50()), Fragment.of(", "), Fragment.encode(Int10.sqliteType.opt(), unsaved.decimal100()), Fragment.of(", "), Fragment.encode(Int18.sqliteType.opt(), unsaved.decimal180()), Fragment.of(")\nON CONFLICT (\"id\")\nDO UPDATE SET\n \"string10\" = EXCLUDED.\"string10\",\n\"string20\" = EXCLUDED.\"string20\",\n\"string50\" = EXCLUDED.\"string50\",\n\"string100\" = EXCLUDED.\"string100\",\n\"string255\" = EXCLUDED.\"string255\",\n\"decimal5_2\" = EXCLUDED.\"decimal5_2\",\n\"decimal10_2\" = EXCLUDED.\"decimal10_2\",\n\"decimal18_4\" = EXCLUDED.\"decimal18_4\",\n\"decimal5_0\" = EXCLUDED.\"decimal5_0\",\n\"decimal10_0\" = EXCLUDED.\"decimal10_0\",\n\"decimal18_0\" = EXCLUDED.\"decimal18_0\"\nRETURNING \"id\", \"string10\", \"string20\", \"string50\", \"string100\", \"string255\", \"decimal5_2\", \"decimal10_2\", \"decimal18_4\", \"decimal5_0\", \"decimal10_0\", \"decimal18_0\"")) + .updateReturning(PrecisionTypesNullRow.rowCodec.exactlyOne()) + .run(c); + } + + @Override + public List upsertBatch( + Iterator unsaved, + Connection c + ) { + return concat(Fragment.of("INSERT INTO \"precision_types_null\"(\"id\", \"string10\", \"string20\", \"string50\", \"string100\", \"string255\", \"decimal5_2\", \"decimal10_2\", \"decimal18_4\", \"decimal5_0\", \"decimal10_0\", \"decimal18_0\")\nVALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\nON CONFLICT (\"id\")\nDO UPDATE SET\n \"string10\" = EXCLUDED.\"string10\",\n\"string20\" = EXCLUDED.\"string20\",\n\"string50\" = EXCLUDED.\"string50\",\n\"string100\" = EXCLUDED.\"string100\",\n\"string255\" = EXCLUDED.\"string255\",\n\"decimal5_2\" = EXCLUDED.\"decimal5_2\",\n\"decimal10_2\" = EXCLUDED.\"decimal10_2\",\n\"decimal18_4\" = EXCLUDED.\"decimal18_4\",\n\"decimal5_0\" = EXCLUDED.\"decimal5_0\",\n\"decimal10_0\" = EXCLUDED.\"decimal10_0\",\n\"decimal18_0\" = EXCLUDED.\"decimal18_0\"\nRETURNING \"id\", \"string10\", \"string20\", \"string50\", \"string100\", \"string255\", \"decimal5_2\", \"decimal10_2\", \"decimal18_4\", \"decimal5_0\", \"decimal10_0\", \"decimal18_0\"")) + .updateReturningEach(PrecisionTypesNullRow.rowCodec, unsaved) + .run(c); + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/precision_types_null/PrecisionTypesNullRepoMock.java b/testers/sqlite/java/generated-and-checked-in/testdb/precision_types_null/PrecisionTypesNullRepoMock.java new file mode 100644 index 0000000000..8162ef8cfe --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/precision_types_null/PrecisionTypesNullRepoMock.java @@ -0,0 +1,157 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precision_types_null; + +import dev.typr.dsl.DeleteBuilder; +import dev.typr.dsl.DeleteBuilderMock; +import dev.typr.dsl.DeleteParams; +import dev.typr.dsl.SelectBuilder; +import dev.typr.dsl.SelectBuilderMock; +import dev.typr.dsl.SelectParams; +import dev.typr.dsl.UpdateBuilder; +import dev.typr.dsl.UpdateBuilderMock; +import dev.typr.dsl.UpdateParams; +import dev.typr.foundations.Connection; +import dev.typr.foundations.ConnectionRead; +import java.lang.RuntimeException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.function.Function; +import java.util.stream.Collectors; + +public record PrecisionTypesNullRepoMock(HashMap map) implements PrecisionTypesNullRepo { + public PrecisionTypesNullRepoMock() { + this(new HashMap()); + } + + public PrecisionTypesNullRepoMock withMap(HashMap map) { + return new PrecisionTypesNullRepoMock(map); + } + + @Override + public DeleteBuilder delete() { + return new DeleteBuilderMock<>(PrecisionTypesNullFields.structure, () -> new ArrayList<>(map.values()), DeleteParams.empty(), row -> row.id(), id -> map.remove(id)); + } + + @Override + public Boolean deleteById( + PrecisionTypesNullId id, + Connection c + ) { + return Optional.ofNullable(map.remove(id)).isPresent(); + } + + @Override + public Integer deleteByIds( + List ids, + Connection c + ) { + var count = 0; + for (var id : ids) { + if (Optional.ofNullable(map.remove(id)).isPresent()) { + count = count + 1;; + } + }; + return count; + } + + @Override + public PrecisionTypesNullRow insert( + PrecisionTypesNullRow unsaved, + Connection c + ) { + if (map.containsKey(unsaved.id())) { + throw new RuntimeException("id " + unsaved.id() + " already exists"); + } + map.put(unsaved.id(), unsaved); + return unsaved; + } + + @Override + public SelectBuilder select() { + return new SelectBuilderMock<>(PrecisionTypesNullFields.structure, () -> new ArrayList<>(map.values()), SelectParams.empty()); + } + + @Override + public List selectAll(ConnectionRead c) { + return new ArrayList<>(map.values()); + } + + @Override + public Optional selectById( + PrecisionTypesNullId id, + ConnectionRead c + ) { + return Optional.ofNullable(map.get(id)); + } + + @Override + public List selectByIds( + List ids, + ConnectionRead c + ) { + var result = new ArrayList(); + for (var id : ids) { + var opt = Optional.ofNullable(map.get(id)); + if (opt.isPresent()) { + result.add(opt.get()); + } + }; + return result; + } + + @Override + public Map selectByIdsTracked( + List ids, + ConnectionRead c + ) { + return selectByIds(ids, c).stream().collect(Collectors.toMap((PrecisionTypesNullRow row) -> row.id(), Function.identity())); + } + + @Override + public UpdateBuilder update() { + return new UpdateBuilderMock<>(PrecisionTypesNullFields.structure, () -> new ArrayList<>(map.values()), UpdateParams.empty(), row -> row); + } + + @Override + public Boolean update( + PrecisionTypesNullRow row, + Connection c + ) { + var shouldUpdate = Optional.ofNullable(map.get(row.id())).filter(oldRow -> !oldRow.equals(row)).isPresent(); + if (shouldUpdate) { + map.put(row.id(), row);; + } + return shouldUpdate; + } + + @Override + public PrecisionTypesNullRow upsert( + PrecisionTypesNullRow unsaved, + Connection c + ) { + map.put(unsaved.id(), unsaved); + return unsaved; + } + + @Override + public List upsertBatch( + Iterator unsaved, + Connection c + ) { + var result = new ArrayList(); + while (unsaved.hasNext()) { + var row = unsaved.next(); + map.put(row.id(), row); + result.add(row); + }; + return result; + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/precision_types_null/PrecisionTypesNullRow.java b/testers/sqlite/java/generated-and-checked-in/testdb/precision_types_null/PrecisionTypesNullRow.java new file mode 100644 index 0000000000..11895fb804 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/precision_types_null/PrecisionTypesNullRow.java @@ -0,0 +1,151 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precision_types_null; + +import com.fasterxml.jackson.annotation.JsonProperty; +import dev.typr.dsl.RowCodecs; +import dev.typr.foundations.RowCodec; +import dev.typr.foundations.Tuple.Tuple12; +import java.util.Optional; +import testdb.precisetypes.Decimal10_2; +import testdb.precisetypes.Decimal18_4; +import testdb.precisetypes.Decimal5_2; +import testdb.precisetypes.Int10; +import testdb.precisetypes.Int18; +import testdb.precisetypes.Int5; +import testdb.precisetypes.String10; +import testdb.precisetypes.String100; +import testdb.precisetypes.String20; +import testdb.precisetypes.String255; +import testdb.precisetypes.String50; + +/** Table: precision_types_null + * Primary key: id + */ +public record PrecisionTypesNullRow( + PrecisionTypesNullId id, + Optional string10, + Optional string20, + Optional string50, + Optional string100, + Optional string255, + @JsonProperty("decimal5_2") Optional decimal52, + @JsonProperty("decimal10_2") Optional decimal102, + @JsonProperty("decimal18_4") Optional decimal184, + @JsonProperty("decimal5_0") Optional decimal50, + @JsonProperty("decimal10_0") Optional decimal100, + @JsonProperty("decimal18_0") Optional decimal180 +) implements Tuple12, Optional, Optional, Optional, Optional, Optional, Optional, Optional, Optional, Optional, Optional> { + public PrecisionTypesNullRow withId(PrecisionTypesNullId id) { + return new PrecisionTypesNullRow(id, string10, string20, string50, string100, string255, decimal52, decimal102, decimal184, decimal50, decimal100, decimal180); + } + + public PrecisionTypesNullRow withString10(Optional string10) { + return new PrecisionTypesNullRow(id, string10, string20, string50, string100, string255, decimal52, decimal102, decimal184, decimal50, decimal100, decimal180); + } + + public PrecisionTypesNullRow withString20(Optional string20) { + return new PrecisionTypesNullRow(id, string10, string20, string50, string100, string255, decimal52, decimal102, decimal184, decimal50, decimal100, decimal180); + } + + public PrecisionTypesNullRow withString50(Optional string50) { + return new PrecisionTypesNullRow(id, string10, string20, string50, string100, string255, decimal52, decimal102, decimal184, decimal50, decimal100, decimal180); + } + + public PrecisionTypesNullRow withString100(Optional string100) { + return new PrecisionTypesNullRow(id, string10, string20, string50, string100, string255, decimal52, decimal102, decimal184, decimal50, decimal100, decimal180); + } + + public PrecisionTypesNullRow withString255(Optional string255) { + return new PrecisionTypesNullRow(id, string10, string20, string50, string100, string255, decimal52, decimal102, decimal184, decimal50, decimal100, decimal180); + } + + public PrecisionTypesNullRow withDecimal52(Optional decimal52) { + return new PrecisionTypesNullRow(id, string10, string20, string50, string100, string255, decimal52, decimal102, decimal184, decimal50, decimal100, decimal180); + } + + public PrecisionTypesNullRow withDecimal102(Optional decimal102) { + return new PrecisionTypesNullRow(id, string10, string20, string50, string100, string255, decimal52, decimal102, decimal184, decimal50, decimal100, decimal180); + } + + public PrecisionTypesNullRow withDecimal184(Optional decimal184) { + return new PrecisionTypesNullRow(id, string10, string20, string50, string100, string255, decimal52, decimal102, decimal184, decimal50, decimal100, decimal180); + } + + public PrecisionTypesNullRow withDecimal50(Optional decimal50) { + return new PrecisionTypesNullRow(id, string10, string20, string50, string100, string255, decimal52, decimal102, decimal184, decimal50, decimal100, decimal180); + } + + public PrecisionTypesNullRow withDecimal100(Optional decimal100) { + return new PrecisionTypesNullRow(id, string10, string20, string50, string100, string255, decimal52, decimal102, decimal184, decimal50, decimal100, decimal180); + } + + public PrecisionTypesNullRow withDecimal180(Optional decimal180) { + return new PrecisionTypesNullRow(id, string10, string20, string50, string100, string255, decimal52, decimal102, decimal184, decimal50, decimal100, decimal180); + } + + public static RowCodec rowCodec = RowCodecs.of(PrecisionTypesNullId.sqliteType, String10.sqliteType.opt(), String20.sqliteType.opt(), String50.sqliteType.opt(), String100.sqliteType.opt(), String255.sqliteType.opt(), Decimal5_2.sqliteType.opt(), Decimal10_2.sqliteType.opt(), Decimal18_4.sqliteType.opt(), Int5.sqliteType.opt(), Int10.sqliteType.opt(), Int18.sqliteType.opt(), PrecisionTypesNullRow::new, row -> new Object[]{row.id(), row.string10(), row.string20(), row.string50(), row.string100(), row.string255(), row.decimal52(), row.decimal102(), row.decimal184(), row.decimal50(), row.decimal100(), row.decimal180()}); + + @Override + public PrecisionTypesNullId _1() { + return id; + } + + @Override + public Optional _10() { + return decimal50; + } + + @Override + public Optional _11() { + return decimal100; + } + + @Override + public Optional _12() { + return decimal180; + } + + @Override + public Optional _2() { + return string10; + } + + @Override + public Optional _3() { + return string20; + } + + @Override + public Optional _4() { + return string50; + } + + @Override + public Optional _5() { + return string100; + } + + @Override + public Optional _6() { + return string255; + } + + @Override + public Optional _7() { + return decimal52; + } + + @Override + public Optional _8() { + return decimal102; + } + + @Override + public Optional _9() { + return decimal184; + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/product_details_with_sales/ProductDetailsWithSalesSqlRepo.java b/testers/sqlite/java/generated-and-checked-in/testdb/product_details_with_sales/ProductDetailsWithSalesSqlRepo.java new file mode 100644 index 0000000000..e79d097271 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/product_details_with_sales/ProductDetailsWithSalesSqlRepo.java @@ -0,0 +1,18 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.product_details_with_sales; + +import dev.typr.foundations.ConnectionRead; +import java.math.BigDecimal; +import java.util.List; +import java.util.Optional; + +public interface ProductDetailsWithSalesSqlRepo { + List apply( + Optional minPrice, + ConnectionRead c + ); +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/product_details_with_sales/ProductDetailsWithSalesSqlRepoImpl.java b/testers/sqlite/java/generated-and-checked-in/testdb/product_details_with_sales/ProductDetailsWithSalesSqlRepoImpl.java new file mode 100644 index 0000000000..4dc02fdc9c --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/product_details_with_sales/ProductDetailsWithSalesSqlRepoImpl.java @@ -0,0 +1,24 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.product_details_with_sales; + +import dev.typr.foundations.ConnectionRead; +import dev.typr.foundations.Fragment; +import dev.typr.foundations.SqliteTypes; +import java.math.BigDecimal; +import java.util.List; +import java.util.Optional; +import static dev.typr.foundations.Fragment.concat; + +public class ProductDetailsWithSalesSqlRepoImpl implements ProductDetailsWithSalesSqlRepo { + @Override + public List apply( + Optional minPrice, + ConnectionRead c + ) { + return concat(Fragment.of("-- Product details enriched with cumulative sales numbers.\n-- Tests: subquery in SELECT, joining on FK, ordering by computed column.\n\nSELECT\n p.product_id,\n p.sku,\n p.name AS product_name,\n p.price,\n COALESCE(SUM(oi.quantity), 0) AS total_units_sold,\n COALESCE(SUM(oi.quantity * oi.unit_price), 0) AS total_revenue\nFROM products p\nLEFT JOIN order_items oi ON p.product_id = oi.product_id\nWHERE ("), Fragment.encode(SqliteTypes.numeric.opt(), minPrice), Fragment.of(" IS NULL OR p.price >= "), Fragment.encode(SqliteTypes.numeric.opt(), minPrice), Fragment.of(")\nGROUP BY p.product_id, p.sku, p.name, p.price\nORDER BY total_revenue DESC, p.product_id")).query(ProductDetailsWithSalesSqlRow.rowCodec.all()).run(c); + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/product_details_with_sales/ProductDetailsWithSalesSqlRow.java b/testers/sqlite/java/generated-and-checked-in/testdb/product_details_with_sales/ProductDetailsWithSalesSqlRow.java new file mode 100644 index 0000000000..5e5cbb9174 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/product_details_with_sales/ProductDetailsWithSalesSqlRow.java @@ -0,0 +1,93 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.product_details_with_sales; + +import com.fasterxml.jackson.annotation.JsonProperty; +import dev.typr.dsl.RowCodecs; +import dev.typr.foundations.RowCodec; +import dev.typr.foundations.SqliteTypes; +import dev.typr.foundations.Tuple.Tuple6; +import java.math.BigDecimal; +import java.util.Optional; +import testdb.products.ProductsId; + +/** SQL file: product_details_with_sales.sql */ +public record ProductDetailsWithSalesSqlRow( + /** Points to {@link testdb.products.ProductsRow#productId()} */ + @JsonProperty("product_id") ProductsId productId, + /** Points to {@link testdb.products.ProductsRow#sku()} */ + String sku, + /** Points to {@link testdb.products.ProductsRow#name()} */ + @JsonProperty("product_name") String productName, + /** Points to {@link testdb.products.ProductsRow#price()} */ + BigDecimal price, + /** Points to {@link testdb.order_items.OrderItemsRow#quantity()} */ + @JsonProperty("total_units_sold") Optional totalUnitsSold, + /** Points to {@link testdb.order_items.OrderItemsRow#unitPrice()} */ + @JsonProperty("total_revenue") Optional totalRevenue +) implements Tuple6, Optional> { + /** Points to {@link testdb.products.ProductsRow#productId()} */ + public ProductDetailsWithSalesSqlRow withProductId(ProductsId productId) { + return new ProductDetailsWithSalesSqlRow(productId, sku, productName, price, totalUnitsSold, totalRevenue); + } + + /** Points to {@link testdb.products.ProductsRow#sku()} */ + public ProductDetailsWithSalesSqlRow withSku(String sku) { + return new ProductDetailsWithSalesSqlRow(productId, sku, productName, price, totalUnitsSold, totalRevenue); + } + + /** Points to {@link testdb.products.ProductsRow#name()} */ + public ProductDetailsWithSalesSqlRow withProductName(String productName) { + return new ProductDetailsWithSalesSqlRow(productId, sku, productName, price, totalUnitsSold, totalRevenue); + } + + /** Points to {@link testdb.products.ProductsRow#price()} */ + public ProductDetailsWithSalesSqlRow withPrice(BigDecimal price) { + return new ProductDetailsWithSalesSqlRow(productId, sku, productName, price, totalUnitsSold, totalRevenue); + } + + /** Points to {@link testdb.order_items.OrderItemsRow#quantity()} */ + public ProductDetailsWithSalesSqlRow withTotalUnitsSold(Optional totalUnitsSold) { + return new ProductDetailsWithSalesSqlRow(productId, sku, productName, price, totalUnitsSold, totalRevenue); + } + + /** Points to {@link testdb.order_items.OrderItemsRow#unitPrice()} */ + public ProductDetailsWithSalesSqlRow withTotalRevenue(Optional totalRevenue) { + return new ProductDetailsWithSalesSqlRow(productId, sku, productName, price, totalUnitsSold, totalRevenue); + } + + public static RowCodec rowCodec = RowCodecs.of(ProductsId.sqliteType, SqliteTypes.varchar, SqliteTypes.text, SqliteTypes.numeric, SqliteTypes.bigint.opt(), SqliteTypes.numeric.opt(), ProductDetailsWithSalesSqlRow::new, row -> new Object[]{row.productId(), row.sku(), row.productName(), row.price(), row.totalUnitsSold(), row.totalRevenue()}); + + @Override + public ProductsId _1() { + return productId; + } + + @Override + public String _2() { + return sku; + } + + @Override + public String _3() { + return productName; + } + + @Override + public BigDecimal _4() { + return price; + } + + @Override + public Optional _5() { + return totalUnitsSold; + } + + @Override + public Optional _6() { + return totalRevenue; + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/products/ProductsFields.java b/testers/sqlite/java/generated-and-checked-in/testdb/products/ProductsFields.java new file mode 100644 index 0000000000..7980559c04 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/products/ProductsFields.java @@ -0,0 +1,97 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.products; + +import dev.typr.dsl.FieldsBase; +import dev.typr.dsl.Path; +import dev.typr.dsl.RelationStructure; +import dev.typr.dsl.SqlExpr; +import dev.typr.dsl.SqlExpr.Field; +import dev.typr.dsl.SqlExpr.FieldLike; +import dev.typr.dsl.SqlExpr.IdField; +import dev.typr.dsl.SqlExpr.OptField; +import dev.typr.dsl.TupleExpr.TupleExpr5; +import dev.typr.foundations.RowCodec; +import dev.typr.foundations.SqliteTypes; +import dev.typr.foundations.data.Json; +import java.math.BigDecimal; +import java.util.List; +import java.util.Optional; + +public class ProductsFields extends TupleExpr5 implements RelationStructure, FieldsBase { + List _path; + + public ProductsFields(List _path) { + this._path = _path; + } + + public static ProductsFields structure = new ProductsFields(java.util.Collections.emptyList()); + + public IdField productId() { + return new IdField(_path, "product_id", ProductsRow::productId, Optional.empty(), Optional.empty(), (row, value) -> row.withProductId(value), ProductsId.sqliteType); + } + + public Field sku() { + return new Field(_path, "sku", ProductsRow::sku, Optional.empty(), Optional.empty(), (row, value) -> row.withSku(value), SqliteTypes.varchar); + } + + public Field name() { + return new Field(_path, "name", ProductsRow::name, Optional.empty(), Optional.empty(), (row, value) -> row.withName(value), SqliteTypes.text); + } + + public Field price() { + return new Field(_path, "price", ProductsRow::price, Optional.empty(), Optional.empty(), (row, value) -> row.withPrice(value), SqliteTypes.numeric); + } + + public OptField metadata() { + return new OptField(_path, "metadata", ProductsRow::metadata, Optional.empty(), Optional.empty(), (row, value) -> row.withMetadata(value), SqliteTypes.json); + } + + @Override + public List _path() { + return _path; + } + + @Override + public List> columns() { + return java.util.List.of(this.productId(), this.sku(), this.name(), this.price(), this.metadata()); + } + + @Override + public RowCodec rowCodec() { + return ProductsRow.rowCodec; + } + + @Override + public RelationStructure withPaths(List _path) { + return new ProductsFields(_path); + } + + @Override + public SqlExpr _1() { + return productId(); + } + + @Override + public SqlExpr _2() { + return sku(); + } + + @Override + public SqlExpr _3() { + return name(); + } + + @Override + public SqlExpr _4() { + return price(); + } + + @Override + public SqlExpr _5() { + return metadata(); + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/products/ProductsId.java b/testers/sqlite/java/generated-and-checked-in/testdb/products/ProductsId.java new file mode 100644 index 0000000000..ac7d3a1cb0 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/products/ProductsId.java @@ -0,0 +1,29 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.products; + +import com.fasterxml.jackson.annotation.JsonValue; +import dev.typr.foundations.Bijection; +import dev.typr.foundations.SqliteType; +import dev.typr.foundations.SqliteTypes; + +/** Type for the primary key of table `products` */ +public record ProductsId(@JsonValue Long value) { + public ProductsId withValue(Long value) { + return new ProductsId(value); + } + + @Override + public java.lang.String toString() { + return value.toString(); + } + + static public Bijection bijection = + Bijection.of(ProductsId::value, ProductsId::new); + + static public SqliteType sqliteType = + SqliteTypes.integer.to(Bijection.of(ProductsId::new, ProductsId::value)); +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/products/ProductsRepo.java b/testers/sqlite/java/generated-and-checked-in/testdb/products/ProductsRepo.java new file mode 100644 index 0000000000..5515f327fa --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/products/ProductsRepo.java @@ -0,0 +1,76 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.products; + +import dev.typr.dsl.DeleteBuilder; +import dev.typr.dsl.SelectBuilder; +import dev.typr.dsl.UpdateBuilder; +import dev.typr.foundations.Connection; +import dev.typr.foundations.ConnectionRead; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +public interface ProductsRepo { + DeleteBuilder delete(); + + Boolean deleteById( + ProductsId productId, + Connection c + ); + + Integer deleteByIds( + List productIds, + Connection c + ); + + ProductsRow insert( + ProductsRow unsaved, + Connection c + ); + + SelectBuilder select(); + + List selectAll(ConnectionRead c); + + Optional selectById( + ProductsId productId, + ConnectionRead c + ); + + List selectByIds( + List productIds, + ConnectionRead c + ); + + Map selectByIdsTracked( + List productIds, + ConnectionRead c + ); + + Optional selectByUniqueSku( + String sku, + ConnectionRead c + ); + + UpdateBuilder update(); + + Boolean update( + ProductsRow row, + Connection c + ); + + ProductsRow upsert( + ProductsRow unsaved, + Connection c + ); + + List upsertBatch( + Iterator unsaved, + Connection c + ); +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/products/ProductsRepoImpl.java b/testers/sqlite/java/generated-and-checked-in/testdb/products/ProductsRepoImpl.java new file mode 100644 index 0000000000..f75814f122 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/products/ProductsRepoImpl.java @@ -0,0 +1,136 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.products; + +import dev.typr.dsl.DeleteBuilder; +import dev.typr.dsl.Dialect; +import dev.typr.dsl.SelectBuilder; +import dev.typr.dsl.UpdateBuilder; +import dev.typr.foundations.Connection; +import dev.typr.foundations.ConnectionRead; +import dev.typr.foundations.Fragment; +import dev.typr.foundations.SqliteTypes; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import static dev.typr.foundations.Fragment.concat; + +public class ProductsRepoImpl implements ProductsRepo { + @Override + public DeleteBuilder delete() { + return DeleteBuilder.of("\"products\"", ProductsFields.structure, Dialect.SQLITE); + } + + @Override + public Boolean deleteById( + ProductsId productId, + Connection c + ) { + return concat(Fragment.of("delete from \"products\" where \"product_id\" = "), Fragment.encode(ProductsId.sqliteType, productId), Fragment.of("")).update().run(c) > 0; + } + + @Override + public Integer deleteByIds( + List productIds, + Connection c + ) { + ArrayList fragments = new ArrayList<>(); + for (var id : productIds) { fragments.add(Fragment.encode(ProductsId.sqliteType, id)); }; + return Fragment.concat(Fragment.of("delete from \"products\" where \"product_id\" in ("), Fragment.comma(fragments), Fragment.of(")")).update().run(c); + } + + @Override + public ProductsRow insert( + ProductsRow unsaved, + Connection c + ) { + return concat(Fragment.of("insert into \"products\"(\"product_id\", \"sku\", \"name\", \"price\", \"metadata\")\nvalues ("), Fragment.encode(ProductsId.sqliteType, unsaved.productId()), Fragment.of(", "), Fragment.encode(SqliteTypes.varchar, unsaved.sku()), Fragment.of(", "), Fragment.encode(SqliteTypes.text, unsaved.name()), Fragment.of(", "), Fragment.encode(SqliteTypes.numeric, unsaved.price()), Fragment.of(", "), Fragment.encode(SqliteTypes.json.opt(), unsaved.metadata()), Fragment.of(")\nRETURNING \"product_id\", \"sku\", \"name\", \"price\", \"metadata\"\n")) + .updateReturning(ProductsRow.rowCodec.exactlyOne()).run(c); + } + + @Override + public SelectBuilder select() { + return SelectBuilder.of("\"products\"", ProductsFields.structure, ProductsRow.rowCodec, Dialect.SQLITE); + } + + @Override + public List selectAll(ConnectionRead c) { + return concat(Fragment.of("select \"product_id\", \"sku\", \"name\", \"price\", \"metadata\"\nfrom \"products\"\n")).query(ProductsRow.rowCodec.all()).run(c); + } + + @Override + public Optional selectById( + ProductsId productId, + ConnectionRead c + ) { + return concat(Fragment.of("select \"product_id\", \"sku\", \"name\", \"price\", \"metadata\"\nfrom \"products\"\nwhere \"product_id\" = "), Fragment.encode(ProductsId.sqliteType, productId), Fragment.of("")).query(ProductsRow.rowCodec.first()).run(c); + } + + @Override + public List selectByIds( + List productIds, + ConnectionRead c + ) { + ArrayList fragments = new ArrayList<>(); + for (var id : productIds) { fragments.add(Fragment.encode(ProductsId.sqliteType, id)); }; + return Fragment.concat(Fragment.of("select \"product_id\", \"sku\", \"name\", \"price\", \"metadata\" from \"products\" where \"product_id\" in ("), Fragment.comma(fragments), Fragment.of(")")).query(ProductsRow.rowCodec.all()).run(c); + } + + @Override + public Map selectByIdsTracked( + List productIds, + ConnectionRead c + ) { + HashMap ret = new HashMap(); + selectByIds(productIds, c).forEach(row -> ret.put(row.productId(), row)); + return ret; + } + + @Override + public Optional selectByUniqueSku( + String sku, + ConnectionRead c + ) { + return concat(Fragment.of("select \"product_id\", \"sku\", \"name\", \"price\", \"metadata\"\nfrom \"products\"\nwhere \"sku\" = "), Fragment.encode(SqliteTypes.varchar, sku), Fragment.of("\n")).query(ProductsRow.rowCodec.first()).run(c); + } + + @Override + public UpdateBuilder update() { + return UpdateBuilder.of("\"products\"", ProductsFields.structure, ProductsRow.rowCodec, Dialect.SQLITE); + } + + @Override + public Boolean update( + ProductsRow row, + Connection c + ) { + ProductsId productId = row.productId();; + return concat(Fragment.of("update \"products\"\nset \"sku\" = "), Fragment.encode(SqliteTypes.varchar, row.sku()), Fragment.of(",\n\"name\" = "), Fragment.encode(SqliteTypes.text, row.name()), Fragment.of(",\n\"price\" = "), Fragment.encode(SqliteTypes.numeric, row.price()), Fragment.of(",\n\"metadata\" = "), Fragment.encode(SqliteTypes.json.opt(), row.metadata()), Fragment.of("\nwhere \"product_id\" = "), Fragment.encode(ProductsId.sqliteType, productId), Fragment.of("")).update().run(c) > 0; + } + + @Override + public ProductsRow upsert( + ProductsRow unsaved, + Connection c + ) { + return concat(Fragment.of("INSERT INTO \"products\"(\"product_id\", \"sku\", \"name\", \"price\", \"metadata\")\nVALUES ("), Fragment.encode(ProductsId.sqliteType, unsaved.productId()), Fragment.of(", "), Fragment.encode(SqliteTypes.varchar, unsaved.sku()), Fragment.of(", "), Fragment.encode(SqliteTypes.text, unsaved.name()), Fragment.of(", "), Fragment.encode(SqliteTypes.numeric, unsaved.price()), Fragment.of(", "), Fragment.encode(SqliteTypes.json.opt(), unsaved.metadata()), Fragment.of(")\nON CONFLICT (\"product_id\")\nDO UPDATE SET\n \"sku\" = EXCLUDED.\"sku\",\n\"name\" = EXCLUDED.\"name\",\n\"price\" = EXCLUDED.\"price\",\n\"metadata\" = EXCLUDED.\"metadata\"\nRETURNING \"product_id\", \"sku\", \"name\", \"price\", \"metadata\"")) + .updateReturning(ProductsRow.rowCodec.exactlyOne()) + .run(c); + } + + @Override + public List upsertBatch( + Iterator unsaved, + Connection c + ) { + return concat(Fragment.of("INSERT INTO \"products\"(\"product_id\", \"sku\", \"name\", \"price\", \"metadata\")\nVALUES (?, ?, ?, ?, ?)\nON CONFLICT (\"product_id\")\nDO UPDATE SET\n \"sku\" = EXCLUDED.\"sku\",\n\"name\" = EXCLUDED.\"name\",\n\"price\" = EXCLUDED.\"price\",\n\"metadata\" = EXCLUDED.\"metadata\"\nRETURNING \"product_id\", \"sku\", \"name\", \"price\", \"metadata\"")) + .updateReturningEach(ProductsRow.rowCodec, unsaved) + .run(c); + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/products/ProductsRepoMock.java b/testers/sqlite/java/generated-and-checked-in/testdb/products/ProductsRepoMock.java new file mode 100644 index 0000000000..2633a2548f --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/products/ProductsRepoMock.java @@ -0,0 +1,165 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.products; + +import dev.typr.dsl.DeleteBuilder; +import dev.typr.dsl.DeleteBuilderMock; +import dev.typr.dsl.DeleteParams; +import dev.typr.dsl.SelectBuilder; +import dev.typr.dsl.SelectBuilderMock; +import dev.typr.dsl.SelectParams; +import dev.typr.dsl.UpdateBuilder; +import dev.typr.dsl.UpdateBuilderMock; +import dev.typr.dsl.UpdateParams; +import dev.typr.foundations.Connection; +import dev.typr.foundations.ConnectionRead; +import java.lang.RuntimeException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.function.Function; +import java.util.stream.Collectors; + +public record ProductsRepoMock(HashMap map) implements ProductsRepo { + public ProductsRepoMock() { + this(new HashMap()); + } + + public ProductsRepoMock withMap(HashMap map) { + return new ProductsRepoMock(map); + } + + @Override + public DeleteBuilder delete() { + return new DeleteBuilderMock<>(ProductsFields.structure, () -> new ArrayList<>(map.values()), DeleteParams.empty(), row -> row.productId(), id -> map.remove(id)); + } + + @Override + public Boolean deleteById( + ProductsId productId, + Connection c + ) { + return Optional.ofNullable(map.remove(productId)).isPresent(); + } + + @Override + public Integer deleteByIds( + List productIds, + Connection c + ) { + var count = 0; + for (var id : productIds) { + if (Optional.ofNullable(map.remove(id)).isPresent()) { + count = count + 1;; + } + }; + return count; + } + + @Override + public ProductsRow insert( + ProductsRow unsaved, + Connection c + ) { + if (map.containsKey(unsaved.productId())) { + throw new RuntimeException("id " + unsaved.productId() + " already exists"); + } + map.put(unsaved.productId(), unsaved); + return unsaved; + } + + @Override + public SelectBuilder select() { + return new SelectBuilderMock<>(ProductsFields.structure, () -> new ArrayList<>(map.values()), SelectParams.empty()); + } + + @Override + public List selectAll(ConnectionRead c) { + return new ArrayList<>(map.values()); + } + + @Override + public Optional selectById( + ProductsId productId, + ConnectionRead c + ) { + return Optional.ofNullable(map.get(productId)); + } + + @Override + public List selectByIds( + List productIds, + ConnectionRead c + ) { + var result = new ArrayList(); + for (var id : productIds) { + var opt = Optional.ofNullable(map.get(id)); + if (opt.isPresent()) { + result.add(opt.get()); + } + }; + return result; + } + + @Override + public Map selectByIdsTracked( + List productIds, + ConnectionRead c + ) { + return selectByIds(productIds, c).stream().collect(Collectors.toMap((ProductsRow row) -> row.productId(), Function.identity())); + } + + @Override + public Optional selectByUniqueSku( + String sku, + ConnectionRead c + ) { + return new ArrayList<>(map.values()).stream().filter(v -> sku.equals(v.sku())).findFirst(); + } + + @Override + public UpdateBuilder update() { + return new UpdateBuilderMock<>(ProductsFields.structure, () -> new ArrayList<>(map.values()), UpdateParams.empty(), row -> row); + } + + @Override + public Boolean update( + ProductsRow row, + Connection c + ) { + var shouldUpdate = Optional.ofNullable(map.get(row.productId())).filter(oldRow -> !oldRow.equals(row)).isPresent(); + if (shouldUpdate) { + map.put(row.productId(), row);; + } + return shouldUpdate; + } + + @Override + public ProductsRow upsert( + ProductsRow unsaved, + Connection c + ) { + map.put(unsaved.productId(), unsaved); + return unsaved; + } + + @Override + public List upsertBatch( + Iterator unsaved, + Connection c + ) { + var result = new ArrayList(); + while (unsaved.hasNext()) { + var row = unsaved.next(); + map.put(row.productId(), row); + result.add(row); + }; + return result; + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/products/ProductsRow.java b/testers/sqlite/java/generated-and-checked-in/testdb/products/ProductsRow.java new file mode 100644 index 0000000000..5bd180a54b --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/products/ProductsRow.java @@ -0,0 +1,77 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.products; + +import com.fasterxml.jackson.annotation.JsonProperty; +import dev.typr.dsl.RowCodecs; +import dev.typr.foundations.RowCodec; +import dev.typr.foundations.SqliteTypes; +import dev.typr.foundations.Tuple.Tuple5; +import dev.typr.foundations.data.Json; +import java.math.BigDecimal; +import java.util.Optional; + +/** Table: products + * Primary key: product_id + */ +public record ProductsRow( + @JsonProperty("product_id") ProductsId productId, + String sku, + String name, + BigDecimal price, + Optional metadata +) implements Tuple5> { + public ProductsRow withProductId(ProductsId productId) { + return new ProductsRow(productId, sku, name, price, metadata); + } + + public ProductsRow withSku(String sku) { + return new ProductsRow(productId, sku, name, price, metadata); + } + + public ProductsRow withName(String name) { + return new ProductsRow(productId, sku, name, price, metadata); + } + + public ProductsRow withPrice(BigDecimal price) { + return new ProductsRow(productId, sku, name, price, metadata); + } + + public ProductsRow withMetadata(Optional metadata) { + return new ProductsRow(productId, sku, name, price, metadata); + } + + public static RowCodec rowCodec = RowCodecs.of(ProductsId.sqliteType, SqliteTypes.varchar, SqliteTypes.text, SqliteTypes.numeric, SqliteTypes.json.opt(), ProductsRow::new, row -> new Object[]{row.productId(), row.sku(), row.name(), row.price(), row.metadata()}); + + @Override + public ProductsId _1() { + return productId; + } + + @Override + public String _2() { + return sku; + } + + @Override + public String _3() { + return name; + } + + @Override + public BigDecimal _4() { + return price; + } + + @Override + public Optional _5() { + return metadata; + } + + public ProductsId id() { + return productId; + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/userdefined/Email.java b/testers/sqlite/java/generated-and-checked-in/testdb/userdefined/Email.java new file mode 100644 index 0000000000..a945f78355 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/userdefined/Email.java @@ -0,0 +1,31 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.userdefined; + +import com.fasterxml.jackson.annotation.JsonValue; +import dev.typr.foundations.Bijection; +import dev.typr.foundations.SqliteType; +import dev.typr.foundations.SqliteTypes; + +/** Shared type `Email` + * Generated from TypeDefinitions matching + */ +public record Email(@JsonValue String value) { + public Email withValue(String value) { + return new Email(value); + } + + @Override + public java.lang.String toString() { + return value.toString(); + } + + static public Bijection bijection = + Bijection.of(Email::value, Email::new); + + static public SqliteType sqliteType = + SqliteTypes.varchar.to(Bijection.of(Email::new, Email::value)); +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/users/UsersFields.java b/testers/sqlite/java/generated-and-checked-in/testdb/users/UsersFields.java new file mode 100644 index 0000000000..1753411e4d --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/users/UsersFields.java @@ -0,0 +1,77 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.users; + +import dev.typr.dsl.FieldsBase; +import dev.typr.dsl.Path; +import dev.typr.dsl.RelationStructure; +import dev.typr.dsl.SqlExpr; +import dev.typr.dsl.SqlExpr.Field; +import dev.typr.dsl.SqlExpr.FieldLike; +import dev.typr.dsl.SqlExpr.IdField; +import dev.typr.dsl.TupleExpr.TupleExpr3; +import dev.typr.foundations.RowCodec; +import dev.typr.foundations.SqliteTypes; +import java.util.List; +import java.util.Optional; +import testdb.userdefined.Email; + +public class UsersFields extends TupleExpr3 implements RelationStructure, FieldsBase { + List _path; + + public UsersFields(List _path) { + this._path = _path; + } + + public static UsersFields structure = new UsersFields(java.util.Collections.emptyList()); + + public IdField userId() { + return new IdField(_path, "user_id", UsersRow::userId, Optional.empty(), Optional.empty(), (row, value) -> row.withUserId(value), UsersId.sqliteType); + } + + public Field username() { + return new Field(_path, "username", UsersRow::username, Optional.empty(), Optional.empty(), (row, value) -> row.withUsername(value), SqliteTypes.varchar); + } + + public Field email() { + return new Field(_path, "email", UsersRow::email, Optional.empty(), Optional.empty(), (row, value) -> row.withEmail(value), Email.sqliteType); + } + + @Override + public List _path() { + return _path; + } + + @Override + public List> columns() { + return java.util.List.of(this.userId(), this.username(), this.email()); + } + + @Override + public RowCodec rowCodec() { + return UsersRow.rowCodec; + } + + @Override + public RelationStructure withPaths(List _path) { + return new UsersFields(_path); + } + + @Override + public SqlExpr _1() { + return userId(); + } + + @Override + public SqlExpr _2() { + return username(); + } + + @Override + public SqlExpr _3() { + return email(); + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/users/UsersId.java b/testers/sqlite/java/generated-and-checked-in/testdb/users/UsersId.java new file mode 100644 index 0000000000..8d57817134 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/users/UsersId.java @@ -0,0 +1,29 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.users; + +import com.fasterxml.jackson.annotation.JsonValue; +import dev.typr.foundations.Bijection; +import dev.typr.foundations.SqliteType; +import dev.typr.foundations.SqliteTypes; + +/** Type for the primary key of table `users` */ +public record UsersId(@JsonValue Long value) { + public UsersId withValue(Long value) { + return new UsersId(value); + } + + @Override + public java.lang.String toString() { + return value.toString(); + } + + static public Bijection bijection = + Bijection.of(UsersId::value, UsersId::new); + + static public SqliteType sqliteType = + SqliteTypes.integer.to(Bijection.of(UsersId::new, UsersId::value)); +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/users/UsersRepo.java b/testers/sqlite/java/generated-and-checked-in/testdb/users/UsersRepo.java new file mode 100644 index 0000000000..a08f1e6584 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/users/UsersRepo.java @@ -0,0 +1,82 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.users; + +import dev.typr.dsl.DeleteBuilder; +import dev.typr.dsl.SelectBuilder; +import dev.typr.dsl.UpdateBuilder; +import dev.typr.foundations.Connection; +import dev.typr.foundations.ConnectionRead; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import testdb.userdefined.Email; + +public interface UsersRepo { + DeleteBuilder delete(); + + Boolean deleteById( + UsersId userId, + Connection c + ); + + Integer deleteByIds( + List userIds, + Connection c + ); + + UsersRow insert( + UsersRow unsaved, + Connection c + ); + + SelectBuilder select(); + + List selectAll(ConnectionRead c); + + Optional selectById( + UsersId userId, + ConnectionRead c + ); + + List selectByIds( + List userIds, + ConnectionRead c + ); + + Map selectByIdsTracked( + List userIds, + ConnectionRead c + ); + + Optional selectByUniqueEmail( + /* user-picked */ Email email, + ConnectionRead c + ); + + Optional selectByUniqueUsername( + String username, + ConnectionRead c + ); + + UpdateBuilder update(); + + Boolean update( + UsersRow row, + Connection c + ); + + UsersRow upsert( + UsersRow unsaved, + Connection c + ); + + List upsertBatch( + Iterator unsaved, + Connection c + ); +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/users/UsersRepoImpl.java b/testers/sqlite/java/generated-and-checked-in/testdb/users/UsersRepoImpl.java new file mode 100644 index 0000000000..b147ee0c9b --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/users/UsersRepoImpl.java @@ -0,0 +1,145 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.users; + +import dev.typr.dsl.DeleteBuilder; +import dev.typr.dsl.Dialect; +import dev.typr.dsl.SelectBuilder; +import dev.typr.dsl.UpdateBuilder; +import dev.typr.foundations.Connection; +import dev.typr.foundations.ConnectionRead; +import dev.typr.foundations.Fragment; +import dev.typr.foundations.SqliteTypes; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import testdb.userdefined.Email; +import static dev.typr.foundations.Fragment.concat; + +public class UsersRepoImpl implements UsersRepo { + @Override + public DeleteBuilder delete() { + return DeleteBuilder.of("\"users\"", UsersFields.structure, Dialect.SQLITE); + } + + @Override + public Boolean deleteById( + UsersId userId, + Connection c + ) { + return concat(Fragment.of("delete from \"users\" where \"user_id\" = "), Fragment.encode(UsersId.sqliteType, userId), Fragment.of("")).update().run(c) > 0; + } + + @Override + public Integer deleteByIds( + List userIds, + Connection c + ) { + ArrayList fragments = new ArrayList<>(); + for (var id : userIds) { fragments.add(Fragment.encode(UsersId.sqliteType, id)); }; + return Fragment.concat(Fragment.of("delete from \"users\" where \"user_id\" in ("), Fragment.comma(fragments), Fragment.of(")")).update().run(c); + } + + @Override + public UsersRow insert( + UsersRow unsaved, + Connection c + ) { + return concat(Fragment.of("insert into \"users\"(\"user_id\", \"username\", \"email\")\nvalues ("), Fragment.encode(UsersId.sqliteType, unsaved.userId()), Fragment.of(", "), Fragment.encode(SqliteTypes.varchar, unsaved.username()), Fragment.of(", "), Fragment.encode(Email.sqliteType, unsaved.email()), Fragment.of(")\nRETURNING \"user_id\", \"username\", \"email\"\n")) + .updateReturning(UsersRow.rowCodec.exactlyOne()).run(c); + } + + @Override + public SelectBuilder select() { + return SelectBuilder.of("\"users\"", UsersFields.structure, UsersRow.rowCodec, Dialect.SQLITE); + } + + @Override + public List selectAll(ConnectionRead c) { + return concat(Fragment.of("select \"user_id\", \"username\", \"email\"\nfrom \"users\"\n")).query(UsersRow.rowCodec.all()).run(c); + } + + @Override + public Optional selectById( + UsersId userId, + ConnectionRead c + ) { + return concat(Fragment.of("select \"user_id\", \"username\", \"email\"\nfrom \"users\"\nwhere \"user_id\" = "), Fragment.encode(UsersId.sqliteType, userId), Fragment.of("")).query(UsersRow.rowCodec.first()).run(c); + } + + @Override + public List selectByIds( + List userIds, + ConnectionRead c + ) { + ArrayList fragments = new ArrayList<>(); + for (var id : userIds) { fragments.add(Fragment.encode(UsersId.sqliteType, id)); }; + return Fragment.concat(Fragment.of("select \"user_id\", \"username\", \"email\" from \"users\" where \"user_id\" in ("), Fragment.comma(fragments), Fragment.of(")")).query(UsersRow.rowCodec.all()).run(c); + } + + @Override + public Map selectByIdsTracked( + List userIds, + ConnectionRead c + ) { + HashMap ret = new HashMap(); + selectByIds(userIds, c).forEach(row -> ret.put(row.userId(), row)); + return ret; + } + + @Override + public Optional selectByUniqueEmail( + /* user-picked */ Email email, + ConnectionRead c + ) { + return concat(Fragment.of("select \"user_id\", \"username\", \"email\"\nfrom \"users\"\nwhere \"email\" = "), Fragment.encode(Email.sqliteType, email), Fragment.of("\n")).query(UsersRow.rowCodec.first()).run(c); + } + + @Override + public Optional selectByUniqueUsername( + String username, + ConnectionRead c + ) { + return concat(Fragment.of("select \"user_id\", \"username\", \"email\"\nfrom \"users\"\nwhere \"username\" = "), Fragment.encode(SqliteTypes.varchar, username), Fragment.of("\n")).query(UsersRow.rowCodec.first()).run(c); + } + + @Override + public UpdateBuilder update() { + return UpdateBuilder.of("\"users\"", UsersFields.structure, UsersRow.rowCodec, Dialect.SQLITE); + } + + @Override + public Boolean update( + UsersRow row, + Connection c + ) { + UsersId userId = row.userId();; + return concat(Fragment.of("update \"users\"\nset \"username\" = "), Fragment.encode(SqliteTypes.varchar, row.username()), Fragment.of(",\n\"email\" = "), Fragment.encode(Email.sqliteType, row.email()), Fragment.of("\nwhere \"user_id\" = "), Fragment.encode(UsersId.sqliteType, userId), Fragment.of("")).update().run(c) > 0; + } + + @Override + public UsersRow upsert( + UsersRow unsaved, + Connection c + ) { + return concat(Fragment.of("INSERT INTO \"users\"(\"user_id\", \"username\", \"email\")\nVALUES ("), Fragment.encode(UsersId.sqliteType, unsaved.userId()), Fragment.of(", "), Fragment.encode(SqliteTypes.varchar, unsaved.username()), Fragment.of(", "), Fragment.encode(Email.sqliteType, unsaved.email()), Fragment.of(")\nON CONFLICT (\"user_id\")\nDO UPDATE SET\n \"username\" = EXCLUDED.\"username\",\n\"email\" = EXCLUDED.\"email\"\nRETURNING \"user_id\", \"username\", \"email\"")) + .updateReturning(UsersRow.rowCodec.exactlyOne()) + .run(c); + } + + @Override + public List upsertBatch( + Iterator unsaved, + Connection c + ) { + return concat(Fragment.of("INSERT INTO \"users\"(\"user_id\", \"username\", \"email\")\nVALUES (?, ?, ?)\nON CONFLICT (\"user_id\")\nDO UPDATE SET\n \"username\" = EXCLUDED.\"username\",\n\"email\" = EXCLUDED.\"email\"\nRETURNING \"user_id\", \"username\", \"email\"")) + .updateReturningEach(UsersRow.rowCodec, unsaved) + .run(c); + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/users/UsersRepoMock.java b/testers/sqlite/java/generated-and-checked-in/testdb/users/UsersRepoMock.java new file mode 100644 index 0000000000..07e5d3e8d6 --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/users/UsersRepoMock.java @@ -0,0 +1,174 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.users; + +import dev.typr.dsl.DeleteBuilder; +import dev.typr.dsl.DeleteBuilderMock; +import dev.typr.dsl.DeleteParams; +import dev.typr.dsl.SelectBuilder; +import dev.typr.dsl.SelectBuilderMock; +import dev.typr.dsl.SelectParams; +import dev.typr.dsl.UpdateBuilder; +import dev.typr.dsl.UpdateBuilderMock; +import dev.typr.dsl.UpdateParams; +import dev.typr.foundations.Connection; +import dev.typr.foundations.ConnectionRead; +import java.lang.RuntimeException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.function.Function; +import java.util.stream.Collectors; +import testdb.userdefined.Email; + +public record UsersRepoMock(HashMap map) implements UsersRepo { + public UsersRepoMock() { + this(new HashMap()); + } + + public UsersRepoMock withMap(HashMap map) { + return new UsersRepoMock(map); + } + + @Override + public DeleteBuilder delete() { + return new DeleteBuilderMock<>(UsersFields.structure, () -> new ArrayList<>(map.values()), DeleteParams.empty(), row -> row.userId(), id -> map.remove(id)); + } + + @Override + public Boolean deleteById( + UsersId userId, + Connection c + ) { + return Optional.ofNullable(map.remove(userId)).isPresent(); + } + + @Override + public Integer deleteByIds( + List userIds, + Connection c + ) { + var count = 0; + for (var id : userIds) { + if (Optional.ofNullable(map.remove(id)).isPresent()) { + count = count + 1;; + } + }; + return count; + } + + @Override + public UsersRow insert( + UsersRow unsaved, + Connection c + ) { + if (map.containsKey(unsaved.userId())) { + throw new RuntimeException("id " + unsaved.userId() + " already exists"); + } + map.put(unsaved.userId(), unsaved); + return unsaved; + } + + @Override + public SelectBuilder select() { + return new SelectBuilderMock<>(UsersFields.structure, () -> new ArrayList<>(map.values()), SelectParams.empty()); + } + + @Override + public List selectAll(ConnectionRead c) { + return new ArrayList<>(map.values()); + } + + @Override + public Optional selectById( + UsersId userId, + ConnectionRead c + ) { + return Optional.ofNullable(map.get(userId)); + } + + @Override + public List selectByIds( + List userIds, + ConnectionRead c + ) { + var result = new ArrayList(); + for (var id : userIds) { + var opt = Optional.ofNullable(map.get(id)); + if (opt.isPresent()) { + result.add(opt.get()); + } + }; + return result; + } + + @Override + public Map selectByIdsTracked( + List userIds, + ConnectionRead c + ) { + return selectByIds(userIds, c).stream().collect(Collectors.toMap((UsersRow row) -> row.userId(), Function.identity())); + } + + @Override + public Optional selectByUniqueEmail( + /* user-picked */ Email email, + ConnectionRead c + ) { + return new ArrayList<>(map.values()).stream().filter(v -> email.equals(v.email())).findFirst(); + } + + @Override + public Optional selectByUniqueUsername( + String username, + ConnectionRead c + ) { + return new ArrayList<>(map.values()).stream().filter(v -> username.equals(v.username())).findFirst(); + } + + @Override + public UpdateBuilder update() { + return new UpdateBuilderMock<>(UsersFields.structure, () -> new ArrayList<>(map.values()), UpdateParams.empty(), row -> row); + } + + @Override + public Boolean update( + UsersRow row, + Connection c + ) { + var shouldUpdate = Optional.ofNullable(map.get(row.userId())).filter(oldRow -> !oldRow.equals(row)).isPresent(); + if (shouldUpdate) { + map.put(row.userId(), row);; + } + return shouldUpdate; + } + + @Override + public UsersRow upsert( + UsersRow unsaved, + Connection c + ) { + map.put(unsaved.userId(), unsaved); + return unsaved; + } + + @Override + public List upsertBatch( + Iterator unsaved, + Connection c + ) { + var result = new ArrayList(); + while (unsaved.hasNext()) { + var row = unsaved.next(); + map.put(row.userId(), row); + result.add(row); + }; + return result; + } +} \ No newline at end of file diff --git a/testers/sqlite/java/generated-and-checked-in/testdb/users/UsersRow.java b/testers/sqlite/java/generated-and-checked-in/testdb/users/UsersRow.java new file mode 100644 index 0000000000..04b302656a --- /dev/null +++ b/testers/sqlite/java/generated-and-checked-in/testdb/users/UsersRow.java @@ -0,0 +1,55 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.users; + +import com.fasterxml.jackson.annotation.JsonProperty; +import dev.typr.dsl.RowCodecs; +import dev.typr.foundations.RowCodec; +import dev.typr.foundations.SqliteTypes; +import dev.typr.foundations.Tuple.Tuple3; +import testdb.userdefined.Email; + +/** Table: users + * Primary key: user_id + */ +public record UsersRow( + @JsonProperty("user_id") UsersId userId, + String username, + /* user-picked */ Email email +) implements Tuple3 { + public UsersRow withUserId(UsersId userId) { + return new UsersRow(userId, username, email); + } + + public UsersRow withUsername(String username) { + return new UsersRow(userId, username, email); + } + + public UsersRow withEmail(/* user-picked */ Email email) { + return new UsersRow(userId, username, email); + } + + public static RowCodec rowCodec = RowCodecs.of(UsersId.sqliteType, SqliteTypes.varchar, Email.sqliteType, UsersRow::new, row -> new Object[]{row.userId(), row.username(), row.email()}); + + @Override + public UsersId _1() { + return userId; + } + + @Override + public String _2() { + return username; + } + + @Override + public /* user-picked */ Email _3() { + return email; + } + + public UsersId id() { + return userId; + } +} \ No newline at end of file diff --git a/testers/sqlite/java/src/java/testdb/AllTypesTest.java b/testers/sqlite/java/src/java/testdb/AllTypesTest.java new file mode 100644 index 0000000000..320d625236 --- /dev/null +++ b/testers/sqlite/java/src/java/testdb/AllTypesTest.java @@ -0,0 +1,311 @@ +package testdb; + +import static org.junit.Assert.*; + +import dev.typr.foundations.data.Json; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.util.Optional; +import java.util.UUID; +import org.junit.Test; +import testdb.all_scalar_types.*; + +/** + * Round-trip every SQLite scalar type through generated codecs. + * + *

SQLite stores values in 5 storage classes regardless of declared type; the type affinity model + * maps declared types to storage classes via substring matching. The columns here exercise every + * affinity (INTEGER, REAL, NUMERIC, TEXT, BLOB) plus the convenience types layered on TEXT (DATE, + * TIME, DATETIME, TIMESTAMP, UUID, JSON). + */ +public class AllTypesTest { + private final AllScalarTypesRepoImpl repo = new AllScalarTypesRepoImpl(); + + /** Create a sample row with all optional columns populated. */ + static AllScalarTypesRow createSampleRow(long id) { + return new AllScalarTypesRow( + new AllScalarTypesId(id), + Optional.of((byte) 42), // tinyint + Optional.of((short) 1000), // smallint + Optional.of(100000), // int + Optional.of(10000000000L), // integer (Long in SqliteTypes.integer) + Optional.of(9223372036854775000L), // bigint + Optional.of(true), // boolean + Optional.of(3.14159), // real (Double) + Optional.of(2.718281828), // double + Optional.of(1.5f), // float + Optional.of(new BigDecimal("12345.67")), // decimal + Optional.of(new BigDecimal("999.999")), // numeric + Optional.of("text content"), // text + Optional.of("varchar_value"), // varchar(100) + Optional.of("char5"), // char(5) + Optional.of("clob content"), // clob + Optional.of(new byte[] {1, 2, 3, 4, 5}), // blob + Optional.of(new byte[] {0x0A, 0x0B, 0x0C}), // binary + Optional.of(LocalDate.of(2025, 1, 15)), // date + Optional.of(LocalTime.of(14, 30, 45)), // time + Optional.of(LocalDateTime.of(2025, 1, 15, 14, 30, 45)), // datetime + Optional.of(LocalDateTime.of(2025, 6, 1, 9, 0, 0)), // timestamp + Optional.of(UUID.fromString("550e8400-e29b-41d4-a716-446655440000")), // uuid + Optional.of(new Json("{\"key\": \"value\"}")), // json + "required_value"); // not null text + } + + @Test + public void testInsertAndSelectAllTypes() { + SqliteTestHelper.run( + c -> { + var row = createSampleRow(1001); + var inserted = repo.insert(row, c); + + assertNotNull(inserted); + assertEquals(row.id(), inserted.id()); + assertEquals(row.colTinyint(), inserted.colTinyint()); + assertEquals(row.colSmallint(), inserted.colSmallint()); + assertEquals(row.colInt(), inserted.colInt()); + assertEquals(row.colInteger(), inserted.colInteger()); + assertEquals(row.colBigint(), inserted.colBigint()); + assertEquals(row.colBoolean(), inserted.colBoolean()); + assertEquals(row.colVarchar(), inserted.colVarchar()); + assertEquals(row.colDate(), inserted.colDate()); + assertEquals(row.colUuid(), inserted.colUuid()); + assertEquals(row.colNotNull(), inserted.colNotNull()); + + var found = repo.selectById(inserted.id(), c); + assertTrue(found.isPresent()); + assertEquals(inserted.id(), found.get().id()); + }); + } + + @Test + public void testUpdateAllTypes() { + SqliteTestHelper.run( + c -> { + var row = createSampleRow(1002); + var inserted = repo.insert(row, c); + + var updated = + inserted + .withColVarchar(Optional.of("updated_varchar")) + .withColDecimal(Optional.of(new BigDecimal("999.99"))) + .withColBoolean(Optional.of(false)); + + boolean wasUpdated = repo.update(updated, c); + assertTrue(wasUpdated); + + var found = repo.selectById(inserted.id(), c).orElseThrow(); + assertEquals(Optional.of("updated_varchar"), found.colVarchar()); + assertEquals(Optional.of(new BigDecimal("999.99")), found.colDecimal()); + assertEquals(Optional.of(false), found.colBoolean()); + }); + } + + @Test + public void testDeleteAllTypes() { + SqliteTestHelper.run( + c -> { + var row = createSampleRow(1003); + var inserted = repo.insert(row, c); + + boolean deleted = repo.deleteById(inserted.id(), c); + assertTrue(deleted); + + var found = repo.selectById(inserted.id(), c); + assertFalse(found.isPresent()); + }); + } + + @Test + public void testInsertWithNulls() { + SqliteTestHelper.run( + c -> { + var row = + new AllScalarTypesRow( + new AllScalarTypesId(1004L), + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.empty(), + Optional.empty(), + "required_only"); + + var inserted = repo.insert(row, c); + assertNotNull(inserted); + + assertTrue(inserted.colTinyint().isEmpty()); + assertTrue(inserted.colSmallint().isEmpty()); + assertTrue(inserted.colInt().isEmpty()); + assertTrue(inserted.colInteger().isEmpty()); + assertTrue(inserted.colBigint().isEmpty()); + assertTrue(inserted.colBoolean().isEmpty()); + assertTrue(inserted.colVarchar().isEmpty()); + assertTrue(inserted.colDate().isEmpty()); + assertTrue(inserted.colUuid().isEmpty()); + assertTrue(inserted.colJson().isEmpty()); + assertEquals("required_only", inserted.colNotNull()); + }); + } + + // ==================== Individual Type Tests ==================== + + @Test + public void testIntegerTypes() { + SqliteTestHelper.run( + c -> { + var row = createSampleRow(1010); + var inserted = repo.insert(row, c); + + assertEquals(Optional.of((byte) 42), inserted.colTinyint()); + assertEquals(Optional.of((short) 1000), inserted.colSmallint()); + assertEquals(Optional.of(100000), inserted.colInt()); + assertEquals(Optional.of(10000000000L), inserted.colInteger()); + assertEquals(Optional.of(9223372036854775000L), inserted.colBigint()); + }); + } + + @Test + public void testBooleanType() { + SqliteTestHelper.run( + c -> { + var row = createSampleRow(1011); + var inserted = repo.insert(row, c); + assertEquals(Optional.of(true), inserted.colBoolean()); + + var flipped = inserted.withColBoolean(Optional.of(false)); + repo.update(flipped, c); + var refetched = repo.selectById(inserted.id(), c).orElseThrow(); + assertEquals(Optional.of(false), refetched.colBoolean()); + }); + } + + @Test + public void testFloatingPointTypes() { + SqliteTestHelper.run( + c -> { + var row = createSampleRow(1012); + var inserted = repo.insert(row, c); + + assertEquals(Optional.of(3.14159), inserted.colReal()); + assertEquals(Optional.of(2.718281828), inserted.colDouble()); + assertEquals(Optional.of(1.5f), inserted.colFloat()); + }); + } + + @Test + public void testDecimalAndNumericTypes() { + SqliteTestHelper.run( + c -> { + var row = createSampleRow(1013); + var inserted = repo.insert(row, c); + + assertEquals( + 0, new BigDecimal("12345.67").compareTo(inserted.colDecimal().orElseThrow())); + assertEquals(0, new BigDecimal("999.999").compareTo(inserted.colNumeric().orElseThrow())); + }); + } + + @Test + public void testTextTypes() { + SqliteTestHelper.run( + c -> { + var row = createSampleRow(1014); + var inserted = repo.insert(row, c); + + assertEquals(Optional.of("text content"), inserted.colText()); + assertEquals(Optional.of("varchar_value"), inserted.colVarchar()); + assertEquals(Optional.of("char5"), inserted.colChar()); + assertEquals(Optional.of("clob content"), inserted.colClob()); + }); + } + + @Test + public void testBlobAndBinaryTypes() { + SqliteTestHelper.run( + c -> { + var blobData = new byte[] {0x00, 0x01, 0x02, (byte) 0xFF, (byte) 0xFE}; + var binaryData = new byte[] {(byte) 0xCA, (byte) 0xFE, (byte) 0xBA, (byte) 0xBE}; + var row = + createSampleRow(1015) + .withColBlob(Optional.of(blobData)) + .withColBinary(Optional.of(binaryData)); + var inserted = repo.insert(row, c); + + assertArrayEquals(blobData, inserted.colBlob().orElseThrow()); + assertArrayEquals(binaryData, inserted.colBinary().orElseThrow()); + }); + } + + @Test + public void testDateTimeTypes() { + SqliteTestHelper.run( + c -> { + var row = createSampleRow(1016); + var inserted = repo.insert(row, c); + + assertEquals(Optional.of(LocalDate.of(2025, 1, 15)), inserted.colDate()); + assertEquals(Optional.of(LocalTime.of(14, 30, 45)), inserted.colTime()); + assertEquals( + Optional.of(LocalDateTime.of(2025, 1, 15, 14, 30, 45)), inserted.colDatetime()); + assertEquals(Optional.of(LocalDateTime.of(2025, 6, 1, 9, 0, 0)), inserted.colTimestamp()); + }); + } + + @Test + public void testUuidType() { + SqliteTestHelper.run( + c -> { + var uuid = UUID.randomUUID(); + var row = createSampleRow(1017).withColUuid(Optional.of(uuid)); + var inserted = repo.insert(row, c); + + assertEquals(Optional.of(uuid), inserted.colUuid()); + }); + } + + @Test + public void testJsonType() { + SqliteTestHelper.run( + c -> { + var jsonValue = new Json("{\"name\":\"test\",\"values\":[1,2,3]}"); + var row = createSampleRow(1018).withColJson(Optional.of(jsonValue)); + var inserted = repo.insert(row, c); + + assertTrue(inserted.colJson().isPresent()); + assertTrue(inserted.colJson().get().value().contains("name")); + }); + } + + @Test + public void testSelectAllReturnsInsertedRow() { + SqliteTestHelper.run( + c -> { + var row = createSampleRow(1019); + repo.insert(row, c); + + var all = repo.selectAll(c); + // Schema seeds one row (id=1) and we inserted id=1019, so at least 2 are present. + assertTrue(all.size() >= 2); + assertTrue(all.stream().anyMatch(r -> r.id().value().equals(1019L))); + }); + } +} diff --git a/testers/sqlite/java/src/java/testdb/BasicCrudTest.java b/testers/sqlite/java/src/java/testdb/BasicCrudTest.java new file mode 100644 index 0000000000..48c83f41f4 --- /dev/null +++ b/testers/sqlite/java/src/java/testdb/BasicCrudTest.java @@ -0,0 +1,54 @@ +package testdb; + +import static org.junit.Assert.*; + +import java.util.List; +import org.junit.Test; +import testdb.customers.*; +import testdb.products.*; + +/** Minimal end-to-end SQLite test: inserts, selects, updates, deletes. */ +public class BasicCrudTest { + private final CustomersRepoImpl customers = new CustomersRepoImpl(); + private final ProductsRepoImpl products = new ProductsRepoImpl(); + + @Test + public void selectAllCustomersFromSeedData() { + List rows = SqliteTestHelper.applyRead(customers::selectAll); + assertEquals(2, rows.size()); + } + + @Test + public void findCustomerById() { + var row = SqliteTestHelper.applyRead(conn -> customers.selectById(new CustomersId(1L), conn)); + assertTrue(row.isPresent()); + assertEquals("John Doe", row.get().name()); + } + + @Test + public void deleteCustomerById() { + // Insert a fresh customer (no FK references) and delete it within the same transaction. + boolean deleted = + SqliteTestHelper.apply( + conn -> { + var inserted = + customers.insert( + new CustomersRowUnsaved( + new CustomersId(999L), + "Disposable", + java.util.Optional.empty(), + new testdb.customtypes.Defaulted.UseDefault<>()), + conn); + return customers.deleteById(inserted.customerId(), conn); + }); + assertTrue(deleted); + } + + @Test + public void productsHaveExpectedPrices() { + var ps = SqliteTestHelper.applyRead(products::selectAll); + assertEquals(2, ps.size()); + var skus = ps.stream().map(ProductsRow::sku).sorted().toList(); + assertEquals(List.of("PROD-001", "PROD-002"), skus); + } +} diff --git a/testers/sqlite/java/src/java/testdb/CompositeKeyTest.java b/testers/sqlite/java/src/java/testdb/CompositeKeyTest.java new file mode 100644 index 0000000000..d77f26ac03 --- /dev/null +++ b/testers/sqlite/java/src/java/testdb/CompositeKeyTest.java @@ -0,0 +1,308 @@ +package testdb; + +import static org.junit.Assert.*; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.util.Optional; +import org.junit.Test; +import testdb.departments.*; +import testdb.employees.*; + +/** + * Composite primary keys: departments (VARCHAR, VARCHAR) and employees (INTEGER, VARCHAR), plus the + * composite foreign key from employees → departments. + * + *

Schema seeds two departments (IT/US-WEST, HR/US-EAST) and two employees (1001/A, 1002/B); each + * test runs inside a per-test rollback so it sees those rows but its own inserts vanish on exit. + */ +public class CompositeKeyTest { + private final DepartmentsRepoImpl departmentsRepo = new DepartmentsRepoImpl(); + private final EmployeesRepoImpl employeesRepo = new EmployeesRepoImpl(); + + // ==================== Departments (String, String) Composite Key ==================== + + @Test + public void testDepartmentsInsert() { + SqliteTestHelper.run( + c -> { + var dept = + new DepartmentsRow( + "ENG", "EU-NORTH", "Engineering Europe", Optional.of(new BigDecimal("750000"))); + var inserted = departmentsRepo.insert(dept, c); + + assertNotNull(inserted); + assertEquals("ENG", inserted.deptCode()); + assertEquals("EU-NORTH", inserted.deptRegion()); + assertEquals("Engineering Europe", inserted.deptName()); + assertEquals(0, new BigDecimal("750000").compareTo(inserted.budget().orElseThrow())); + }); + } + + @Test + public void testDepartmentsSelectByCompositeId() { + SqliteTestHelper.run( + c -> { + var id = new DepartmentsId("IT", "US-WEST"); // from seed + var found = departmentsRepo.selectById(id, c); + + assertTrue(found.isPresent()); + assertEquals("IT", found.get().deptCode()); + assertEquals("US-WEST", found.get().deptRegion()); + assertEquals("Information Technology", found.get().deptName()); + }); + } + + @Test + public void testDepartmentsCompositeIdFromRow() { + SqliteTestHelper.run( + c -> { + var dept = + new DepartmentsRow( + "SALES", "APAC", "Sales APAC", Optional.of(new BigDecimal("500000"))); + var inserted = departmentsRepo.insert(dept, c); + + var compositeId = inserted.compositeId(); + assertEquals("SALES", compositeId.deptCode()); + assertEquals("APAC", compositeId.deptRegion()); + + var found = departmentsRepo.selectById(compositeId, c); + assertTrue(found.isPresent()); + assertEquals(inserted, found.get()); + }); + } + + @Test + public void testDepartmentsUpdate() { + SqliteTestHelper.run( + c -> { + var dept = + new DepartmentsRow( + "FINANCE", "US-CENTRAL", "Finance", Optional.of(new BigDecimal("800000"))); + var inserted = departmentsRepo.insert(dept, c); + + var updated = inserted.withBudget(Optional.of(new BigDecimal("900000"))); + boolean wasUpdated = departmentsRepo.update(updated, c); + assertTrue(wasUpdated); + + var found = departmentsRepo.selectById(inserted.compositeId(), c).orElseThrow(); + assertEquals(0, new BigDecimal("900000").compareTo(found.budget().orElseThrow())); + }); + } + + @Test + public void testDepartmentsDelete() { + SqliteTestHelper.run( + c -> { + var dept = new DepartmentsRow("TEMP", "TEMP-REGION", "Temporary", Optional.empty()); + var inserted = departmentsRepo.insert(dept, c); + + boolean deleted = departmentsRepo.deleteById(inserted.compositeId(), c); + assertTrue(deleted); + + var found = departmentsRepo.selectById(inserted.compositeId(), c); + assertFalse(found.isPresent()); + }); + } + + @Test + public void testDepartmentsMultipleSameCode() { + SqliteTestHelper.run( + c -> { + var d1 = new DepartmentsRow("ENG2", "US", "Engineering US", Optional.empty()); + var d2 = new DepartmentsRow("ENG2", "EU", "Engineering EU", Optional.empty()); + var d3 = new DepartmentsRow("ENG2", "APAC", "Engineering APAC", Optional.empty()); + + departmentsRepo.insert(d1, c); + departmentsRepo.insert(d2, c); + departmentsRepo.insert(d3, c); + + assertTrue(departmentsRepo.selectById(new DepartmentsId("ENG2", "US"), c).isPresent()); + assertTrue(departmentsRepo.selectById(new DepartmentsId("ENG2", "EU"), c).isPresent()); + assertTrue(departmentsRepo.selectById(new DepartmentsId("ENG2", "APAC"), c).isPresent()); + }); + } + + // ==================== Employees (Long, String) Composite Key ==================== + + @Test + public void testEmployeesInsert() { + SqliteTestHelper.run( + c -> { + // Schema already has IT/US-WEST as a department, reuse it for FK + var emp = + new EmployeesRow( + 2001L, + "A", + "IT", + "US-WEST", + "Alice Johnson", + Optional.of(new BigDecimal("95000")), + LocalDate.of(2025, 1, 15)); + var inserted = employeesRepo.insert(emp, c); + + assertNotNull(inserted); + assertEquals(Long.valueOf(2001L), inserted.empNumber()); + assertEquals("A", inserted.empSuffix()); + assertEquals("Alice Johnson", inserted.empName()); + }); + } + + @Test + public void testEmployeesSelectByCompositeId() { + SqliteTestHelper.run( + c -> { + var id = new EmployeesId(1001L, "A"); // from seed + var found = employeesRepo.selectById(id, c); + + assertTrue(found.isPresent()); + assertEquals(Long.valueOf(1001L), found.get().empNumber()); + assertEquals("A", found.get().empSuffix()); + assertEquals("Alice Johnson", found.get().empName()); + }); + } + + @Test + public void testEmployeesCompositeIdFromRow() { + SqliteTestHelper.run( + c -> { + var emp = + new EmployeesRow( + 3001L, + "C", + "HR", + "US-EAST", + "Carol White", + Optional.empty(), + LocalDate.of(2025, 3, 1)); + var inserted = employeesRepo.insert(emp, c); + + var compositeId = inserted.compositeId(); + assertEquals(Long.valueOf(3001L), compositeId.empNumber()); + assertEquals("C", compositeId.empSuffix()); + + var found = employeesRepo.selectById(compositeId, c); + assertTrue(found.isPresent()); + }); + } + + @Test + public void testEmployeesUpdate() { + SqliteTestHelper.run( + c -> { + var emp = + new EmployeesRow( + 4001L, + "D", + "IT", + "US-WEST", + "David Brown", + Optional.of(new BigDecimal("120000")), + LocalDate.of(2025, 4, 1)); + var inserted = employeesRepo.insert(emp, c); + + var updated = inserted.withSalary(Optional.of(new BigDecimal("130000"))); + employeesRepo.update(updated, c); + + var found = employeesRepo.selectById(inserted.compositeId(), c).orElseThrow(); + assertEquals(0, new BigDecimal("130000").compareTo(found.salary().orElseThrow())); + }); + } + + @Test + public void testEmployeesDelete() { + SqliteTestHelper.run( + c -> { + var emp = + new EmployeesRow( + 5001L, + "X", + "IT", + "US-WEST", + "To Be Deleted", + Optional.empty(), + LocalDate.of(2025, 5, 1)); + var inserted = employeesRepo.insert(emp, c); + + boolean deleted = employeesRepo.deleteById(inserted.compositeId(), c); + assertTrue(deleted); + + var found = employeesRepo.selectById(inserted.compositeId(), c); + assertFalse(found.isPresent()); + }); + } + + @Test + public void testEmployeesMultipleSameNumber() { + SqliteTestHelper.run( + c -> { + var e1 = + new EmployeesRow( + 9999L, + "A", + "IT", + "US-WEST", + "Employee A", + Optional.empty(), + LocalDate.of(2025, 1, 1)); + var e2 = + new EmployeesRow( + 9999L, + "B", + "IT", + "US-WEST", + "Employee B", + Optional.empty(), + LocalDate.of(2025, 1, 1)); + var e3 = + new EmployeesRow( + 9999L, + "C", + "IT", + "US-WEST", + "Employee C", + Optional.empty(), + LocalDate.of(2025, 1, 1)); + + employeesRepo.insert(e1, c); + employeesRepo.insert(e2, c); + employeesRepo.insert(e3, c); + + assertTrue(employeesRepo.selectById(new EmployeesId(9999L, "A"), c).isPresent()); + assertTrue(employeesRepo.selectById(new EmployeesId(9999L, "B"), c).isPresent()); + assertTrue(employeesRepo.selectById(new EmployeesId(9999L, "C"), c).isPresent()); + }); + } + + // ==================== Composite FK Relationship ==================== + + @Test + public void testEmployeeDepartmentForeignKey() { + SqliteTestHelper.run( + c -> { + var dept = + new DepartmentsRow( + "FK_TEST", "FK_REGION", "FK Test Dept", Optional.of(new BigDecimal("500000"))); + departmentsRepo.insert(dept, c); + + var emp = + new EmployeesRow( + 6001L, + "F", + "FK_TEST", + "FK_REGION", + "FK Employee", + Optional.of(new BigDecimal("60000")), + LocalDate.of(2025, 6, 1)); + var insertedEmp = employeesRepo.insert(emp, c); + + assertEquals(dept.deptCode(), insertedEmp.deptCode()); + assertEquals(dept.deptRegion(), insertedEmp.deptRegion()); + + var foundDept = + departmentsRepo.selectById( + new DepartmentsId(insertedEmp.deptCode(), insertedEmp.deptRegion()), c); + assertTrue(foundDept.isPresent()); + }); + } +} diff --git a/testers/sqlite/java/src/java/testdb/DSLTest.java b/testers/sqlite/java/src/java/testdb/DSLTest.java new file mode 100644 index 0000000000..5f0b43237a --- /dev/null +++ b/testers/sqlite/java/src/java/testdb/DSLTest.java @@ -0,0 +1,204 @@ +package testdb; + +import static org.junit.Assert.*; + +import dev.typr.foundations.Bijection; +import java.time.LocalDateTime; +import java.util.Optional; +import org.junit.Test; +import testdb.customers.*; +import testdb.userdefined.Email; + +/** + * Exercises the generated type-safe DSL through {@code Dialect.SQLITE}: the rendered SQL passes + * through the SQLite query planner without errors and produces the expected results. + */ +public class DSLTest { + private final CustomersRepoImpl repo = new CustomersRepoImpl(); + + private static CustomersRow row(long id, String name) { + return new CustomersRow( + new CustomersId(id), name, Optional.empty(), LocalDateTime.of(2025, 1, 1, 0, 0)); + } + + @Test + public void testSelectWithWhere() { + SqliteTestHelper.run( + c -> { + repo.insert( + new CustomersRow( + new CustomersId(5001L), + "DSL Test User", + Optional.of(new Email("dsl@test.com")), + LocalDateTime.of(2025, 1, 1, 0, 0)), + c); + + var results = repo.select().where(cu -> cu.name().isEqual("DSL Test User")).toList(c); + assertEquals(1, results.size()); + assertEquals("DSL Test User", results.get(0).name()); + }); + } + + @Test + public void testSelectWithOrderByAsc() { + SqliteTestHelper.run( + c -> { + repo.insert(row(5002L, "Zebra"), c); + repo.insert(row(5003L, "Alpha"), c); + repo.insert(row(5004L, "Mike"), c); + + var results = + repo.select() + .where(cu -> cu.customerId().greaterThan(new CustomersId(5001L))) + .orderBy(cu -> cu.name().asc()) + .toList(c); + + assertEquals(3, results.size()); + assertEquals("Alpha", results.get(0).name()); + assertEquals("Mike", results.get(1).name()); + assertEquals("Zebra", results.get(2).name()); + }); + } + + @Test + public void testSelectWithOrderByDesc() { + SqliteTestHelper.run( + c -> { + repo.insert(row(5005L, "DescA"), c); + repo.insert(row(5006L, "DescB"), c); + repo.insert(row(5007L, "DescC"), c); + + var results = + repo.select() + .where(cu -> cu.name().like("Desc%", Bijection.asString())) + .orderBy(cu -> cu.name().desc()) + .toList(c); + + assertEquals(3, results.size()); + assertEquals("DescC", results.get(0).name()); + assertEquals("DescA", results.get(2).name()); + }); + } + + @Test + public void testSelectWithLimit() { + SqliteTestHelper.run( + c -> { + for (int i = 0; i < 10; i++) { + repo.insert(row(5100L + i, "Limit" + i), c); + } + var results = + repo.select() + .where(cu -> cu.name().like("Limit%", Bijection.asString())) + .limit(3) + .toList(c); + assertEquals(3, results.size()); + }); + } + + @Test + public void testSelectWithOffset() { + SqliteTestHelper.run( + c -> { + repo.insert(row(5200L, "OffsetA"), c); + repo.insert(row(5201L, "OffsetB"), c); + repo.insert(row(5202L, "OffsetC"), c); + repo.insert(row(5203L, "OffsetD"), c); + + var results = + repo.select() + .where(cu -> cu.name().like("Offset%", Bijection.asString())) + .orderBy(cu -> cu.name().asc()) + .offset(2) + .limit(10) + .toList(c); + + assertEquals(2, results.size()); + assertEquals("OffsetC", results.get(0).name()); + assertEquals("OffsetD", results.get(1).name()); + }); + } + + @Test + public void testSelectWithCount() { + SqliteTestHelper.run( + c -> { + repo.insert(row(5300L, "CountA"), c); + repo.insert(row(5301L, "CountB"), c); + repo.insert(row(5302L, "CountC"), c); + + var count = + repo.select().where(cu -> cu.name().like("Count%", Bijection.asString())).count(c); + + assertEquals(3, count); + }); + } + + @Test + public void testSelectWithLike() { + SqliteTestHelper.run( + c -> { + repo.insert(row(5400L, "LikeTest_ABC"), c); + repo.insert(row(5401L, "LikeTest_XYZ"), c); + repo.insert(row(5402L, "OtherName"), c); + + var results = + repo.select() + .where(cu -> cu.name().like("LikeTest%", Bijection.asString())) + .toList(c); + + assertEquals(2, results.size()); + }); + } + + @Test + public void testSelectWithIn() { + SqliteTestHelper.run( + c -> { + repo.insert(row(5500L, "InTest1"), c); + repo.insert(row(5501L, "InTest2"), c); + repo.insert(row(5502L, "InTest3"), c); + + var results = + repo.select() + .where(cu -> cu.customerId().in(new CustomersId(5500L), new CustomersId(5502L))) + .toList(c); + + assertEquals(2, results.size()); + }); + } + + @Test + public void testUpdateBuilder() { + SqliteTestHelper.run( + c -> { + repo.insert(row(5600L, "UpdateMe"), c); + + int updated = + repo.update() + .where(cu -> cu.customerId().isEqual(new CustomersId(5600L))) + .setValue(CustomersFields::name, "Updated") + .execute(c); + + assertEquals(1, updated); + + var found = repo.selectById(new CustomersId(5600L), c).orElseThrow(); + assertEquals("Updated", found.name()); + }); + } + + @Test + public void testDeleteBuilder() { + SqliteTestHelper.run( + c -> { + repo.insert(row(5700L, "DeleteA"), c); + repo.insert(row(5701L, "DeleteB"), c); + repo.insert(row(5702L, "DeleteC"), c); + + int deleted = + repo.delete().where(cu -> cu.name().like("Delete%", Bijection.asString())).execute(c); + + assertEquals(3, deleted); + }); + } +} diff --git a/testers/sqlite/java/src/java/testdb/DatabaseFeaturesTest.java b/testers/sqlite/java/src/java/testdb/DatabaseFeaturesTest.java new file mode 100644 index 0000000000..15a1a8f90a --- /dev/null +++ b/testers/sqlite/java/src/java/testdb/DatabaseFeaturesTest.java @@ -0,0 +1,220 @@ +package testdb; + +import static org.junit.Assert.*; + +import dev.typr.foundations.data.Json; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.Optional; +import java.util.UUID; +import org.junit.Test; +import testdb.customer_orders.CustomerOrdersViewRepoImpl; +import testdb.customers.*; +import testdb.customtypes.Defaulted; +import testdb.order_details.OrderDetailsViewRepoImpl; +import testdb.orders.*; +import testdb.products.*; +import testdb.userdefined.Email; + +/** + * Tests SQLite-specific feature claims from SqliteAdapter: + * + *

    + *
  • RETURNING (supportsReturning=true, since SQLite 3.35) — every insert path uses it + *
  • ON CONFLICT upserts (upsertStrategy=Returning, since SQLite 3.24) + *
  • AUTOINCREMENT primary keys via the unsaved-row pattern + *
  • UUID / JSON / BLOB / DateTime round-trips through TEXT-affinity storage + *
  • Views (customer_orders, order_details) + *
+ */ +public class DatabaseFeaturesTest { + private final CustomersRepoImpl customersRepo = new CustomersRepoImpl(); + private final ProductsRepoImpl productsRepo = new ProductsRepoImpl(); + private final OrdersRepoImpl ordersRepo = new OrdersRepoImpl(); + private final CustomerOrdersViewRepoImpl customerOrdersView = new CustomerOrdersViewRepoImpl(); + private final OrderDetailsViewRepoImpl orderDetailsView = new OrderDetailsViewRepoImpl(); + + // ==================== RETURNING ==================== + + @Test + public void testInsertReturningPopulatesGeneratedColumns() { + SqliteTestHelper.run( + c -> { + // The unsaved-row path leans on AUTOINCREMENT + DEFAULT CURRENT_TIMESTAMP — both must + // come + // back via the RETURNING clause. + var unsaved = new CustomersRowUnsaved(new CustomersId(10001L), "Returning Test"); + var inserted = customersRepo.insert(unsaved, c); + + assertNotNull(inserted); + assertEquals(Long.valueOf(10001L), inserted.customerId().value()); + // createdAt comes from DEFAULT CURRENT_TIMESTAMP — RETURNING gives us the resolved value. + assertNotNull(inserted.createdAt()); + }); + } + + @Test + public void testInsertWithProvidedDefault() { + SqliteTestHelper.run( + c -> { + var explicit = LocalDateTime.of(2020, 5, 1, 12, 0); + var unsaved = + new CustomersRowUnsaved( + new CustomersId(10002L), + "Explicit Default", + Optional.of(new Email("user@x.com")), + new Defaulted.Provided<>(explicit)); + var inserted = customersRepo.insert(unsaved, c); + + assertEquals(explicit, inserted.createdAt()); + }); + } + + // ==================== ON CONFLICT upsert ==================== + + @Test + public void testUpsertInsertsNew() { + SqliteTestHelper.run( + c -> { + var customer = + new CustomersRow( + new CustomersId(20001L), + "Upsert Insert", + Optional.empty(), + LocalDateTime.of(2025, 1, 1, 0, 0)); + var result = customersRepo.upsert(customer, c); + assertEquals("Upsert Insert", result.name()); + }); + } + + @Test + public void testUpsertUpdatesOnConflict() { + SqliteTestHelper.run( + c -> { + var customer = + new CustomersRow( + new CustomersId(20002L), + "Original", + Optional.of(new Email("a@x.com")), + LocalDateTime.of(2025, 1, 1, 0, 0)); + customersRepo.insert(customer, c); + + var updated = + customer.withName("Updated via Upsert").withEmail(Optional.of(new Email("b@x.com"))); + var result = customersRepo.upsert(updated, c); + + assertEquals("Updated via Upsert", result.name()); + assertEquals(Optional.of(new Email("b@x.com")), result.email()); + + // Confirm there's still only one row for that ID + var found = customersRepo.selectById(new CustomersId(20002L), c).orElseThrow(); + assertEquals("Updated via Upsert", found.name()); + }); + } + + // ==================== Round-trip-only types ==================== + + @Test + public void testUuidPersistsAsCanonicalText() { + SqliteTestHelper.run( + c -> { + var uuid = UUID.randomUUID(); + // Use the products table since it has a metadata json column AND a sku unique constraint. + // Insert a UUID via the all_scalar_types tester (covered by AllTypesTest). Here just + // verify a fresh UUID round-trips through the products.metadata path. + var product = + new ProductsRow( + new ProductsId(30001L), + "SKU-UUID-" + uuid, + "UUID Product", + new BigDecimal("1.00"), + Optional.of(new Json("{\"uuid\":\"" + uuid + "\"}"))); + var inserted = productsRepo.insert(product, c); + assertTrue(inserted.metadata().orElseThrow().value().contains(uuid.toString())); + }); + } + + // ==================== Views ==================== + + @Test + public void testCustomerOrdersView() { + SqliteTestHelper.run( + c -> { + var rows = customerOrdersView.selectAll(c); + // Schema's view does a LEFT JOIN customers ⨝ orders. Seed has 2 customers + 2 orders, + // so the result is 2 rows (each customer joined to their one order). + assertEquals(2, rows.size()); + assertTrue(rows.stream().anyMatch(r -> r.customerName().equals(Optional.of("John Doe")))); + assertTrue( + rows.stream().anyMatch(r -> r.customerName().equals(Optional.of("Jane Smith")))); + }); + } + + @Test + public void testOrderDetailsView() { + SqliteTestHelper.run( + c -> { + var rows = orderDetailsView.selectAll(c); + // Seed has 3 order_items rows, so the view produces 3 (orders × items × products joined). + assertEquals(3, rows.size()); + // line_total is the computed expression quantity * unit_price; sqlglot can't infer its + // numeric type through SQLite's affinity model and falls back to TEXT, so we just check + // it's non-empty and parses as a positive BigDecimal. + rows.forEach( + r -> { + var s = r.lineTotal().orElseThrow(); + assertTrue(new BigDecimal(s).compareTo(BigDecimal.ZERO) > 0); + }); + }); + } + + // ==================== AUTOINCREMENT ==================== + + @Test + public void testInsertWithExplicitId() { + SqliteTestHelper.run( + c -> { + // The customers PK is AUTOINCREMENT, but the codegen surfaces it as required on + // CustomersRow. We provide it; SQLite respects it. + var row = + new CustomersRow( + new CustomersId(50001L), + "Explicit ID", + Optional.empty(), + LocalDateTime.of(2025, 1, 1, 0, 0)); + var inserted = customersRepo.insert(row, c); + assertEquals(Long.valueOf(50001L), inserted.customerId().value()); + }); + } + + @Test + public void testSelectByIdsReturnsRequested() { + SqliteTestHelper.run( + c -> { + // Seed customers 1 and 2 — selectByIds is the supportsArrays=false path; it should still + // work via IN-clause expansion. + var found = + customersRepo.selectByIds( + java.util.List.of(new CustomersId(1L), new CustomersId(2L)), c); + assertEquals(2, found.size()); + }); + } + + @Test + public void testOrderInsertWithForeignKeyValue() { + SqliteTestHelper.run( + c -> { + var order = + new OrdersRow( + new OrdersId(70001L), + new CustomersId(1L), + LocalDate.of(2025, 7, 1), + Optional.of(new BigDecimal("250.00")), + "pending"); + var inserted = ordersRepo.insert(order, c); + assertEquals(Long.valueOf(70001L), inserted.orderId().value()); + assertEquals(Long.valueOf(1L), inserted.customerId().value()); + }); + } +} diff --git a/testers/sqlite/java/src/java/testdb/ForeignKeyTest.java b/testers/sqlite/java/src/java/testdb/ForeignKeyTest.java new file mode 100644 index 0000000000..8eabf82008 --- /dev/null +++ b/testers/sqlite/java/src/java/testdb/ForeignKeyTest.java @@ -0,0 +1,189 @@ +package testdb; + +import static org.junit.Assert.*; + +import java.math.BigDecimal; +import java.sql.SQLException; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.Optional; +import org.junit.Test; +import testdb.customers.*; +import testdb.order_items.*; +import testdb.orders.*; +import testdb.products.*; +import testdb.userdefined.Email; + +/** + * Foreign-key relationships: customers → orders → order_items ← products. SQLite enforces FKs only + * when `PRAGMA foreign_keys = ON`; SqliteTestHelper sets it via the SqliteConfig builder, so + * violations should throw. + */ +public class ForeignKeyTest { + private final CustomersRepoImpl customersRepo = new CustomersRepoImpl(); + private final ProductsRepoImpl productsRepo = new ProductsRepoImpl(); + private final OrdersRepoImpl ordersRepo = new OrdersRepoImpl(); + private final OrderItemsRepoImpl orderItemsRepo = new OrderItemsRepoImpl(); + + @Test + public void testCustomerInsert() { + SqliteTestHelper.run( + c -> { + var customer = + new CustomersRow( + new CustomersId(100L), + "John Doe", + Optional.of(new Email("john@example.com")), + LocalDateTime.of(2025, 1, 1, 12, 0)); + var inserted = customersRepo.insert(customer, c); + + assertNotNull(inserted); + assertEquals("John Doe", inserted.name()); + assertEquals(Optional.of(new Email("john@example.com")), inserted.email()); + }); + } + + @Test + public void testProductInsert() { + SqliteTestHelper.run( + c -> { + var product = + new ProductsRow( + new ProductsId(100L), + "PROD-100", + "Test Product", + new BigDecimal("29.99"), + Optional.empty()); + var inserted = productsRepo.insert(product, c); + + assertNotNull(inserted); + assertEquals("PROD-100", inserted.sku()); + assertEquals(0, new BigDecimal("29.99").compareTo(inserted.price())); + }); + } + + @Test + public void testOrderWithCustomerFK() { + SqliteTestHelper.run( + c -> { + var customer = + new CustomersRow( + new CustomersId(101L), + "Jane Smith", + Optional.of(new Email("jane@example.com")), + LocalDateTime.of(2025, 1, 2, 12, 0)); + var insertedCustomer = customersRepo.insert(customer, c); + + var order = + new OrdersRow( + new OrdersId(101L), + insertedCustomer.customerId(), + LocalDate.of(2025, 1, 15), + Optional.of(new BigDecimal("99.99")), + "pending"); + + var insertedOrder = ordersRepo.insert(order, c); + + assertNotNull(insertedOrder); + assertEquals(insertedCustomer.customerId(), insertedOrder.customerId()); + }); + } + + @Test + public void testOrderItemsWithCompositePK() { + SqliteTestHelper.run( + c -> { + customersRepo.insert( + new CustomersRow( + new CustomersId(102L), + "Test Customer", + Optional.empty(), + LocalDateTime.of(2025, 1, 1, 0, 0)), + c); + var product = + productsRepo.insert( + new ProductsRow( + new ProductsId(102L), + "PROD-102", + "Widget", + new BigDecimal("49.99"), + Optional.empty()), + c); + var order = + ordersRepo.insert( + new OrdersRow( + new OrdersId(102L), + new CustomersId(102L), + LocalDate.of(2025, 1, 16), + Optional.of(new BigDecimal("149.97")), + "pending"), + c); + + var item = + new OrderItemsRow(order.orderId(), product.productId(), 3L, new BigDecimal("49.99")); + + var insertedItem = orderItemsRepo.insert(item, c); + + assertEquals(Long.valueOf(3L), insertedItem.quantity()); + assertEquals(0, new BigDecimal("49.99").compareTo(insertedItem.unitPrice())); + }); + } + + @Test + public void testForeignKeyEnforcedOnInsert() { + // Insert an order pointing at a non-existent customer — SQLite (with FK ON) should reject it. + boolean threw = false; + try { + SqliteTestHelper.run( + c -> { + ordersRepo.insert( + new OrdersRow( + new OrdersId(9999L), + new CustomersId(99999L), // not in DB + LocalDate.of(2025, 1, 1), + Optional.empty(), + "pending"), + c); + }); + } catch (RuntimeException e) { + // SQLite throws SQLITE_CONSTRAINT_FOREIGNKEY → wrapped by foundations + threw = + e.getMessage() != null && e.getMessage().toLowerCase().contains("foreign key") + || (e.getCause() instanceof SQLException) + || e.getMessage() != null && e.getMessage().contains("FOREIGN KEY"); + } + assertTrue("Expected FK violation, got nothing", threw); + } + + @Test + public void testTypeSafeIds() { + SqliteTestHelper.run( + c -> { + var customerId = new CustomersId(200L); + var productId = new ProductsId(200L); + var orderId = new OrdersId(200L); + + // These three IDs are distinct types — the compiler refuses to mix them. + customersRepo.insert( + new CustomersRow( + customerId, "Type Safe", Optional.empty(), LocalDateTime.of(2025, 1, 1, 0, 0)), + c); + productsRepo.insert( + new ProductsRow( + productId, + "SKU-200", + "Type Safe Product", + new BigDecimal("1.00"), + Optional.empty()), + c); + ordersRepo.insert( + new OrdersRow( + orderId, customerId, LocalDate.of(2025, 1, 1), Optional.empty(), "pending"), + c); + + assertTrue(customersRepo.selectById(customerId, c).isPresent()); + assertTrue(productsRepo.selectById(productId, c).isPresent()); + assertTrue(ordersRepo.selectById(orderId, c).isPresent()); + }); + } +} diff --git a/testers/sqlite/java/src/java/testdb/MockRepoTest.java b/testers/sqlite/java/src/java/testdb/MockRepoTest.java new file mode 100644 index 0000000000..867b7c2738 --- /dev/null +++ b/testers/sqlite/java/src/java/testdb/MockRepoTest.java @@ -0,0 +1,197 @@ +package testdb; + +import static org.junit.Assert.*; + +import dev.typr.dsl.MockConnection; +import dev.typr.foundations.Bijection; +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.Optional; +import org.junit.Test; +import testdb.customers.*; +import testdb.departments.*; +import testdb.userdefined.Email; + +/** Generated mock repositories — exercised entirely in-process, no SQLite connection. */ +public class MockRepoTest { + private static CustomersRepoMock createCustomersMock() { + return new CustomersRepoMock( + unsaved -> unsaved.toRow(() -> LocalDateTime.of(2025, 1, 1, 0, 0))); + } + + private final CustomersRepoMock customersMock = createCustomersMock(); + private final DepartmentsRepoMock departmentsMock = new DepartmentsRepoMock(); + + @Test + public void testMockInsertAndSelect() { + var customer = + new CustomersRow( + new CustomersId(1L), + "Mock User", + Optional.of(new Email("mock@test.com")), + LocalDateTime.of(2025, 1, 1, 0, 0)); + + var inserted = customersMock.insert(customer, null); + assertNotNull(inserted); + assertEquals("Mock User", inserted.name()); + + var found = customersMock.selectById(new CustomersId(1L), null); + assertTrue(found.isPresent()); + assertEquals("Mock User", found.get().name()); + } + + @Test + public void testMockUpdate() { + var customer = + new CustomersRow( + new CustomersId(2L), + "Original Name", + Optional.empty(), + LocalDateTime.of(2025, 1, 1, 0, 0)); + customersMock.insert(customer, null); + + var updated = customer.withName("Updated Name"); + customersMock.update(updated, null); + + var found = customersMock.selectById(new CustomersId(2L), null).orElseThrow(); + assertEquals("Updated Name", found.name()); + } + + @Test + public void testMockDelete() { + var customer = + new CustomersRow( + new CustomersId(3L), "To Delete", Optional.empty(), LocalDateTime.of(2025, 1, 1, 0, 0)); + customersMock.insert(customer, null); + assertTrue(customersMock.selectById(new CustomersId(3L), null).isPresent()); + + customersMock.deleteById(new CustomersId(3L), null); + assertFalse(customersMock.selectById(new CustomersId(3L), null).isPresent()); + } + + @Test + public void testMockSelectAll() { + var mock = createCustomersMock(); + mock.insert( + new CustomersRow( + new CustomersId(10L), "U1", Optional.empty(), LocalDateTime.of(2025, 1, 1, 0, 0)), + null); + mock.insert( + new CustomersRow( + new CustomersId(11L), "U2", Optional.empty(), LocalDateTime.of(2025, 1, 1, 0, 0)), + null); + mock.insert( + new CustomersRow( + new CustomersId(12L), "U3", Optional.empty(), LocalDateTime.of(2025, 1, 1, 0, 0)), + null); + + var all = mock.selectAll(null); + assertEquals(3, all.size()); + } + + @Test + public void testMockWithCompositeKey() { + var dept = + new DepartmentsRow( + "MOCK_IT", "MOCK_US", "Mock IT US", Optional.of(new BigDecimal("500000"))); + + departmentsMock.insert(dept, null); + + var id = new DepartmentsId("MOCK_IT", "MOCK_US"); + var found = departmentsMock.selectById(id, null); + + assertTrue(found.isPresent()); + assertEquals("Mock IT US", found.get().deptName()); + } + + @Test + public void testMockDSLQuery() { + var mock = createCustomersMock(); + + mock.insert( + new CustomersRow( + new CustomersId(100L), "Alice", Optional.empty(), LocalDateTime.of(2025, 1, 1, 0, 0)), + null); + mock.insert( + new CustomersRow( + new CustomersId(101L), "Bob", Optional.empty(), LocalDateTime.of(2025, 1, 1, 0, 0)), + null); + mock.insert( + new CustomersRow( + new CustomersId(102L), "Charlie", Optional.empty(), LocalDateTime.of(2025, 1, 1, 0, 0)), + null); + + var results = + mock.select() + .where(c -> c.customerId().greaterThan(new CustomersId(100L))) + .orderBy(c -> c.name().asc()) + .toList(null); + + assertEquals(2, results.size()); + assertEquals("Bob", results.get(0).name()); + assertEquals("Charlie", results.get(1).name()); + } + + @Test + public void testMockDSLCount() { + var mock = createCustomersMock(); + + mock.insert( + new CustomersRow( + new CustomersId(200L), "Count1", Optional.empty(), LocalDateTime.of(2025, 1, 1, 0, 0)), + MockConnection.instance); + mock.insert( + new CustomersRow( + new CustomersId(201L), "Count2", Optional.empty(), LocalDateTime.of(2025, 1, 1, 0, 0)), + MockConnection.instance); + mock.insert( + new CustomersRow( + new CustomersId(202L), "Other", Optional.empty(), LocalDateTime.of(2025, 1, 1, 0, 0)), + MockConnection.instance); + + var count = + mock.select() + .where(c -> c.name().like("Count%", Bijection.asString())) + .count(MockConnection.instance); + + assertEquals(2, count); + } + + @Test + public void testMockDSLLimit() { + var mock = createCustomersMock(); + for (int i = 0; i < 10; i++) { + mock.insert( + new CustomersRow( + new CustomersId(300L + i), + "Limit" + i, + Optional.empty(), + LocalDateTime.of(2025, 1, 1, 0, 0)), + null); + } + var results = + mock.select() + .where(c -> c.name().like("Limit%", Bijection.asString())) + .limit(5) + .toList(null); + + assertEquals(5, results.size()); + } + + @Test + public void testMockIsolation() { + var mock1 = createCustomersMock(); + var mock2 = createCustomersMock(); + + mock1.insert( + new CustomersRow( + new CustomersId(400L), + "Mock1 Only", + Optional.empty(), + LocalDateTime.of(2025, 1, 1, 0, 0)), + null); + + assertTrue(mock1.selectById(new CustomersId(400L), null).isPresent()); + assertFalse(mock2.selectById(new CustomersId(400L), null).isPresent()); + } +} diff --git a/testers/sqlite/java/src/java/testdb/SqlScriptTest.java b/testers/sqlite/java/src/java/testdb/SqlScriptTest.java new file mode 100644 index 0000000000..3dca9c6c85 --- /dev/null +++ b/testers/sqlite/java/src/java/testdb/SqlScriptTest.java @@ -0,0 +1,202 @@ +package testdb; + +import static org.junit.Assert.*; + +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.Optional; +import org.junit.Test; +import testdb.all_scalar_types_search.AllScalarTypesSearchSqlRepoImpl; +import testdb.customer_search.CustomerSearchSqlRepoImpl; +import testdb.delete_old_orders.DeleteOldOrdersSqlRepoImpl; +import testdb.order_summary_by_customer.OrderSummaryByCustomerSqlRepoImpl; +import testdb.product_details_with_sales.ProductDetailsWithSalesSqlRepoImpl; + +/** + * End-to-end exercise of every generated SQL-script repo. Verifies parameter encoding, result + * decoding, and the typr ↔ sqlglot type-lineage hand-off (e.g. customer_id returning a typed + * CustomersId rather than raw Long). + */ +public class SqlScriptTest { + private final CustomerSearchSqlRepoImpl customerSearch = new CustomerSearchSqlRepoImpl(); + private final OrderSummaryByCustomerSqlRepoImpl orderSummary = + new OrderSummaryByCustomerSqlRepoImpl(); + private final ProductDetailsWithSalesSqlRepoImpl productDetails = + new ProductDetailsWithSalesSqlRepoImpl(); + private final AllScalarTypesSearchSqlRepoImpl scalarSearch = + new AllScalarTypesSearchSqlRepoImpl(); + private final DeleteOldOrdersSqlRepoImpl deleteOld = new DeleteOldOrdersSqlRepoImpl(); + + // ============== customer_search.sql ============== + + @Test + public void testCustomerSearchAll() { + SqliteTestHelper.run( + c -> { + var rows = + customerSearch.apply(Optional.empty(), Optional.empty(), Optional.empty(), 100L, c); + assertEquals(2, rows.size()); // seeded John Doe + Jane Smith + }); + } + + @Test + public void testCustomerSearchByNamePattern() { + SqliteTestHelper.run( + c -> { + var rows = + customerSearch.apply( + Optional.of("John%"), Optional.empty(), Optional.empty(), 100L, c); + assertEquals(1, rows.size()); + assertEquals("John Doe", rows.get(0).name()); + }); + } + + @Test + public void testCustomerSearchByEmailPattern() { + SqliteTestHelper.run( + c -> { + var rows = + customerSearch.apply( + Optional.empty(), Optional.of("%jane%"), Optional.empty(), 100L, c); + assertEquals(1, rows.size()); + assertEquals("Jane Smith", rows.get(0).name()); + }); + } + + @Test + public void testCustomerSearchLimit() { + SqliteTestHelper.run( + c -> { + var rows = + customerSearch.apply(Optional.empty(), Optional.empty(), Optional.empty(), 1L, c); + assertEquals(1, rows.size()); + }); + } + + @Test + public void testCustomerSearchByCreatedAfter() { + SqliteTestHelper.run( + c -> { + var future = LocalDateTime.of(2099, 1, 1, 0, 0); + var rows = + customerSearch.apply( + Optional.empty(), Optional.empty(), Optional.of(future), 100L, c); + assertEquals(0, rows.size()); + }); + } + + // ============== order_summary_by_customer.sql ============== + + @Test + public void testOrderSummaryByCustomerInRange() { + SqliteTestHelper.run( + c -> { + var rows = orderSummary.apply(LocalDate.of(2025, 1, 1), LocalDate.of(2025, 12, 31), c); + // Two seeded customers, both with orders in range + assertEquals(2, rows.size()); + // Sum across both customers' orders should match seed totals (79.98 + 29.99) + var totalRevenue = + rows.stream() + .map(r -> r.totalRevenue().orElse(BigDecimal.ZERO)) + .reduce(BigDecimal.ZERO, BigDecimal::add); + assertEquals(0, new BigDecimal("109.97").compareTo(totalRevenue)); + }); + } + + @Test + public void testOrderSummaryEmptyDateRange() { + SqliteTestHelper.run( + c -> { + var rows = orderSummary.apply(LocalDate.of(2099, 1, 1), LocalDate.of(2099, 12, 31), c); + // Both seeded customers have orders, but neither is in the 2099 range; the WHERE clause + // filters out every row (the `IS NULL` branch only matches customers with no order at + // all). + assertEquals(0, rows.size()); + }); + } + + // ============== product_details_with_sales.sql ============== + + @Test + public void testProductDetailsAll() { + SqliteTestHelper.run( + c -> { + var rows = productDetails.apply(Optional.empty(), c); + assertEquals(2, rows.size()); + }); + } + + @Test + public void testProductDetailsByMinPrice() { + SqliteTestHelper.run( + c -> { + var rows = productDetails.apply(Optional.of(new BigDecimal("40.00")), c); + // Only Widget B (49.99) clears the bar + assertEquals(1, rows.size()); + assertEquals("Widget B", rows.get(0).productName()); + }); + } + + // ============== all_scalar_types_search.sql ============== + + @Test + public void testAllScalarSearchAll() { + SqliteTestHelper.run( + c -> { + var rows = scalarSearch.apply(Optional.empty(), Optional.empty(), Optional.empty(), c); + assertEquals(1, rows.size()); // seed has one row + }); + } + + @Test + public void testAllScalarSearchByMinId() { + SqliteTestHelper.run( + c -> { + var rows = scalarSearch.apply(Optional.of(100L), Optional.empty(), Optional.empty(), c); + assertEquals(0, rows.size()); + }); + } + + @Test + public void testAllScalarSearchByTextPattern() { + SqliteTestHelper.run( + c -> { + var rows = scalarSearch.apply(Optional.empty(), Optional.of("hel%"), Optional.empty(), c); + assertEquals(1, rows.size()); + }); + } + + // ============== delete_old_orders.sql ============== + + @Test + public void testDeleteOldOrders() { + SqliteTestHelper.run( + c -> { + // Insert a completed order with no order_items (so the FK to order_items doesn't block + // delete), + // then delete it through the script. + var ordersRepo = new testdb.orders.OrdersRepoImpl(); + ordersRepo.insert( + new testdb.orders.OrdersRow( + new testdb.orders.OrdersId(9001L), + new testdb.customers.CustomersId(1L), + LocalDate.of(2020, 1, 1), + Optional.of(new BigDecimal("10.00")), + "completed"), + c); + + int deleted = deleteOld.apply(LocalDate.of(2025, 1, 1), c); + assertEquals(1, deleted); + }); + } + + @Test + public void testDeleteOldOrdersNoneMatch() { + SqliteTestHelper.run( + c -> { + int deleted = deleteOld.apply(LocalDate.of(1900, 1, 1), c); + assertEquals(0, deleted); + }); + } +} diff --git a/testers/sqlite/java/src/java/testdb/SqliteTestHelper.java b/testers/sqlite/java/src/java/testdb/SqliteTestHelper.java new file mode 100644 index 0000000000..f76e752f8a --- /dev/null +++ b/testers/sqlite/java/src/java/testdb/SqliteTestHelper.java @@ -0,0 +1,101 @@ +package testdb; + +import dev.typr.foundations.Connection; +import dev.typr.foundations.ConnectionRead; +import dev.typr.foundations.SqlConsumer; +import dev.typr.foundations.SqlFunction; +import dev.typr.foundations.Transactor; +import dev.typr.foundations.connect.ConnectionSettings; +import dev.typr.foundations.connect.SqliteConfig; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * Drives a single in-memory SQLite DB across all tests. SQLite's xerial driver can't run a + * multi-statement string in one {@code Statement.execute()} call (unlike DuckDB), so we cannot rely + * on {@link ConnectionSettings#connectionInitSql}. Instead, on first use we open the connection + * source ourselves, split the schema on {@code ;} boundaries, and execute each statement. + * + *

SQLite's in-memory database is bound to a single connection, so {@link Transactor} reuses one + * connection underneath. Each {@code apply}/{@code run} is wrapped in {@link + * Transactor#rollbackOnly()}, which BEGINs and ROLLBACKs around the test body — keeping per-test + * isolation while the schema (which we COMMIT during init) survives. + */ +public class SqliteTestHelper { + private static final SqliteConfig CONFIG = SqliteConfig.inMemory().foreignKeys(true).build(); + private static final Transactor BASE = Transactor.create(CONFIG, ConnectionSettings.EMPTY); + private static final Transactor TRANSACTOR = BASE.rollbackOnly(); + private static final AtomicBoolean INITIALISED = new AtomicBoolean(false); + + private static void ensureInitialised() { + if (INITIALISED.compareAndSet(false, true)) { + String schema; + try { + schema = Files.readString(Path.of("sql-init/sqlite/00-schema.sql")); + } catch (IOException e) { + throw new RuntimeException("Failed to read SQLite schema", e); + } + + // Use the non-rollback base transactor so the schema commits and survives subsequent + // rollback-only test transactions. + BASE.transact( + conn -> { + try (Statement stmt = conn.unwrap().createStatement()) { + for (String chunk : splitStatements(schema)) { + String s = chunk.trim(); + if (!s.isEmpty()) stmt.execute(s); + } + } catch (SQLException e) { + throw new RuntimeException("Failed to load SQLite schema", e); + } + return null; + }); + } + } + + /** Split a SQL string on `;` outside of `'...'` literals, stripping `-- ...` line comments. */ + private static java.util.List splitStatements(String sql) { + java.util.List out = new java.util.ArrayList<>(); + StringBuilder cur = new StringBuilder(); + boolean inString = false; + int i = 0; + while (i < sql.length()) { + char c = sql.charAt(i); + if (!inString && c == '-' && i + 1 < sql.length() && sql.charAt(i + 1) == '-') { + while (i < sql.length() && sql.charAt(i) != '\n') i++; + } else if (c == '\'') { + cur.append(c); + inString = !inString; + i++; + } else if (c == ';' && !inString) { + out.add(cur.toString()); + cur.setLength(0); + i++; + } else { + cur.append(c); + i++; + } + } + out.add(cur.toString()); + return out; + } + + public static T apply(SqlFunction f) { + ensureInitialised(); + return TRANSACTOR.transact(f); + } + + public static void run(SqlConsumer f) { + ensureInitialised(); + TRANSACTOR.transactVoid(f); + } + + public static T applyRead(SqlFunction f) { + ensureInitialised(); + return TRANSACTOR.transactRead(f); + } +} diff --git a/testers/sqlite/java/src/java/testdb/TestInsertTest.java b/testers/sqlite/java/src/java/testdb/TestInsertTest.java new file mode 100644 index 0000000000..5f72f319ed --- /dev/null +++ b/testers/sqlite/java/src/java/testdb/TestInsertTest.java @@ -0,0 +1,123 @@ +package testdb; + +import static org.junit.Assert.*; + +import java.util.Random; +import org.junit.Test; + +/** + * TestInsert generates random data for required columns; this verifies that the SqliteAdapter arm + * in ComputedTestInserts produces values that actually round-trip through every supported table. + */ +public class TestInsertTest { + private final TestInsert testInsert = new TestInsert(new Random(1172222373)); + + @Test + public void testCustomersInsert() { + SqliteTestHelper.run( + c -> { + var row = testInsert.Customers().insert(c); + assertNotNull(row); + assertNotNull(row.customerId()); + assertNotNull(row.name()); + }); + } + + @Test + public void testCustomersWithCustomization() { + SqliteTestHelper.run( + c -> { + var row = testInsert.Customers().with(r -> r.withName("Custom Name")).insert(c); + assertNotNull(row); + assertEquals("Custom Name", row.name()); + }); + } + + @Test + public void testDepartmentsInsert() { + SqliteTestHelper.run( + c -> { + var row = testInsert.Departments().insert(c); + assertNotNull(row); + assertNotNull(row.deptCode()); + assertNotNull(row.deptRegion()); + assertNotNull(row.deptName()); + }); + } + + @Test + public void testProductsInsert() { + SqliteTestHelper.run( + c -> { + var row = testInsert.Products().insert(c); + assertNotNull(row); + assertNotNull(row.productId()); + assertNotNull(row.sku()); + assertNotNull(row.name()); + assertNotNull(row.price()); + }); + } + + @Test + public void testAllScalarTypesInsert() { + SqliteTestHelper.run( + c -> { + var row = testInsert.AllScalarTypes().insert(c); + assertNotNull(row); + assertNotNull(row.id()); + assertNotNull(row.colNotNull()); // the only required column + }); + } + + @Test + public void testEmployeesWithDepartmentFK() { + SqliteTestHelper.run( + c -> { + var dept = testInsert.Departments().insert(c); + // SQLite's TestInsert API takes the FK id as a required parameter (codegen wires it to + // the composite-FK constraint on employees → departments). + var emp = testInsert.Employees(dept.compositeId()).insert(c); + + assertNotNull(emp); + assertEquals(dept.deptCode(), emp.deptCode()); + assertEquals(dept.deptRegion(), emp.deptRegion()); + }); + } + + @Test + public void testOrdersWithCustomerFK() { + SqliteTestHelper.run( + c -> { + var customer = testInsert.Customers().insert(c); + var order = testInsert.Orders(customer.customerId()).insert(c); + + assertNotNull(order); + assertEquals(customer.customerId(), order.customerId()); + }); + } + + @Test + public void testMultipleInserts() { + SqliteTestHelper.run( + c -> { + var row1 = testInsert.Customers().insert(c); + var row2 = testInsert.Customers().insert(c); + var row3 = testInsert.Customers().insert(c); + + assertNotEquals(row1.customerId(), row2.customerId()); + assertNotEquals(row2.customerId(), row3.customerId()); + assertNotEquals(row1.customerId(), row3.customerId()); + }); + } + + @Test + public void testInsertWithSeededRandom() { + // Reproducibility: two TestInsert instances with the same seed produce the same generated name + // (modulo any sequence-based ID; we compare names, which come from the alphanumeric generator). + var name1 = + SqliteTestHelper.apply(c -> new TestInsert(new Random(123)).Customers().insert(c).name()); + var name2 = + SqliteTestHelper.apply(c -> new TestInsert(new Random(123)).Customers().insert(c).name()); + assertEquals(name1, name2); + } +} diff --git a/testers/sqlite/java/src/java/testdb/TupleInTest.java b/testers/sqlite/java/src/java/testdb/TupleInTest.java new file mode 100644 index 0000000000..f1b99cde47 --- /dev/null +++ b/testers/sqlite/java/src/java/testdb/TupleInTest.java @@ -0,0 +1,111 @@ +package testdb; + +import static org.junit.Assert.*; + +import java.math.BigDecimal; +import java.util.List; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; +import org.junit.Test; +import testdb.departments.*; + +/** + * Tuple IN against composite IDs. + * + *

{@code Dialect.SQLITE.supportsTupleIn = true} (since SQLite 3.7.11) — this exercises that + * claim by running {@code (a, b) IN ((1,2), (3,4))} via the generated {@code compositeIdIn} field + * on departments (string×string composite PK). + */ +public class TupleInTest { + + private final DepartmentsRepoImpl repo = new DepartmentsRepoImpl(); + + @Test + public void compositeIdInWithMultipleIds() { + SqliteTestHelper.run( + c -> { + var d1 = repo.insert(new DepartmentsRow("TI_A", "US", "A US", Optional.empty()), c); + var d2 = repo.insert(new DepartmentsRow("TI_A", "EU", "A EU", Optional.empty()), c); + var d3 = repo.insert(new DepartmentsRow("TI_B", "US", "B US", Optional.empty()), c); + repo.insert(new DepartmentsRow("TI_B", "EU", "B EU", Optional.empty()), c); + + var result = + repo.select() + .where(d -> d.compositeIdIn(List.of(d1.compositeId(), d3.compositeId()))) + .toList(c); + + assertEquals(2, result.size()); + var ids = result.stream().map(DepartmentsRow::compositeId).collect(Collectors.toSet()); + assertEquals(Set.of(d1.compositeId(), d3.compositeId()), ids); + assertFalse(ids.contains(d2.compositeId())); + }); + } + + @Test + public void compositeIdInWithSingleId() { + SqliteTestHelper.run( + c -> { + var d1 = repo.insert(new DepartmentsRow("TI_S", "APAC", "S APAC", Optional.empty()), c); + repo.insert(new DepartmentsRow("TI_S", "EMEA", "S EMEA", Optional.empty()), c); + + var result = + repo.select().where(d -> d.compositeIdIn(List.of(d1.compositeId()))).toList(c); + + assertEquals(1, result.size()); + assertEquals(d1, result.get(0)); + }); + } + + @Test + public void compositeIdInWithEmptyList() { + SqliteTestHelper.run( + c -> { + var result = repo.select().where(d -> d.compositeIdIn(List.of())).toList(c); + assertTrue(result.isEmpty()); + }); + } + + @Test + public void compositeIdInWithNonExistentIds() { + SqliteTestHelper.run( + c -> { + var result = + repo.select() + .where( + d -> + d.compositeIdIn( + List.of( + new DepartmentsId("NOPE", "NEVER"), + new DepartmentsId("ALSO", "MISSING")))) + .toList(c); + assertTrue(result.isEmpty()); + }); + } + + @Test + public void compositeIdInCombinedWithOtherConditions() { + SqliteTestHelper.run( + c -> { + var d1 = + repo.insert( + new DepartmentsRow( + "TI_C", "US", "Combined US", Optional.of(new BigDecimal("100000"))), + c); + var d2 = + repo.insert( + new DepartmentsRow( + "TI_C", "EU", "Combined EU", Optional.of(new BigDecimal("50000"))), + c); + + var result = + repo.select() + .where(d -> d.compositeIdIn(List.of(d1.compositeId(), d2.compositeId()))) + .where(d -> d.budget().greaterThan(new BigDecimal("75000"))) + .toList(c); + + assertEquals(1, result.size()); + assertEquals(d1, result.get(0)); + }); + } +} diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/DefaultedDeserializer.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/DefaultedDeserializer.kt new file mode 100644 index 0000000000..70fc745ec0 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/DefaultedDeserializer.kt @@ -0,0 +1,63 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb + +import com.fasterxml.jackson.core.JsonParser +import com.fasterxml.jackson.core.JsonToken +import com.fasterxml.jackson.databind.BeanProperty +import com.fasterxml.jackson.databind.DeserializationContext +import com.fasterxml.jackson.databind.JavaType +import com.fasterxml.jackson.databind.JsonDeserializer +import com.fasterxml.jackson.databind.deser.ContextualDeserializer +import java.io.IOException +import java.lang.Class +import java.lang.RuntimeException +import testdb.customtypes.Defaulted +import testdb.customtypes.Defaulted.Provided +import testdb.customtypes.Defaulted.UseDefault + +/** Jackson deserializer for Defaulted types */ +data class DefaultedDeserializer( + val valueType: JavaType, + val defaultedClass: Class<*> +) : JsonDeserializer>(), ContextualDeserializer { + override fun createContextual( + ctxt: DeserializationContext, + property: BeanProperty + ): JsonDeserializer<*> { + val contextType: JavaType = ctxt.getContextualType() + val type: JavaType = (if (contextType == null && property != null) property.getType() else contextType) + if (type != null && type.containedTypeCount() > 0) { + return DefaultedDeserializer(type.containedType(0), type.getRawClass()); + } + throw RuntimeException("unexpected") + } + + @Throws(IOException::class) + override fun deserialize( + p: JsonParser, + ctxt: DeserializationContext + ): Defaulted<*> { + if (p.currentToken() == JsonToken.VALUE_STRING) { + val text: kotlin.String = p.getText(); + if ("defaulted".equals(text)) { + return UseDefault(); + } + throw IOException("Expected 'defaulted' but got: " + text); + } + if (p.currentToken() == JsonToken.START_OBJECT) { + p.nextToken(); + if (p.currentToken() == JsonToken.FIELD_NAME && "provided".equals(p.currentName())) { + p.nextToken(); + val value: Any = ctxt.readValue(p, valueType); + p.nextToken(); + return Provided(value); + } + + } + throw IOException("Expected 'provided' field but got: " + p.currentName()) + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/DefaultedSerializer.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/DefaultedSerializer.kt new file mode 100644 index 0000000000..6c87cba94f --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/DefaultedSerializer.kt @@ -0,0 +1,37 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb + +import com.fasterxml.jackson.core.JsonGenerator +import com.fasterxml.jackson.databind.JsonSerializer +import com.fasterxml.jackson.databind.SerializerProvider +import java.io.IOException +import testdb.customtypes.Defaulted +import testdb.customtypes.Defaulted.Provided +import testdb.customtypes.Defaulted.UseDefault + +/** Jackson serializer for Defaulted types */ +class DefaultedSerializer() : JsonSerializer>() { + @Throws(IOException::class) + override fun serialize( + value: Defaulted<*>, + gen: JsonGenerator, + serializers: SerializerProvider + ) { + when (val __r = value) { + null -> gen.writeNull() + is UseDefault<*> -> { val u = __r; gen.writeString("defaulted") } + is Provided<*> -> { + val p = __r + gen.writeStartObject(); + gen.writeFieldName("provided"); + serializers.defaultSerializeValue(p.value, gen); + gen.writeEndObject(); + } + else -> throw IOException("Unknown Defaulted subtype: " + value.javaClass.name) + } + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/TestInsert.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/TestInsert.kt new file mode 100644 index 0000000000..7b390d874f --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/TestInsert.kt @@ -0,0 +1,186 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb + +import dev.typr.foundations.data.Json +import dev.typr.foundations.internal.RandomHelper +import dev.typr.foundationskt.Connection +import java.math.BigDecimal +import java.math.BigInteger +import java.time.LocalDate +import java.time.LocalDateTime +import java.time.LocalTime +import java.util.Random +import java.util.UUID +import testdb.all_scalar_types.AllScalarTypesId +import testdb.all_scalar_types.AllScalarTypesRepoImpl +import testdb.all_scalar_types.AllScalarTypesRow +import testdb.customers.CustomersId +import testdb.customers.CustomersRepoImpl +import testdb.customers.CustomersRow +import testdb.customers.CustomersRowUnsaved +import testdb.customtypes.Defaulted +import testdb.customtypes.Defaulted.UseDefault +import testdb.departments.DepartmentsId +import testdb.departments.DepartmentsRepoImpl +import testdb.departments.DepartmentsRow +import testdb.employees.EmployeesRepoImpl +import testdb.employees.EmployeesRow +import testdb.employees.EmployeesRowUnsaved +import testdb.order_items.OrderItemsRepoImpl +import testdb.order_items.OrderItemsRow +import testdb.order_items.OrderItemsRowUnsaved +import testdb.orders.OrdersId +import testdb.orders.OrdersRepoImpl +import testdb.orders.OrdersRow +import testdb.orders.OrdersRowUnsaved +import testdb.precisetypes.Decimal10_2 +import testdb.precisetypes.Decimal18_4 +import testdb.precisetypes.Decimal5_2 +import testdb.precisetypes.Int10 +import testdb.precisetypes.Int18 +import testdb.precisetypes.Int5 +import testdb.precisetypes.String10 +import testdb.precisetypes.String100 +import testdb.precisetypes.String20 +import testdb.precisetypes.String255 +import testdb.precisetypes.String50 +import testdb.precision_types.PrecisionTypesId +import testdb.precision_types.PrecisionTypesRepoImpl +import testdb.precision_types.PrecisionTypesRow +import testdb.precision_types_null.PrecisionTypesNullId +import testdb.precision_types_null.PrecisionTypesNullRepoImpl +import testdb.precision_types_null.PrecisionTypesNullRow +import testdb.products.ProductsId +import testdb.products.ProductsRepoImpl +import testdb.products.ProductsRow +import testdb.userdefined.Email +import testdb.users.UsersId +import testdb.users.UsersRepoImpl +import testdb.users.UsersRow + +/** Methods to generate random data for `Ident(TestInsert)` */ +data class TestInsert(val random: Random) { + fun AllScalarTypes( + colNotNull: kotlin.String, + id: AllScalarTypesId = AllScalarTypesId(random.nextLong()), + colTinyint: kotlin.Byte? = if (random.nextBoolean()) null else random.nextInt(kotlin.Byte.MAX_VALUE.toInt()).toByte(), + colSmallint: kotlin.Short? = if (random.nextBoolean()) null else random.nextInt(kotlin.Short.MAX_VALUE.toInt()).toShort(), + colInt: Int? = if (random.nextBoolean()) null else random.nextInt(), + colInteger: kotlin.Long? = if (random.nextBoolean()) null else random.nextLong(), + colBigint: kotlin.Long? = if (random.nextBoolean()) null else random.nextLong(), + colBoolean: kotlin.Boolean? = if (random.nextBoolean()) null else random.nextBoolean(), + colReal: kotlin.Double? = if (random.nextBoolean()) null else random.nextDouble(), + colDouble: kotlin.Double? = if (random.nextBoolean()) null else random.nextDouble(), + colFloat: kotlin.Float? = if (random.nextBoolean()) null else random.nextFloat(), + colDecimal: BigDecimal? = if (random.nextBoolean()) null else BigDecimal.valueOf(random.nextDouble()), + colNumeric: BigDecimal? = if (random.nextBoolean()) null else BigDecimal.valueOf(random.nextDouble()), + colText: kotlin.String? = null, + colVarchar: kotlin.String? = null, + colChar: kotlin.String? = null, + colClob: kotlin.String? = null, + colBlob: ByteArray? = null, + colBinary: ByteArray? = null, + colDate: LocalDate? = if (random.nextBoolean()) null else LocalDate.ofEpochDay(random.nextInt(30000).toLong()), + colTime: LocalTime? = if (random.nextBoolean()) null else LocalTime.ofSecondOfDay(random.nextInt(24 * 60 * 60).toLong()), + colDatetime: LocalDateTime? = if (random.nextBoolean()) null else LocalDateTime.of(LocalDate.ofEpochDay(random.nextInt(30000).toLong()), LocalTime.ofSecondOfDay(random.nextInt(24 * 60 * 60).toLong())), + colTimestamp: LocalDateTime? = if (random.nextBoolean()) null else LocalDateTime.of(LocalDate.ofEpochDay(random.nextInt(30000).toLong()), LocalTime.ofSecondOfDay(random.nextInt(24 * 60 * 60).toLong())), + colUuid: UUID? = if (random.nextBoolean()) null else RandomHelper.randomUUID(random), + colJson: Json? = if (random.nextBoolean()) null else Json("{}"), + c: Connection + ): AllScalarTypesRow = (AllScalarTypesRepoImpl()).insert(AllScalarTypesRow(id = id, colTinyint = colTinyint, colSmallint = colSmallint, colInt = colInt, colInteger = colInteger, colBigint = colBigint, colBoolean = colBoolean, colReal = colReal, colDouble = colDouble, colFloat = colFloat, colDecimal = colDecimal, colNumeric = colNumeric, colText = colText, colVarchar = colVarchar, colChar = colChar, colClob = colClob, colBlob = colBlob, colBinary = colBinary, colDate = colDate, colTime = colTime, colDatetime = colDatetime, colTimestamp = colTimestamp, colUuid = colUuid, colJson = colJson, colNotNull = colNotNull), c) + + fun Customers( + name: kotlin.String, + customerId: CustomersId = CustomersId(random.nextLong()), + email: /* user-picked */ Email? = null, + createdAt: Defaulted = UseDefault(), + c: Connection + ): CustomersRow = (CustomersRepoImpl()).insert(CustomersRowUnsaved(customerId = customerId, name = name, email = email, createdAt = createdAt), c) + + fun Departments( + deptCode: kotlin.String, + deptRegion: kotlin.String, + deptName: kotlin.String, + budget: BigDecimal? = if (random.nextBoolean()) null else BigDecimal.valueOf(random.nextDouble()), + c: Connection + ): DepartmentsRow = (DepartmentsRepoImpl()).insert(DepartmentsRow(deptCode = deptCode, deptRegion = deptRegion, deptName = deptName, budget = budget), c) + + fun Employees( + DepartmentsId: DepartmentsId, + empSuffix: kotlin.String, + empName: kotlin.String, + empNumber: kotlin.Long = random.nextLong(), + salary: BigDecimal? = if (random.nextBoolean()) null else BigDecimal.valueOf(random.nextDouble()), + hireDate: Defaulted = UseDefault(), + c: Connection + ): EmployeesRow = (EmployeesRepoImpl()).insert(EmployeesRowUnsaved(empNumber = empNumber, empSuffix = empSuffix, deptCode = DepartmentsId.deptCode, deptRegion = DepartmentsId.deptRegion, empName = empName, salary = salary, hireDate = hireDate), c) + + fun OrderItems( + orderId: OrdersId, + productId: ProductsId, + unitPrice: BigDecimal = BigDecimal.valueOf(random.nextDouble()), + quantity: Defaulted = UseDefault(), + c: Connection + ): OrderItemsRow = (OrderItemsRepoImpl()).insert(OrderItemsRowUnsaved(orderId = orderId, productId = productId, unitPrice = unitPrice, quantity = quantity), c) + + fun Orders( + customerId: CustomersId, + orderId: OrdersId = OrdersId(random.nextLong()), + orderDate: LocalDate = LocalDate.ofEpochDay(random.nextInt(30000).toLong()), + totalAmount: BigDecimal? = if (random.nextBoolean()) null else BigDecimal.valueOf(random.nextDouble()), + status: Defaulted = UseDefault(), + c: Connection + ): OrdersRow = (OrdersRepoImpl()).insert(OrdersRowUnsaved(orderId = orderId, customerId = customerId, orderDate = orderDate, totalAmount = totalAmount, status = status), c) + + fun PrecisionTypes( + id: PrecisionTypesId = PrecisionTypesId(random.nextLong()), + string10: String10 = String10.truncate(RandomHelper.alphanumeric(random, 10)), + string20: String20 = String20.truncate(RandomHelper.alphanumeric(random, 20)), + string50: String50 = String50.truncate(RandomHelper.alphanumeric(random, 20)), + string100: String100 = String100.truncate(RandomHelper.alphanumeric(random, 20)), + string255: String255 = String255.truncate(RandomHelper.alphanumeric(random, 20)), + decimal52: Decimal5_2 = Decimal5_2.unsafeForce(BigDecimal.valueOf(Math.abs(random.nextInt()) % 1000.toLong()).add(BigDecimal.valueOf(Math.abs(random.nextInt()) % 100.toLong()).movePointLeft(2))), + decimal102: Decimal10_2 = Decimal10_2.unsafeForce(BigDecimal.valueOf(Math.abs(random.nextInt()) % 1000000.toLong()).add(BigDecimal.valueOf(Math.abs(random.nextInt()) % 100.toLong()).movePointLeft(2))), + decimal184: Decimal18_4 = Decimal18_4.unsafeForce(BigDecimal.valueOf(Math.abs(random.nextInt()) % 1000000.toLong()).add(BigDecimal.valueOf(Math.abs(random.nextInt()) % 10000.toLong()).movePointLeft(4))), + decimal50: Int5 = Int5.unsafeForce(BigInteger.valueOf(Math.abs(random.nextInt()) % 100000.toLong())), + decimal100: Int10 = Int10.unsafeForce(BigInteger.valueOf(Math.abs(random.nextInt()) % 1000000000.toLong())), + decimal180: Int18 = Int18.unsafeForce(BigInteger.valueOf(Math.abs(random.nextInt()) % 1000000000.toLong())), + c: Connection + ): PrecisionTypesRow = (PrecisionTypesRepoImpl()).insert(PrecisionTypesRow(id = id, string10 = string10, string20 = string20, string50 = string50, string100 = string100, string255 = string255, decimal52 = decimal52, decimal102 = decimal102, decimal184 = decimal184, decimal50 = decimal50, decimal100 = decimal100, decimal180 = decimal180), c) + + fun PrecisionTypesNull( + id: PrecisionTypesNullId = PrecisionTypesNullId(random.nextLong()), + string10: String10? = if (random.nextBoolean()) null else String10.truncate(RandomHelper.alphanumeric(random, 10)), + string20: String20? = if (random.nextBoolean()) null else String20.truncate(RandomHelper.alphanumeric(random, 20)), + string50: String50? = if (random.nextBoolean()) null else String50.truncate(RandomHelper.alphanumeric(random, 20)), + string100: String100? = if (random.nextBoolean()) null else String100.truncate(RandomHelper.alphanumeric(random, 20)), + string255: String255? = if (random.nextBoolean()) null else String255.truncate(RandomHelper.alphanumeric(random, 20)), + decimal52: Decimal5_2? = if (random.nextBoolean()) null else Decimal5_2.unsafeForce(BigDecimal.valueOf(Math.abs(random.nextInt()) % 1000.toLong()).add(BigDecimal.valueOf(Math.abs(random.nextInt()) % 100.toLong()).movePointLeft(2))), + decimal102: Decimal10_2? = if (random.nextBoolean()) null else Decimal10_2.unsafeForce(BigDecimal.valueOf(Math.abs(random.nextInt()) % 1000000.toLong()).add(BigDecimal.valueOf(Math.abs(random.nextInt()) % 100.toLong()).movePointLeft(2))), + decimal184: Decimal18_4? = if (random.nextBoolean()) null else Decimal18_4.unsafeForce(BigDecimal.valueOf(Math.abs(random.nextInt()) % 1000000.toLong()).add(BigDecimal.valueOf(Math.abs(random.nextInt()) % 10000.toLong()).movePointLeft(4))), + decimal50: Int5? = if (random.nextBoolean()) null else Int5.unsafeForce(BigInteger.valueOf(Math.abs(random.nextInt()) % 100000.toLong())), + decimal100: Int10? = if (random.nextBoolean()) null else Int10.unsafeForce(BigInteger.valueOf(Math.abs(random.nextInt()) % 1000000000.toLong())), + decimal180: Int18? = if (random.nextBoolean()) null else Int18.unsafeForce(BigInteger.valueOf(Math.abs(random.nextInt()) % 1000000000.toLong())), + c: Connection + ): PrecisionTypesNullRow = (PrecisionTypesNullRepoImpl()).insert(PrecisionTypesNullRow(id = id, string10 = string10, string20 = string20, string50 = string50, string100 = string100, string255 = string255, decimal52 = decimal52, decimal102 = decimal102, decimal184 = decimal184, decimal50 = decimal50, decimal100 = decimal100, decimal180 = decimal180), c) + + fun Products( + sku: kotlin.String, + name: kotlin.String, + productId: ProductsId = ProductsId(random.nextLong()), + price: BigDecimal = BigDecimal.valueOf(random.nextDouble()), + metadata: Json? = if (random.nextBoolean()) null else Json("{}"), + c: Connection + ): ProductsRow = (ProductsRepoImpl()).insert(ProductsRow(productId = productId, sku = sku, name = name, price = price, metadata = metadata), c) + + fun Users( + username: kotlin.String, + email: /* user-picked */ Email, + userId: UsersId = UsersId(random.nextLong()), + c: Connection + ): UsersRow = (UsersRepoImpl()).insert(UsersRow(userId = userId, username = username, email = email), c) +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/all_scalar_types/AllScalarTypesFields.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/all_scalar_types/AllScalarTypesFields.kt new file mode 100644 index 0000000000..2dbbfc2860 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/all_scalar_types/AllScalarTypesFields.kt @@ -0,0 +1,139 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.all_scalar_types + +import dev.typr.dsl.FieldsBase +import dev.typr.dsl.Path +import dev.typr.dsl.SqlExpr.FieldLike +import dev.typr.dslkt.RelationStructure +import dev.typr.dslkt.SqlExpr +import dev.typr.dslkt.SqlExpr.Field +import dev.typr.dslkt.SqlExpr.IdField +import dev.typr.dslkt.SqlExpr.OptField +import dev.typr.dslkt.TupleExpr25 +import dev.typr.foundations.RowCodec +import dev.typr.foundations.data.Json +import dev.typr.foundationskt.SqliteTypes +import java.math.BigDecimal +import java.time.LocalDate +import java.time.LocalDateTime +import java.time.LocalTime +import java.util.UUID +import kotlin.collections.List + +data class AllScalarTypesFields(val _path: List) : TupleExpr25, RelationStructure, FieldsBase { + override fun _1(): SqlExpr = id() + + override fun _10(): SqlExpr = colFloat() + + override fun _11(): SqlExpr = colDecimal() + + override fun _12(): SqlExpr = colNumeric() + + override fun _13(): SqlExpr = colText() + + override fun _14(): SqlExpr = colVarchar() + + override fun _15(): SqlExpr = colChar() + + override fun _16(): SqlExpr = colClob() + + override fun _17(): SqlExpr = colBlob() + + override fun _18(): SqlExpr = colBinary() + + override fun _19(): SqlExpr = colDate() + + override fun _2(): SqlExpr = colTinyint() + + override fun _20(): SqlExpr = colTime() + + override fun _21(): SqlExpr = colDatetime() + + override fun _22(): SqlExpr = colTimestamp() + + override fun _23(): SqlExpr = colUuid() + + override fun _24(): SqlExpr = colJson() + + override fun _25(): SqlExpr = colNotNull() + + override fun _3(): SqlExpr = colSmallint() + + override fun _4(): SqlExpr = colInt() + + override fun _5(): SqlExpr = colInteger() + + override fun _6(): SqlExpr = colBigint() + + override fun _7(): SqlExpr = colBoolean() + + override fun _8(): SqlExpr = colReal() + + override fun _9(): SqlExpr = colDouble() + + override fun _path(): List = _path + + fun colBigint(): OptField = OptField(_path, "col_bigint", AllScalarTypesRow::colBigint, null, null, { row, value -> row.copy(colBigint = value) }, SqliteTypes.bigint.underlying) + + fun colBinary(): OptField = OptField(_path, "col_binary", AllScalarTypesRow::colBinary, null, null, { row, value -> row.copy(colBinary = value) }, SqliteTypes.binary.underlying) + + fun colBlob(): OptField = OptField(_path, "col_blob", AllScalarTypesRow::colBlob, null, null, { row, value -> row.copy(colBlob = value) }, SqliteTypes.blob.underlying) + + fun colBoolean(): OptField = OptField(_path, "col_boolean", AllScalarTypesRow::colBoolean, null, null, { row, value -> row.copy(colBoolean = value) }, SqliteTypes.boolean_.underlying) + + fun colChar(): OptField = OptField(_path, "col_char", AllScalarTypesRow::colChar, null, null, { row, value -> row.copy(colChar = value) }, SqliteTypes.char_.underlying) + + fun colClob(): OptField = OptField(_path, "col_clob", AllScalarTypesRow::colClob, null, null, { row, value -> row.copy(colClob = value) }, SqliteTypes.clob.underlying) + + fun colDate(): OptField = OptField(_path, "col_date", AllScalarTypesRow::colDate, null, null, { row, value -> row.copy(colDate = value) }, SqliteTypes.date.underlying) + + fun colDatetime(): OptField = OptField(_path, "col_datetime", AllScalarTypesRow::colDatetime, null, null, { row, value -> row.copy(colDatetime = value) }, SqliteTypes.timestamp.underlying) + + fun colDecimal(): OptField = OptField(_path, "col_decimal", AllScalarTypesRow::colDecimal, null, null, { row, value -> row.copy(colDecimal = value) }, SqliteTypes.numeric.underlying) + + fun colDouble(): OptField = OptField(_path, "col_double", AllScalarTypesRow::colDouble, null, null, { row, value -> row.copy(colDouble = value) }, SqliteTypes.double_.underlying) + + fun colFloat(): OptField = OptField(_path, "col_float", AllScalarTypesRow::colFloat, null, null, { row, value -> row.copy(colFloat = value) }, SqliteTypes.float_.underlying) + + fun colInt(): OptField = OptField(_path, "col_int", AllScalarTypesRow::colInt, null, null, { row, value -> row.copy(colInt = value) }, SqliteTypes.int_.underlying) + + fun colInteger(): OptField = OptField(_path, "col_integer", AllScalarTypesRow::colInteger, null, null, { row, value -> row.copy(colInteger = value) }, SqliteTypes.integer.underlying) + + fun colJson(): OptField = OptField(_path, "col_json", AllScalarTypesRow::colJson, null, null, { row, value -> row.copy(colJson = value) }, SqliteTypes.json.underlying) + + fun colNotNull(): Field = Field(_path, "col_not_null", AllScalarTypesRow::colNotNull, null, null, { row, value -> row.copy(colNotNull = value) }, SqliteTypes.text.underlying) + + fun colNumeric(): OptField = OptField(_path, "col_numeric", AllScalarTypesRow::colNumeric, null, null, { row, value -> row.copy(colNumeric = value) }, SqliteTypes.numeric.underlying) + + fun colReal(): OptField = OptField(_path, "col_real", AllScalarTypesRow::colReal, null, null, { row, value -> row.copy(colReal = value) }, SqliteTypes.real.underlying) + + fun colSmallint(): OptField = OptField(_path, "col_smallint", AllScalarTypesRow::colSmallint, null, null, { row, value -> row.copy(colSmallint = value) }, SqliteTypes.smallint.underlying) + + fun colText(): OptField = OptField(_path, "col_text", AllScalarTypesRow::colText, null, null, { row, value -> row.copy(colText = value) }, SqliteTypes.text.underlying) + + fun colTime(): OptField = OptField(_path, "col_time", AllScalarTypesRow::colTime, null, null, { row, value -> row.copy(colTime = value) }, SqliteTypes.time.underlying) + + fun colTimestamp(): OptField = OptField(_path, "col_timestamp", AllScalarTypesRow::colTimestamp, null, null, { row, value -> row.copy(colTimestamp = value) }, SqliteTypes.timestamp.underlying) + + fun colTinyint(): OptField = OptField(_path, "col_tinyint", AllScalarTypesRow::colTinyint, null, null, { row, value -> row.copy(colTinyint = value) }, SqliteTypes.tinyint.underlying) + + fun colUuid(): OptField = OptField(_path, "col_uuid", AllScalarTypesRow::colUuid, null, null, { row, value -> row.copy(colUuid = value) }, SqliteTypes.uuid.underlying) + + fun colVarchar(): OptField = OptField(_path, "col_varchar", AllScalarTypesRow::colVarchar, null, null, { row, value -> row.copy(colVarchar = value) }, SqliteTypes.varchar.underlying) + + override fun columns(): List> = listOf(this.id().underlying, this.colTinyint().underlying, this.colSmallint().underlying, this.colInt().underlying, this.colInteger().underlying, this.colBigint().underlying, this.colBoolean().underlying, this.colReal().underlying, this.colDouble().underlying, this.colFloat().underlying, this.colDecimal().underlying, this.colNumeric().underlying, this.colText().underlying, this.colVarchar().underlying, this.colChar().underlying, this.colClob().underlying, this.colBlob().underlying, this.colBinary().underlying, this.colDate().underlying, this.colTime().underlying, this.colDatetime().underlying, this.colTimestamp().underlying, this.colUuid().underlying, this.colJson().underlying, this.colNotNull().underlying) + + fun id(): IdField = IdField(_path, "id", AllScalarTypesRow::id, null, null, { row, value -> row.copy(id = value) }, AllScalarTypesId.sqliteType.underlying) + + override fun rowCodec(): RowCodec = AllScalarTypesRow.rowCodec.underlying + + override fun withPaths(_path: List): RelationStructure = AllScalarTypesFields(_path) + + companion object { + val structure: AllScalarTypesFields = AllScalarTypesFields(emptyList()) + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/all_scalar_types/AllScalarTypesId.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/all_scalar_types/AllScalarTypesId.kt new file mode 100644 index 0000000000..3c4a889c2e --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/all_scalar_types/AllScalarTypesId.kt @@ -0,0 +1,26 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.all_scalar_types + +import com.fasterxml.jackson.annotation.JsonValue +import dev.typr.foundationskt.Bijection +import dev.typr.foundationskt.SqliteType +import dev.typr.foundationskt.SqliteTypes + +/** Type for the primary key of table `all_scalar_types` */ +data class AllScalarTypesId(@field:JsonValue val value: kotlin.Long) { + override fun toString(): kotlin.String { + return value.toString() + } + + companion object { + val bijection: Bijection = + Bijection.of(AllScalarTypesId::value, ::AllScalarTypesId) + + val sqliteType: SqliteType = + SqliteTypes.integer.to(Bijection.of(::AllScalarTypesId, AllScalarTypesId::value)) + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/all_scalar_types/AllScalarTypesRepo.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/all_scalar_types/AllScalarTypesRepo.kt new file mode 100644 index 0000000000..ad5d51036a --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/all_scalar_types/AllScalarTypesRepo.kt @@ -0,0 +1,70 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.all_scalar_types + +import dev.typr.dslkt.DeleteBuilder +import dev.typr.dslkt.SelectBuilder +import dev.typr.dslkt.UpdateBuilder +import dev.typr.foundationskt.Connection +import dev.typr.foundationskt.ConnectionRead +import kotlin.collections.Iterator +import kotlin.collections.List +import kotlin.collections.Map + +interface AllScalarTypesRepo { + abstract fun delete(): DeleteBuilder + + abstract fun deleteById( + id: AllScalarTypesId, + c: Connection + ): kotlin.Boolean + + abstract fun deleteByIds( + ids: List, + c: Connection + ): Int + + abstract fun insert( + unsaved: AllScalarTypesRow, + c: Connection + ): AllScalarTypesRow + + abstract fun select(): SelectBuilder + + abstract fun selectAll(c: ConnectionRead): List + + abstract fun selectById( + id: AllScalarTypesId, + c: ConnectionRead + ): AllScalarTypesRow? + + abstract fun selectByIds( + ids: List, + c: ConnectionRead + ): List + + abstract fun selectByIdsTracked( + ids: List, + c: ConnectionRead + ): Map + + abstract fun update(): UpdateBuilder + + abstract fun update( + row: AllScalarTypesRow, + c: Connection + ): kotlin.Boolean + + abstract fun upsert( + unsaved: AllScalarTypesRow, + c: Connection + ): AllScalarTypesRow + + abstract fun upsertBatch( + unsaved: Iterator, + c: Connection + ): List +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/all_scalar_types/AllScalarTypesRepoImpl.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/all_scalar_types/AllScalarTypesRepoImpl.kt new file mode 100644 index 0000000000..31f0126c71 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/all_scalar_types/AllScalarTypesRepoImpl.kt @@ -0,0 +1,95 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.all_scalar_types + +import dev.typr.dslkt.DeleteBuilder +import dev.typr.dslkt.Dialect +import dev.typr.dslkt.SelectBuilder +import dev.typr.dslkt.UpdateBuilder +import dev.typr.foundationskt.Connection +import dev.typr.foundationskt.ConnectionRead +import dev.typr.foundationskt.Fragment +import dev.typr.foundationskt.SqliteTypes +import java.util.ArrayList +import kotlin.collections.Iterator +import kotlin.collections.List +import kotlin.collections.Map +import kotlin.collections.MutableMap + +class AllScalarTypesRepoImpl() : AllScalarTypesRepo { + override fun delete(): DeleteBuilder = DeleteBuilder.of("\"all_scalar_types\"", AllScalarTypesFields.structure, Dialect.SQLITE) + + override fun deleteById( + id: AllScalarTypesId, + c: Connection + ): kotlin.Boolean = Fragment.concat(Fragment.of("delete from \"all_scalar_types\" where \"id\" = "), Fragment.encode(AllScalarTypesId.sqliteType, id), Fragment.of("")).update().run(c) > 0 + + override fun deleteByIds( + ids: List, + c: Connection + ): Int { + val fragments: ArrayList = ArrayList() + for (id in ids) { fragments.add(Fragment.encode(AllScalarTypesId.sqliteType, id)) } + return Fragment.concat(Fragment.of("delete from \"all_scalar_types\" where \"id\" in ("), Fragment.comma(fragments.toMutableList()), Fragment.of(")")).update().run(c) + } + + override fun insert( + unsaved: AllScalarTypesRow, + c: Connection + ): AllScalarTypesRow = Fragment.concat(Fragment.of("insert into \"all_scalar_types\"(\"id\", \"col_tinyint\", \"col_smallint\", \"col_int\", \"col_integer\", \"col_bigint\", \"col_boolean\", \"col_real\", \"col_double\", \"col_float\", \"col_decimal\", \"col_numeric\", \"col_text\", \"col_varchar\", \"col_char\", \"col_clob\", \"col_blob\", \"col_binary\", \"col_date\", \"col_time\", \"col_datetime\", \"col_timestamp\", \"col_uuid\", \"col_json\", \"col_not_null\")\nvalues ("), Fragment.encode(AllScalarTypesId.sqliteType, unsaved.id), Fragment.of(", "), Fragment.encode(SqliteTypes.tinyint.opt(), unsaved.colTinyint), Fragment.of(", "), Fragment.encode(SqliteTypes.smallint.opt(), unsaved.colSmallint), Fragment.of(", "), Fragment.encode(SqliteTypes.int_.opt(), unsaved.colInt), Fragment.of(", "), Fragment.encode(SqliteTypes.integer.opt(), unsaved.colInteger), Fragment.of(", "), Fragment.encode(SqliteTypes.bigint.opt(), unsaved.colBigint), Fragment.of(", "), Fragment.encode(SqliteTypes.boolean_.opt(), unsaved.colBoolean), Fragment.of(", "), Fragment.encode(SqliteTypes.real.opt(), unsaved.colReal), Fragment.of(", "), Fragment.encode(SqliteTypes.double_.opt(), unsaved.colDouble), Fragment.of(", "), Fragment.encode(SqliteTypes.float_.opt(), unsaved.colFloat), Fragment.of(", "), Fragment.encode(SqliteTypes.numeric.opt(), unsaved.colDecimal), Fragment.of(", "), Fragment.encode(SqliteTypes.numeric.opt(), unsaved.colNumeric), Fragment.of(", "), Fragment.encode(SqliteTypes.text.opt(), unsaved.colText), Fragment.of(", "), Fragment.encode(SqliteTypes.varchar.opt(), unsaved.colVarchar), Fragment.of(", "), Fragment.encode(SqliteTypes.char_.opt(), unsaved.colChar), Fragment.of(", "), Fragment.encode(SqliteTypes.clob.opt(), unsaved.colClob), Fragment.of(", "), Fragment.encode(SqliteTypes.blob.opt(), unsaved.colBlob), Fragment.of(", "), Fragment.encode(SqliteTypes.binary.opt(), unsaved.colBinary), Fragment.of(", "), Fragment.encode(SqliteTypes.date.opt(), unsaved.colDate), Fragment.of(", "), Fragment.encode(SqliteTypes.time.opt(), unsaved.colTime), Fragment.of(", "), Fragment.encode(SqliteTypes.timestamp.opt(), unsaved.colDatetime), Fragment.of(", "), Fragment.encode(SqliteTypes.timestamp.opt(), unsaved.colTimestamp), Fragment.of(", "), Fragment.encode(SqliteTypes.uuid.opt(), unsaved.colUuid), Fragment.of(", "), Fragment.encode(SqliteTypes.json.opt(), unsaved.colJson), Fragment.of(", "), Fragment.encode(SqliteTypes.text, unsaved.colNotNull), Fragment.of(")\nRETURNING \"id\", \"col_tinyint\", \"col_smallint\", \"col_int\", \"col_integer\", \"col_bigint\", \"col_boolean\", \"col_real\", \"col_double\", \"col_float\", \"col_decimal\", \"col_numeric\", \"col_text\", \"col_varchar\", \"col_char\", \"col_clob\", \"col_blob\", \"col_binary\", \"col_date\", \"col_time\", \"col_datetime\", \"col_timestamp\", \"col_uuid\", \"col_json\", \"col_not_null\"\n")) + .updateReturning(AllScalarTypesRow.rowCodec.exactlyOne()).run(c) + + override fun select(): SelectBuilder = SelectBuilder.of("\"all_scalar_types\"", AllScalarTypesFields.structure, AllScalarTypesRow.rowCodec, Dialect.SQLITE) + + override fun selectAll(c: ConnectionRead): List = Fragment.concat(Fragment.of("select \"id\", \"col_tinyint\", \"col_smallint\", \"col_int\", \"col_integer\", \"col_bigint\", \"col_boolean\", \"col_real\", \"col_double\", \"col_float\", \"col_decimal\", \"col_numeric\", \"col_text\", \"col_varchar\", \"col_char\", \"col_clob\", \"col_blob\", \"col_binary\", \"col_date\", \"col_time\", \"col_datetime\", \"col_timestamp\", \"col_uuid\", \"col_json\", \"col_not_null\"\nfrom \"all_scalar_types\"\n")).query(AllScalarTypesRow.rowCodec.all()).run(c) + + override fun selectById( + id: AllScalarTypesId, + c: ConnectionRead + ): AllScalarTypesRow? = Fragment.concat(Fragment.of("select \"id\", \"col_tinyint\", \"col_smallint\", \"col_int\", \"col_integer\", \"col_bigint\", \"col_boolean\", \"col_real\", \"col_double\", \"col_float\", \"col_decimal\", \"col_numeric\", \"col_text\", \"col_varchar\", \"col_char\", \"col_clob\", \"col_blob\", \"col_binary\", \"col_date\", \"col_time\", \"col_datetime\", \"col_timestamp\", \"col_uuid\", \"col_json\", \"col_not_null\"\nfrom \"all_scalar_types\"\nwhere \"id\" = "), Fragment.encode(AllScalarTypesId.sqliteType, id), Fragment.of("")).query(AllScalarTypesRow.rowCodec.first()).run(c) + + override fun selectByIds( + ids: List, + c: ConnectionRead + ): List { + val fragments: ArrayList = ArrayList() + for (id in ids) { fragments.add(Fragment.encode(AllScalarTypesId.sqliteType, id)) } + return Fragment.concat(Fragment.of("select \"id\", \"col_tinyint\", \"col_smallint\", \"col_int\", \"col_integer\", \"col_bigint\", \"col_boolean\", \"col_real\", \"col_double\", \"col_float\", \"col_decimal\", \"col_numeric\", \"col_text\", \"col_varchar\", \"col_char\", \"col_clob\", \"col_blob\", \"col_binary\", \"col_date\", \"col_time\", \"col_datetime\", \"col_timestamp\", \"col_uuid\", \"col_json\", \"col_not_null\" from \"all_scalar_types\" where \"id\" in ("), Fragment.comma(fragments.toMutableList()), Fragment.of(")")).query(AllScalarTypesRow.rowCodec.all()).run(c) + } + + override fun selectByIdsTracked( + ids: List, + c: ConnectionRead + ): Map { + val ret: MutableMap = mutableMapOf() + selectByIds(ids, c).forEach({ row -> ret.put(row.id, row) }) + return ret.toMap() + } + + override fun update(): UpdateBuilder = UpdateBuilder.of("\"all_scalar_types\"", AllScalarTypesFields.structure, AllScalarTypesRow.rowCodec, Dialect.SQLITE) + + override fun update( + row: AllScalarTypesRow, + c: Connection + ): kotlin.Boolean { + val id: AllScalarTypesId = row.id + return Fragment.concat(Fragment.of("update \"all_scalar_types\"\nset \"col_tinyint\" = "), Fragment.encode(SqliteTypes.tinyint.opt(), row.colTinyint), Fragment.of(",\n\"col_smallint\" = "), Fragment.encode(SqliteTypes.smallint.opt(), row.colSmallint), Fragment.of(",\n\"col_int\" = "), Fragment.encode(SqliteTypes.int_.opt(), row.colInt), Fragment.of(",\n\"col_integer\" = "), Fragment.encode(SqliteTypes.integer.opt(), row.colInteger), Fragment.of(",\n\"col_bigint\" = "), Fragment.encode(SqliteTypes.bigint.opt(), row.colBigint), Fragment.of(",\n\"col_boolean\" = "), Fragment.encode(SqliteTypes.boolean_.opt(), row.colBoolean), Fragment.of(",\n\"col_real\" = "), Fragment.encode(SqliteTypes.real.opt(), row.colReal), Fragment.of(",\n\"col_double\" = "), Fragment.encode(SqliteTypes.double_.opt(), row.colDouble), Fragment.of(",\n\"col_float\" = "), Fragment.encode(SqliteTypes.float_.opt(), row.colFloat), Fragment.of(",\n\"col_decimal\" = "), Fragment.encode(SqliteTypes.numeric.opt(), row.colDecimal), Fragment.of(",\n\"col_numeric\" = "), Fragment.encode(SqliteTypes.numeric.opt(), row.colNumeric), Fragment.of(",\n\"col_text\" = "), Fragment.encode(SqliteTypes.text.opt(), row.colText), Fragment.of(",\n\"col_varchar\" = "), Fragment.encode(SqliteTypes.varchar.opt(), row.colVarchar), Fragment.of(",\n\"col_char\" = "), Fragment.encode(SqliteTypes.char_.opt(), row.colChar), Fragment.of(",\n\"col_clob\" = "), Fragment.encode(SqliteTypes.clob.opt(), row.colClob), Fragment.of(",\n\"col_blob\" = "), Fragment.encode(SqliteTypes.blob.opt(), row.colBlob), Fragment.of(",\n\"col_binary\" = "), Fragment.encode(SqliteTypes.binary.opt(), row.colBinary), Fragment.of(",\n\"col_date\" = "), Fragment.encode(SqliteTypes.date.opt(), row.colDate), Fragment.of(",\n\"col_time\" = "), Fragment.encode(SqliteTypes.time.opt(), row.colTime), Fragment.of(",\n\"col_datetime\" = "), Fragment.encode(SqliteTypes.timestamp.opt(), row.colDatetime), Fragment.of(",\n\"col_timestamp\" = "), Fragment.encode(SqliteTypes.timestamp.opt(), row.colTimestamp), Fragment.of(",\n\"col_uuid\" = "), Fragment.encode(SqliteTypes.uuid.opt(), row.colUuid), Fragment.of(",\n\"col_json\" = "), Fragment.encode(SqliteTypes.json.opt(), row.colJson), Fragment.of(",\n\"col_not_null\" = "), Fragment.encode(SqliteTypes.text, row.colNotNull), Fragment.of("\nwhere \"id\" = "), Fragment.encode(AllScalarTypesId.sqliteType, id), Fragment.of("")).update().run(c) > 0 + } + + override fun upsert( + unsaved: AllScalarTypesRow, + c: Connection + ): AllScalarTypesRow = Fragment.concat(Fragment.of("INSERT INTO \"all_scalar_types\"(\"id\", \"col_tinyint\", \"col_smallint\", \"col_int\", \"col_integer\", \"col_bigint\", \"col_boolean\", \"col_real\", \"col_double\", \"col_float\", \"col_decimal\", \"col_numeric\", \"col_text\", \"col_varchar\", \"col_char\", \"col_clob\", \"col_blob\", \"col_binary\", \"col_date\", \"col_time\", \"col_datetime\", \"col_timestamp\", \"col_uuid\", \"col_json\", \"col_not_null\")\nVALUES ("), Fragment.encode(AllScalarTypesId.sqliteType, unsaved.id), Fragment.of(", "), Fragment.encode(SqliteTypes.tinyint.opt(), unsaved.colTinyint), Fragment.of(", "), Fragment.encode(SqliteTypes.smallint.opt(), unsaved.colSmallint), Fragment.of(", "), Fragment.encode(SqliteTypes.int_.opt(), unsaved.colInt), Fragment.of(", "), Fragment.encode(SqliteTypes.integer.opt(), unsaved.colInteger), Fragment.of(", "), Fragment.encode(SqliteTypes.bigint.opt(), unsaved.colBigint), Fragment.of(", "), Fragment.encode(SqliteTypes.boolean_.opt(), unsaved.colBoolean), Fragment.of(", "), Fragment.encode(SqliteTypes.real.opt(), unsaved.colReal), Fragment.of(", "), Fragment.encode(SqliteTypes.double_.opt(), unsaved.colDouble), Fragment.of(", "), Fragment.encode(SqliteTypes.float_.opt(), unsaved.colFloat), Fragment.of(", "), Fragment.encode(SqliteTypes.numeric.opt(), unsaved.colDecimal), Fragment.of(", "), Fragment.encode(SqliteTypes.numeric.opt(), unsaved.colNumeric), Fragment.of(", "), Fragment.encode(SqliteTypes.text.opt(), unsaved.colText), Fragment.of(", "), Fragment.encode(SqliteTypes.varchar.opt(), unsaved.colVarchar), Fragment.of(", "), Fragment.encode(SqliteTypes.char_.opt(), unsaved.colChar), Fragment.of(", "), Fragment.encode(SqliteTypes.clob.opt(), unsaved.colClob), Fragment.of(", "), Fragment.encode(SqliteTypes.blob.opt(), unsaved.colBlob), Fragment.of(", "), Fragment.encode(SqliteTypes.binary.opt(), unsaved.colBinary), Fragment.of(", "), Fragment.encode(SqliteTypes.date.opt(), unsaved.colDate), Fragment.of(", "), Fragment.encode(SqliteTypes.time.opt(), unsaved.colTime), Fragment.of(", "), Fragment.encode(SqliteTypes.timestamp.opt(), unsaved.colDatetime), Fragment.of(", "), Fragment.encode(SqliteTypes.timestamp.opt(), unsaved.colTimestamp), Fragment.of(", "), Fragment.encode(SqliteTypes.uuid.opt(), unsaved.colUuid), Fragment.of(", "), Fragment.encode(SqliteTypes.json.opt(), unsaved.colJson), Fragment.of(", "), Fragment.encode(SqliteTypes.text, unsaved.colNotNull), Fragment.of(")\nON CONFLICT (\"id\")\nDO UPDATE SET\n \"col_tinyint\" = EXCLUDED.\"col_tinyint\",\n\"col_smallint\" = EXCLUDED.\"col_smallint\",\n\"col_int\" = EXCLUDED.\"col_int\",\n\"col_integer\" = EXCLUDED.\"col_integer\",\n\"col_bigint\" = EXCLUDED.\"col_bigint\",\n\"col_boolean\" = EXCLUDED.\"col_boolean\",\n\"col_real\" = EXCLUDED.\"col_real\",\n\"col_double\" = EXCLUDED.\"col_double\",\n\"col_float\" = EXCLUDED.\"col_float\",\n\"col_decimal\" = EXCLUDED.\"col_decimal\",\n\"col_numeric\" = EXCLUDED.\"col_numeric\",\n\"col_text\" = EXCLUDED.\"col_text\",\n\"col_varchar\" = EXCLUDED.\"col_varchar\",\n\"col_char\" = EXCLUDED.\"col_char\",\n\"col_clob\" = EXCLUDED.\"col_clob\",\n\"col_blob\" = EXCLUDED.\"col_blob\",\n\"col_binary\" = EXCLUDED.\"col_binary\",\n\"col_date\" = EXCLUDED.\"col_date\",\n\"col_time\" = EXCLUDED.\"col_time\",\n\"col_datetime\" = EXCLUDED.\"col_datetime\",\n\"col_timestamp\" = EXCLUDED.\"col_timestamp\",\n\"col_uuid\" = EXCLUDED.\"col_uuid\",\n\"col_json\" = EXCLUDED.\"col_json\",\n\"col_not_null\" = EXCLUDED.\"col_not_null\"\nRETURNING \"id\", \"col_tinyint\", \"col_smallint\", \"col_int\", \"col_integer\", \"col_bigint\", \"col_boolean\", \"col_real\", \"col_double\", \"col_float\", \"col_decimal\", \"col_numeric\", \"col_text\", \"col_varchar\", \"col_char\", \"col_clob\", \"col_blob\", \"col_binary\", \"col_date\", \"col_time\", \"col_datetime\", \"col_timestamp\", \"col_uuid\", \"col_json\", \"col_not_null\"")) + .updateReturning(AllScalarTypesRow.rowCodec.exactlyOne()) + .run(c) + + override fun upsertBatch( + unsaved: Iterator, + c: Connection + ): List = Fragment.concat(Fragment.of("INSERT INTO \"all_scalar_types\"(\"id\", \"col_tinyint\", \"col_smallint\", \"col_int\", \"col_integer\", \"col_bigint\", \"col_boolean\", \"col_real\", \"col_double\", \"col_float\", \"col_decimal\", \"col_numeric\", \"col_text\", \"col_varchar\", \"col_char\", \"col_clob\", \"col_blob\", \"col_binary\", \"col_date\", \"col_time\", \"col_datetime\", \"col_timestamp\", \"col_uuid\", \"col_json\", \"col_not_null\")\nVALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\nON CONFLICT (\"id\")\nDO UPDATE SET\n \"col_tinyint\" = EXCLUDED.\"col_tinyint\",\n\"col_smallint\" = EXCLUDED.\"col_smallint\",\n\"col_int\" = EXCLUDED.\"col_int\",\n\"col_integer\" = EXCLUDED.\"col_integer\",\n\"col_bigint\" = EXCLUDED.\"col_bigint\",\n\"col_boolean\" = EXCLUDED.\"col_boolean\",\n\"col_real\" = EXCLUDED.\"col_real\",\n\"col_double\" = EXCLUDED.\"col_double\",\n\"col_float\" = EXCLUDED.\"col_float\",\n\"col_decimal\" = EXCLUDED.\"col_decimal\",\n\"col_numeric\" = EXCLUDED.\"col_numeric\",\n\"col_text\" = EXCLUDED.\"col_text\",\n\"col_varchar\" = EXCLUDED.\"col_varchar\",\n\"col_char\" = EXCLUDED.\"col_char\",\n\"col_clob\" = EXCLUDED.\"col_clob\",\n\"col_blob\" = EXCLUDED.\"col_blob\",\n\"col_binary\" = EXCLUDED.\"col_binary\",\n\"col_date\" = EXCLUDED.\"col_date\",\n\"col_time\" = EXCLUDED.\"col_time\",\n\"col_datetime\" = EXCLUDED.\"col_datetime\",\n\"col_timestamp\" = EXCLUDED.\"col_timestamp\",\n\"col_uuid\" = EXCLUDED.\"col_uuid\",\n\"col_json\" = EXCLUDED.\"col_json\",\n\"col_not_null\" = EXCLUDED.\"col_not_null\"\nRETURNING \"id\", \"col_tinyint\", \"col_smallint\", \"col_int\", \"col_integer\", \"col_bigint\", \"col_boolean\", \"col_real\", \"col_double\", \"col_float\", \"col_decimal\", \"col_numeric\", \"col_text\", \"col_varchar\", \"col_char\", \"col_clob\", \"col_blob\", \"col_binary\", \"col_date\", \"col_time\", \"col_datetime\", \"col_timestamp\", \"col_uuid\", \"col_json\", \"col_not_null\"")) + .updateReturningEach(AllScalarTypesRow.rowCodec, unsaved) + .run(c) +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/all_scalar_types/AllScalarTypesRepoMock.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/all_scalar_types/AllScalarTypesRepoMock.kt new file mode 100644 index 0000000000..1542ef1c41 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/all_scalar_types/AllScalarTypesRepoMock.kt @@ -0,0 +1,119 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.all_scalar_types + +import dev.typr.dslkt.DeleteBuilder +import dev.typr.dslkt.DeleteBuilderMock +import dev.typr.dslkt.DeleteParams +import dev.typr.dslkt.SelectBuilder +import dev.typr.dslkt.SelectBuilderMock +import dev.typr.dslkt.SelectParams +import dev.typr.dslkt.UpdateBuilder +import dev.typr.dslkt.UpdateBuilderMock +import dev.typr.dslkt.UpdateParams +import dev.typr.foundationskt.Connection +import dev.typr.foundationskt.ConnectionRead +import java.lang.RuntimeException +import java.util.ArrayList +import kotlin.collections.Iterator +import kotlin.collections.List +import kotlin.collections.Map +import kotlin.collections.MutableMap + +data class AllScalarTypesRepoMock(val map: MutableMap = mutableMapOf()) : AllScalarTypesRepo { + override fun delete(): DeleteBuilder = DeleteBuilderMock(AllScalarTypesFields.structure, { map.values.toList() }, DeleteParams.empty(), { row -> row.id }, { id -> map.remove(id) }) + + override fun deleteById( + id: AllScalarTypesId, + c: Connection + ): kotlin.Boolean = map.remove(id) != null + + override fun deleteByIds( + ids: List, + c: Connection + ): Int { + var count = 0 + for (id in ids) { + if (map.remove(id) != null) { + count = count + 1 + } + } + return count + } + + override fun insert( + unsaved: AllScalarTypesRow, + c: Connection + ): AllScalarTypesRow { + if (map.containsKey(unsaved.id)) { + throw RuntimeException("id " + unsaved.id + " already exists") + } + map[unsaved.id] = unsaved + return unsaved + } + + override fun select(): SelectBuilder = SelectBuilderMock(AllScalarTypesFields.structure, { map.values.toList() }, SelectParams.empty()) + + override fun selectAll(c: ConnectionRead): List = map.values.toList() + + override fun selectById( + id: AllScalarTypesId, + c: ConnectionRead + ): AllScalarTypesRow? = map[id] + + override fun selectByIds( + ids: List, + c: ConnectionRead + ): List { + val result = ArrayList() + for (id in ids) { + val opt = map[id] + if (opt != null) { + result.add(opt) + } + } + return result + } + + override fun selectByIdsTracked( + ids: List, + c: ConnectionRead + ): Map = selectByIds(ids, c).associateBy({ row: AllScalarTypesRow -> row.id }) + + override fun update(): UpdateBuilder = UpdateBuilderMock(AllScalarTypesFields.structure, { map.values.toList() }, UpdateParams.empty(), { row -> row }) + + override fun update( + row: AllScalarTypesRow, + c: Connection + ): kotlin.Boolean { + val shouldUpdate = map[row.id]?.takeIf({ oldRow -> (oldRow != row) }) != null + if (shouldUpdate) { + map[row.id] = row + } + return shouldUpdate + } + + override fun upsert( + unsaved: AllScalarTypesRow, + c: Connection + ): AllScalarTypesRow { + map[unsaved.id] = unsaved + return unsaved + } + + override fun upsertBatch( + unsaved: Iterator, + c: Connection + ): List { + val result = ArrayList() + while (unsaved.hasNext()) { + val row = unsaved.next() + map[row.id] = row + result.add(row) + } + return result + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/all_scalar_types/AllScalarTypesRow.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/all_scalar_types/AllScalarTypesRow.kt new file mode 100644 index 0000000000..8300acaa5c --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/all_scalar_types/AllScalarTypesRow.kt @@ -0,0 +1,102 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.all_scalar_types + +import com.fasterxml.jackson.annotation.JsonProperty +import dev.typr.foundations.Tuple.Tuple25 +import dev.typr.foundations.data.Json +import dev.typr.foundationskt.RowCodec +import dev.typr.foundationskt.SqliteTypes +import java.math.BigDecimal +import java.time.LocalDate +import java.time.LocalDateTime +import java.time.LocalTime +import java.util.UUID + +/** Table: all_scalar_types + * Primary key: id + */ +data class AllScalarTypesRow( + val id: AllScalarTypesId, + @field:JsonProperty("col_tinyint") val colTinyint: kotlin.Byte?, + @field:JsonProperty("col_smallint") val colSmallint: kotlin.Short?, + @field:JsonProperty("col_int") val colInt: Int?, + @field:JsonProperty("col_integer") val colInteger: kotlin.Long?, + @field:JsonProperty("col_bigint") val colBigint: kotlin.Long?, + @field:JsonProperty("col_boolean") val colBoolean: kotlin.Boolean?, + @field:JsonProperty("col_real") val colReal: kotlin.Double?, + @field:JsonProperty("col_double") val colDouble: kotlin.Double?, + @field:JsonProperty("col_float") val colFloat: kotlin.Float?, + @field:JsonProperty("col_decimal") val colDecimal: BigDecimal?, + @field:JsonProperty("col_numeric") val colNumeric: BigDecimal?, + @field:JsonProperty("col_text") val colText: kotlin.String?, + @field:JsonProperty("col_varchar") val colVarchar: kotlin.String?, + @field:JsonProperty("col_char") val colChar: kotlin.String?, + @field:JsonProperty("col_clob") val colClob: kotlin.String?, + @field:JsonProperty("col_blob") val colBlob: ByteArray?, + @field:JsonProperty("col_binary") val colBinary: ByteArray?, + @field:JsonProperty("col_date") val colDate: LocalDate?, + @field:JsonProperty("col_time") val colTime: LocalTime?, + @field:JsonProperty("col_datetime") val colDatetime: LocalDateTime?, + @field:JsonProperty("col_timestamp") val colTimestamp: LocalDateTime?, + @field:JsonProperty("col_uuid") val colUuid: UUID?, + @field:JsonProperty("col_json") val colJson: Json?, + @field:JsonProperty("col_not_null") val colNotNull: kotlin.String +) : Tuple25 { + override fun _1(): AllScalarTypesId = id + + override fun _10(): kotlin.Float? = colFloat + + override fun _11(): BigDecimal? = colDecimal + + override fun _12(): BigDecimal? = colNumeric + + override fun _13(): kotlin.String? = colText + + override fun _14(): kotlin.String? = colVarchar + + override fun _15(): kotlin.String? = colChar + + override fun _16(): kotlin.String? = colClob + + override fun _17(): ByteArray? = colBlob + + override fun _18(): ByteArray? = colBinary + + override fun _19(): LocalDate? = colDate + + override fun _2(): kotlin.Byte? = colTinyint + + override fun _20(): LocalTime? = colTime + + override fun _21(): LocalDateTime? = colDatetime + + override fun _22(): LocalDateTime? = colTimestamp + + override fun _23(): UUID? = colUuid + + override fun _24(): Json? = colJson + + override fun _25(): kotlin.String = colNotNull + + override fun _3(): kotlin.Short? = colSmallint + + override fun _4(): Int? = colInt + + override fun _5(): kotlin.Long? = colInteger + + override fun _6(): kotlin.Long? = colBigint + + override fun _7(): kotlin.Boolean? = colBoolean + + override fun _8(): kotlin.Double? = colReal + + override fun _9(): kotlin.Double? = colDouble + + companion object { + val rowCodec: RowCodec = RowCodec(dev.typr.foundations.RowCodec.create(listOf(AllScalarTypesId.sqliteType.underlying, SqliteTypes.tinyint.opt().underlying, SqliteTypes.smallint.opt().underlying, SqliteTypes.int_.opt().underlying, SqliteTypes.integer.opt().underlying, SqliteTypes.bigint.opt().underlying, SqliteTypes.boolean_.opt().underlying, SqliteTypes.real.opt().underlying, SqliteTypes.double_.opt().underlying, SqliteTypes.float_.opt().underlying, SqliteTypes.numeric.opt().underlying, SqliteTypes.numeric.opt().underlying, SqliteTypes.text.opt().underlying, SqliteTypes.varchar.opt().underlying, SqliteTypes.char_.opt().underlying, SqliteTypes.clob.opt().underlying, SqliteTypes.blob.opt().underlying, SqliteTypes.binary.opt().underlying, SqliteTypes.date.opt().underlying, SqliteTypes.time.opt().underlying, SqliteTypes.timestamp.opt().underlying, SqliteTypes.timestamp.opt().underlying, SqliteTypes.uuid.opt().underlying, SqliteTypes.json.opt().underlying, SqliteTypes.text.underlying), { a -> AllScalarTypesRow(a[0] as AllScalarTypesId, a[1] as kotlin.Byte?, a[2] as kotlin.Short?, a[3] as Int?, a[4] as kotlin.Long?, a[5] as kotlin.Long?, a[6] as kotlin.Boolean?, a[7] as kotlin.Double?, a[8] as kotlin.Double?, a[9] as kotlin.Float?, a[10] as BigDecimal?, a[11] as BigDecimal?, a[12] as kotlin.String?, a[13] as kotlin.String?, a[14] as kotlin.String?, a[15] as kotlin.String?, a[16] as ByteArray?, a[17] as ByteArray?, a[18] as LocalDate?, a[19] as LocalTime?, a[20] as LocalDateTime?, a[21] as LocalDateTime?, a[22] as UUID?, a[23] as Json?, a[24] as kotlin.String) }, { row: AllScalarTypesRow -> arrayOf(row.id, row.colTinyint, row.colSmallint, row.colInt, row.colInteger, row.colBigint, row.colBoolean, row.colReal, row.colDouble, row.colFloat, row.colDecimal, row.colNumeric, row.colText, row.colVarchar, row.colChar, row.colClob, row.colBlob, row.colBinary, row.colDate, row.colTime, row.colDatetime, row.colTimestamp, row.colUuid, row.colJson, row.colNotNull) })) + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/all_scalar_types_search/AllScalarTypesSearchSqlRepo.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/all_scalar_types_search/AllScalarTypesSearchSqlRepo.kt new file mode 100644 index 0000000000..efcaea55b6 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/all_scalar_types_search/AllScalarTypesSearchSqlRepo.kt @@ -0,0 +1,19 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.all_scalar_types_search + +import dev.typr.foundationskt.ConnectionRead +import java.time.LocalDate +import kotlin.collections.List + +interface AllScalarTypesSearchSqlRepo { + abstract fun apply( + minId: kotlin.Long?, + textPattern: kotlin.String?, + afterDate: LocalDate?, + c: ConnectionRead + ): List +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/all_scalar_types_search/AllScalarTypesSearchSqlRepoImpl.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/all_scalar_types_search/AllScalarTypesSearchSqlRepoImpl.kt new file mode 100644 index 0000000000..089461c5ee --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/all_scalar_types_search/AllScalarTypesSearchSqlRepoImpl.kt @@ -0,0 +1,21 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.all_scalar_types_search + +import dev.typr.foundationskt.ConnectionRead +import dev.typr.foundationskt.Fragment +import dev.typr.foundationskt.SqliteTypes +import java.time.LocalDate +import kotlin.collections.List + +class AllScalarTypesSearchSqlRepoImpl() : AllScalarTypesSearchSqlRepo { + override fun apply( + minId: kotlin.Long?, + textPattern: kotlin.String?, + afterDate: LocalDate?, + c: ConnectionRead + ): List = Fragment.concat(Fragment.of("-- Filter the all_scalar_types table by a handful of columns.\n-- Tests: a parameter for each affinity (INTEGER, REAL, TEXT, DATE).\n\nSELECT\n id,\n col_tinyint,\n col_smallint,\n col_integer,\n col_bigint,\n col_real,\n col_double,\n col_decimal,\n col_text,\n col_date,\n col_uuid,\n col_json\nFROM all_scalar_types\nWHERE\n ("), Fragment.encode(SqliteTypes.integer.opt(), minId), Fragment.of(" IS NULL OR id >= "), Fragment.encode(SqliteTypes.integer.opt(), minId), Fragment.of(")\n AND ("), Fragment.encode(SqliteTypes.text.opt(), textPattern), Fragment.of(" IS NULL OR col_text LIKE "), Fragment.encode(SqliteTypes.text.opt(), textPattern), Fragment.of(")\n AND ("), Fragment.encode(SqliteTypes.date.opt(), afterDate), Fragment.of(" IS NULL OR col_date >= "), Fragment.encode(SqliteTypes.date.opt(), afterDate), Fragment.of(")\nORDER BY id")).query(AllScalarTypesSearchSqlRow.rowCodec.all()).run(c) +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/all_scalar_types_search/AllScalarTypesSearchSqlRow.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/all_scalar_types_search/AllScalarTypesSearchSqlRow.kt new file mode 100644 index 0000000000..ca309ef856 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/all_scalar_types_search/AllScalarTypesSearchSqlRow.kt @@ -0,0 +1,73 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.all_scalar_types_search + +import com.fasterxml.jackson.annotation.JsonProperty +import dev.typr.dslkt.RowCodecs +import dev.typr.foundations.Tuple.Tuple12 +import dev.typr.foundations.data.Json +import dev.typr.foundationskt.RowCodec +import dev.typr.foundationskt.SqliteTypes +import java.math.BigDecimal +import java.time.LocalDate +import java.util.UUID +import testdb.all_scalar_types.AllScalarTypesId + +/** SQL file: all_scalar_types_search.sql */ +data class AllScalarTypesSearchSqlRow( + /** Points to [testdb.all_scalar_types.AllScalarTypesRow.id] */ + val id: AllScalarTypesId, + /** Points to [testdb.all_scalar_types.AllScalarTypesRow.colTinyint] */ + @field:JsonProperty("col_tinyint") val colTinyint: kotlin.Byte?, + /** Points to [testdb.all_scalar_types.AllScalarTypesRow.colSmallint] */ + @field:JsonProperty("col_smallint") val colSmallint: kotlin.Short?, + /** Points to [testdb.all_scalar_types.AllScalarTypesRow.colInteger] */ + @field:JsonProperty("col_integer") val colInteger: kotlin.Long?, + /** Points to [testdb.all_scalar_types.AllScalarTypesRow.colBigint] */ + @field:JsonProperty("col_bigint") val colBigint: kotlin.Long?, + /** Points to [testdb.all_scalar_types.AllScalarTypesRow.colReal] */ + @field:JsonProperty("col_real") val colReal: kotlin.Double?, + /** Points to [testdb.all_scalar_types.AllScalarTypesRow.colDouble] */ + @field:JsonProperty("col_double") val colDouble: kotlin.Double?, + /** Points to [testdb.all_scalar_types.AllScalarTypesRow.colDecimal] */ + @field:JsonProperty("col_decimal") val colDecimal: BigDecimal?, + /** Points to [testdb.all_scalar_types.AllScalarTypesRow.colText] */ + @field:JsonProperty("col_text") val colText: kotlin.String?, + /** Points to [testdb.all_scalar_types.AllScalarTypesRow.colDate] */ + @field:JsonProperty("col_date") val colDate: LocalDate?, + /** Points to [testdb.all_scalar_types.AllScalarTypesRow.colUuid] */ + @field:JsonProperty("col_uuid") val colUuid: UUID?, + /** Points to [testdb.all_scalar_types.AllScalarTypesRow.colJson] */ + @field:JsonProperty("col_json") val colJson: Json? +) : Tuple12 { + override fun _1(): AllScalarTypesId = id + + override fun _10(): LocalDate? = colDate + + override fun _11(): UUID? = colUuid + + override fun _12(): Json? = colJson + + override fun _2(): kotlin.Byte? = colTinyint + + override fun _3(): kotlin.Short? = colSmallint + + override fun _4(): kotlin.Long? = colInteger + + override fun _5(): kotlin.Long? = colBigint + + override fun _6(): kotlin.Double? = colReal + + override fun _7(): kotlin.Double? = colDouble + + override fun _8(): BigDecimal? = colDecimal + + override fun _9(): kotlin.String? = colText + + companion object { + val rowCodec: RowCodec = RowCodecs.of(AllScalarTypesId.sqliteType, SqliteTypes.tinyint.opt(), SqliteTypes.smallint.opt(), SqliteTypes.integer.opt(), SqliteTypes.bigint.opt(), SqliteTypes.real.opt(), SqliteTypes.double_.opt(), SqliteTypes.numeric.opt(), SqliteTypes.text.opt(), SqliteTypes.date.opt(), SqliteTypes.uuid.opt(), SqliteTypes.json.opt(), { t0: AllScalarTypesId, t1: kotlin.Byte?, t2: kotlin.Short?, t3: kotlin.Long?, t4: kotlin.Long?, t5: kotlin.Double?, t6: kotlin.Double?, t7: BigDecimal?, t8: kotlin.String?, t9: LocalDate?, t10: UUID?, t11: Json? -> AllScalarTypesSearchSqlRow(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11) }, { row: AllScalarTypesSearchSqlRow -> arrayOf(row.id, row.colTinyint, row.colSmallint, row.colInteger, row.colBigint, row.colReal, row.colDouble, row.colDecimal, row.colText, row.colDate, row.colUuid, row.colJson) }) + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/bridge/Customer.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/bridge/Customer.kt new file mode 100644 index 0000000000..0e6e978f8e --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/bridge/Customer.kt @@ -0,0 +1,15 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.bridge + + + +/** Bridge composite type: Customer */ +data class Customer( + val created_at: kotlin.String?, + val customer_id: kotlin.String, + val email: kotlin.String? +) \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/customer_orders/CustomerOrdersViewFields.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/customer_orders/CustomerOrdersViewFields.kt new file mode 100644 index 0000000000..eea5ca1274 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/customer_orders/CustomerOrdersViewFields.kt @@ -0,0 +1,64 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.customer_orders + +import dev.typr.dsl.FieldsBase +import dev.typr.dsl.Path +import dev.typr.dsl.SqlExpr.FieldLike +import dev.typr.dslkt.RelationStructure +import dev.typr.dslkt.SqlExpr +import dev.typr.dslkt.SqlExpr.OptField +import dev.typr.dslkt.TupleExpr7 +import dev.typr.foundations.RowCodec +import dev.typr.foundationskt.SqliteTypes +import java.math.BigDecimal +import java.time.LocalDate +import kotlin.collections.List +import testdb.customers.CustomersId +import testdb.orders.OrdersId +import testdb.userdefined.Email + +data class CustomerOrdersViewFields(val _path: List) : TupleExpr7, RelationStructure, FieldsBase { + override fun _1(): SqlExpr = customerId() + + override fun _2(): SqlExpr = customerName() + + override fun _3(): SqlExpr = email() + + override fun _4(): SqlExpr = orderId() + + override fun _5(): SqlExpr = orderDate() + + override fun _6(): SqlExpr = totalAmount() + + override fun _7(): SqlExpr = status() + + override fun _path(): List = _path + + override fun columns(): List> = listOf(this.customerId().underlying, this.customerName().underlying, this.email().underlying, this.orderId().underlying, this.orderDate().underlying, this.totalAmount().underlying, this.status().underlying) + + fun customerId(): OptField = OptField(_path, "customer_id", CustomerOrdersViewRow::customerId, null, null, { row, value -> row.copy(customerId = value) }, CustomersId.sqliteType.underlying) + + fun customerName(): OptField = OptField(_path, "customer_name", CustomerOrdersViewRow::customerName, null, null, { row, value -> row.copy(customerName = value) }, SqliteTypes.text.underlying) + + fun email(): OptField = OptField(_path, "email", CustomerOrdersViewRow::email, null, null, { row, value -> row.copy(email = value) }, Email.sqliteType.underlying) + + fun orderDate(): OptField = OptField(_path, "order_date", CustomerOrdersViewRow::orderDate, null, null, { row, value -> row.copy(orderDate = value) }, SqliteTypes.date.underlying) + + fun orderId(): OptField = OptField(_path, "order_id", CustomerOrdersViewRow::orderId, null, null, { row, value -> row.copy(orderId = value) }, OrdersId.sqliteType.underlying) + + override fun rowCodec(): RowCodec = CustomerOrdersViewRow.rowCodec.underlying + + fun status(): OptField = OptField(_path, "status", CustomerOrdersViewRow::status, null, null, { row, value -> row.copy(status = value) }, SqliteTypes.text.underlying) + + fun totalAmount(): OptField = OptField(_path, "total_amount", CustomerOrdersViewRow::totalAmount, null, null, { row, value -> row.copy(totalAmount = value) }, SqliteTypes.numeric.underlying) + + override fun withPaths(_path: List): RelationStructure = CustomerOrdersViewFields(_path) + + companion object { + val structure: CustomerOrdersViewFields = CustomerOrdersViewFields(emptyList()) + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/customer_orders/CustomerOrdersViewRepo.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/customer_orders/CustomerOrdersViewRepo.kt new file mode 100644 index 0000000000..df2b47034b --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/customer_orders/CustomerOrdersViewRepo.kt @@ -0,0 +1,16 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.customer_orders + +import dev.typr.dslkt.SelectBuilder +import dev.typr.foundationskt.ConnectionRead +import kotlin.collections.List + +interface CustomerOrdersViewRepo { + abstract fun select(): SelectBuilder + + abstract fun selectAll(c: ConnectionRead): List +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/customer_orders/CustomerOrdersViewRepoImpl.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/customer_orders/CustomerOrdersViewRepoImpl.kt new file mode 100644 index 0000000000..122d3d91b3 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/customer_orders/CustomerOrdersViewRepoImpl.kt @@ -0,0 +1,18 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.customer_orders + +import dev.typr.dslkt.Dialect +import dev.typr.dslkt.SelectBuilder +import dev.typr.foundationskt.ConnectionRead +import dev.typr.foundationskt.Fragment +import kotlin.collections.List + +class CustomerOrdersViewRepoImpl() : CustomerOrdersViewRepo { + override fun select(): SelectBuilder = SelectBuilder.of("\"customer_orders\"", CustomerOrdersViewFields.structure, CustomerOrdersViewRow.rowCodec, Dialect.SQLITE) + + override fun selectAll(c: ConnectionRead): List = Fragment.concat(Fragment.of("select \"customer_id\", \"customer_name\", \"email\", \"order_id\", \"order_date\", \"total_amount\", \"status\"\nfrom \"customer_orders\"\n")).query(CustomerOrdersViewRow.rowCodec.all()).run(c) +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/customer_orders/CustomerOrdersViewRow.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/customer_orders/CustomerOrdersViewRow.kt new file mode 100644 index 0000000000..c793e79832 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/customer_orders/CustomerOrdersViewRow.kt @@ -0,0 +1,53 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.customer_orders + +import com.fasterxml.jackson.annotation.JsonProperty +import dev.typr.dslkt.RowCodecs +import dev.typr.foundations.Tuple.Tuple7 +import dev.typr.foundationskt.RowCodec +import dev.typr.foundationskt.SqliteTypes +import java.math.BigDecimal +import java.time.LocalDate +import testdb.customers.CustomersId +import testdb.orders.OrdersId +import testdb.userdefined.Email + +/** View: customer_orders */ +data class CustomerOrdersViewRow( + /** Points to [testdb.customers.CustomersRow.customerId] */ + @field:JsonProperty("customer_id") val customerId: CustomersId?, + /** Points to [testdb.customers.CustomersRow.customerName] */ + @field:JsonProperty("customer_name") val customerName: kotlin.String?, + /** Points to [testdb.customers.CustomersRow.email] */ + val email: /* user-picked */ Email?, + /** Points to [testdb.orders.OrdersRow.orderId] */ + @field:JsonProperty("order_id") val orderId: OrdersId?, + /** Points to [testdb.orders.OrdersRow.orderDate] */ + @field:JsonProperty("order_date") val orderDate: LocalDate?, + /** Points to [testdb.orders.OrdersRow.totalAmount] */ + @field:JsonProperty("total_amount") val totalAmount: BigDecimal?, + /** Points to [testdb.orders.OrdersRow.status] */ + val status: kotlin.String? +) : Tuple7 { + override fun _1(): CustomersId? = customerId + + override fun _2(): kotlin.String? = customerName + + override fun _3(): /* user-picked */ Email? = email + + override fun _4(): OrdersId? = orderId + + override fun _5(): LocalDate? = orderDate + + override fun _6(): BigDecimal? = totalAmount + + override fun _7(): kotlin.String? = status + + companion object { + val rowCodec: RowCodec = RowCodecs.of(CustomersId.sqliteType.opt(), SqliteTypes.text.opt(), Email.sqliteType.opt(), OrdersId.sqliteType.opt(), SqliteTypes.date.opt(), SqliteTypes.numeric.opt(), SqliteTypes.text.opt(), { t0: CustomersId?, t1: kotlin.String?, t2: /* user-picked */ Email?, t3: OrdersId?, t4: LocalDate?, t5: BigDecimal?, t6: kotlin.String? -> CustomerOrdersViewRow(t0, t1, t2, t3, t4, t5, t6) }, { row: CustomerOrdersViewRow -> arrayOf(row.customerId, row.customerName, row.email, row.orderId, row.orderDate, row.totalAmount, row.status) }) + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/customer_search/CustomerSearchSqlRepo.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/customer_search/CustomerSearchSqlRepo.kt new file mode 100644 index 0000000000..b257ae7c99 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/customer_search/CustomerSearchSqlRepo.kt @@ -0,0 +1,20 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.customer_search + +import dev.typr.foundationskt.ConnectionRead +import java.time.LocalDateTime +import kotlin.collections.List + +interface CustomerSearchSqlRepo { + abstract fun apply( + namePattern: kotlin.String?, + emailPattern: kotlin.String?, + createdAfter: LocalDateTime?, + maxResults: kotlin.Long, + c: ConnectionRead + ): List +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/customer_search/CustomerSearchSqlRepoImpl.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/customer_search/CustomerSearchSqlRepoImpl.kt new file mode 100644 index 0000000000..0f92f19b15 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/customer_search/CustomerSearchSqlRepoImpl.kt @@ -0,0 +1,22 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.customer_search + +import dev.typr.foundationskt.ConnectionRead +import dev.typr.foundationskt.Fragment +import dev.typr.foundationskt.SqliteTypes +import java.time.LocalDateTime +import kotlin.collections.List + +class CustomerSearchSqlRepoImpl() : CustomerSearchSqlRepo { + override fun apply( + namePattern: kotlin.String?, + emailPattern: kotlin.String?, + createdAfter: LocalDateTime?, + maxResults: kotlin.Long, + c: ConnectionRead + ): List = Fragment.concat(Fragment.of("-- Customer search with multiple optional filters.\n-- Tests: optional parameters, LIKE patterns, complex WHERE, ORDER BY/LIMIT.\n\nSELECT\n customer_id,\n name,\n email,\n created_at\nFROM customers\nWHERE\n ("), Fragment.encode(SqliteTypes.text.opt(), namePattern), Fragment.of(" IS NULL OR name LIKE "), Fragment.encode(SqliteTypes.text.opt(), namePattern), Fragment.of(")\n AND ("), Fragment.encode(SqliteTypes.text.opt(), emailPattern), Fragment.of(" IS NULL OR email LIKE "), Fragment.encode(SqliteTypes.text.opt(), emailPattern), Fragment.of(")\n AND ("), Fragment.encode(SqliteTypes.timestamp.opt(), createdAfter), Fragment.of(" IS NULL OR created_at >= "), Fragment.encode(SqliteTypes.timestamp.opt(), createdAfter), Fragment.of(")\nORDER BY created_at DESC, customer_id\nLIMIT "), Fragment.encode(SqliteTypes.bigint, maxResults), Fragment.of("")).query(CustomerSearchSqlRow.rowCodec.all()).run(c) +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/customer_search/CustomerSearchSqlRow.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/customer_search/CustomerSearchSqlRow.kt new file mode 100644 index 0000000000..277d9713af --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/customer_search/CustomerSearchSqlRow.kt @@ -0,0 +1,39 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.customer_search + +import com.fasterxml.jackson.annotation.JsonProperty +import dev.typr.dslkt.RowCodecs +import dev.typr.foundations.Tuple.Tuple4 +import dev.typr.foundationskt.RowCodec +import dev.typr.foundationskt.SqliteTypes +import java.time.LocalDateTime +import testdb.customers.CustomersId +import testdb.userdefined.Email + +/** SQL file: customer_search.sql */ +data class CustomerSearchSqlRow( + /** Points to [testdb.customers.CustomersRow.customerId] */ + @field:JsonProperty("customer_id") val customerId: CustomersId, + /** Points to [testdb.customers.CustomersRow.name] */ + val name: kotlin.String, + /** Points to [testdb.customers.CustomersRow.email] */ + val email: /* user-picked */ Email?, + /** Points to [testdb.customers.CustomersRow.createdAt] */ + @field:JsonProperty("created_at") val createdAt: LocalDateTime +) : Tuple4 { + override fun _1(): CustomersId = customerId + + override fun _2(): kotlin.String = name + + override fun _3(): /* user-picked */ Email? = email + + override fun _4(): LocalDateTime = createdAt + + companion object { + val rowCodec: RowCodec = RowCodecs.of(CustomersId.sqliteType, SqliteTypes.text, Email.sqliteType.opt(), SqliteTypes.timestamp, { t0: CustomersId, t1: kotlin.String, t2: /* user-picked */ Email?, t3: LocalDateTime -> CustomerSearchSqlRow(t0, t1, t2, t3) }, { row: CustomerSearchSqlRow -> arrayOf(row.customerId, row.name, row.email, row.createdAt) }) + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/customers/CustomersFields.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/customers/CustomersFields.kt new file mode 100644 index 0000000000..a9bcc03a61 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/customers/CustomersFields.kt @@ -0,0 +1,51 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.customers + +import dev.typr.dsl.FieldsBase +import dev.typr.dsl.Path +import dev.typr.dsl.SqlExpr.FieldLike +import dev.typr.dslkt.RelationStructure +import dev.typr.dslkt.SqlExpr +import dev.typr.dslkt.SqlExpr.Field +import dev.typr.dslkt.SqlExpr.IdField +import dev.typr.dslkt.SqlExpr.OptField +import dev.typr.dslkt.TupleExpr4 +import dev.typr.foundations.RowCodec +import dev.typr.foundationskt.SqliteTypes +import java.time.LocalDateTime +import kotlin.collections.List +import testdb.userdefined.Email + +data class CustomersFields(val _path: List) : TupleExpr4, RelationStructure, FieldsBase { + override fun _1(): SqlExpr = customerId() + + override fun _2(): SqlExpr = name() + + override fun _3(): SqlExpr = email() + + override fun _4(): SqlExpr = createdAt() + + override fun _path(): List = _path + + override fun columns(): List> = listOf(this.customerId().underlying, this.name().underlying, this.email().underlying, this.createdAt().underlying) + + fun createdAt(): Field = Field(_path, "created_at", CustomersRow::createdAt, null, null, { row, value -> row.copy(createdAt = value) }, SqliteTypes.timestamp.underlying) + + fun customerId(): IdField = IdField(_path, "customer_id", CustomersRow::customerId, null, null, { row, value -> row.copy(customerId = value) }, CustomersId.sqliteType.underlying) + + fun email(): OptField = OptField(_path, "email", CustomersRow::email, null, null, { row, value -> row.copy(email = value) }, Email.sqliteType.underlying) + + fun name(): Field = Field(_path, "name", CustomersRow::name, null, null, { row, value -> row.copy(name = value) }, SqliteTypes.text.underlying) + + override fun rowCodec(): RowCodec = CustomersRow.rowCodec.underlying + + override fun withPaths(_path: List): RelationStructure = CustomersFields(_path) + + companion object { + val structure: CustomersFields = CustomersFields(emptyList()) + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/customers/CustomersId.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/customers/CustomersId.kt new file mode 100644 index 0000000000..5d68dbf286 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/customers/CustomersId.kt @@ -0,0 +1,26 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.customers + +import com.fasterxml.jackson.annotation.JsonValue +import dev.typr.foundationskt.Bijection +import dev.typr.foundationskt.SqliteType +import dev.typr.foundationskt.SqliteTypes + +/** Type for the primary key of table `customers` */ +data class CustomersId(@field:JsonValue val value: kotlin.Long) { + override fun toString(): kotlin.String { + return value.toString() + } + + companion object { + val bijection: Bijection = + Bijection.of(CustomersId::value, ::CustomersId) + + val sqliteType: SqliteType = + SqliteTypes.integer.to(Bijection.of(::CustomersId, CustomersId::value)) + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/customers/CustomersRepo.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/customers/CustomersRepo.kt new file mode 100644 index 0000000000..9168275377 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/customers/CustomersRepo.kt @@ -0,0 +1,75 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.customers + +import dev.typr.dslkt.DeleteBuilder +import dev.typr.dslkt.SelectBuilder +import dev.typr.dslkt.UpdateBuilder +import dev.typr.foundationskt.Connection +import dev.typr.foundationskt.ConnectionRead +import kotlin.collections.Iterator +import kotlin.collections.List +import kotlin.collections.Map + +interface CustomersRepo { + abstract fun delete(): DeleteBuilder + + abstract fun deleteById( + customerId: CustomersId, + c: Connection + ): kotlin.Boolean + + abstract fun deleteByIds( + customerIds: List, + c: Connection + ): Int + + abstract fun insert( + unsaved: CustomersRow, + c: Connection + ): CustomersRow + + abstract fun insert( + unsaved: CustomersRowUnsaved, + c: Connection + ): CustomersRow + + abstract fun select(): SelectBuilder + + abstract fun selectAll(c: ConnectionRead): List + + abstract fun selectById( + customerId: CustomersId, + c: ConnectionRead + ): CustomersRow? + + abstract fun selectByIds( + customerIds: List, + c: ConnectionRead + ): List + + abstract fun selectByIdsTracked( + customerIds: List, + c: ConnectionRead + ): Map + + abstract fun update(): UpdateBuilder + + abstract fun update( + row: CustomersRow, + c: Connection + ): kotlin.Boolean + + abstract fun upsert( + unsaved: CustomersRow, + c: Connection + ): CustomersRow + + abstract fun upsertBatch( + unsaved: Iterator, + c: Connection + ): List +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/customers/CustomersRepoImpl.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/customers/CustomersRepoImpl.kt new file mode 100644 index 0000000000..8eddc04b51 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/customers/CustomersRepoImpl.kt @@ -0,0 +1,117 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.customers + +import dev.typr.dslkt.DeleteBuilder +import dev.typr.dslkt.Dialect +import dev.typr.dslkt.SelectBuilder +import dev.typr.dslkt.UpdateBuilder +import dev.typr.foundationskt.Connection +import dev.typr.foundationskt.ConnectionRead +import dev.typr.foundationskt.Fragment +import dev.typr.foundationskt.SqliteTypes +import java.util.ArrayList +import kotlin.collections.Iterator +import kotlin.collections.List +import kotlin.collections.Map +import kotlin.collections.MutableMap +import testdb.userdefined.Email + +class CustomersRepoImpl() : CustomersRepo { + override fun delete(): DeleteBuilder = DeleteBuilder.of("\"customers\"", CustomersFields.structure, Dialect.SQLITE) + + override fun deleteById( + customerId: CustomersId, + c: Connection + ): kotlin.Boolean = Fragment.concat(Fragment.of("delete from \"customers\" where \"customer_id\" = "), Fragment.encode(CustomersId.sqliteType, customerId), Fragment.of("")).update().run(c) > 0 + + override fun deleteByIds( + customerIds: List, + c: Connection + ): Int { + val fragments: ArrayList = ArrayList() + for (id in customerIds) { fragments.add(Fragment.encode(CustomersId.sqliteType, id)) } + return Fragment.concat(Fragment.of("delete from \"customers\" where \"customer_id\" in ("), Fragment.comma(fragments.toMutableList()), Fragment.of(")")).update().run(c) + } + + override fun insert( + unsaved: CustomersRow, + c: Connection + ): CustomersRow = Fragment.concat(Fragment.of("insert into \"customers\"(\"customer_id\", \"name\", \"email\", \"created_at\")\nvalues ("), Fragment.encode(CustomersId.sqliteType, unsaved.customerId), Fragment.of(", "), Fragment.encode(SqliteTypes.text, unsaved.name), Fragment.of(", "), Fragment.encode(Email.sqliteType.opt(), unsaved.email), Fragment.of(", "), Fragment.encode(SqliteTypes.timestamp, unsaved.createdAt), Fragment.of(")\nRETURNING \"customer_id\", \"name\", \"email\", \"created_at\"\n")) + .updateReturning(CustomersRow.rowCodec.exactlyOne()).run(c) + + override fun insert( + unsaved: CustomersRowUnsaved, + c: Connection + ): CustomersRow { + val columns: ArrayList = ArrayList() + val values: ArrayList = ArrayList() + columns.add(Fragment.of("\"customer_id\"")) + values.add(Fragment.concat(Fragment.encode(CustomersId.sqliteType, unsaved.customerId), Fragment.of(""))) + columns.add(Fragment.of("\"name\"")) + values.add(Fragment.concat(Fragment.encode(SqliteTypes.text, unsaved.name), Fragment.of(""))) + columns.add(Fragment.of("\"email\"")) + values.add(Fragment.concat(Fragment.encode(Email.sqliteType.opt(), unsaved.email), Fragment.of(""))) + unsaved.createdAt.visit( + { }, + { value -> columns.add(Fragment.of("\"created_at\"")) + values.add(Fragment.concat(Fragment.encode(SqliteTypes.timestamp, value), Fragment.of(""))) } + ); + val q: Fragment = Fragment.concat(Fragment.of("insert into \"customers\"("), Fragment.comma(columns.toMutableList()), Fragment.of(")\nvalues ("), Fragment.comma(values.toMutableList()), Fragment.of(")\nRETURNING \"customer_id\", \"name\", \"email\", \"created_at\"\n")) + return q.updateReturning(CustomersRow.rowCodec.exactlyOne()).run(c) + } + + override fun select(): SelectBuilder = SelectBuilder.of("\"customers\"", CustomersFields.structure, CustomersRow.rowCodec, Dialect.SQLITE) + + override fun selectAll(c: ConnectionRead): List = Fragment.concat(Fragment.of("select \"customer_id\", \"name\", \"email\", \"created_at\"\nfrom \"customers\"\n")).query(CustomersRow.rowCodec.all()).run(c) + + override fun selectById( + customerId: CustomersId, + c: ConnectionRead + ): CustomersRow? = Fragment.concat(Fragment.of("select \"customer_id\", \"name\", \"email\", \"created_at\"\nfrom \"customers\"\nwhere \"customer_id\" = "), Fragment.encode(CustomersId.sqliteType, customerId), Fragment.of("")).query(CustomersRow.rowCodec.first()).run(c) + + override fun selectByIds( + customerIds: List, + c: ConnectionRead + ): List { + val fragments: ArrayList = ArrayList() + for (id in customerIds) { fragments.add(Fragment.encode(CustomersId.sqliteType, id)) } + return Fragment.concat(Fragment.of("select \"customer_id\", \"name\", \"email\", \"created_at\" from \"customers\" where \"customer_id\" in ("), Fragment.comma(fragments.toMutableList()), Fragment.of(")")).query(CustomersRow.rowCodec.all()).run(c) + } + + override fun selectByIdsTracked( + customerIds: List, + c: ConnectionRead + ): Map { + val ret: MutableMap = mutableMapOf() + selectByIds(customerIds, c).forEach({ row -> ret.put(row.customerId, row) }) + return ret.toMap() + } + + override fun update(): UpdateBuilder = UpdateBuilder.of("\"customers\"", CustomersFields.structure, CustomersRow.rowCodec, Dialect.SQLITE) + + override fun update( + row: CustomersRow, + c: Connection + ): kotlin.Boolean { + val customerId: CustomersId = row.customerId + return Fragment.concat(Fragment.of("update \"customers\"\nset \"name\" = "), Fragment.encode(SqliteTypes.text, row.name), Fragment.of(",\n\"email\" = "), Fragment.encode(Email.sqliteType.opt(), row.email), Fragment.of(",\n\"created_at\" = "), Fragment.encode(SqliteTypes.timestamp, row.createdAt), Fragment.of("\nwhere \"customer_id\" = "), Fragment.encode(CustomersId.sqliteType, customerId), Fragment.of("")).update().run(c) > 0 + } + + override fun upsert( + unsaved: CustomersRow, + c: Connection + ): CustomersRow = Fragment.concat(Fragment.of("INSERT INTO \"customers\"(\"customer_id\", \"name\", \"email\", \"created_at\")\nVALUES ("), Fragment.encode(CustomersId.sqliteType, unsaved.customerId), Fragment.of(", "), Fragment.encode(SqliteTypes.text, unsaved.name), Fragment.of(", "), Fragment.encode(Email.sqliteType.opt(), unsaved.email), Fragment.of(", "), Fragment.encode(SqliteTypes.timestamp, unsaved.createdAt), Fragment.of(")\nON CONFLICT (\"customer_id\")\nDO UPDATE SET\n \"name\" = EXCLUDED.\"name\",\n\"email\" = EXCLUDED.\"email\",\n\"created_at\" = EXCLUDED.\"created_at\"\nRETURNING \"customer_id\", \"name\", \"email\", \"created_at\"")) + .updateReturning(CustomersRow.rowCodec.exactlyOne()) + .run(c) + + override fun upsertBatch( + unsaved: Iterator, + c: Connection + ): List = Fragment.concat(Fragment.of("INSERT INTO \"customers\"(\"customer_id\", \"name\", \"email\", \"created_at\")\nVALUES (?, ?, ?, ?)\nON CONFLICT (\"customer_id\")\nDO UPDATE SET\n \"name\" = EXCLUDED.\"name\",\n\"email\" = EXCLUDED.\"email\",\n\"created_at\" = EXCLUDED.\"created_at\"\nRETURNING \"customer_id\", \"name\", \"email\", \"created_at\"")) + .updateReturningEach(CustomersRow.rowCodec, unsaved) + .run(c) +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/customers/CustomersRepoMock.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/customers/CustomersRepoMock.kt new file mode 100644 index 0000000000..f7e1bd61a2 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/customers/CustomersRepoMock.kt @@ -0,0 +1,127 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.customers + +import dev.typr.dslkt.DeleteBuilder +import dev.typr.dslkt.DeleteBuilderMock +import dev.typr.dslkt.DeleteParams +import dev.typr.dslkt.SelectBuilder +import dev.typr.dslkt.SelectBuilderMock +import dev.typr.dslkt.SelectParams +import dev.typr.dslkt.UpdateBuilder +import dev.typr.dslkt.UpdateBuilderMock +import dev.typr.dslkt.UpdateParams +import dev.typr.foundationskt.Connection +import dev.typr.foundationskt.ConnectionRead +import java.lang.RuntimeException +import java.util.ArrayList +import kotlin.collections.Iterator +import kotlin.collections.List +import kotlin.collections.Map +import kotlin.collections.MutableMap + +data class CustomersRepoMock( + val toRow: (CustomersRowUnsaved) -> CustomersRow, + val map: MutableMap = mutableMapOf() +) : CustomersRepo { + override fun delete(): DeleteBuilder = DeleteBuilderMock(CustomersFields.structure, { map.values.toList() }, DeleteParams.empty(), { row -> row.customerId }, { id -> map.remove(id) }) + + override fun deleteById( + customerId: CustomersId, + c: Connection + ): kotlin.Boolean = map.remove(customerId) != null + + override fun deleteByIds( + customerIds: List, + c: Connection + ): Int { + var count = 0 + for (id in customerIds) { + if (map.remove(id) != null) { + count = count + 1 + } + } + return count + } + + override fun insert( + unsaved: CustomersRow, + c: Connection + ): CustomersRow { + if (map.containsKey(unsaved.customerId)) { + throw RuntimeException("id " + unsaved.customerId + " already exists") + } + map[unsaved.customerId] = unsaved + return unsaved + } + + override fun insert( + unsaved: CustomersRowUnsaved, + c: Connection + ): CustomersRow = insert(toRow(unsaved), c) + + override fun select(): SelectBuilder = SelectBuilderMock(CustomersFields.structure, { map.values.toList() }, SelectParams.empty()) + + override fun selectAll(c: ConnectionRead): List = map.values.toList() + + override fun selectById( + customerId: CustomersId, + c: ConnectionRead + ): CustomersRow? = map[customerId] + + override fun selectByIds( + customerIds: List, + c: ConnectionRead + ): List { + val result = ArrayList() + for (id in customerIds) { + val opt = map[id] + if (opt != null) { + result.add(opt) + } + } + return result + } + + override fun selectByIdsTracked( + customerIds: List, + c: ConnectionRead + ): Map = selectByIds(customerIds, c).associateBy({ row: CustomersRow -> row.customerId }) + + override fun update(): UpdateBuilder = UpdateBuilderMock(CustomersFields.structure, { map.values.toList() }, UpdateParams.empty(), { row -> row }) + + override fun update( + row: CustomersRow, + c: Connection + ): kotlin.Boolean { + val shouldUpdate = map[row.customerId]?.takeIf({ oldRow -> (oldRow != row) }) != null + if (shouldUpdate) { + map[row.customerId] = row + } + return shouldUpdate + } + + override fun upsert( + unsaved: CustomersRow, + c: Connection + ): CustomersRow { + map[unsaved.customerId] = unsaved + return unsaved + } + + override fun upsertBatch( + unsaved: Iterator, + c: Connection + ): List { + val result = ArrayList() + while (unsaved.hasNext()) { + val row = unsaved.next() + map[row.customerId] = row + result.add(row) + } + return result + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/customers/CustomersRow.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/customers/CustomersRow.kt new file mode 100644 index 0000000000..8a8c7e115b --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/customers/CustomersRow.kt @@ -0,0 +1,42 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.customers + +import com.fasterxml.jackson.annotation.JsonProperty +import dev.typr.dslkt.RowCodecs +import dev.typr.foundations.Tuple.Tuple4 +import dev.typr.foundationskt.RowCodec +import dev.typr.foundationskt.SqliteTypes +import java.time.LocalDateTime +import testdb.customtypes.Defaulted +import testdb.userdefined.Email + +/** Table: customers + * Primary key: customer_id + */ +data class CustomersRow( + @field:JsonProperty("customer_id") val customerId: CustomersId, + val name: kotlin.String, + val email: /* user-picked */ Email?, + /** Default: CURRENT_TIMESTAMP */ + @field:JsonProperty("created_at") val createdAt: LocalDateTime +) : Tuple4 { + override fun _1(): CustomersId = customerId + + override fun _2(): kotlin.String = name + + override fun _3(): /* user-picked */ Email? = email + + override fun _4(): LocalDateTime = createdAt + + fun id(): CustomersId = customerId + + fun toUnsavedRow(createdAt: Defaulted = Defaulted.Provided(this.createdAt)): CustomersRowUnsaved = CustomersRowUnsaved(customerId, name, email, createdAt) + + companion object { + val rowCodec: RowCodec = RowCodecs.of(CustomersId.sqliteType, SqliteTypes.text, Email.sqliteType.opt(), SqliteTypes.timestamp, { t0: CustomersId, t1: kotlin.String, t2: /* user-picked */ Email?, t3: LocalDateTime -> CustomersRow(t0, t1, t2, t3) }, { row: CustomersRow -> arrayOf(row.customerId, row.name, row.email, row.createdAt) }) + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/customers/CustomersRowUnsaved.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/customers/CustomersRowUnsaved.kt new file mode 100644 index 0000000000..79ddf2ea27 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/customers/CustomersRowUnsaved.kt @@ -0,0 +1,23 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.customers + +import com.fasterxml.jackson.annotation.JsonProperty +import java.time.LocalDateTime +import testdb.customtypes.Defaulted +import testdb.customtypes.Defaulted.UseDefault +import testdb.userdefined.Email + +/** This class corresponds to a row in table `customers` which has not been persisted yet */ +data class CustomersRowUnsaved( + @field:JsonProperty("customer_id") val customerId: CustomersId, + val name: kotlin.String, + val email: /* user-picked */ Email? = null, + /** Default: CURRENT_TIMESTAMP */ + @field:JsonProperty("created_at") val createdAt: Defaulted = UseDefault() +) { + fun toRow(createdAtDefault: () -> LocalDateTime): CustomersRow = CustomersRow(customerId = customerId, name = name, email = email, createdAt = createdAt.getOrElse(createdAtDefault)) +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/customtypes/Defaulted.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/customtypes/Defaulted.kt new file mode 100644 index 0000000000..fb73ba17ed --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/customtypes/Defaulted.kt @@ -0,0 +1,60 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.customtypes + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize +import com.fasterxml.jackson.databind.annotation.JsonSerialize +import testdb.DefaultedDeserializer +import testdb.DefaultedSerializer + +@JsonSerialize(using = DefaultedSerializer::class) +@JsonDeserialize(using = DefaultedDeserializer::class) +/** This signals a value where if you don't provide it, postgres will generate it for you */ +sealed interface Defaulted { + data class Provided(val value: T) : Defaulted { + override fun fold( + onDefault: () -> U, + onProvided: (T) -> U + ): U = onProvided(value) + + override fun getOrElse(onDefault: () -> T): T = value + + override fun visit( + onDefault: () -> Unit, + onProvided: (T) -> Unit + ) { + onProvided(value) + } + } + + class UseDefault : Defaulted { + override fun fold( + onDefault: () -> U, + onProvided: (T) -> U + ): U = onDefault() + + override fun getOrElse(onDefault: () -> T): T = onDefault() + + override fun visit( + onDefault: () -> Unit, + onProvided: (T) -> Unit + ) { + onDefault() + } + } + + abstract fun fold( + onDefault: () -> U, + onProvided: (T) -> U + ): U + + abstract fun getOrElse(onDefault: () -> T): T + + abstract fun visit( + onDefault: () -> Unit, + onProvided: (T) -> Unit + ) +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/delete_old_orders/DeleteOldOrdersSqlRepo.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/delete_old_orders/DeleteOldOrdersSqlRepo.kt new file mode 100644 index 0000000000..3bf91c2cc2 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/delete_old_orders/DeleteOldOrdersSqlRepo.kt @@ -0,0 +1,16 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.delete_old_orders + +import dev.typr.foundationskt.Connection +import java.time.LocalDate + +interface DeleteOldOrdersSqlRepo { + abstract fun apply( + cutoffDate: LocalDate, + c: Connection + ): Int +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/delete_old_orders/DeleteOldOrdersSqlRepoImpl.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/delete_old_orders/DeleteOldOrdersSqlRepoImpl.kt new file mode 100644 index 0000000000..5987d79a93 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/delete_old_orders/DeleteOldOrdersSqlRepoImpl.kt @@ -0,0 +1,18 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.delete_old_orders + +import dev.typr.foundationskt.Connection +import dev.typr.foundationskt.Fragment +import dev.typr.foundationskt.SqliteTypes +import java.time.LocalDate + +class DeleteOldOrdersSqlRepoImpl() : DeleteOldOrdersSqlRepo { + override fun apply( + cutoffDate: LocalDate, + c: Connection + ): Int = Fragment.concat(Fragment.of("-- Delete completed orders older than a cutoff date.\n-- Tests: DELETE statement with required date param, no result columns.\n--\n-- SQLite stores DATE as ISO-8601 TEXT, so sqlglot can't infer that\n-- order_date < :cutoff_date wants a LocalDate. We pin the type\n-- explicitly with the `:name:Type!` annotation — same opt-in pattern\n-- as the other dialects use for parameters not otherwise resolvable\n-- from schema lineage.\nDELETE FROM orders\nWHERE status = 'completed' AND order_date < "), Fragment.encode(SqliteTypes.date, cutoffDate), Fragment.of("")).update().run(c) +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/departments/DepartmentsFields.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/departments/DepartmentsFields.kt new file mode 100644 index 0000000000..a13a440a09 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/departments/DepartmentsFields.kt @@ -0,0 +1,55 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.departments + +import dev.typr.dsl.FieldsBase +import dev.typr.dsl.Path +import dev.typr.dsl.SqlExpr.FieldLike +import dev.typr.dslkt.RelationStructure +import dev.typr.dslkt.SqlExpr +import dev.typr.dslkt.SqlExpr.Field +import dev.typr.dslkt.SqlExpr.IdField +import dev.typr.dslkt.SqlExpr.OptField +import dev.typr.dslkt.TupleExpr +import dev.typr.dslkt.TupleExpr4 +import dev.typr.foundations.RowCodec +import dev.typr.foundationskt.SqliteTypes +import java.math.BigDecimal +import kotlin.collections.List + +data class DepartmentsFields(val _path: List) : TupleExpr4, RelationStructure, FieldsBase { + override fun _1(): SqlExpr = deptCode() + + override fun _2(): SqlExpr = deptRegion() + + override fun _3(): SqlExpr = deptName() + + override fun _4(): SqlExpr = budget() + + override fun _path(): List = _path + + fun budget(): OptField = OptField(_path, "budget", DepartmentsRow::budget, null, null, { row, value -> row.copy(budget = value) }, SqliteTypes.numeric.underlying) + + override fun columns(): List> = listOf(this.deptCode().underlying, this.deptRegion().underlying, this.deptName().underlying, this.budget().underlying) + + fun compositeIdIn(compositeIds: List): SqlExpr = TupleExpr.of(deptCode(), deptRegion()).among(compositeIds) + + fun compositeIdIs(compositeId: DepartmentsId): SqlExpr = SqlExpr.all(deptCode().isEqual(compositeId.deptCode), deptRegion().isEqual(compositeId.deptRegion)) + + fun deptCode(): IdField = IdField(_path, "dept_code", DepartmentsRow::deptCode, null, null, { row, value -> row.copy(deptCode = value) }, SqliteTypes.varchar.underlying) + + fun deptName(): Field = Field(_path, "dept_name", DepartmentsRow::deptName, null, null, { row, value -> row.copy(deptName = value) }, SqliteTypes.text.underlying) + + fun deptRegion(): IdField = IdField(_path, "dept_region", DepartmentsRow::deptRegion, null, null, { row, value -> row.copy(deptRegion = value) }, SqliteTypes.varchar.underlying) + + override fun rowCodec(): RowCodec = DepartmentsRow.rowCodec.underlying + + override fun withPaths(_path: List): RelationStructure = DepartmentsFields(_path) + + companion object { + val structure: DepartmentsFields = DepartmentsFields(emptyList()) + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/departments/DepartmentsId.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/departments/DepartmentsId.kt new file mode 100644 index 0000000000..f3812ca350 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/departments/DepartmentsId.kt @@ -0,0 +1,26 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.departments + +import com.fasterxml.jackson.annotation.JsonProperty +import dev.typr.dslkt.RowCodecs +import dev.typr.foundations.Tuple.Tuple2 +import dev.typr.foundationskt.RowCodec +import dev.typr.foundationskt.SqliteTypes + +/** Type for the composite primary key of table `departments` */ +data class DepartmentsId( + @field:JsonProperty("dept_code") val deptCode: kotlin.String, + @field:JsonProperty("dept_region") val deptRegion: kotlin.String +) : Tuple2 { + override fun _1(): kotlin.String = deptCode + + override fun _2(): kotlin.String = deptRegion + + companion object { + val rowCodec: RowCodec = RowCodecs.of(SqliteTypes.varchar, SqliteTypes.varchar, { t0: kotlin.String, t1: kotlin.String -> DepartmentsId(t0, t1) }, { row: DepartmentsId -> arrayOf(row.deptCode, row.deptRegion) }) + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/departments/DepartmentsRepo.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/departments/DepartmentsRepo.kt new file mode 100644 index 0000000000..47ffbe813d --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/departments/DepartmentsRepo.kt @@ -0,0 +1,70 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.departments + +import dev.typr.dslkt.DeleteBuilder +import dev.typr.dslkt.SelectBuilder +import dev.typr.dslkt.UpdateBuilder +import dev.typr.foundationskt.Connection +import dev.typr.foundationskt.ConnectionRead +import kotlin.collections.Iterator +import kotlin.collections.List +import kotlin.collections.Map + +interface DepartmentsRepo { + abstract fun delete(): DeleteBuilder + + abstract fun deleteById( + compositeId: DepartmentsId, + c: Connection + ): kotlin.Boolean + + abstract fun deleteByIds( + compositeIds: List, + c: Connection + ): Int + + abstract fun insert( + unsaved: DepartmentsRow, + c: Connection + ): DepartmentsRow + + abstract fun select(): SelectBuilder + + abstract fun selectAll(c: ConnectionRead): List + + abstract fun selectById( + compositeId: DepartmentsId, + c: ConnectionRead + ): DepartmentsRow? + + abstract fun selectByIds( + compositeIds: List, + c: ConnectionRead + ): List + + abstract fun selectByIdsTracked( + compositeIds: List, + c: ConnectionRead + ): Map + + abstract fun update(): UpdateBuilder + + abstract fun update( + row: DepartmentsRow, + c: Connection + ): kotlin.Boolean + + abstract fun upsert( + unsaved: DepartmentsRow, + c: Connection + ): DepartmentsRow + + abstract fun upsertBatch( + unsaved: Iterator, + c: Connection + ): List +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/departments/DepartmentsRepoImpl.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/departments/DepartmentsRepoImpl.kt new file mode 100644 index 0000000000..d8652d6b48 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/departments/DepartmentsRepoImpl.kt @@ -0,0 +1,95 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.departments + +import dev.typr.dslkt.DeleteBuilder +import dev.typr.dslkt.Dialect +import dev.typr.dslkt.SelectBuilder +import dev.typr.dslkt.UpdateBuilder +import dev.typr.foundationskt.Connection +import dev.typr.foundationskt.ConnectionRead +import dev.typr.foundationskt.Fragment +import dev.typr.foundationskt.SqliteTypes +import java.util.ArrayList +import kotlin.collections.Iterator +import kotlin.collections.List +import kotlin.collections.Map +import kotlin.collections.MutableMap + +class DepartmentsRepoImpl() : DepartmentsRepo { + override fun delete(): DeleteBuilder = DeleteBuilder.of("\"departments\"", DepartmentsFields.structure, Dialect.SQLITE) + + override fun deleteById( + compositeId: DepartmentsId, + c: Connection + ): kotlin.Boolean = Fragment.concat(Fragment.of("delete from \"departments\" where \"dept_code\" = "), Fragment.encode(SqliteTypes.varchar, compositeId.deptCode), Fragment.of(" AND \"dept_region\" = "), Fragment.encode(SqliteTypes.varchar, compositeId.deptRegion), Fragment.of("")).update().run(c) > 0 + + override fun deleteByIds( + compositeIds: List, + c: Connection + ): Int { + val fragments: ArrayList = ArrayList() + for (id in compositeIds) { fragments.add(Fragment.concat(Fragment.of("("), Fragment.encode(SqliteTypes.varchar, id.deptCode), Fragment.of(", "), Fragment.encode(SqliteTypes.varchar, id.deptRegion), Fragment.of(")"))) } + return Fragment.concat(Fragment.of("delete from \"departments\" where (\"dept_code\", \"dept_region\") in ("), Fragment.comma(fragments.toMutableList()), Fragment.of(")")).update().run(c) + } + + override fun insert( + unsaved: DepartmentsRow, + c: Connection + ): DepartmentsRow = Fragment.concat(Fragment.of("insert into \"departments\"(\"dept_code\", \"dept_region\", \"dept_name\", \"budget\")\nvalues ("), Fragment.encode(SqliteTypes.varchar, unsaved.deptCode), Fragment.of(", "), Fragment.encode(SqliteTypes.varchar, unsaved.deptRegion), Fragment.of(", "), Fragment.encode(SqliteTypes.text, unsaved.deptName), Fragment.of(", "), Fragment.encode(SqliteTypes.numeric.opt(), unsaved.budget), Fragment.of(")\nRETURNING \"dept_code\", \"dept_region\", \"dept_name\", \"budget\"\n")) + .updateReturning(DepartmentsRow.rowCodec.exactlyOne()).run(c) + + override fun select(): SelectBuilder = SelectBuilder.of("\"departments\"", DepartmentsFields.structure, DepartmentsRow.rowCodec, Dialect.SQLITE) + + override fun selectAll(c: ConnectionRead): List = Fragment.concat(Fragment.of("select \"dept_code\", \"dept_region\", \"dept_name\", \"budget\"\nfrom \"departments\"\n")).query(DepartmentsRow.rowCodec.all()).run(c) + + override fun selectById( + compositeId: DepartmentsId, + c: ConnectionRead + ): DepartmentsRow? = Fragment.concat(Fragment.of("select \"dept_code\", \"dept_region\", \"dept_name\", \"budget\"\nfrom \"departments\"\nwhere \"dept_code\" = "), Fragment.encode(SqliteTypes.varchar, compositeId.deptCode), Fragment.of(" AND \"dept_region\" = "), Fragment.encode(SqliteTypes.varchar, compositeId.deptRegion), Fragment.of("")).query(DepartmentsRow.rowCodec.first()).run(c) + + override fun selectByIds( + compositeIds: List, + c: ConnectionRead + ): List { + val fragments: ArrayList = ArrayList() + for (id in compositeIds) { fragments.add(Fragment.concat(Fragment.of("("), Fragment.encode(SqliteTypes.varchar, id.deptCode), Fragment.of(", "), Fragment.encode(SqliteTypes.varchar, id.deptRegion), Fragment.of(")"))) } + return Fragment.concat(Fragment.of("select \"dept_code\", \"dept_region\", \"dept_name\", \"budget\" from \"departments\" where (\"dept_code\", \"dept_region\") in ("), Fragment.comma(fragments.toMutableList()), Fragment.of(")")).query(DepartmentsRow.rowCodec.all()).run(c) + } + + override fun selectByIdsTracked( + compositeIds: List, + c: ConnectionRead + ): Map { + val ret: MutableMap = mutableMapOf() + selectByIds(compositeIds, c).forEach({ row -> ret.put(row.compositeId(), row) }) + return ret.toMap() + } + + override fun update(): UpdateBuilder = UpdateBuilder.of("\"departments\"", DepartmentsFields.structure, DepartmentsRow.rowCodec, Dialect.SQLITE) + + override fun update( + row: DepartmentsRow, + c: Connection + ): kotlin.Boolean { + val compositeId: DepartmentsId = row.compositeId() + return Fragment.concat(Fragment.of("update \"departments\"\nset \"dept_name\" = "), Fragment.encode(SqliteTypes.text, row.deptName), Fragment.of(",\n\"budget\" = "), Fragment.encode(SqliteTypes.numeric.opt(), row.budget), Fragment.of("\nwhere \"dept_code\" = "), Fragment.encode(SqliteTypes.varchar, compositeId.deptCode), Fragment.of(" AND \"dept_region\" = "), Fragment.encode(SqliteTypes.varchar, compositeId.deptRegion), Fragment.of("")).update().run(c) > 0 + } + + override fun upsert( + unsaved: DepartmentsRow, + c: Connection + ): DepartmentsRow = Fragment.concat(Fragment.of("INSERT INTO \"departments\"(\"dept_code\", \"dept_region\", \"dept_name\", \"budget\")\nVALUES ("), Fragment.encode(SqliteTypes.varchar, unsaved.deptCode), Fragment.of(", "), Fragment.encode(SqliteTypes.varchar, unsaved.deptRegion), Fragment.of(", "), Fragment.encode(SqliteTypes.text, unsaved.deptName), Fragment.of(", "), Fragment.encode(SqliteTypes.numeric.opt(), unsaved.budget), Fragment.of(")\nON CONFLICT (\"dept_code\", \"dept_region\")\nDO UPDATE SET\n \"dept_name\" = EXCLUDED.\"dept_name\",\n\"budget\" = EXCLUDED.\"budget\"\nRETURNING \"dept_code\", \"dept_region\", \"dept_name\", \"budget\"")) + .updateReturning(DepartmentsRow.rowCodec.exactlyOne()) + .run(c) + + override fun upsertBatch( + unsaved: Iterator, + c: Connection + ): List = Fragment.concat(Fragment.of("INSERT INTO \"departments\"(\"dept_code\", \"dept_region\", \"dept_name\", \"budget\")\nVALUES (?, ?, ?, ?)\nON CONFLICT (\"dept_code\", \"dept_region\")\nDO UPDATE SET\n \"dept_name\" = EXCLUDED.\"dept_name\",\n\"budget\" = EXCLUDED.\"budget\"\nRETURNING \"dept_code\", \"dept_region\", \"dept_name\", \"budget\"")) + .updateReturningEach(DepartmentsRow.rowCodec, unsaved) + .run(c) +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/departments/DepartmentsRepoMock.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/departments/DepartmentsRepoMock.kt new file mode 100644 index 0000000000..e233331865 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/departments/DepartmentsRepoMock.kt @@ -0,0 +1,119 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.departments + +import dev.typr.dslkt.DeleteBuilder +import dev.typr.dslkt.DeleteBuilderMock +import dev.typr.dslkt.DeleteParams +import dev.typr.dslkt.SelectBuilder +import dev.typr.dslkt.SelectBuilderMock +import dev.typr.dslkt.SelectParams +import dev.typr.dslkt.UpdateBuilder +import dev.typr.dslkt.UpdateBuilderMock +import dev.typr.dslkt.UpdateParams +import dev.typr.foundationskt.Connection +import dev.typr.foundationskt.ConnectionRead +import java.lang.RuntimeException +import java.util.ArrayList +import kotlin.collections.Iterator +import kotlin.collections.List +import kotlin.collections.Map +import kotlin.collections.MutableMap + +data class DepartmentsRepoMock(val map: MutableMap = mutableMapOf()) : DepartmentsRepo { + override fun delete(): DeleteBuilder = DeleteBuilderMock(DepartmentsFields.structure, { map.values.toList() }, DeleteParams.empty(), { row -> row.compositeId() }, { id -> map.remove(id) }) + + override fun deleteById( + compositeId: DepartmentsId, + c: Connection + ): kotlin.Boolean = map.remove(compositeId) != null + + override fun deleteByIds( + compositeIds: List, + c: Connection + ): Int { + var count = 0 + for (id in compositeIds) { + if (map.remove(id) != null) { + count = count + 1 + } + } + return count + } + + override fun insert( + unsaved: DepartmentsRow, + c: Connection + ): DepartmentsRow { + if (map.containsKey(unsaved.compositeId())) { + throw RuntimeException("id " + unsaved.compositeId() + " already exists") + } + map[unsaved.compositeId()] = unsaved + return unsaved + } + + override fun select(): SelectBuilder = SelectBuilderMock(DepartmentsFields.structure, { map.values.toList() }, SelectParams.empty()) + + override fun selectAll(c: ConnectionRead): List = map.values.toList() + + override fun selectById( + compositeId: DepartmentsId, + c: ConnectionRead + ): DepartmentsRow? = map[compositeId] + + override fun selectByIds( + compositeIds: List, + c: ConnectionRead + ): List { + val result = ArrayList() + for (id in compositeIds) { + val opt = map[id] + if (opt != null) { + result.add(opt) + } + } + return result + } + + override fun selectByIdsTracked( + compositeIds: List, + c: ConnectionRead + ): Map = selectByIds(compositeIds, c).associateBy({ row: DepartmentsRow -> row.compositeId() }) + + override fun update(): UpdateBuilder = UpdateBuilderMock(DepartmentsFields.structure, { map.values.toList() }, UpdateParams.empty(), { row -> row }) + + override fun update( + row: DepartmentsRow, + c: Connection + ): kotlin.Boolean { + val shouldUpdate = map[row.compositeId()]?.takeIf({ oldRow -> (oldRow != row) }) != null + if (shouldUpdate) { + map[row.compositeId()] = row + } + return shouldUpdate + } + + override fun upsert( + unsaved: DepartmentsRow, + c: Connection + ): DepartmentsRow { + map[unsaved.compositeId()] = unsaved + return unsaved + } + + override fun upsertBatch( + unsaved: Iterator, + c: Connection + ): List { + val result = ArrayList() + while (unsaved.hasNext()) { + val row = unsaved.next() + map[row.compositeId()] = row + result.add(row) + } + return result + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/departments/DepartmentsRow.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/departments/DepartmentsRow.kt new file mode 100644 index 0000000000..e162ee3a44 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/departments/DepartmentsRow.kt @@ -0,0 +1,45 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.departments + +import com.fasterxml.jackson.annotation.JsonProperty +import dev.typr.dslkt.RowCodecs +import dev.typr.foundations.Tuple.Tuple4 +import dev.typr.foundationskt.RowCodec +import dev.typr.foundationskt.SqliteTypes +import java.math.BigDecimal + +/** Table: departments + * Composite primary key: dept_code, dept_region + */ +data class DepartmentsRow( + @field:JsonProperty("dept_code") val deptCode: kotlin.String, + @field:JsonProperty("dept_region") val deptRegion: kotlin.String, + @field:JsonProperty("dept_name") val deptName: kotlin.String, + val budget: BigDecimal? +) : Tuple4 { + override fun _1(): kotlin.String = deptCode + + override fun _2(): kotlin.String = deptRegion + + override fun _3(): kotlin.String = deptName + + override fun _4(): BigDecimal? = budget + + fun compositeId(): DepartmentsId = DepartmentsId(deptCode, deptRegion) + + fun id(): DepartmentsId = this.compositeId() + + companion object { + val rowCodec: RowCodec = RowCodecs.of(SqliteTypes.varchar, SqliteTypes.varchar, SqliteTypes.text, SqliteTypes.numeric.opt(), { t0: kotlin.String, t1: kotlin.String, t2: kotlin.String, t3: BigDecimal? -> DepartmentsRow(t0, t1, t2, t3) }, { row: DepartmentsRow -> arrayOf(row.deptCode, row.deptRegion, row.deptName, row.budget) }) + + fun apply( + compositeId: DepartmentsId, + deptName: kotlin.String, + budget: BigDecimal? + ): DepartmentsRow = DepartmentsRow(compositeId.deptCode, compositeId.deptRegion, deptName, budget) + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/employees/EmployeesFields.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/employees/EmployeesFields.kt new file mode 100644 index 0000000000..cde33c5823 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/employees/EmployeesFields.kt @@ -0,0 +1,78 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.employees + +import dev.typr.dsl.FieldsBase +import dev.typr.dsl.Path +import dev.typr.dsl.SqlExpr.FieldLike +import dev.typr.dslkt.ForeignKey +import dev.typr.dslkt.RelationStructure +import dev.typr.dslkt.SqlExpr +import dev.typr.dslkt.SqlExpr.Field +import dev.typr.dslkt.SqlExpr.IdField +import dev.typr.dslkt.SqlExpr.OptField +import dev.typr.dslkt.TupleExpr +import dev.typr.dslkt.TupleExpr7 +import dev.typr.foundations.RowCodec +import dev.typr.foundationskt.SqliteTypes +import java.math.BigDecimal +import java.time.LocalDate +import kotlin.collections.List +import testdb.departments.DepartmentsFields +import testdb.departments.DepartmentsId +import testdb.departments.DepartmentsRow + +data class EmployeesFields(val _path: List) : TupleExpr7, RelationStructure, FieldsBase { + override fun _1(): SqlExpr = empNumber() + + override fun _2(): SqlExpr = empSuffix() + + override fun _3(): SqlExpr = deptCode() + + override fun _4(): SqlExpr = deptRegion() + + override fun _5(): SqlExpr = empName() + + override fun _6(): SqlExpr = salary() + + override fun _7(): SqlExpr = hireDate() + + override fun _path(): List = _path + + override fun columns(): List> = listOf(this.empNumber().underlying, this.empSuffix().underlying, this.deptCode().underlying, this.deptRegion().underlying, this.empName().underlying, this.salary().underlying, this.hireDate().underlying) + + fun compositeIdIn(compositeIds: List): SqlExpr = TupleExpr.of(empNumber(), empSuffix()).among(compositeIds) + + fun compositeIdIs(compositeId: EmployeesId): SqlExpr = SqlExpr.all(empNumber().isEqual(compositeId.empNumber), empSuffix().isEqual(compositeId.empSuffix)) + + fun deptCode(): Field = Field(_path, "dept_code", EmployeesRow::deptCode, null, null, { row, value -> row.copy(deptCode = value) }, SqliteTypes.varchar.underlying) + + fun deptRegion(): Field = Field(_path, "dept_region", EmployeesRow::deptRegion, null, null, { row, value -> row.copy(deptRegion = value) }, SqliteTypes.varchar.underlying) + + fun empName(): Field = Field(_path, "emp_name", EmployeesRow::empName, null, null, { row, value -> row.copy(empName = value) }, SqliteTypes.text.underlying) + + fun empNumber(): IdField = IdField(_path, "emp_number", EmployeesRow::empNumber, null, null, { row, value -> row.copy(empNumber = value) }, SqliteTypes.integer.underlying) + + fun empSuffix(): IdField = IdField(_path, "emp_suffix", EmployeesRow::empSuffix, null, null, { row, value -> row.copy(empSuffix = value) }, SqliteTypes.varchar.underlying) + + fun extractIdentDepartmentsIdIn(ids: List): SqlExpr = TupleExpr.of(deptCode(), deptRegion()).among(ids) + + fun extractIdentDepartmentsIdIs(id: DepartmentsId): SqlExpr = SqlExpr.all(deptCode().isEqual(id.deptCode), deptRegion().isEqual(id.deptRegion)) + + fun fkDepartments(): ForeignKey = ForeignKey.of("employees_fk_0").withColumnPair(deptCode(), DepartmentsFields::deptCode).withColumnPair(deptRegion(), DepartmentsFields::deptRegion) + + fun hireDate(): Field = Field(_path, "hire_date", EmployeesRow::hireDate, null, null, { row, value -> row.copy(hireDate = value) }, SqliteTypes.date.underlying) + + override fun rowCodec(): RowCodec = EmployeesRow.rowCodec.underlying + + fun salary(): OptField = OptField(_path, "salary", EmployeesRow::salary, null, null, { row, value -> row.copy(salary = value) }, SqliteTypes.numeric.underlying) + + override fun withPaths(_path: List): RelationStructure = EmployeesFields(_path) + + companion object { + val structure: EmployeesFields = EmployeesFields(emptyList()) + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/employees/EmployeesId.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/employees/EmployeesId.kt new file mode 100644 index 0000000000..cbd9cf1222 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/employees/EmployeesId.kt @@ -0,0 +1,26 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.employees + +import com.fasterxml.jackson.annotation.JsonProperty +import dev.typr.dslkt.RowCodecs +import dev.typr.foundations.Tuple.Tuple2 +import dev.typr.foundationskt.RowCodec +import dev.typr.foundationskt.SqliteTypes + +/** Type for the composite primary key of table `employees` */ +data class EmployeesId( + @field:JsonProperty("emp_number") val empNumber: kotlin.Long, + @field:JsonProperty("emp_suffix") val empSuffix: kotlin.String +) : Tuple2 { + override fun _1(): kotlin.Long = empNumber + + override fun _2(): kotlin.String = empSuffix + + companion object { + val rowCodec: RowCodec = RowCodecs.of(SqliteTypes.integer, SqliteTypes.varchar, { t0: kotlin.Long, t1: kotlin.String -> EmployeesId(t0, t1) }, { row: EmployeesId -> arrayOf(row.empNumber, row.empSuffix) }) + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/employees/EmployeesRepo.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/employees/EmployeesRepo.kt new file mode 100644 index 0000000000..fb5da1fc10 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/employees/EmployeesRepo.kt @@ -0,0 +1,75 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.employees + +import dev.typr.dslkt.DeleteBuilder +import dev.typr.dslkt.SelectBuilder +import dev.typr.dslkt.UpdateBuilder +import dev.typr.foundationskt.Connection +import dev.typr.foundationskt.ConnectionRead +import kotlin.collections.Iterator +import kotlin.collections.List +import kotlin.collections.Map + +interface EmployeesRepo { + abstract fun delete(): DeleteBuilder + + abstract fun deleteById( + compositeId: EmployeesId, + c: Connection + ): kotlin.Boolean + + abstract fun deleteByIds( + compositeIds: List, + c: Connection + ): Int + + abstract fun insert( + unsaved: EmployeesRow, + c: Connection + ): EmployeesRow + + abstract fun insert( + unsaved: EmployeesRowUnsaved, + c: Connection + ): EmployeesRow + + abstract fun select(): SelectBuilder + + abstract fun selectAll(c: ConnectionRead): List + + abstract fun selectById( + compositeId: EmployeesId, + c: ConnectionRead + ): EmployeesRow? + + abstract fun selectByIds( + compositeIds: List, + c: ConnectionRead + ): List + + abstract fun selectByIdsTracked( + compositeIds: List, + c: ConnectionRead + ): Map + + abstract fun update(): UpdateBuilder + + abstract fun update( + row: EmployeesRow, + c: Connection + ): kotlin.Boolean + + abstract fun upsert( + unsaved: EmployeesRow, + c: Connection + ): EmployeesRow + + abstract fun upsertBatch( + unsaved: Iterator, + c: Connection + ): List +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/employees/EmployeesRepoImpl.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/employees/EmployeesRepoImpl.kt new file mode 100644 index 0000000000..dfe15321bb --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/employees/EmployeesRepoImpl.kt @@ -0,0 +1,122 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.employees + +import dev.typr.dslkt.DeleteBuilder +import dev.typr.dslkt.Dialect +import dev.typr.dslkt.SelectBuilder +import dev.typr.dslkt.UpdateBuilder +import dev.typr.foundationskt.Connection +import dev.typr.foundationskt.ConnectionRead +import dev.typr.foundationskt.Fragment +import dev.typr.foundationskt.SqliteTypes +import java.util.ArrayList +import kotlin.collections.Iterator +import kotlin.collections.List +import kotlin.collections.Map +import kotlin.collections.MutableMap + +class EmployeesRepoImpl() : EmployeesRepo { + override fun delete(): DeleteBuilder = DeleteBuilder.of("\"employees\"", EmployeesFields.structure, Dialect.SQLITE) + + override fun deleteById( + compositeId: EmployeesId, + c: Connection + ): kotlin.Boolean = Fragment.concat(Fragment.of("delete from \"employees\" where \"emp_number\" = "), Fragment.encode(SqliteTypes.integer, compositeId.empNumber), Fragment.of(" AND \"emp_suffix\" = "), Fragment.encode(SqliteTypes.varchar, compositeId.empSuffix), Fragment.of("")).update().run(c) > 0 + + override fun deleteByIds( + compositeIds: List, + c: Connection + ): Int { + val fragments: ArrayList = ArrayList() + for (id in compositeIds) { fragments.add(Fragment.concat(Fragment.of("("), Fragment.encode(SqliteTypes.integer, id.empNumber), Fragment.of(", "), Fragment.encode(SqliteTypes.varchar, id.empSuffix), Fragment.of(")"))) } + return Fragment.concat(Fragment.of("delete from \"employees\" where (\"emp_number\", \"emp_suffix\") in ("), Fragment.comma(fragments.toMutableList()), Fragment.of(")")).update().run(c) + } + + override fun insert( + unsaved: EmployeesRow, + c: Connection + ): EmployeesRow = Fragment.concat(Fragment.of("insert into \"employees\"(\"emp_number\", \"emp_suffix\", \"dept_code\", \"dept_region\", \"emp_name\", \"salary\", \"hire_date\")\nvalues ("), Fragment.encode(SqliteTypes.integer, unsaved.empNumber), Fragment.of(", "), Fragment.encode(SqliteTypes.varchar, unsaved.empSuffix), Fragment.of(", "), Fragment.encode(SqliteTypes.varchar, unsaved.deptCode), Fragment.of(", "), Fragment.encode(SqliteTypes.varchar, unsaved.deptRegion), Fragment.of(", "), Fragment.encode(SqliteTypes.text, unsaved.empName), Fragment.of(", "), Fragment.encode(SqliteTypes.numeric.opt(), unsaved.salary), Fragment.of(", "), Fragment.encode(SqliteTypes.date, unsaved.hireDate), Fragment.of(")\nRETURNING \"emp_number\", \"emp_suffix\", \"dept_code\", \"dept_region\", \"emp_name\", \"salary\", \"hire_date\"\n")) + .updateReturning(EmployeesRow.rowCodec.exactlyOne()).run(c) + + override fun insert( + unsaved: EmployeesRowUnsaved, + c: Connection + ): EmployeesRow { + val columns: ArrayList = ArrayList() + val values: ArrayList = ArrayList() + columns.add(Fragment.of("\"emp_number\"")) + values.add(Fragment.concat(Fragment.encode(SqliteTypes.integer, unsaved.empNumber), Fragment.of(""))) + columns.add(Fragment.of("\"emp_suffix\"")) + values.add(Fragment.concat(Fragment.encode(SqliteTypes.varchar, unsaved.empSuffix), Fragment.of(""))) + columns.add(Fragment.of("\"dept_code\"")) + values.add(Fragment.concat(Fragment.encode(SqliteTypes.varchar, unsaved.deptCode), Fragment.of(""))) + columns.add(Fragment.of("\"dept_region\"")) + values.add(Fragment.concat(Fragment.encode(SqliteTypes.varchar, unsaved.deptRegion), Fragment.of(""))) + columns.add(Fragment.of("\"emp_name\"")) + values.add(Fragment.concat(Fragment.encode(SqliteTypes.text, unsaved.empName), Fragment.of(""))) + columns.add(Fragment.of("\"salary\"")) + values.add(Fragment.concat(Fragment.encode(SqliteTypes.numeric.opt(), unsaved.salary), Fragment.of(""))) + unsaved.hireDate.visit( + { }, + { value -> columns.add(Fragment.of("\"hire_date\"")) + values.add(Fragment.concat(Fragment.encode(SqliteTypes.date, value), Fragment.of(""))) } + ); + val q: Fragment = Fragment.concat(Fragment.of("insert into \"employees\"("), Fragment.comma(columns.toMutableList()), Fragment.of(")\nvalues ("), Fragment.comma(values.toMutableList()), Fragment.of(")\nRETURNING \"emp_number\", \"emp_suffix\", \"dept_code\", \"dept_region\", \"emp_name\", \"salary\", \"hire_date\"\n")) + return q.updateReturning(EmployeesRow.rowCodec.exactlyOne()).run(c) + } + + override fun select(): SelectBuilder = SelectBuilder.of("\"employees\"", EmployeesFields.structure, EmployeesRow.rowCodec, Dialect.SQLITE) + + override fun selectAll(c: ConnectionRead): List = Fragment.concat(Fragment.of("select \"emp_number\", \"emp_suffix\", \"dept_code\", \"dept_region\", \"emp_name\", \"salary\", \"hire_date\"\nfrom \"employees\"\n")).query(EmployeesRow.rowCodec.all()).run(c) + + override fun selectById( + compositeId: EmployeesId, + c: ConnectionRead + ): EmployeesRow? = Fragment.concat(Fragment.of("select \"emp_number\", \"emp_suffix\", \"dept_code\", \"dept_region\", \"emp_name\", \"salary\", \"hire_date\"\nfrom \"employees\"\nwhere \"emp_number\" = "), Fragment.encode(SqliteTypes.integer, compositeId.empNumber), Fragment.of(" AND \"emp_suffix\" = "), Fragment.encode(SqliteTypes.varchar, compositeId.empSuffix), Fragment.of("")).query(EmployeesRow.rowCodec.first()).run(c) + + override fun selectByIds( + compositeIds: List, + c: ConnectionRead + ): List { + val fragments: ArrayList = ArrayList() + for (id in compositeIds) { fragments.add(Fragment.concat(Fragment.of("("), Fragment.encode(SqliteTypes.integer, id.empNumber), Fragment.of(", "), Fragment.encode(SqliteTypes.varchar, id.empSuffix), Fragment.of(")"))) } + return Fragment.concat(Fragment.of("select \"emp_number\", \"emp_suffix\", \"dept_code\", \"dept_region\", \"emp_name\", \"salary\", \"hire_date\" from \"employees\" where (\"emp_number\", \"emp_suffix\") in ("), Fragment.comma(fragments.toMutableList()), Fragment.of(")")).query(EmployeesRow.rowCodec.all()).run(c) + } + + override fun selectByIdsTracked( + compositeIds: List, + c: ConnectionRead + ): Map { + val ret: MutableMap = mutableMapOf() + selectByIds(compositeIds, c).forEach({ row -> ret.put(row.compositeId(), row) }) + return ret.toMap() + } + + override fun update(): UpdateBuilder = UpdateBuilder.of("\"employees\"", EmployeesFields.structure, EmployeesRow.rowCodec, Dialect.SQLITE) + + override fun update( + row: EmployeesRow, + c: Connection + ): kotlin.Boolean { + val compositeId: EmployeesId = row.compositeId() + return Fragment.concat(Fragment.of("update \"employees\"\nset \"dept_code\" = "), Fragment.encode(SqliteTypes.varchar, row.deptCode), Fragment.of(",\n\"dept_region\" = "), Fragment.encode(SqliteTypes.varchar, row.deptRegion), Fragment.of(",\n\"emp_name\" = "), Fragment.encode(SqliteTypes.text, row.empName), Fragment.of(",\n\"salary\" = "), Fragment.encode(SqliteTypes.numeric.opt(), row.salary), Fragment.of(",\n\"hire_date\" = "), Fragment.encode(SqliteTypes.date, row.hireDate), Fragment.of("\nwhere \"emp_number\" = "), Fragment.encode(SqliteTypes.integer, compositeId.empNumber), Fragment.of(" AND \"emp_suffix\" = "), Fragment.encode(SqliteTypes.varchar, compositeId.empSuffix), Fragment.of("")).update().run(c) > 0 + } + + override fun upsert( + unsaved: EmployeesRow, + c: Connection + ): EmployeesRow = Fragment.concat(Fragment.of("INSERT INTO \"employees\"(\"emp_number\", \"emp_suffix\", \"dept_code\", \"dept_region\", \"emp_name\", \"salary\", \"hire_date\")\nVALUES ("), Fragment.encode(SqliteTypes.integer, unsaved.empNumber), Fragment.of(", "), Fragment.encode(SqliteTypes.varchar, unsaved.empSuffix), Fragment.of(", "), Fragment.encode(SqliteTypes.varchar, unsaved.deptCode), Fragment.of(", "), Fragment.encode(SqliteTypes.varchar, unsaved.deptRegion), Fragment.of(", "), Fragment.encode(SqliteTypes.text, unsaved.empName), Fragment.of(", "), Fragment.encode(SqliteTypes.numeric.opt(), unsaved.salary), Fragment.of(", "), Fragment.encode(SqliteTypes.date, unsaved.hireDate), Fragment.of(")\nON CONFLICT (\"emp_number\", \"emp_suffix\")\nDO UPDATE SET\n \"dept_code\" = EXCLUDED.\"dept_code\",\n\"dept_region\" = EXCLUDED.\"dept_region\",\n\"emp_name\" = EXCLUDED.\"emp_name\",\n\"salary\" = EXCLUDED.\"salary\",\n\"hire_date\" = EXCLUDED.\"hire_date\"\nRETURNING \"emp_number\", \"emp_suffix\", \"dept_code\", \"dept_region\", \"emp_name\", \"salary\", \"hire_date\"")) + .updateReturning(EmployeesRow.rowCodec.exactlyOne()) + .run(c) + + override fun upsertBatch( + unsaved: Iterator, + c: Connection + ): List = Fragment.concat(Fragment.of("INSERT INTO \"employees\"(\"emp_number\", \"emp_suffix\", \"dept_code\", \"dept_region\", \"emp_name\", \"salary\", \"hire_date\")\nVALUES (?, ?, ?, ?, ?, ?, ?)\nON CONFLICT (\"emp_number\", \"emp_suffix\")\nDO UPDATE SET\n \"dept_code\" = EXCLUDED.\"dept_code\",\n\"dept_region\" = EXCLUDED.\"dept_region\",\n\"emp_name\" = EXCLUDED.\"emp_name\",\n\"salary\" = EXCLUDED.\"salary\",\n\"hire_date\" = EXCLUDED.\"hire_date\"\nRETURNING \"emp_number\", \"emp_suffix\", \"dept_code\", \"dept_region\", \"emp_name\", \"salary\", \"hire_date\"")) + .updateReturningEach(EmployeesRow.rowCodec, unsaved) + .run(c) +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/employees/EmployeesRepoMock.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/employees/EmployeesRepoMock.kt new file mode 100644 index 0000000000..55532862cd --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/employees/EmployeesRepoMock.kt @@ -0,0 +1,127 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.employees + +import dev.typr.dslkt.DeleteBuilder +import dev.typr.dslkt.DeleteBuilderMock +import dev.typr.dslkt.DeleteParams +import dev.typr.dslkt.SelectBuilder +import dev.typr.dslkt.SelectBuilderMock +import dev.typr.dslkt.SelectParams +import dev.typr.dslkt.UpdateBuilder +import dev.typr.dslkt.UpdateBuilderMock +import dev.typr.dslkt.UpdateParams +import dev.typr.foundationskt.Connection +import dev.typr.foundationskt.ConnectionRead +import java.lang.RuntimeException +import java.util.ArrayList +import kotlin.collections.Iterator +import kotlin.collections.List +import kotlin.collections.Map +import kotlin.collections.MutableMap + +data class EmployeesRepoMock( + val toRow: (EmployeesRowUnsaved) -> EmployeesRow, + val map: MutableMap = mutableMapOf() +) : EmployeesRepo { + override fun delete(): DeleteBuilder = DeleteBuilderMock(EmployeesFields.structure, { map.values.toList() }, DeleteParams.empty(), { row -> row.compositeId() }, { id -> map.remove(id) }) + + override fun deleteById( + compositeId: EmployeesId, + c: Connection + ): kotlin.Boolean = map.remove(compositeId) != null + + override fun deleteByIds( + compositeIds: List, + c: Connection + ): Int { + var count = 0 + for (id in compositeIds) { + if (map.remove(id) != null) { + count = count + 1 + } + } + return count + } + + override fun insert( + unsaved: EmployeesRow, + c: Connection + ): EmployeesRow { + if (map.containsKey(unsaved.compositeId())) { + throw RuntimeException("id " + unsaved.compositeId() + " already exists") + } + map[unsaved.compositeId()] = unsaved + return unsaved + } + + override fun insert( + unsaved: EmployeesRowUnsaved, + c: Connection + ): EmployeesRow = insert(toRow(unsaved), c) + + override fun select(): SelectBuilder = SelectBuilderMock(EmployeesFields.structure, { map.values.toList() }, SelectParams.empty()) + + override fun selectAll(c: ConnectionRead): List = map.values.toList() + + override fun selectById( + compositeId: EmployeesId, + c: ConnectionRead + ): EmployeesRow? = map[compositeId] + + override fun selectByIds( + compositeIds: List, + c: ConnectionRead + ): List { + val result = ArrayList() + for (id in compositeIds) { + val opt = map[id] + if (opt != null) { + result.add(opt) + } + } + return result + } + + override fun selectByIdsTracked( + compositeIds: List, + c: ConnectionRead + ): Map = selectByIds(compositeIds, c).associateBy({ row: EmployeesRow -> row.compositeId() }) + + override fun update(): UpdateBuilder = UpdateBuilderMock(EmployeesFields.structure, { map.values.toList() }, UpdateParams.empty(), { row -> row }) + + override fun update( + row: EmployeesRow, + c: Connection + ): kotlin.Boolean { + val shouldUpdate = map[row.compositeId()]?.takeIf({ oldRow -> (oldRow != row) }) != null + if (shouldUpdate) { + map[row.compositeId()] = row + } + return shouldUpdate + } + + override fun upsert( + unsaved: EmployeesRow, + c: Connection + ): EmployeesRow { + map[unsaved.compositeId()] = unsaved + return unsaved + } + + override fun upsertBatch( + unsaved: Iterator, + c: Connection + ): List { + val result = ArrayList() + while (unsaved.hasNext()) { + val row = unsaved.next() + map[row.compositeId()] = row + result.add(row) + } + return result + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/employees/EmployeesRow.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/employees/EmployeesRow.kt new file mode 100644 index 0000000000..d6aeb66f91 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/employees/EmployeesRow.kt @@ -0,0 +1,67 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.employees + +import com.fasterxml.jackson.annotation.JsonProperty +import dev.typr.dslkt.RowCodecs +import dev.typr.foundations.Tuple.Tuple7 +import dev.typr.foundationskt.RowCodec +import dev.typr.foundationskt.SqliteTypes +import java.math.BigDecimal +import java.time.LocalDate +import testdb.customtypes.Defaulted +import testdb.departments.DepartmentsId + +/** Table: employees + * Composite primary key: emp_number, emp_suffix + */ +data class EmployeesRow( + @field:JsonProperty("emp_number") val empNumber: kotlin.Long, + @field:JsonProperty("emp_suffix") val empSuffix: kotlin.String, + /** Points to [testdb.departments.DepartmentsRow.deptCode] */ + @field:JsonProperty("dept_code") val deptCode: kotlin.String, + /** Points to [testdb.departments.DepartmentsRow.deptRegion] */ + @field:JsonProperty("dept_region") val deptRegion: kotlin.String, + @field:JsonProperty("emp_name") val empName: kotlin.String, + val salary: BigDecimal?, + /** Default: CURRENT_DATE */ + @field:JsonProperty("hire_date") val hireDate: LocalDate +) : Tuple7 { + override fun _1(): kotlin.Long = empNumber + + override fun _2(): kotlin.String = empSuffix + + override fun _3(): kotlin.String = deptCode + + override fun _4(): kotlin.String = deptRegion + + override fun _5(): kotlin.String = empName + + override fun _6(): BigDecimal? = salary + + override fun _7(): LocalDate = hireDate + + fun compositeId(): EmployeesId = EmployeesId(empNumber, empSuffix) + + fun extractDepartmentsId(): DepartmentsId = DepartmentsId(deptCode = deptCode, deptRegion = deptRegion) + + fun id(): EmployeesId = this.compositeId() + + fun toUnsavedRow(hireDate: Defaulted = Defaulted.Provided(this.hireDate)): EmployeesRowUnsaved = EmployeesRowUnsaved(empNumber, empSuffix, deptCode, deptRegion, empName, salary, hireDate) + + companion object { + val rowCodec: RowCodec = RowCodecs.of(SqliteTypes.integer, SqliteTypes.varchar, SqliteTypes.varchar, SqliteTypes.varchar, SqliteTypes.text, SqliteTypes.numeric.opt(), SqliteTypes.date, { t0: kotlin.Long, t1: kotlin.String, t2: kotlin.String, t3: kotlin.String, t4: kotlin.String, t5: BigDecimal?, t6: LocalDate -> EmployeesRow(t0, t1, t2, t3, t4, t5, t6) }, { row: EmployeesRow -> arrayOf(row.empNumber, row.empSuffix, row.deptCode, row.deptRegion, row.empName, row.salary, row.hireDate) }) + + fun apply( + compositeId: EmployeesId, + deptCode: kotlin.String, + deptRegion: kotlin.String, + empName: kotlin.String, + salary: BigDecimal?, + hireDate: LocalDate + ): EmployeesRow = EmployeesRow(compositeId.empNumber, compositeId.empSuffix, deptCode, deptRegion, empName, salary, hireDate) + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/employees/EmployeesRowUnsaved.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/employees/EmployeesRowUnsaved.kt new file mode 100644 index 0000000000..37d3ff4eb1 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/employees/EmployeesRowUnsaved.kt @@ -0,0 +1,28 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.employees + +import com.fasterxml.jackson.annotation.JsonProperty +import java.math.BigDecimal +import java.time.LocalDate +import testdb.customtypes.Defaulted +import testdb.customtypes.Defaulted.UseDefault + +/** This class corresponds to a row in table `employees` which has not been persisted yet */ +data class EmployeesRowUnsaved( + @field:JsonProperty("emp_number") val empNumber: kotlin.Long, + @field:JsonProperty("emp_suffix") val empSuffix: kotlin.String, + /** Points to [testdb.departments.DepartmentsRow.deptCode] */ + @field:JsonProperty("dept_code") val deptCode: kotlin.String, + /** Points to [testdb.departments.DepartmentsRow.deptRegion] */ + @field:JsonProperty("dept_region") val deptRegion: kotlin.String, + @field:JsonProperty("emp_name") val empName: kotlin.String, + val salary: BigDecimal? = null, + /** Default: CURRENT_DATE */ + @field:JsonProperty("hire_date") val hireDate: Defaulted = UseDefault() +) { + fun toRow(hireDateDefault: () -> LocalDate): EmployeesRow = EmployeesRow(empNumber = empNumber, empSuffix = empSuffix, deptCode = deptCode, deptRegion = deptRegion, empName = empName, salary = salary, hireDate = hireDate.getOrElse(hireDateDefault)) +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/order_details/OrderDetailsViewFields.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/order_details/OrderDetailsViewFields.kt new file mode 100644 index 0000000000..dbcd013d4b --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/order_details/OrderDetailsViewFields.kt @@ -0,0 +1,62 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.order_details + +import dev.typr.dsl.FieldsBase +import dev.typr.dsl.Path +import dev.typr.dsl.SqlExpr.FieldLike +import dev.typr.dslkt.RelationStructure +import dev.typr.dslkt.SqlExpr +import dev.typr.dslkt.SqlExpr.OptField +import dev.typr.dslkt.TupleExpr7 +import dev.typr.foundations.RowCodec +import dev.typr.foundationskt.SqliteTypes +import java.math.BigDecimal +import java.time.LocalDate +import kotlin.collections.List +import testdb.orders.OrdersId + +data class OrderDetailsViewFields(val _path: List) : TupleExpr7, RelationStructure, FieldsBase { + override fun _1(): SqlExpr = orderId() + + override fun _2(): SqlExpr = orderDate() + + override fun _3(): SqlExpr = customerName() + + override fun _4(): SqlExpr = productName() + + override fun _5(): SqlExpr = quantity() + + override fun _6(): SqlExpr = unitPrice() + + override fun _7(): SqlExpr = lineTotal() + + override fun _path(): List = _path + + override fun columns(): List> = listOf(this.orderId().underlying, this.orderDate().underlying, this.customerName().underlying, this.productName().underlying, this.quantity().underlying, this.unitPrice().underlying, this.lineTotal().underlying) + + fun customerName(): OptField = OptField(_path, "customer_name", OrderDetailsViewRow::customerName, null, null, { row, value -> row.copy(customerName = value) }, SqliteTypes.text.underlying) + + fun lineTotal(): OptField = OptField(_path, "line_total", OrderDetailsViewRow::lineTotal, null, null, { row, value -> row.copy(lineTotal = value) }, SqliteTypes.text.underlying) + + fun orderDate(): OptField = OptField(_path, "order_date", OrderDetailsViewRow::orderDate, null, null, { row, value -> row.copy(orderDate = value) }, SqliteTypes.date.underlying) + + fun orderId(): OptField = OptField(_path, "order_id", OrderDetailsViewRow::orderId, null, null, { row, value -> row.copy(orderId = value) }, OrdersId.sqliteType.underlying) + + fun productName(): OptField = OptField(_path, "product_name", OrderDetailsViewRow::productName, null, null, { row, value -> row.copy(productName = value) }, SqliteTypes.text.underlying) + + fun quantity(): OptField = OptField(_path, "quantity", OrderDetailsViewRow::quantity, null, null, { row, value -> row.copy(quantity = value) }, SqliteTypes.integer.underlying) + + override fun rowCodec(): RowCodec = OrderDetailsViewRow.rowCodec.underlying + + fun unitPrice(): OptField = OptField(_path, "unit_price", OrderDetailsViewRow::unitPrice, null, null, { row, value -> row.copy(unitPrice = value) }, SqliteTypes.numeric.underlying) + + override fun withPaths(_path: List): RelationStructure = OrderDetailsViewFields(_path) + + companion object { + val structure: OrderDetailsViewFields = OrderDetailsViewFields(emptyList()) + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/order_details/OrderDetailsViewRepo.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/order_details/OrderDetailsViewRepo.kt new file mode 100644 index 0000000000..91beb3854c --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/order_details/OrderDetailsViewRepo.kt @@ -0,0 +1,16 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.order_details + +import dev.typr.dslkt.SelectBuilder +import dev.typr.foundationskt.ConnectionRead +import kotlin.collections.List + +interface OrderDetailsViewRepo { + abstract fun select(): SelectBuilder + + abstract fun selectAll(c: ConnectionRead): List +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/order_details/OrderDetailsViewRepoImpl.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/order_details/OrderDetailsViewRepoImpl.kt new file mode 100644 index 0000000000..bb53a3f74c --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/order_details/OrderDetailsViewRepoImpl.kt @@ -0,0 +1,18 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.order_details + +import dev.typr.dslkt.Dialect +import dev.typr.dslkt.SelectBuilder +import dev.typr.foundationskt.ConnectionRead +import dev.typr.foundationskt.Fragment +import kotlin.collections.List + +class OrderDetailsViewRepoImpl() : OrderDetailsViewRepo { + override fun select(): SelectBuilder = SelectBuilder.of("\"order_details\"", OrderDetailsViewFields.structure, OrderDetailsViewRow.rowCodec, Dialect.SQLITE) + + override fun selectAll(c: ConnectionRead): List = Fragment.concat(Fragment.of("select \"order_id\", \"order_date\", \"customer_name\", \"product_name\", \"quantity\", \"unit_price\", \"line_total\"\nfrom \"order_details\"\n")).query(OrderDetailsViewRow.rowCodec.all()).run(c) +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/order_details/OrderDetailsViewRow.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/order_details/OrderDetailsViewRow.kt new file mode 100644 index 0000000000..63eac0542a --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/order_details/OrderDetailsViewRow.kt @@ -0,0 +1,50 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.order_details + +import com.fasterxml.jackson.annotation.JsonProperty +import dev.typr.dslkt.RowCodecs +import dev.typr.foundations.Tuple.Tuple7 +import dev.typr.foundationskt.RowCodec +import dev.typr.foundationskt.SqliteTypes +import java.math.BigDecimal +import java.time.LocalDate +import testdb.orders.OrdersId + +/** View: order_details */ +data class OrderDetailsViewRow( + /** Points to [testdb.orders.OrdersRow.orderId] */ + @field:JsonProperty("order_id") val orderId: OrdersId?, + /** Points to [testdb.orders.OrdersRow.orderDate] */ + @field:JsonProperty("order_date") val orderDate: LocalDate?, + /** Points to [testdb.customers.CustomersRow.customerName] */ + @field:JsonProperty("customer_name") val customerName: kotlin.String?, + /** Points to [testdb.products.ProductsRow.productName] */ + @field:JsonProperty("product_name") val productName: kotlin.String?, + /** Points to [testdb.order_items.OrderItemsRow.quantity] */ + val quantity: kotlin.Long?, + /** Points to [testdb.order_items.OrderItemsRow.unitPrice] */ + @field:JsonProperty("unit_price") val unitPrice: BigDecimal?, + @field:JsonProperty("line_total") val lineTotal: kotlin.String? +) : Tuple7 { + override fun _1(): OrdersId? = orderId + + override fun _2(): LocalDate? = orderDate + + override fun _3(): kotlin.String? = customerName + + override fun _4(): kotlin.String? = productName + + override fun _5(): kotlin.Long? = quantity + + override fun _6(): BigDecimal? = unitPrice + + override fun _7(): kotlin.String? = lineTotal + + companion object { + val rowCodec: RowCodec = RowCodecs.of(OrdersId.sqliteType.opt(), SqliteTypes.date.opt(), SqliteTypes.text.opt(), SqliteTypes.text.opt(), SqliteTypes.integer.opt(), SqliteTypes.numeric.opt(), SqliteTypes.text.opt(), { t0: OrdersId?, t1: LocalDate?, t2: kotlin.String?, t3: kotlin.String?, t4: kotlin.Long?, t5: BigDecimal?, t6: kotlin.String? -> OrderDetailsViewRow(t0, t1, t2, t3, t4, t5, t6) }, { row: OrderDetailsViewRow -> arrayOf(row.orderId, row.orderDate, row.customerName, row.productName, row.quantity, row.unitPrice, row.lineTotal) }) + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/order_items/OrderItemsFields.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/order_items/OrderItemsFields.kt new file mode 100644 index 0000000000..f95f4fd037 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/order_items/OrderItemsFields.kt @@ -0,0 +1,65 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.order_items + +import dev.typr.dsl.FieldsBase +import dev.typr.dsl.Path +import dev.typr.dsl.SqlExpr.FieldLike +import dev.typr.dslkt.ForeignKey +import dev.typr.dslkt.RelationStructure +import dev.typr.dslkt.SqlExpr +import dev.typr.dslkt.SqlExpr.Field +import dev.typr.dslkt.SqlExpr.IdField +import dev.typr.dslkt.TupleExpr +import dev.typr.dslkt.TupleExpr4 +import dev.typr.foundations.RowCodec +import dev.typr.foundationskt.SqliteTypes +import java.math.BigDecimal +import kotlin.collections.List +import testdb.orders.OrdersFields +import testdb.orders.OrdersId +import testdb.orders.OrdersRow +import testdb.products.ProductsFields +import testdb.products.ProductsId +import testdb.products.ProductsRow + +data class OrderItemsFields(val _path: List) : TupleExpr4, RelationStructure, FieldsBase { + override fun _1(): SqlExpr = orderId() + + override fun _2(): SqlExpr = productId() + + override fun _3(): SqlExpr = quantity() + + override fun _4(): SqlExpr = unitPrice() + + override fun _path(): List = _path + + override fun columns(): List> = listOf(this.orderId().underlying, this.productId().underlying, this.quantity().underlying, this.unitPrice().underlying) + + fun compositeIdIn(compositeIds: List): SqlExpr = TupleExpr.of(orderId(), productId()).among(compositeIds) + + fun compositeIdIs(compositeId: OrderItemsId): SqlExpr = SqlExpr.all(orderId().isEqual(compositeId.orderId), productId().isEqual(compositeId.productId)) + + fun fkOrders(): ForeignKey = ForeignKey.of("order_items_fk_1").withColumnPair(orderId(), OrdersFields::orderId) + + fun fkProducts(): ForeignKey = ForeignKey.of("order_items_fk_0").withColumnPair(productId(), ProductsFields::productId) + + fun orderId(): IdField = IdField(_path, "order_id", OrderItemsRow::orderId, null, null, { row, value -> row.copy(orderId = value) }, OrdersId.sqliteType.underlying) + + fun productId(): IdField = IdField(_path, "product_id", OrderItemsRow::productId, null, null, { row, value -> row.copy(productId = value) }, ProductsId.sqliteType.underlying) + + fun quantity(): Field = Field(_path, "quantity", OrderItemsRow::quantity, null, null, { row, value -> row.copy(quantity = value) }, SqliteTypes.integer.underlying) + + override fun rowCodec(): RowCodec = OrderItemsRow.rowCodec.underlying + + fun unitPrice(): Field = Field(_path, "unit_price", OrderItemsRow::unitPrice, null, null, { row, value -> row.copy(unitPrice = value) }, SqliteTypes.numeric.underlying) + + override fun withPaths(_path: List): RelationStructure = OrderItemsFields(_path) + + companion object { + val structure: OrderItemsFields = OrderItemsFields(emptyList()) + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/order_items/OrderItemsId.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/order_items/OrderItemsId.kt new file mode 100644 index 0000000000..8d7778da95 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/order_items/OrderItemsId.kt @@ -0,0 +1,27 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.order_items + +import com.fasterxml.jackson.annotation.JsonProperty +import dev.typr.dslkt.RowCodecs +import dev.typr.foundations.Tuple.Tuple2 +import dev.typr.foundationskt.RowCodec +import testdb.orders.OrdersId +import testdb.products.ProductsId + +/** Type for the composite primary key of table `order_items` */ +data class OrderItemsId( + @field:JsonProperty("order_id") val orderId: OrdersId, + @field:JsonProperty("product_id") val productId: ProductsId +) : Tuple2 { + override fun _1(): OrdersId = orderId + + override fun _2(): ProductsId = productId + + companion object { + val rowCodec: RowCodec = RowCodecs.of(OrdersId.sqliteType, ProductsId.sqliteType, { t0: OrdersId, t1: ProductsId -> OrderItemsId(t0, t1) }, { row: OrderItemsId -> arrayOf(row.orderId, row.productId) }) + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/order_items/OrderItemsRepo.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/order_items/OrderItemsRepo.kt new file mode 100644 index 0000000000..14ef088e8e --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/order_items/OrderItemsRepo.kt @@ -0,0 +1,75 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.order_items + +import dev.typr.dslkt.DeleteBuilder +import dev.typr.dslkt.SelectBuilder +import dev.typr.dslkt.UpdateBuilder +import dev.typr.foundationskt.Connection +import dev.typr.foundationskt.ConnectionRead +import kotlin.collections.Iterator +import kotlin.collections.List +import kotlin.collections.Map + +interface OrderItemsRepo { + abstract fun delete(): DeleteBuilder + + abstract fun deleteById( + compositeId: OrderItemsId, + c: Connection + ): kotlin.Boolean + + abstract fun deleteByIds( + compositeIds: List, + c: Connection + ): Int + + abstract fun insert( + unsaved: OrderItemsRow, + c: Connection + ): OrderItemsRow + + abstract fun insert( + unsaved: OrderItemsRowUnsaved, + c: Connection + ): OrderItemsRow + + abstract fun select(): SelectBuilder + + abstract fun selectAll(c: ConnectionRead): List + + abstract fun selectById( + compositeId: OrderItemsId, + c: ConnectionRead + ): OrderItemsRow? + + abstract fun selectByIds( + compositeIds: List, + c: ConnectionRead + ): List + + abstract fun selectByIdsTracked( + compositeIds: List, + c: ConnectionRead + ): Map + + abstract fun update(): UpdateBuilder + + abstract fun update( + row: OrderItemsRow, + c: Connection + ): kotlin.Boolean + + abstract fun upsert( + unsaved: OrderItemsRow, + c: Connection + ): OrderItemsRow + + abstract fun upsertBatch( + unsaved: Iterator, + c: Connection + ): List +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/order_items/OrderItemsRepoImpl.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/order_items/OrderItemsRepoImpl.kt new file mode 100644 index 0000000000..7ec4b68df2 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/order_items/OrderItemsRepoImpl.kt @@ -0,0 +1,118 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.order_items + +import dev.typr.dslkt.DeleteBuilder +import dev.typr.dslkt.Dialect +import dev.typr.dslkt.SelectBuilder +import dev.typr.dslkt.UpdateBuilder +import dev.typr.foundationskt.Connection +import dev.typr.foundationskt.ConnectionRead +import dev.typr.foundationskt.Fragment +import dev.typr.foundationskt.SqliteTypes +import java.util.ArrayList +import kotlin.collections.Iterator +import kotlin.collections.List +import kotlin.collections.Map +import kotlin.collections.MutableMap +import testdb.orders.OrdersId +import testdb.products.ProductsId + +class OrderItemsRepoImpl() : OrderItemsRepo { + override fun delete(): DeleteBuilder = DeleteBuilder.of("\"order_items\"", OrderItemsFields.structure, Dialect.SQLITE) + + override fun deleteById( + compositeId: OrderItemsId, + c: Connection + ): kotlin.Boolean = Fragment.concat(Fragment.of("delete from \"order_items\" where \"order_id\" = "), Fragment.encode(OrdersId.sqliteType, compositeId.orderId), Fragment.of(" AND \"product_id\" = "), Fragment.encode(ProductsId.sqliteType, compositeId.productId), Fragment.of("")).update().run(c) > 0 + + override fun deleteByIds( + compositeIds: List, + c: Connection + ): Int { + val fragments: ArrayList = ArrayList() + for (id in compositeIds) { fragments.add(Fragment.concat(Fragment.of("("), Fragment.encode(OrdersId.sqliteType, id.orderId), Fragment.of(", "), Fragment.encode(ProductsId.sqliteType, id.productId), Fragment.of(")"))) } + return Fragment.concat(Fragment.of("delete from \"order_items\" where (\"order_id\", \"product_id\") in ("), Fragment.comma(fragments.toMutableList()), Fragment.of(")")).update().run(c) + } + + override fun insert( + unsaved: OrderItemsRow, + c: Connection + ): OrderItemsRow = Fragment.concat(Fragment.of("insert into \"order_items\"(\"order_id\", \"product_id\", \"quantity\", \"unit_price\")\nvalues ("), Fragment.encode(OrdersId.sqliteType, unsaved.orderId), Fragment.of(", "), Fragment.encode(ProductsId.sqliteType, unsaved.productId), Fragment.of(", "), Fragment.encode(SqliteTypes.integer, unsaved.quantity), Fragment.of(", "), Fragment.encode(SqliteTypes.numeric, unsaved.unitPrice), Fragment.of(")\nRETURNING \"order_id\", \"product_id\", \"quantity\", \"unit_price\"\n")) + .updateReturning(OrderItemsRow.rowCodec.exactlyOne()).run(c) + + override fun insert( + unsaved: OrderItemsRowUnsaved, + c: Connection + ): OrderItemsRow { + val columns: ArrayList = ArrayList() + val values: ArrayList = ArrayList() + columns.add(Fragment.of("\"order_id\"")) + values.add(Fragment.concat(Fragment.encode(OrdersId.sqliteType, unsaved.orderId), Fragment.of(""))) + columns.add(Fragment.of("\"product_id\"")) + values.add(Fragment.concat(Fragment.encode(ProductsId.sqliteType, unsaved.productId), Fragment.of(""))) + columns.add(Fragment.of("\"unit_price\"")) + values.add(Fragment.concat(Fragment.encode(SqliteTypes.numeric, unsaved.unitPrice), Fragment.of(""))) + unsaved.quantity.visit( + { }, + { value -> columns.add(Fragment.of("\"quantity\"")) + values.add(Fragment.concat(Fragment.encode(SqliteTypes.integer, value), Fragment.of(""))) } + ); + val q: Fragment = Fragment.concat(Fragment.of("insert into \"order_items\"("), Fragment.comma(columns.toMutableList()), Fragment.of(")\nvalues ("), Fragment.comma(values.toMutableList()), Fragment.of(")\nRETURNING \"order_id\", \"product_id\", \"quantity\", \"unit_price\"\n")) + return q.updateReturning(OrderItemsRow.rowCodec.exactlyOne()).run(c) + } + + override fun select(): SelectBuilder = SelectBuilder.of("\"order_items\"", OrderItemsFields.structure, OrderItemsRow.rowCodec, Dialect.SQLITE) + + override fun selectAll(c: ConnectionRead): List = Fragment.concat(Fragment.of("select \"order_id\", \"product_id\", \"quantity\", \"unit_price\"\nfrom \"order_items\"\n")).query(OrderItemsRow.rowCodec.all()).run(c) + + override fun selectById( + compositeId: OrderItemsId, + c: ConnectionRead + ): OrderItemsRow? = Fragment.concat(Fragment.of("select \"order_id\", \"product_id\", \"quantity\", \"unit_price\"\nfrom \"order_items\"\nwhere \"order_id\" = "), Fragment.encode(OrdersId.sqliteType, compositeId.orderId), Fragment.of(" AND \"product_id\" = "), Fragment.encode(ProductsId.sqliteType, compositeId.productId), Fragment.of("")).query(OrderItemsRow.rowCodec.first()).run(c) + + override fun selectByIds( + compositeIds: List, + c: ConnectionRead + ): List { + val fragments: ArrayList = ArrayList() + for (id in compositeIds) { fragments.add(Fragment.concat(Fragment.of("("), Fragment.encode(OrdersId.sqliteType, id.orderId), Fragment.of(", "), Fragment.encode(ProductsId.sqliteType, id.productId), Fragment.of(")"))) } + return Fragment.concat(Fragment.of("select \"order_id\", \"product_id\", \"quantity\", \"unit_price\" from \"order_items\" where (\"order_id\", \"product_id\") in ("), Fragment.comma(fragments.toMutableList()), Fragment.of(")")).query(OrderItemsRow.rowCodec.all()).run(c) + } + + override fun selectByIdsTracked( + compositeIds: List, + c: ConnectionRead + ): Map { + val ret: MutableMap = mutableMapOf() + selectByIds(compositeIds, c).forEach({ row -> ret.put(row.compositeId(), row) }) + return ret.toMap() + } + + override fun update(): UpdateBuilder = UpdateBuilder.of("\"order_items\"", OrderItemsFields.structure, OrderItemsRow.rowCodec, Dialect.SQLITE) + + override fun update( + row: OrderItemsRow, + c: Connection + ): kotlin.Boolean { + val compositeId: OrderItemsId = row.compositeId() + return Fragment.concat(Fragment.of("update \"order_items\"\nset \"quantity\" = "), Fragment.encode(SqliteTypes.integer, row.quantity), Fragment.of(",\n\"unit_price\" = "), Fragment.encode(SqliteTypes.numeric, row.unitPrice), Fragment.of("\nwhere \"order_id\" = "), Fragment.encode(OrdersId.sqliteType, compositeId.orderId), Fragment.of(" AND \"product_id\" = "), Fragment.encode(ProductsId.sqliteType, compositeId.productId), Fragment.of("")).update().run(c) > 0 + } + + override fun upsert( + unsaved: OrderItemsRow, + c: Connection + ): OrderItemsRow = Fragment.concat(Fragment.of("INSERT INTO \"order_items\"(\"order_id\", \"product_id\", \"quantity\", \"unit_price\")\nVALUES ("), Fragment.encode(OrdersId.sqliteType, unsaved.orderId), Fragment.of(", "), Fragment.encode(ProductsId.sqliteType, unsaved.productId), Fragment.of(", "), Fragment.encode(SqliteTypes.integer, unsaved.quantity), Fragment.of(", "), Fragment.encode(SqliteTypes.numeric, unsaved.unitPrice), Fragment.of(")\nON CONFLICT (\"order_id\", \"product_id\")\nDO UPDATE SET\n \"quantity\" = EXCLUDED.\"quantity\",\n\"unit_price\" = EXCLUDED.\"unit_price\"\nRETURNING \"order_id\", \"product_id\", \"quantity\", \"unit_price\"")) + .updateReturning(OrderItemsRow.rowCodec.exactlyOne()) + .run(c) + + override fun upsertBatch( + unsaved: Iterator, + c: Connection + ): List = Fragment.concat(Fragment.of("INSERT INTO \"order_items\"(\"order_id\", \"product_id\", \"quantity\", \"unit_price\")\nVALUES (?, ?, ?, ?)\nON CONFLICT (\"order_id\", \"product_id\")\nDO UPDATE SET\n \"quantity\" = EXCLUDED.\"quantity\",\n\"unit_price\" = EXCLUDED.\"unit_price\"\nRETURNING \"order_id\", \"product_id\", \"quantity\", \"unit_price\"")) + .updateReturningEach(OrderItemsRow.rowCodec, unsaved) + .run(c) +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/order_items/OrderItemsRepoMock.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/order_items/OrderItemsRepoMock.kt new file mode 100644 index 0000000000..d36877b323 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/order_items/OrderItemsRepoMock.kt @@ -0,0 +1,127 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.order_items + +import dev.typr.dslkt.DeleteBuilder +import dev.typr.dslkt.DeleteBuilderMock +import dev.typr.dslkt.DeleteParams +import dev.typr.dslkt.SelectBuilder +import dev.typr.dslkt.SelectBuilderMock +import dev.typr.dslkt.SelectParams +import dev.typr.dslkt.UpdateBuilder +import dev.typr.dslkt.UpdateBuilderMock +import dev.typr.dslkt.UpdateParams +import dev.typr.foundationskt.Connection +import dev.typr.foundationskt.ConnectionRead +import java.lang.RuntimeException +import java.util.ArrayList +import kotlin.collections.Iterator +import kotlin.collections.List +import kotlin.collections.Map +import kotlin.collections.MutableMap + +data class OrderItemsRepoMock( + val toRow: (OrderItemsRowUnsaved) -> OrderItemsRow, + val map: MutableMap = mutableMapOf() +) : OrderItemsRepo { + override fun delete(): DeleteBuilder = DeleteBuilderMock(OrderItemsFields.structure, { map.values.toList() }, DeleteParams.empty(), { row -> row.compositeId() }, { id -> map.remove(id) }) + + override fun deleteById( + compositeId: OrderItemsId, + c: Connection + ): kotlin.Boolean = map.remove(compositeId) != null + + override fun deleteByIds( + compositeIds: List, + c: Connection + ): Int { + var count = 0 + for (id in compositeIds) { + if (map.remove(id) != null) { + count = count + 1 + } + } + return count + } + + override fun insert( + unsaved: OrderItemsRow, + c: Connection + ): OrderItemsRow { + if (map.containsKey(unsaved.compositeId())) { + throw RuntimeException("id " + unsaved.compositeId() + " already exists") + } + map[unsaved.compositeId()] = unsaved + return unsaved + } + + override fun insert( + unsaved: OrderItemsRowUnsaved, + c: Connection + ): OrderItemsRow = insert(toRow(unsaved), c) + + override fun select(): SelectBuilder = SelectBuilderMock(OrderItemsFields.structure, { map.values.toList() }, SelectParams.empty()) + + override fun selectAll(c: ConnectionRead): List = map.values.toList() + + override fun selectById( + compositeId: OrderItemsId, + c: ConnectionRead + ): OrderItemsRow? = map[compositeId] + + override fun selectByIds( + compositeIds: List, + c: ConnectionRead + ): List { + val result = ArrayList() + for (id in compositeIds) { + val opt = map[id] + if (opt != null) { + result.add(opt) + } + } + return result + } + + override fun selectByIdsTracked( + compositeIds: List, + c: ConnectionRead + ): Map = selectByIds(compositeIds, c).associateBy({ row: OrderItemsRow -> row.compositeId() }) + + override fun update(): UpdateBuilder = UpdateBuilderMock(OrderItemsFields.structure, { map.values.toList() }, UpdateParams.empty(), { row -> row }) + + override fun update( + row: OrderItemsRow, + c: Connection + ): kotlin.Boolean { + val shouldUpdate = map[row.compositeId()]?.takeIf({ oldRow -> (oldRow != row) }) != null + if (shouldUpdate) { + map[row.compositeId()] = row + } + return shouldUpdate + } + + override fun upsert( + unsaved: OrderItemsRow, + c: Connection + ): OrderItemsRow { + map[unsaved.compositeId()] = unsaved + return unsaved + } + + override fun upsertBatch( + unsaved: Iterator, + c: Connection + ): List { + val result = ArrayList() + while (unsaved.hasNext()) { + val row = unsaved.next() + map[row.compositeId()] = row + result.add(row) + } + return result + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/order_items/OrderItemsRow.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/order_items/OrderItemsRow.kt new file mode 100644 index 0000000000..865325686b --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/order_items/OrderItemsRow.kt @@ -0,0 +1,53 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.order_items + +import com.fasterxml.jackson.annotation.JsonProperty +import dev.typr.dslkt.RowCodecs +import dev.typr.foundations.Tuple.Tuple4 +import dev.typr.foundationskt.RowCodec +import dev.typr.foundationskt.SqliteTypes +import java.math.BigDecimal +import testdb.customtypes.Defaulted +import testdb.orders.OrdersId +import testdb.products.ProductsId + +/** Table: order_items + * Composite primary key: order_id, product_id + */ +data class OrderItemsRow( + /** Points to [testdb.orders.OrdersRow.orderId] */ + @field:JsonProperty("order_id") val orderId: OrdersId, + /** Points to [testdb.products.ProductsRow.productId] */ + @field:JsonProperty("product_id") val productId: ProductsId, + /** Default: 1 */ + val quantity: kotlin.Long, + @field:JsonProperty("unit_price") val unitPrice: BigDecimal +) : Tuple4 { + override fun _1(): OrdersId = orderId + + override fun _2(): ProductsId = productId + + override fun _3(): kotlin.Long = quantity + + override fun _4(): BigDecimal = unitPrice + + fun compositeId(): OrderItemsId = OrderItemsId(orderId, productId) + + fun id(): OrderItemsId = this.compositeId() + + fun toUnsavedRow(quantity: Defaulted = Defaulted.Provided(this.quantity)): OrderItemsRowUnsaved = OrderItemsRowUnsaved(orderId, productId, unitPrice, quantity) + + companion object { + val rowCodec: RowCodec = RowCodecs.of(OrdersId.sqliteType, ProductsId.sqliteType, SqliteTypes.integer, SqliteTypes.numeric, { t0: OrdersId, t1: ProductsId, t2: kotlin.Long, t3: BigDecimal -> OrderItemsRow(t0, t1, t2, t3) }, { row: OrderItemsRow -> arrayOf(row.orderId, row.productId, row.quantity, row.unitPrice) }) + + fun apply( + compositeId: OrderItemsId, + quantity: kotlin.Long, + unitPrice: BigDecimal + ): OrderItemsRow = OrderItemsRow(compositeId.orderId, compositeId.productId, quantity, unitPrice) + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/order_items/OrderItemsRowUnsaved.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/order_items/OrderItemsRowUnsaved.kt new file mode 100644 index 0000000000..0402c9da1a --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/order_items/OrderItemsRowUnsaved.kt @@ -0,0 +1,26 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.order_items + +import com.fasterxml.jackson.annotation.JsonProperty +import java.math.BigDecimal +import testdb.customtypes.Defaulted +import testdb.customtypes.Defaulted.UseDefault +import testdb.orders.OrdersId +import testdb.products.ProductsId + +/** This class corresponds to a row in table `order_items` which has not been persisted yet */ +data class OrderItemsRowUnsaved( + /** Points to [testdb.orders.OrdersRow.orderId] */ + @field:JsonProperty("order_id") val orderId: OrdersId, + /** Points to [testdb.products.ProductsRow.productId] */ + @field:JsonProperty("product_id") val productId: ProductsId, + @field:JsonProperty("unit_price") val unitPrice: BigDecimal, + /** Default: 1 */ + val quantity: Defaulted = UseDefault() +) { + fun toRow(quantityDefault: () -> kotlin.Long): OrderItemsRow = OrderItemsRow(orderId = orderId, productId = productId, quantity = quantity.getOrElse(quantityDefault), unitPrice = unitPrice) +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/order_summary_by_customer/OrderSummaryByCustomerSqlRepo.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/order_summary_by_customer/OrderSummaryByCustomerSqlRepo.kt new file mode 100644 index 0000000000..ac5366ec05 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/order_summary_by_customer/OrderSummaryByCustomerSqlRepo.kt @@ -0,0 +1,18 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.order_summary_by_customer + +import dev.typr.foundationskt.ConnectionRead +import java.time.LocalDate +import kotlin.collections.List + +interface OrderSummaryByCustomerSqlRepo { + abstract fun apply( + fromDate: LocalDate, + toDate: LocalDate, + c: ConnectionRead + ): List +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/order_summary_by_customer/OrderSummaryByCustomerSqlRepoImpl.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/order_summary_by_customer/OrderSummaryByCustomerSqlRepoImpl.kt new file mode 100644 index 0000000000..0c415d4508 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/order_summary_by_customer/OrderSummaryByCustomerSqlRepoImpl.kt @@ -0,0 +1,20 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.order_summary_by_customer + +import dev.typr.foundationskt.ConnectionRead +import dev.typr.foundationskt.Fragment +import dev.typr.foundationskt.SqliteTypes +import java.time.LocalDate +import kotlin.collections.List + +class OrderSummaryByCustomerSqlRepoImpl() : OrderSummaryByCustomerSqlRepo { + override fun apply( + fromDate: LocalDate, + toDate: LocalDate, + c: ConnectionRead + ): List = Fragment.concat(Fragment.of("-- Summary stats per customer over an order date range.\n-- Tests: GROUP BY, aggregates with NULL-aware results, JOIN, date params.\n\nSELECT\n c.customer_id,\n c.name AS customer_name,\n COUNT(o.order_id) AS order_count,\n COALESCE(SUM(o.total_amount), 0) AS total_revenue,\n MAX(o.order_date) AS last_order_date\nFROM customers c\nLEFT JOIN orders o ON c.customer_id = o.customer_id\nWHERE o.order_date IS NULL\n OR (o.order_date >= "), Fragment.encode(SqliteTypes.date, fromDate), Fragment.of(" AND o.order_date <= "), Fragment.encode(SqliteTypes.date, toDate), Fragment.of(")\nGROUP BY c.customer_id, c.name\nORDER BY total_revenue DESC, c.customer_id")).query(OrderSummaryByCustomerSqlRow.rowCodec.all()).run(c) +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/order_summary_by_customer/OrderSummaryByCustomerSqlRow.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/order_summary_by_customer/OrderSummaryByCustomerSqlRow.kt new file mode 100644 index 0000000000..7907f4a1ea --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/order_summary_by_customer/OrderSummaryByCustomerSqlRow.kt @@ -0,0 +1,43 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.order_summary_by_customer + +import com.fasterxml.jackson.annotation.JsonProperty +import dev.typr.dslkt.RowCodecs +import dev.typr.foundations.Tuple.Tuple5 +import dev.typr.foundationskt.RowCodec +import dev.typr.foundationskt.SqliteTypes +import java.math.BigDecimal +import java.time.LocalDate +import testdb.customers.CustomersId + +/** SQL file: order_summary_by_customer.sql */ +data class OrderSummaryByCustomerSqlRow( + /** Points to [testdb.customers.CustomersRow.customerId] */ + @field:JsonProperty("customer_id") val customerId: CustomersId, + /** Points to [testdb.customers.CustomersRow.name] */ + @field:JsonProperty("customer_name") val customerName: kotlin.String, + /** Points to [testdb.orders.OrdersRow.orderId] */ + @field:JsonProperty("order_count") val orderCount: kotlin.Long?, + /** Points to [testdb.orders.OrdersRow.totalAmount] */ + @field:JsonProperty("total_revenue") val totalRevenue: BigDecimal?, + /** Points to [testdb.orders.OrdersRow.orderDate] */ + @field:JsonProperty("last_order_date") val lastOrderDate: LocalDate? +) : Tuple5 { + override fun _1(): CustomersId = customerId + + override fun _2(): kotlin.String = customerName + + override fun _3(): kotlin.Long? = orderCount + + override fun _4(): BigDecimal? = totalRevenue + + override fun _5(): LocalDate? = lastOrderDate + + companion object { + val rowCodec: RowCodec = RowCodecs.of(CustomersId.sqliteType, SqliteTypes.text, SqliteTypes.bigint.opt(), SqliteTypes.numeric.opt(), SqliteTypes.date.opt(), { t0: CustomersId, t1: kotlin.String, t2: kotlin.Long?, t3: BigDecimal?, t4: LocalDate? -> OrderSummaryByCustomerSqlRow(t0, t1, t2, t3, t4) }, { row: OrderSummaryByCustomerSqlRow -> arrayOf(row.customerId, row.customerName, row.orderCount, row.totalRevenue, row.lastOrderDate) }) + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/orders/OrdersFields.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/orders/OrdersFields.kt new file mode 100644 index 0000000000..4862cf807c --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/orders/OrdersFields.kt @@ -0,0 +1,61 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.orders + +import dev.typr.dsl.FieldsBase +import dev.typr.dsl.Path +import dev.typr.dsl.SqlExpr.FieldLike +import dev.typr.dslkt.ForeignKey +import dev.typr.dslkt.RelationStructure +import dev.typr.dslkt.SqlExpr +import dev.typr.dslkt.SqlExpr.Field +import dev.typr.dslkt.SqlExpr.IdField +import dev.typr.dslkt.SqlExpr.OptField +import dev.typr.dslkt.TupleExpr5 +import dev.typr.foundations.RowCodec +import dev.typr.foundationskt.SqliteTypes +import java.math.BigDecimal +import java.time.LocalDate +import kotlin.collections.List +import testdb.customers.CustomersFields +import testdb.customers.CustomersId +import testdb.customers.CustomersRow + +data class OrdersFields(val _path: List) : TupleExpr5, RelationStructure, FieldsBase { + override fun _1(): SqlExpr = orderId() + + override fun _2(): SqlExpr = customerId() + + override fun _3(): SqlExpr = orderDate() + + override fun _4(): SqlExpr = totalAmount() + + override fun _5(): SqlExpr = status() + + override fun _path(): List = _path + + override fun columns(): List> = listOf(this.orderId().underlying, this.customerId().underlying, this.orderDate().underlying, this.totalAmount().underlying, this.status().underlying) + + fun customerId(): Field = Field(_path, "customer_id", OrdersRow::customerId, null, null, { row, value -> row.copy(customerId = value) }, CustomersId.sqliteType.underlying) + + fun fkCustomers(): ForeignKey = ForeignKey.of("orders_fk_0").withColumnPair(customerId(), CustomersFields::customerId) + + fun orderDate(): Field = Field(_path, "order_date", OrdersRow::orderDate, null, null, { row, value -> row.copy(orderDate = value) }, SqliteTypes.date.underlying) + + fun orderId(): IdField = IdField(_path, "order_id", OrdersRow::orderId, null, null, { row, value -> row.copy(orderId = value) }, OrdersId.sqliteType.underlying) + + override fun rowCodec(): RowCodec = OrdersRow.rowCodec.underlying + + fun status(): Field = Field(_path, "status", OrdersRow::status, null, null, { row, value -> row.copy(status = value) }, SqliteTypes.text.underlying) + + fun totalAmount(): OptField = OptField(_path, "total_amount", OrdersRow::totalAmount, null, null, { row, value -> row.copy(totalAmount = value) }, SqliteTypes.numeric.underlying) + + override fun withPaths(_path: List): RelationStructure = OrdersFields(_path) + + companion object { + val structure: OrdersFields = OrdersFields(emptyList()) + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/orders/OrdersId.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/orders/OrdersId.kt new file mode 100644 index 0000000000..a1cc46cdbc --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/orders/OrdersId.kt @@ -0,0 +1,26 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.orders + +import com.fasterxml.jackson.annotation.JsonValue +import dev.typr.foundationskt.Bijection +import dev.typr.foundationskt.SqliteType +import dev.typr.foundationskt.SqliteTypes + +/** Type for the primary key of table `orders` */ +data class OrdersId(@field:JsonValue val value: kotlin.Long) { + override fun toString(): kotlin.String { + return value.toString() + } + + companion object { + val bijection: Bijection = + Bijection.of(OrdersId::value, ::OrdersId) + + val sqliteType: SqliteType = + SqliteTypes.integer.to(Bijection.of(::OrdersId, OrdersId::value)) + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/orders/OrdersRepo.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/orders/OrdersRepo.kt new file mode 100644 index 0000000000..c41a22a8e3 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/orders/OrdersRepo.kt @@ -0,0 +1,75 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.orders + +import dev.typr.dslkt.DeleteBuilder +import dev.typr.dslkt.SelectBuilder +import dev.typr.dslkt.UpdateBuilder +import dev.typr.foundationskt.Connection +import dev.typr.foundationskt.ConnectionRead +import kotlin.collections.Iterator +import kotlin.collections.List +import kotlin.collections.Map + +interface OrdersRepo { + abstract fun delete(): DeleteBuilder + + abstract fun deleteById( + orderId: OrdersId, + c: Connection + ): kotlin.Boolean + + abstract fun deleteByIds( + orderIds: List, + c: Connection + ): Int + + abstract fun insert( + unsaved: OrdersRow, + c: Connection + ): OrdersRow + + abstract fun insert( + unsaved: OrdersRowUnsaved, + c: Connection + ): OrdersRow + + abstract fun select(): SelectBuilder + + abstract fun selectAll(c: ConnectionRead): List + + abstract fun selectById( + orderId: OrdersId, + c: ConnectionRead + ): OrdersRow? + + abstract fun selectByIds( + orderIds: List, + c: ConnectionRead + ): List + + abstract fun selectByIdsTracked( + orderIds: List, + c: ConnectionRead + ): Map + + abstract fun update(): UpdateBuilder + + abstract fun update( + row: OrdersRow, + c: Connection + ): kotlin.Boolean + + abstract fun upsert( + unsaved: OrdersRow, + c: Connection + ): OrdersRow + + abstract fun upsertBatch( + unsaved: Iterator, + c: Connection + ): List +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/orders/OrdersRepoImpl.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/orders/OrdersRepoImpl.kt new file mode 100644 index 0000000000..04ef984d86 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/orders/OrdersRepoImpl.kt @@ -0,0 +1,119 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.orders + +import dev.typr.dslkt.DeleteBuilder +import dev.typr.dslkt.Dialect +import dev.typr.dslkt.SelectBuilder +import dev.typr.dslkt.UpdateBuilder +import dev.typr.foundationskt.Connection +import dev.typr.foundationskt.ConnectionRead +import dev.typr.foundationskt.Fragment +import dev.typr.foundationskt.SqliteTypes +import java.util.ArrayList +import kotlin.collections.Iterator +import kotlin.collections.List +import kotlin.collections.Map +import kotlin.collections.MutableMap +import testdb.customers.CustomersId + +class OrdersRepoImpl() : OrdersRepo { + override fun delete(): DeleteBuilder = DeleteBuilder.of("\"orders\"", OrdersFields.structure, Dialect.SQLITE) + + override fun deleteById( + orderId: OrdersId, + c: Connection + ): kotlin.Boolean = Fragment.concat(Fragment.of("delete from \"orders\" where \"order_id\" = "), Fragment.encode(OrdersId.sqliteType, orderId), Fragment.of("")).update().run(c) > 0 + + override fun deleteByIds( + orderIds: List, + c: Connection + ): Int { + val fragments: ArrayList = ArrayList() + for (id in orderIds) { fragments.add(Fragment.encode(OrdersId.sqliteType, id)) } + return Fragment.concat(Fragment.of("delete from \"orders\" where \"order_id\" in ("), Fragment.comma(fragments.toMutableList()), Fragment.of(")")).update().run(c) + } + + override fun insert( + unsaved: OrdersRow, + c: Connection + ): OrdersRow = Fragment.concat(Fragment.of("insert into \"orders\"(\"order_id\", \"customer_id\", \"order_date\", \"total_amount\", \"status\")\nvalues ("), Fragment.encode(OrdersId.sqliteType, unsaved.orderId), Fragment.of(", "), Fragment.encode(CustomersId.sqliteType, unsaved.customerId), Fragment.of(", "), Fragment.encode(SqliteTypes.date, unsaved.orderDate), Fragment.of(", "), Fragment.encode(SqliteTypes.numeric.opt(), unsaved.totalAmount), Fragment.of(", "), Fragment.encode(SqliteTypes.text, unsaved.status), Fragment.of(")\nRETURNING \"order_id\", \"customer_id\", \"order_date\", \"total_amount\", \"status\"\n")) + .updateReturning(OrdersRow.rowCodec.exactlyOne()).run(c) + + override fun insert( + unsaved: OrdersRowUnsaved, + c: Connection + ): OrdersRow { + val columns: ArrayList = ArrayList() + val values: ArrayList = ArrayList() + columns.add(Fragment.of("\"order_id\"")) + values.add(Fragment.concat(Fragment.encode(OrdersId.sqliteType, unsaved.orderId), Fragment.of(""))) + columns.add(Fragment.of("\"customer_id\"")) + values.add(Fragment.concat(Fragment.encode(CustomersId.sqliteType, unsaved.customerId), Fragment.of(""))) + columns.add(Fragment.of("\"order_date\"")) + values.add(Fragment.concat(Fragment.encode(SqliteTypes.date, unsaved.orderDate), Fragment.of(""))) + columns.add(Fragment.of("\"total_amount\"")) + values.add(Fragment.concat(Fragment.encode(SqliteTypes.numeric.opt(), unsaved.totalAmount), Fragment.of(""))) + unsaved.status.visit( + { }, + { value -> columns.add(Fragment.of("\"status\"")) + values.add(Fragment.concat(Fragment.encode(SqliteTypes.text, value), Fragment.of(""))) } + ); + val q: Fragment = Fragment.concat(Fragment.of("insert into \"orders\"("), Fragment.comma(columns.toMutableList()), Fragment.of(")\nvalues ("), Fragment.comma(values.toMutableList()), Fragment.of(")\nRETURNING \"order_id\", \"customer_id\", \"order_date\", \"total_amount\", \"status\"\n")) + return q.updateReturning(OrdersRow.rowCodec.exactlyOne()).run(c) + } + + override fun select(): SelectBuilder = SelectBuilder.of("\"orders\"", OrdersFields.structure, OrdersRow.rowCodec, Dialect.SQLITE) + + override fun selectAll(c: ConnectionRead): List = Fragment.concat(Fragment.of("select \"order_id\", \"customer_id\", \"order_date\", \"total_amount\", \"status\"\nfrom \"orders\"\n")).query(OrdersRow.rowCodec.all()).run(c) + + override fun selectById( + orderId: OrdersId, + c: ConnectionRead + ): OrdersRow? = Fragment.concat(Fragment.of("select \"order_id\", \"customer_id\", \"order_date\", \"total_amount\", \"status\"\nfrom \"orders\"\nwhere \"order_id\" = "), Fragment.encode(OrdersId.sqliteType, orderId), Fragment.of("")).query(OrdersRow.rowCodec.first()).run(c) + + override fun selectByIds( + orderIds: List, + c: ConnectionRead + ): List { + val fragments: ArrayList = ArrayList() + for (id in orderIds) { fragments.add(Fragment.encode(OrdersId.sqliteType, id)) } + return Fragment.concat(Fragment.of("select \"order_id\", \"customer_id\", \"order_date\", \"total_amount\", \"status\" from \"orders\" where \"order_id\" in ("), Fragment.comma(fragments.toMutableList()), Fragment.of(")")).query(OrdersRow.rowCodec.all()).run(c) + } + + override fun selectByIdsTracked( + orderIds: List, + c: ConnectionRead + ): Map { + val ret: MutableMap = mutableMapOf() + selectByIds(orderIds, c).forEach({ row -> ret.put(row.orderId, row) }) + return ret.toMap() + } + + override fun update(): UpdateBuilder = UpdateBuilder.of("\"orders\"", OrdersFields.structure, OrdersRow.rowCodec, Dialect.SQLITE) + + override fun update( + row: OrdersRow, + c: Connection + ): kotlin.Boolean { + val orderId: OrdersId = row.orderId + return Fragment.concat(Fragment.of("update \"orders\"\nset \"customer_id\" = "), Fragment.encode(CustomersId.sqliteType, row.customerId), Fragment.of(",\n\"order_date\" = "), Fragment.encode(SqliteTypes.date, row.orderDate), Fragment.of(",\n\"total_amount\" = "), Fragment.encode(SqliteTypes.numeric.opt(), row.totalAmount), Fragment.of(",\n\"status\" = "), Fragment.encode(SqliteTypes.text, row.status), Fragment.of("\nwhere \"order_id\" = "), Fragment.encode(OrdersId.sqliteType, orderId), Fragment.of("")).update().run(c) > 0 + } + + override fun upsert( + unsaved: OrdersRow, + c: Connection + ): OrdersRow = Fragment.concat(Fragment.of("INSERT INTO \"orders\"(\"order_id\", \"customer_id\", \"order_date\", \"total_amount\", \"status\")\nVALUES ("), Fragment.encode(OrdersId.sqliteType, unsaved.orderId), Fragment.of(", "), Fragment.encode(CustomersId.sqliteType, unsaved.customerId), Fragment.of(", "), Fragment.encode(SqliteTypes.date, unsaved.orderDate), Fragment.of(", "), Fragment.encode(SqliteTypes.numeric.opt(), unsaved.totalAmount), Fragment.of(", "), Fragment.encode(SqliteTypes.text, unsaved.status), Fragment.of(")\nON CONFLICT (\"order_id\")\nDO UPDATE SET\n \"customer_id\" = EXCLUDED.\"customer_id\",\n\"order_date\" = EXCLUDED.\"order_date\",\n\"total_amount\" = EXCLUDED.\"total_amount\",\n\"status\" = EXCLUDED.\"status\"\nRETURNING \"order_id\", \"customer_id\", \"order_date\", \"total_amount\", \"status\"")) + .updateReturning(OrdersRow.rowCodec.exactlyOne()) + .run(c) + + override fun upsertBatch( + unsaved: Iterator, + c: Connection + ): List = Fragment.concat(Fragment.of("INSERT INTO \"orders\"(\"order_id\", \"customer_id\", \"order_date\", \"total_amount\", \"status\")\nVALUES (?, ?, ?, ?, ?)\nON CONFLICT (\"order_id\")\nDO UPDATE SET\n \"customer_id\" = EXCLUDED.\"customer_id\",\n\"order_date\" = EXCLUDED.\"order_date\",\n\"total_amount\" = EXCLUDED.\"total_amount\",\n\"status\" = EXCLUDED.\"status\"\nRETURNING \"order_id\", \"customer_id\", \"order_date\", \"total_amount\", \"status\"")) + .updateReturningEach(OrdersRow.rowCodec, unsaved) + .run(c) +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/orders/OrdersRepoMock.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/orders/OrdersRepoMock.kt new file mode 100644 index 0000000000..de77051166 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/orders/OrdersRepoMock.kt @@ -0,0 +1,127 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.orders + +import dev.typr.dslkt.DeleteBuilder +import dev.typr.dslkt.DeleteBuilderMock +import dev.typr.dslkt.DeleteParams +import dev.typr.dslkt.SelectBuilder +import dev.typr.dslkt.SelectBuilderMock +import dev.typr.dslkt.SelectParams +import dev.typr.dslkt.UpdateBuilder +import dev.typr.dslkt.UpdateBuilderMock +import dev.typr.dslkt.UpdateParams +import dev.typr.foundationskt.Connection +import dev.typr.foundationskt.ConnectionRead +import java.lang.RuntimeException +import java.util.ArrayList +import kotlin.collections.Iterator +import kotlin.collections.List +import kotlin.collections.Map +import kotlin.collections.MutableMap + +data class OrdersRepoMock( + val toRow: (OrdersRowUnsaved) -> OrdersRow, + val map: MutableMap = mutableMapOf() +) : OrdersRepo { + override fun delete(): DeleteBuilder = DeleteBuilderMock(OrdersFields.structure, { map.values.toList() }, DeleteParams.empty(), { row -> row.orderId }, { id -> map.remove(id) }) + + override fun deleteById( + orderId: OrdersId, + c: Connection + ): kotlin.Boolean = map.remove(orderId) != null + + override fun deleteByIds( + orderIds: List, + c: Connection + ): Int { + var count = 0 + for (id in orderIds) { + if (map.remove(id) != null) { + count = count + 1 + } + } + return count + } + + override fun insert( + unsaved: OrdersRow, + c: Connection + ): OrdersRow { + if (map.containsKey(unsaved.orderId)) { + throw RuntimeException("id " + unsaved.orderId + " already exists") + } + map[unsaved.orderId] = unsaved + return unsaved + } + + override fun insert( + unsaved: OrdersRowUnsaved, + c: Connection + ): OrdersRow = insert(toRow(unsaved), c) + + override fun select(): SelectBuilder = SelectBuilderMock(OrdersFields.structure, { map.values.toList() }, SelectParams.empty()) + + override fun selectAll(c: ConnectionRead): List = map.values.toList() + + override fun selectById( + orderId: OrdersId, + c: ConnectionRead + ): OrdersRow? = map[orderId] + + override fun selectByIds( + orderIds: List, + c: ConnectionRead + ): List { + val result = ArrayList() + for (id in orderIds) { + val opt = map[id] + if (opt != null) { + result.add(opt) + } + } + return result + } + + override fun selectByIdsTracked( + orderIds: List, + c: ConnectionRead + ): Map = selectByIds(orderIds, c).associateBy({ row: OrdersRow -> row.orderId }) + + override fun update(): UpdateBuilder = UpdateBuilderMock(OrdersFields.structure, { map.values.toList() }, UpdateParams.empty(), { row -> row }) + + override fun update( + row: OrdersRow, + c: Connection + ): kotlin.Boolean { + val shouldUpdate = map[row.orderId]?.takeIf({ oldRow -> (oldRow != row) }) != null + if (shouldUpdate) { + map[row.orderId] = row + } + return shouldUpdate + } + + override fun upsert( + unsaved: OrdersRow, + c: Connection + ): OrdersRow { + map[unsaved.orderId] = unsaved + return unsaved + } + + override fun upsertBatch( + unsaved: Iterator, + c: Connection + ): List { + val result = ArrayList() + while (unsaved.hasNext()) { + val row = unsaved.next() + map[row.orderId] = row + result.add(row) + } + return result + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/orders/OrdersRow.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/orders/OrdersRow.kt new file mode 100644 index 0000000000..10ae2872e8 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/orders/OrdersRow.kt @@ -0,0 +1,47 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.orders + +import com.fasterxml.jackson.annotation.JsonProperty +import dev.typr.dslkt.RowCodecs +import dev.typr.foundations.Tuple.Tuple5 +import dev.typr.foundationskt.RowCodec +import dev.typr.foundationskt.SqliteTypes +import java.math.BigDecimal +import java.time.LocalDate +import testdb.customers.CustomersId +import testdb.customtypes.Defaulted + +/** Table: orders + * Primary key: order_id + */ +data class OrdersRow( + @field:JsonProperty("order_id") val orderId: OrdersId, + /** Points to [testdb.customers.CustomersRow.customerId] */ + @field:JsonProperty("customer_id") val customerId: CustomersId, + @field:JsonProperty("order_date") val orderDate: LocalDate, + @field:JsonProperty("total_amount") val totalAmount: BigDecimal?, + /** Default: 'pending' */ + val status: kotlin.String +) : Tuple5 { + override fun _1(): OrdersId = orderId + + override fun _2(): CustomersId = customerId + + override fun _3(): LocalDate = orderDate + + override fun _4(): BigDecimal? = totalAmount + + override fun _5(): kotlin.String = status + + fun id(): OrdersId = orderId + + fun toUnsavedRow(status: Defaulted = Defaulted.Provided(this.status)): OrdersRowUnsaved = OrdersRowUnsaved(orderId, customerId, orderDate, totalAmount, status) + + companion object { + val rowCodec: RowCodec = RowCodecs.of(OrdersId.sqliteType, CustomersId.sqliteType, SqliteTypes.date, SqliteTypes.numeric.opt(), SqliteTypes.text, { t0: OrdersId, t1: CustomersId, t2: LocalDate, t3: BigDecimal?, t4: kotlin.String -> OrdersRow(t0, t1, t2, t3, t4) }, { row: OrdersRow -> arrayOf(row.orderId, row.customerId, row.orderDate, row.totalAmount, row.status) }) + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/orders/OrdersRowUnsaved.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/orders/OrdersRowUnsaved.kt new file mode 100644 index 0000000000..02195dcd6d --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/orders/OrdersRowUnsaved.kt @@ -0,0 +1,26 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.orders + +import com.fasterxml.jackson.annotation.JsonProperty +import java.math.BigDecimal +import java.time.LocalDate +import testdb.customers.CustomersId +import testdb.customtypes.Defaulted +import testdb.customtypes.Defaulted.UseDefault + +/** This class corresponds to a row in table `orders` which has not been persisted yet */ +data class OrdersRowUnsaved( + @field:JsonProperty("order_id") val orderId: OrdersId, + /** Points to [testdb.customers.CustomersRow.customerId] */ + @field:JsonProperty("customer_id") val customerId: CustomersId, + @field:JsonProperty("order_date") val orderDate: LocalDate, + @field:JsonProperty("total_amount") val totalAmount: BigDecimal? = null, + /** Default: 'pending' */ + val status: Defaulted = UseDefault() +) { + fun toRow(statusDefault: () -> kotlin.String): OrdersRow = OrdersRow(orderId = orderId, customerId = customerId, orderDate = orderDate, totalAmount = totalAmount, status = status.getOrElse(statusDefault)) +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/precisetypes/Decimal10_2.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/precisetypes/Decimal10_2.kt new file mode 100644 index 0000000000..6a4d5523c9 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/precisetypes/Decimal10_2.kt @@ -0,0 +1,68 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precisetypes + +import com.fasterxml.jackson.annotation.JsonValue +import dev.typr.foundations.data.precise.DecimalN +import dev.typr.foundationskt.Bijection +import dev.typr.foundationskt.SqliteType +import dev.typr.foundationskt.SqliteTypes +import java.lang.IllegalArgumentException +import java.math.BigDecimal +import java.math.RoundingMode + +@kotlin.ConsistentCopyVisibility +data class Decimal10_2 private constructor(@field:JsonValue val value: BigDecimal) : DecimalN { + override fun decimalValue(): BigDecimal = value + + override fun equals(other: Any?): kotlin.Boolean { + if (this === other) return true + if (other !is DecimalN) return false + return decimalValue().compareTo(other.decimalValue()) == 0 + } + + override fun hashCode(): Int = decimalValue().stripTrailingZeros().hashCode() + + override fun precision(): Int = 10 + + override fun scale(): Int = 2 + + override fun semanticEquals(other: DecimalN): kotlin.Boolean = if (other == null) false else decimalValue().compareTo(other.decimalValue()) == 0 + + override fun semanticHashCode(): Int = decimalValue().stripTrailingZeros().hashCode() + + override fun toString(): kotlin.String { + return value.toString() + } + + companion object { + fun of(value: BigDecimal): Decimal10_2? { + val scaled = value.setScale(2, RoundingMode.HALF_UP) + return if (scaled.precision() <= 10) Decimal10_2(scaled) else null + } + + fun unsafeForce(value: BigDecimal): Decimal10_2 { + val scaled = value.setScale(2, RoundingMode.HALF_UP) + if (scaled.precision() > 10) throw IllegalArgumentException("Value exceeds precision(10, 2)") + return Decimal10_2(scaled) + } + + fun of(value: Int): Decimal10_2 = Decimal10_2(BigDecimal.valueOf(value.toLong())) + + fun of(value: kotlin.Long): Decimal10_2? = Decimal10_2.of(BigDecimal.valueOf(value)) + + fun of(value: kotlin.Double): Decimal10_2? = Decimal10_2.of(BigDecimal.valueOf(value)) + + val Zero: Decimal10_2 = + Decimal10_2(BigDecimal.ZERO) + + val bijection: Bijection = + Bijection.of(Decimal10_2::value, ::Decimal10_2) + + val sqliteType: SqliteType = + SqliteTypes.numeric.to(Bijection.of(::Decimal10_2, Decimal10_2::value)) + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/precisetypes/Decimal18_4.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/precisetypes/Decimal18_4.kt new file mode 100644 index 0000000000..16488498c5 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/precisetypes/Decimal18_4.kt @@ -0,0 +1,68 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precisetypes + +import com.fasterxml.jackson.annotation.JsonValue +import dev.typr.foundations.data.precise.DecimalN +import dev.typr.foundationskt.Bijection +import dev.typr.foundationskt.SqliteType +import dev.typr.foundationskt.SqliteTypes +import java.lang.IllegalArgumentException +import java.math.BigDecimal +import java.math.RoundingMode + +@kotlin.ConsistentCopyVisibility +data class Decimal18_4 private constructor(@field:JsonValue val value: BigDecimal) : DecimalN { + override fun decimalValue(): BigDecimal = value + + override fun equals(other: Any?): kotlin.Boolean { + if (this === other) return true + if (other !is DecimalN) return false + return decimalValue().compareTo(other.decimalValue()) == 0 + } + + override fun hashCode(): Int = decimalValue().stripTrailingZeros().hashCode() + + override fun precision(): Int = 18 + + override fun scale(): Int = 4 + + override fun semanticEquals(other: DecimalN): kotlin.Boolean = if (other == null) false else decimalValue().compareTo(other.decimalValue()) == 0 + + override fun semanticHashCode(): Int = decimalValue().stripTrailingZeros().hashCode() + + override fun toString(): kotlin.String { + return value.toString() + } + + companion object { + fun of(value: BigDecimal): Decimal18_4? { + val scaled = value.setScale(4, RoundingMode.HALF_UP) + return if (scaled.precision() <= 18) Decimal18_4(scaled) else null + } + + fun unsafeForce(value: BigDecimal): Decimal18_4 { + val scaled = value.setScale(4, RoundingMode.HALF_UP) + if (scaled.precision() > 18) throw IllegalArgumentException("Value exceeds precision(18, 4)") + return Decimal18_4(scaled) + } + + fun of(value: Int): Decimal18_4 = Decimal18_4(BigDecimal.valueOf(value.toLong())) + + fun of(value: kotlin.Long): Decimal18_4? = Decimal18_4.of(BigDecimal.valueOf(value)) + + fun of(value: kotlin.Double): Decimal18_4? = Decimal18_4.of(BigDecimal.valueOf(value)) + + val Zero: Decimal18_4 = + Decimal18_4(BigDecimal.ZERO) + + val bijection: Bijection = + Bijection.of(Decimal18_4::value, ::Decimal18_4) + + val sqliteType: SqliteType = + SqliteTypes.numeric.to(Bijection.of(::Decimal18_4, Decimal18_4::value)) + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/precisetypes/Decimal5_2.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/precisetypes/Decimal5_2.kt new file mode 100644 index 0000000000..9cfe0aab52 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/precisetypes/Decimal5_2.kt @@ -0,0 +1,68 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precisetypes + +import com.fasterxml.jackson.annotation.JsonValue +import dev.typr.foundations.data.precise.DecimalN +import dev.typr.foundationskt.Bijection +import dev.typr.foundationskt.SqliteType +import dev.typr.foundationskt.SqliteTypes +import java.lang.IllegalArgumentException +import java.math.BigDecimal +import java.math.RoundingMode + +@kotlin.ConsistentCopyVisibility +data class Decimal5_2 private constructor(@field:JsonValue val value: BigDecimal) : DecimalN { + override fun decimalValue(): BigDecimal = value + + override fun equals(other: Any?): kotlin.Boolean { + if (this === other) return true + if (other !is DecimalN) return false + return decimalValue().compareTo(other.decimalValue()) == 0 + } + + override fun hashCode(): Int = decimalValue().stripTrailingZeros().hashCode() + + override fun precision(): Int = 5 + + override fun scale(): Int = 2 + + override fun semanticEquals(other: DecimalN): kotlin.Boolean = if (other == null) false else decimalValue().compareTo(other.decimalValue()) == 0 + + override fun semanticHashCode(): Int = decimalValue().stripTrailingZeros().hashCode() + + override fun toString(): kotlin.String { + return value.toString() + } + + companion object { + fun of(value: BigDecimal): Decimal5_2? { + val scaled = value.setScale(2, RoundingMode.HALF_UP) + return if (scaled.precision() <= 5) Decimal5_2(scaled) else null + } + + fun unsafeForce(value: BigDecimal): Decimal5_2 { + val scaled = value.setScale(2, RoundingMode.HALF_UP) + if (scaled.precision() > 5) throw IllegalArgumentException("Value exceeds precision(5, 2)") + return Decimal5_2(scaled) + } + + fun of(value: Int): Decimal5_2 = Decimal5_2(BigDecimal.valueOf(value.toLong())) + + fun of(value: kotlin.Long): Decimal5_2? = Decimal5_2.of(BigDecimal.valueOf(value)) + + fun of(value: kotlin.Double): Decimal5_2? = Decimal5_2.of(BigDecimal.valueOf(value)) + + val Zero: Decimal5_2 = + Decimal5_2(BigDecimal.ZERO) + + val bijection: Bijection = + Bijection.of(Decimal5_2::value, ::Decimal5_2) + + val sqliteType: SqliteType = + SqliteTypes.numeric.to(Bijection.of(::Decimal5_2, Decimal5_2::value)) + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/precisetypes/Int10.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/precisetypes/Int10.kt new file mode 100644 index 0000000000..744161f263 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/precisetypes/Int10.kt @@ -0,0 +1,64 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precisetypes + +import com.fasterxml.jackson.annotation.JsonValue +import dev.typr.foundations.data.precise.DecimalN +import dev.typr.foundationskt.Bijection +import dev.typr.foundationskt.SqliteType +import dev.typr.foundationskt.SqliteTypes +import java.lang.IllegalArgumentException +import java.math.BigDecimal +import java.math.BigInteger + +@kotlin.ConsistentCopyVisibility +data class Int10 private constructor(@field:JsonValue val value: BigInteger) : DecimalN { + override fun decimalValue(): BigDecimal = BigDecimal(value) + + override fun equals(other: Any?): kotlin.Boolean { + if (this === other) return true + if (other !is DecimalN) return false + return decimalValue().compareTo(other.decimalValue()) == 0 + } + + override fun hashCode(): Int = decimalValue().stripTrailingZeros().hashCode() + + override fun precision(): Int = 10 + + override fun scale(): Int = 0 + + override fun semanticEquals(other: DecimalN): kotlin.Boolean = if (other == null) false else decimalValue().compareTo(other.decimalValue()) == 0 + + override fun semanticHashCode(): Int = decimalValue().stripTrailingZeros().hashCode() + + override fun toString(): kotlin.String { + return value.toString() + } + + companion object { + fun of(value: BigInteger): Int10? = if (value.bitLength() <= 40) Int10(value) else null + + fun unsafeForce(value: BigInteger): Int10 { + if (value.bitLength() > 40) { + throw IllegalArgumentException("Value exceeds precision(10, 0)") + } + return Int10(value) + } + + fun of(value: Int): Int10 = Int10(BigInteger.valueOf(value.toLong())) + + fun of(value: kotlin.Long): Int10? = Int10.of(BigInteger.valueOf(value)) + + val Zero: Int10 = + Int10(BigInteger.ZERO) + + val bijection: Bijection = + Bijection.of(Int10::value, ::Int10) + + val sqliteType: SqliteType = + SqliteTypes.numeric.to(Bijection.of({ bd: BigDecimal -> Int10(bd.toBigIntegerExact()) }, { v: Int10 -> BigDecimal(v.value) })) + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/precisetypes/Int18.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/precisetypes/Int18.kt new file mode 100644 index 0000000000..80867983f2 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/precisetypes/Int18.kt @@ -0,0 +1,64 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precisetypes + +import com.fasterxml.jackson.annotation.JsonValue +import dev.typr.foundations.data.precise.DecimalN +import dev.typr.foundationskt.Bijection +import dev.typr.foundationskt.SqliteType +import dev.typr.foundationskt.SqliteTypes +import java.lang.IllegalArgumentException +import java.math.BigDecimal +import java.math.BigInteger + +@kotlin.ConsistentCopyVisibility +data class Int18 private constructor(@field:JsonValue val value: BigInteger) : DecimalN { + override fun decimalValue(): BigDecimal = BigDecimal(value) + + override fun equals(other: Any?): kotlin.Boolean { + if (this === other) return true + if (other !is DecimalN) return false + return decimalValue().compareTo(other.decimalValue()) == 0 + } + + override fun hashCode(): Int = decimalValue().stripTrailingZeros().hashCode() + + override fun precision(): Int = 18 + + override fun scale(): Int = 0 + + override fun semanticEquals(other: DecimalN): kotlin.Boolean = if (other == null) false else decimalValue().compareTo(other.decimalValue()) == 0 + + override fun semanticHashCode(): Int = decimalValue().stripTrailingZeros().hashCode() + + override fun toString(): kotlin.String { + return value.toString() + } + + companion object { + fun of(value: BigInteger): Int18? = if (value.bitLength() <= 72) Int18(value) else null + + fun unsafeForce(value: BigInteger): Int18 { + if (value.bitLength() > 72) { + throw IllegalArgumentException("Value exceeds precision(18, 0)") + } + return Int18(value) + } + + fun of(value: Int): Int18 = Int18(BigInteger.valueOf(value.toLong())) + + fun of(value: kotlin.Long): Int18? = Int18.of(BigInteger.valueOf(value)) + + val Zero: Int18 = + Int18(BigInteger.ZERO) + + val bijection: Bijection = + Bijection.of(Int18::value, ::Int18) + + val sqliteType: SqliteType = + SqliteTypes.numeric.to(Bijection.of({ bd: BigDecimal -> Int18(bd.toBigIntegerExact()) }, { v: Int18 -> BigDecimal(v.value) })) + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/precisetypes/Int5.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/precisetypes/Int5.kt new file mode 100644 index 0000000000..61be8296bc --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/precisetypes/Int5.kt @@ -0,0 +1,64 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precisetypes + +import com.fasterxml.jackson.annotation.JsonValue +import dev.typr.foundations.data.precise.DecimalN +import dev.typr.foundationskt.Bijection +import dev.typr.foundationskt.SqliteType +import dev.typr.foundationskt.SqliteTypes +import java.lang.IllegalArgumentException +import java.math.BigDecimal +import java.math.BigInteger + +@kotlin.ConsistentCopyVisibility +data class Int5 private constructor(@field:JsonValue val value: BigInteger) : DecimalN { + override fun decimalValue(): BigDecimal = BigDecimal(value) + + override fun equals(other: Any?): kotlin.Boolean { + if (this === other) return true + if (other !is DecimalN) return false + return decimalValue().compareTo(other.decimalValue()) == 0 + } + + override fun hashCode(): Int = decimalValue().stripTrailingZeros().hashCode() + + override fun precision(): Int = 5 + + override fun scale(): Int = 0 + + override fun semanticEquals(other: DecimalN): kotlin.Boolean = if (other == null) false else decimalValue().compareTo(other.decimalValue()) == 0 + + override fun semanticHashCode(): Int = decimalValue().stripTrailingZeros().hashCode() + + override fun toString(): kotlin.String { + return value.toString() + } + + companion object { + fun of(value: BigInteger): Int5? = if (value.bitLength() <= 20) Int5(value) else null + + fun unsafeForce(value: BigInteger): Int5 { + if (value.bitLength() > 20) { + throw IllegalArgumentException("Value exceeds precision(5, 0)") + } + return Int5(value) + } + + fun of(value: Int): Int5 = Int5(BigInteger.valueOf(value.toLong())) + + fun of(value: kotlin.Long): Int5? = Int5.of(BigInteger.valueOf(value)) + + val Zero: Int5 = + Int5(BigInteger.ZERO) + + val bijection: Bijection = + Bijection.of(Int5::value, ::Int5) + + val sqliteType: SqliteType = + SqliteTypes.numeric.to(Bijection.of({ bd: BigDecimal -> Int5(bd.toBigIntegerExact()) }, { v: Int5 -> BigDecimal(v.value) })) + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/precisetypes/String10.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/precisetypes/String10.kt new file mode 100644 index 0000000000..bd99dc8b5e --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/precisetypes/String10.kt @@ -0,0 +1,55 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precisetypes + +import com.fasterxml.jackson.annotation.JsonValue +import dev.typr.foundations.data.precise.StringN +import dev.typr.foundationskt.Bijection +import dev.typr.foundationskt.SqliteType +import dev.typr.foundationskt.SqliteTypes +import java.lang.IllegalArgumentException + +@kotlin.ConsistentCopyVisibility +data class String10 private constructor(@field:JsonValue val value: kotlin.String) : StringN { + override fun equals(other: Any?): kotlin.Boolean { + if (this === other) return true + if (other !is StringN) return false + return value == other.rawValue() + } + + override fun hashCode(): Int = value.hashCode() + + override fun maxLength(): Int = 10 + + override fun rawValue(): kotlin.String = value + + override fun semanticEquals(other: StringN): kotlin.Boolean = if (other == null) false else (value == other.rawValue()) + + override fun semanticHashCode(): Int = value.hashCode() + + override fun toString(): kotlin.String { + return value + } + + companion object { + fun of(value: kotlin.String): String10? = if (value.length <= 10) String10(value) else null + + fun unsafeForce(value: kotlin.String): String10 { + if (value.length > 10) { + throw IllegalArgumentException("Value length ${value.length} exceeds maximum 10") + } + return String10(value) + } + + fun truncate(value: kotlin.String): String10 = String10(if (value.length <= 10) value else value.substring(0, 10)) + + val bijection: Bijection = + Bijection.of(String10::value, ::String10) + + val sqliteType: SqliteType = + SqliteTypes.varchar.to(Bijection.of(::String10, String10::value)) + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/precisetypes/String100.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/precisetypes/String100.kt new file mode 100644 index 0000000000..d7355e49c6 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/precisetypes/String100.kt @@ -0,0 +1,55 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precisetypes + +import com.fasterxml.jackson.annotation.JsonValue +import dev.typr.foundations.data.precise.StringN +import dev.typr.foundationskt.Bijection +import dev.typr.foundationskt.SqliteType +import dev.typr.foundationskt.SqliteTypes +import java.lang.IllegalArgumentException + +@kotlin.ConsistentCopyVisibility +data class String100 private constructor(@field:JsonValue val value: kotlin.String) : StringN { + override fun equals(other: Any?): kotlin.Boolean { + if (this === other) return true + if (other !is StringN) return false + return value == other.rawValue() + } + + override fun hashCode(): Int = value.hashCode() + + override fun maxLength(): Int = 100 + + override fun rawValue(): kotlin.String = value + + override fun semanticEquals(other: StringN): kotlin.Boolean = if (other == null) false else (value == other.rawValue()) + + override fun semanticHashCode(): Int = value.hashCode() + + override fun toString(): kotlin.String { + return value + } + + companion object { + fun of(value: kotlin.String): String100? = if (value.length <= 100) String100(value) else null + + fun unsafeForce(value: kotlin.String): String100 { + if (value.length > 100) { + throw IllegalArgumentException("Value length ${value.length} exceeds maximum 100") + } + return String100(value) + } + + fun truncate(value: kotlin.String): String100 = String100(if (value.length <= 100) value else value.substring(0, 100)) + + val bijection: Bijection = + Bijection.of(String100::value, ::String100) + + val sqliteType: SqliteType = + SqliteTypes.varchar.to(Bijection.of(::String100, String100::value)) + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/precisetypes/String20.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/precisetypes/String20.kt new file mode 100644 index 0000000000..806519fbb6 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/precisetypes/String20.kt @@ -0,0 +1,55 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precisetypes + +import com.fasterxml.jackson.annotation.JsonValue +import dev.typr.foundations.data.precise.StringN +import dev.typr.foundationskt.Bijection +import dev.typr.foundationskt.SqliteType +import dev.typr.foundationskt.SqliteTypes +import java.lang.IllegalArgumentException + +@kotlin.ConsistentCopyVisibility +data class String20 private constructor(@field:JsonValue val value: kotlin.String) : StringN { + override fun equals(other: Any?): kotlin.Boolean { + if (this === other) return true + if (other !is StringN) return false + return value == other.rawValue() + } + + override fun hashCode(): Int = value.hashCode() + + override fun maxLength(): Int = 20 + + override fun rawValue(): kotlin.String = value + + override fun semanticEquals(other: StringN): kotlin.Boolean = if (other == null) false else (value == other.rawValue()) + + override fun semanticHashCode(): Int = value.hashCode() + + override fun toString(): kotlin.String { + return value + } + + companion object { + fun of(value: kotlin.String): String20? = if (value.length <= 20) String20(value) else null + + fun unsafeForce(value: kotlin.String): String20 { + if (value.length > 20) { + throw IllegalArgumentException("Value length ${value.length} exceeds maximum 20") + } + return String20(value) + } + + fun truncate(value: kotlin.String): String20 = String20(if (value.length <= 20) value else value.substring(0, 20)) + + val bijection: Bijection = + Bijection.of(String20::value, ::String20) + + val sqliteType: SqliteType = + SqliteTypes.varchar.to(Bijection.of(::String20, String20::value)) + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/precisetypes/String255.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/precisetypes/String255.kt new file mode 100644 index 0000000000..8fac0762b2 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/precisetypes/String255.kt @@ -0,0 +1,55 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precisetypes + +import com.fasterxml.jackson.annotation.JsonValue +import dev.typr.foundations.data.precise.StringN +import dev.typr.foundationskt.Bijection +import dev.typr.foundationskt.SqliteType +import dev.typr.foundationskt.SqliteTypes +import java.lang.IllegalArgumentException + +@kotlin.ConsistentCopyVisibility +data class String255 private constructor(@field:JsonValue val value: kotlin.String) : StringN { + override fun equals(other: Any?): kotlin.Boolean { + if (this === other) return true + if (other !is StringN) return false + return value == other.rawValue() + } + + override fun hashCode(): Int = value.hashCode() + + override fun maxLength(): Int = 255 + + override fun rawValue(): kotlin.String = value + + override fun semanticEquals(other: StringN): kotlin.Boolean = if (other == null) false else (value == other.rawValue()) + + override fun semanticHashCode(): Int = value.hashCode() + + override fun toString(): kotlin.String { + return value + } + + companion object { + fun of(value: kotlin.String): String255? = if (value.length <= 255) String255(value) else null + + fun unsafeForce(value: kotlin.String): String255 { + if (value.length > 255) { + throw IllegalArgumentException("Value length ${value.length} exceeds maximum 255") + } + return String255(value) + } + + fun truncate(value: kotlin.String): String255 = String255(if (value.length <= 255) value else value.substring(0, 255)) + + val bijection: Bijection = + Bijection.of(String255::value, ::String255) + + val sqliteType: SqliteType = + SqliteTypes.varchar.to(Bijection.of(::String255, String255::value)) + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/precisetypes/String50.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/precisetypes/String50.kt new file mode 100644 index 0000000000..7a4ac614d8 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/precisetypes/String50.kt @@ -0,0 +1,55 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precisetypes + +import com.fasterxml.jackson.annotation.JsonValue +import dev.typr.foundations.data.precise.StringN +import dev.typr.foundationskt.Bijection +import dev.typr.foundationskt.SqliteType +import dev.typr.foundationskt.SqliteTypes +import java.lang.IllegalArgumentException + +@kotlin.ConsistentCopyVisibility +data class String50 private constructor(@field:JsonValue val value: kotlin.String) : StringN { + override fun equals(other: Any?): kotlin.Boolean { + if (this === other) return true + if (other !is StringN) return false + return value == other.rawValue() + } + + override fun hashCode(): Int = value.hashCode() + + override fun maxLength(): Int = 50 + + override fun rawValue(): kotlin.String = value + + override fun semanticEquals(other: StringN): kotlin.Boolean = if (other == null) false else (value == other.rawValue()) + + override fun semanticHashCode(): Int = value.hashCode() + + override fun toString(): kotlin.String { + return value + } + + companion object { + fun of(value: kotlin.String): String50? = if (value.length <= 50) String50(value) else null + + fun unsafeForce(value: kotlin.String): String50 { + if (value.length > 50) { + throw IllegalArgumentException("Value length ${value.length} exceeds maximum 50") + } + return String50(value) + } + + fun truncate(value: kotlin.String): String50 = String50(if (value.length <= 50) value else value.substring(0, 50)) + + val bijection: Bijection = + Bijection.of(String50::value, ::String50) + + val sqliteType: SqliteType = + SqliteTypes.varchar.to(Bijection.of(::String50, String50::value)) + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/precision_types/PrecisionTypesFields.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/precision_types/PrecisionTypesFields.kt new file mode 100644 index 0000000000..8160a6a42d --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/precision_types/PrecisionTypesFields.kt @@ -0,0 +1,90 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precision_types + +import dev.typr.dsl.FieldsBase +import dev.typr.dsl.Path +import dev.typr.dsl.SqlExpr.FieldLike +import dev.typr.dslkt.RelationStructure +import dev.typr.dslkt.SqlExpr +import dev.typr.dslkt.SqlExpr.Field +import dev.typr.dslkt.SqlExpr.IdField +import dev.typr.dslkt.TupleExpr12 +import dev.typr.foundations.RowCodec +import kotlin.collections.List +import testdb.precisetypes.Decimal10_2 +import testdb.precisetypes.Decimal18_4 +import testdb.precisetypes.Decimal5_2 +import testdb.precisetypes.Int10 +import testdb.precisetypes.Int18 +import testdb.precisetypes.Int5 +import testdb.precisetypes.String10 +import testdb.precisetypes.String100 +import testdb.precisetypes.String20 +import testdb.precisetypes.String255 +import testdb.precisetypes.String50 + +data class PrecisionTypesFields(val _path: List) : TupleExpr12, RelationStructure, FieldsBase { + override fun _1(): SqlExpr = id() + + override fun _10(): SqlExpr = decimal50() + + override fun _11(): SqlExpr = decimal100() + + override fun _12(): SqlExpr = decimal180() + + override fun _2(): SqlExpr = string10() + + override fun _3(): SqlExpr = string20() + + override fun _4(): SqlExpr = string50() + + override fun _5(): SqlExpr = string100() + + override fun _6(): SqlExpr = string255() + + override fun _7(): SqlExpr = decimal52() + + override fun _8(): SqlExpr = decimal102() + + override fun _9(): SqlExpr = decimal184() + + override fun _path(): List = _path + + override fun columns(): List> = listOf(this.id().underlying, this.string10().underlying, this.string20().underlying, this.string50().underlying, this.string100().underlying, this.string255().underlying, this.decimal52().underlying, this.decimal102().underlying, this.decimal184().underlying, this.decimal50().underlying, this.decimal100().underlying, this.decimal180().underlying) + + fun decimal100(): Field = Field(_path, "decimal10_0", PrecisionTypesRow::decimal100, null, null, { row, value -> row.copy(decimal100 = value) }, Int10.sqliteType.underlying) + + fun decimal102(): Field = Field(_path, "decimal10_2", PrecisionTypesRow::decimal102, null, null, { row, value -> row.copy(decimal102 = value) }, Decimal10_2.sqliteType.underlying) + + fun decimal180(): Field = Field(_path, "decimal18_0", PrecisionTypesRow::decimal180, null, null, { row, value -> row.copy(decimal180 = value) }, Int18.sqliteType.underlying) + + fun decimal184(): Field = Field(_path, "decimal18_4", PrecisionTypesRow::decimal184, null, null, { row, value -> row.copy(decimal184 = value) }, Decimal18_4.sqliteType.underlying) + + fun decimal50(): Field = Field(_path, "decimal5_0", PrecisionTypesRow::decimal50, null, null, { row, value -> row.copy(decimal50 = value) }, Int5.sqliteType.underlying) + + fun decimal52(): Field = Field(_path, "decimal5_2", PrecisionTypesRow::decimal52, null, null, { row, value -> row.copy(decimal52 = value) }, Decimal5_2.sqliteType.underlying) + + fun id(): IdField = IdField(_path, "id", PrecisionTypesRow::id, null, null, { row, value -> row.copy(id = value) }, PrecisionTypesId.sqliteType.underlying) + + override fun rowCodec(): RowCodec = PrecisionTypesRow.rowCodec.underlying + + fun string10(): Field = Field(_path, "string10", PrecisionTypesRow::string10, null, null, { row, value -> row.copy(string10 = value) }, String10.sqliteType.underlying) + + fun string100(): Field = Field(_path, "string100", PrecisionTypesRow::string100, null, null, { row, value -> row.copy(string100 = value) }, String100.sqliteType.underlying) + + fun string20(): Field = Field(_path, "string20", PrecisionTypesRow::string20, null, null, { row, value -> row.copy(string20 = value) }, String20.sqliteType.underlying) + + fun string255(): Field = Field(_path, "string255", PrecisionTypesRow::string255, null, null, { row, value -> row.copy(string255 = value) }, String255.sqliteType.underlying) + + fun string50(): Field = Field(_path, "string50", PrecisionTypesRow::string50, null, null, { row, value -> row.copy(string50 = value) }, String50.sqliteType.underlying) + + override fun withPaths(_path: List): RelationStructure = PrecisionTypesFields(_path) + + companion object { + val structure: PrecisionTypesFields = PrecisionTypesFields(emptyList()) + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/precision_types/PrecisionTypesId.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/precision_types/PrecisionTypesId.kt new file mode 100644 index 0000000000..5714b2eba0 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/precision_types/PrecisionTypesId.kt @@ -0,0 +1,26 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precision_types + +import com.fasterxml.jackson.annotation.JsonValue +import dev.typr.foundationskt.Bijection +import dev.typr.foundationskt.SqliteType +import dev.typr.foundationskt.SqliteTypes + +/** Type for the primary key of table `precision_types` */ +data class PrecisionTypesId(@field:JsonValue val value: kotlin.Long) { + override fun toString(): kotlin.String { + return value.toString() + } + + companion object { + val bijection: Bijection = + Bijection.of(PrecisionTypesId::value, ::PrecisionTypesId) + + val sqliteType: SqliteType = + SqliteTypes.integer.to(Bijection.of(::PrecisionTypesId, PrecisionTypesId::value)) + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/precision_types/PrecisionTypesRepo.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/precision_types/PrecisionTypesRepo.kt new file mode 100644 index 0000000000..0bfcaefaf1 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/precision_types/PrecisionTypesRepo.kt @@ -0,0 +1,70 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precision_types + +import dev.typr.dslkt.DeleteBuilder +import dev.typr.dslkt.SelectBuilder +import dev.typr.dslkt.UpdateBuilder +import dev.typr.foundationskt.Connection +import dev.typr.foundationskt.ConnectionRead +import kotlin.collections.Iterator +import kotlin.collections.List +import kotlin.collections.Map + +interface PrecisionTypesRepo { + abstract fun delete(): DeleteBuilder + + abstract fun deleteById( + id: PrecisionTypesId, + c: Connection + ): kotlin.Boolean + + abstract fun deleteByIds( + ids: List, + c: Connection + ): Int + + abstract fun insert( + unsaved: PrecisionTypesRow, + c: Connection + ): PrecisionTypesRow + + abstract fun select(): SelectBuilder + + abstract fun selectAll(c: ConnectionRead): List + + abstract fun selectById( + id: PrecisionTypesId, + c: ConnectionRead + ): PrecisionTypesRow? + + abstract fun selectByIds( + ids: List, + c: ConnectionRead + ): List + + abstract fun selectByIdsTracked( + ids: List, + c: ConnectionRead + ): Map + + abstract fun update(): UpdateBuilder + + abstract fun update( + row: PrecisionTypesRow, + c: Connection + ): kotlin.Boolean + + abstract fun upsert( + unsaved: PrecisionTypesRow, + c: Connection + ): PrecisionTypesRow + + abstract fun upsertBatch( + unsaved: Iterator, + c: Connection + ): List +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/precision_types/PrecisionTypesRepoImpl.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/precision_types/PrecisionTypesRepoImpl.kt new file mode 100644 index 0000000000..d045c912d1 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/precision_types/PrecisionTypesRepoImpl.kt @@ -0,0 +1,105 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precision_types + +import dev.typr.dslkt.DeleteBuilder +import dev.typr.dslkt.Dialect +import dev.typr.dslkt.SelectBuilder +import dev.typr.dslkt.UpdateBuilder +import dev.typr.foundationskt.Connection +import dev.typr.foundationskt.ConnectionRead +import dev.typr.foundationskt.Fragment +import java.util.ArrayList +import kotlin.collections.Iterator +import kotlin.collections.List +import kotlin.collections.Map +import kotlin.collections.MutableMap +import testdb.precisetypes.Decimal10_2 +import testdb.precisetypes.Decimal18_4 +import testdb.precisetypes.Decimal5_2 +import testdb.precisetypes.Int10 +import testdb.precisetypes.Int18 +import testdb.precisetypes.Int5 +import testdb.precisetypes.String10 +import testdb.precisetypes.String100 +import testdb.precisetypes.String20 +import testdb.precisetypes.String255 +import testdb.precisetypes.String50 + +class PrecisionTypesRepoImpl() : PrecisionTypesRepo { + override fun delete(): DeleteBuilder = DeleteBuilder.of("\"precision_types\"", PrecisionTypesFields.structure, Dialect.SQLITE) + + override fun deleteById( + id: PrecisionTypesId, + c: Connection + ): kotlin.Boolean = Fragment.concat(Fragment.of("delete from \"precision_types\" where \"id\" = "), Fragment.encode(PrecisionTypesId.sqliteType, id), Fragment.of("")).update().run(c) > 0 + + override fun deleteByIds( + ids: List, + c: Connection + ): Int { + val fragments: ArrayList = ArrayList() + for (id in ids) { fragments.add(Fragment.encode(PrecisionTypesId.sqliteType, id)) } + return Fragment.concat(Fragment.of("delete from \"precision_types\" where \"id\" in ("), Fragment.comma(fragments.toMutableList()), Fragment.of(")")).update().run(c) + } + + override fun insert( + unsaved: PrecisionTypesRow, + c: Connection + ): PrecisionTypesRow = Fragment.concat(Fragment.of("insert into \"precision_types\"(\"id\", \"string10\", \"string20\", \"string50\", \"string100\", \"string255\", \"decimal5_2\", \"decimal10_2\", \"decimal18_4\", \"decimal5_0\", \"decimal10_0\", \"decimal18_0\")\nvalues ("), Fragment.encode(PrecisionTypesId.sqliteType, unsaved.id), Fragment.of(", "), Fragment.encode(String10.sqliteType, unsaved.string10), Fragment.of(", "), Fragment.encode(String20.sqliteType, unsaved.string20), Fragment.of(", "), Fragment.encode(String50.sqliteType, unsaved.string50), Fragment.of(", "), Fragment.encode(String100.sqliteType, unsaved.string100), Fragment.of(", "), Fragment.encode(String255.sqliteType, unsaved.string255), Fragment.of(", "), Fragment.encode(Decimal5_2.sqliteType, unsaved.decimal52), Fragment.of(", "), Fragment.encode(Decimal10_2.sqliteType, unsaved.decimal102), Fragment.of(", "), Fragment.encode(Decimal18_4.sqliteType, unsaved.decimal184), Fragment.of(", "), Fragment.encode(Int5.sqliteType, unsaved.decimal50), Fragment.of(", "), Fragment.encode(Int10.sqliteType, unsaved.decimal100), Fragment.of(", "), Fragment.encode(Int18.sqliteType, unsaved.decimal180), Fragment.of(")\nRETURNING \"id\", \"string10\", \"string20\", \"string50\", \"string100\", \"string255\", \"decimal5_2\", \"decimal10_2\", \"decimal18_4\", \"decimal5_0\", \"decimal10_0\", \"decimal18_0\"\n")) + .updateReturning(PrecisionTypesRow.rowCodec.exactlyOne()).run(c) + + override fun select(): SelectBuilder = SelectBuilder.of("\"precision_types\"", PrecisionTypesFields.structure, PrecisionTypesRow.rowCodec, Dialect.SQLITE) + + override fun selectAll(c: ConnectionRead): List = Fragment.concat(Fragment.of("select \"id\", \"string10\", \"string20\", \"string50\", \"string100\", \"string255\", \"decimal5_2\", \"decimal10_2\", \"decimal18_4\", \"decimal5_0\", \"decimal10_0\", \"decimal18_0\"\nfrom \"precision_types\"\n")).query(PrecisionTypesRow.rowCodec.all()).run(c) + + override fun selectById( + id: PrecisionTypesId, + c: ConnectionRead + ): PrecisionTypesRow? = Fragment.concat(Fragment.of("select \"id\", \"string10\", \"string20\", \"string50\", \"string100\", \"string255\", \"decimal5_2\", \"decimal10_2\", \"decimal18_4\", \"decimal5_0\", \"decimal10_0\", \"decimal18_0\"\nfrom \"precision_types\"\nwhere \"id\" = "), Fragment.encode(PrecisionTypesId.sqliteType, id), Fragment.of("")).query(PrecisionTypesRow.rowCodec.first()).run(c) + + override fun selectByIds( + ids: List, + c: ConnectionRead + ): List { + val fragments: ArrayList = ArrayList() + for (id in ids) { fragments.add(Fragment.encode(PrecisionTypesId.sqliteType, id)) } + return Fragment.concat(Fragment.of("select \"id\", \"string10\", \"string20\", \"string50\", \"string100\", \"string255\", \"decimal5_2\", \"decimal10_2\", \"decimal18_4\", \"decimal5_0\", \"decimal10_0\", \"decimal18_0\" from \"precision_types\" where \"id\" in ("), Fragment.comma(fragments.toMutableList()), Fragment.of(")")).query(PrecisionTypesRow.rowCodec.all()).run(c) + } + + override fun selectByIdsTracked( + ids: List, + c: ConnectionRead + ): Map { + val ret: MutableMap = mutableMapOf() + selectByIds(ids, c).forEach({ row -> ret.put(row.id, row) }) + return ret.toMap() + } + + override fun update(): UpdateBuilder = UpdateBuilder.of("\"precision_types\"", PrecisionTypesFields.structure, PrecisionTypesRow.rowCodec, Dialect.SQLITE) + + override fun update( + row: PrecisionTypesRow, + c: Connection + ): kotlin.Boolean { + val id: PrecisionTypesId = row.id + return Fragment.concat(Fragment.of("update \"precision_types\"\nset \"string10\" = "), Fragment.encode(String10.sqliteType, row.string10), Fragment.of(",\n\"string20\" = "), Fragment.encode(String20.sqliteType, row.string20), Fragment.of(",\n\"string50\" = "), Fragment.encode(String50.sqliteType, row.string50), Fragment.of(",\n\"string100\" = "), Fragment.encode(String100.sqliteType, row.string100), Fragment.of(",\n\"string255\" = "), Fragment.encode(String255.sqliteType, row.string255), Fragment.of(",\n\"decimal5_2\" = "), Fragment.encode(Decimal5_2.sqliteType, row.decimal52), Fragment.of(",\n\"decimal10_2\" = "), Fragment.encode(Decimal10_2.sqliteType, row.decimal102), Fragment.of(",\n\"decimal18_4\" = "), Fragment.encode(Decimal18_4.sqliteType, row.decimal184), Fragment.of(",\n\"decimal5_0\" = "), Fragment.encode(Int5.sqliteType, row.decimal50), Fragment.of(",\n\"decimal10_0\" = "), Fragment.encode(Int10.sqliteType, row.decimal100), Fragment.of(",\n\"decimal18_0\" = "), Fragment.encode(Int18.sqliteType, row.decimal180), Fragment.of("\nwhere \"id\" = "), Fragment.encode(PrecisionTypesId.sqliteType, id), Fragment.of("")).update().run(c) > 0 + } + + override fun upsert( + unsaved: PrecisionTypesRow, + c: Connection + ): PrecisionTypesRow = Fragment.concat(Fragment.of("INSERT INTO \"precision_types\"(\"id\", \"string10\", \"string20\", \"string50\", \"string100\", \"string255\", \"decimal5_2\", \"decimal10_2\", \"decimal18_4\", \"decimal5_0\", \"decimal10_0\", \"decimal18_0\")\nVALUES ("), Fragment.encode(PrecisionTypesId.sqliteType, unsaved.id), Fragment.of(", "), Fragment.encode(String10.sqliteType, unsaved.string10), Fragment.of(", "), Fragment.encode(String20.sqliteType, unsaved.string20), Fragment.of(", "), Fragment.encode(String50.sqliteType, unsaved.string50), Fragment.of(", "), Fragment.encode(String100.sqliteType, unsaved.string100), Fragment.of(", "), Fragment.encode(String255.sqliteType, unsaved.string255), Fragment.of(", "), Fragment.encode(Decimal5_2.sqliteType, unsaved.decimal52), Fragment.of(", "), Fragment.encode(Decimal10_2.sqliteType, unsaved.decimal102), Fragment.of(", "), Fragment.encode(Decimal18_4.sqliteType, unsaved.decimal184), Fragment.of(", "), Fragment.encode(Int5.sqliteType, unsaved.decimal50), Fragment.of(", "), Fragment.encode(Int10.sqliteType, unsaved.decimal100), Fragment.of(", "), Fragment.encode(Int18.sqliteType, unsaved.decimal180), Fragment.of(")\nON CONFLICT (\"id\")\nDO UPDATE SET\n \"string10\" = EXCLUDED.\"string10\",\n\"string20\" = EXCLUDED.\"string20\",\n\"string50\" = EXCLUDED.\"string50\",\n\"string100\" = EXCLUDED.\"string100\",\n\"string255\" = EXCLUDED.\"string255\",\n\"decimal5_2\" = EXCLUDED.\"decimal5_2\",\n\"decimal10_2\" = EXCLUDED.\"decimal10_2\",\n\"decimal18_4\" = EXCLUDED.\"decimal18_4\",\n\"decimal5_0\" = EXCLUDED.\"decimal5_0\",\n\"decimal10_0\" = EXCLUDED.\"decimal10_0\",\n\"decimal18_0\" = EXCLUDED.\"decimal18_0\"\nRETURNING \"id\", \"string10\", \"string20\", \"string50\", \"string100\", \"string255\", \"decimal5_2\", \"decimal10_2\", \"decimal18_4\", \"decimal5_0\", \"decimal10_0\", \"decimal18_0\"")) + .updateReturning(PrecisionTypesRow.rowCodec.exactlyOne()) + .run(c) + + override fun upsertBatch( + unsaved: Iterator, + c: Connection + ): List = Fragment.concat(Fragment.of("INSERT INTO \"precision_types\"(\"id\", \"string10\", \"string20\", \"string50\", \"string100\", \"string255\", \"decimal5_2\", \"decimal10_2\", \"decimal18_4\", \"decimal5_0\", \"decimal10_0\", \"decimal18_0\")\nVALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\nON CONFLICT (\"id\")\nDO UPDATE SET\n \"string10\" = EXCLUDED.\"string10\",\n\"string20\" = EXCLUDED.\"string20\",\n\"string50\" = EXCLUDED.\"string50\",\n\"string100\" = EXCLUDED.\"string100\",\n\"string255\" = EXCLUDED.\"string255\",\n\"decimal5_2\" = EXCLUDED.\"decimal5_2\",\n\"decimal10_2\" = EXCLUDED.\"decimal10_2\",\n\"decimal18_4\" = EXCLUDED.\"decimal18_4\",\n\"decimal5_0\" = EXCLUDED.\"decimal5_0\",\n\"decimal10_0\" = EXCLUDED.\"decimal10_0\",\n\"decimal18_0\" = EXCLUDED.\"decimal18_0\"\nRETURNING \"id\", \"string10\", \"string20\", \"string50\", \"string100\", \"string255\", \"decimal5_2\", \"decimal10_2\", \"decimal18_4\", \"decimal5_0\", \"decimal10_0\", \"decimal18_0\"")) + .updateReturningEach(PrecisionTypesRow.rowCodec, unsaved) + .run(c) +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/precision_types/PrecisionTypesRepoMock.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/precision_types/PrecisionTypesRepoMock.kt new file mode 100644 index 0000000000..f25e6b7613 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/precision_types/PrecisionTypesRepoMock.kt @@ -0,0 +1,119 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precision_types + +import dev.typr.dslkt.DeleteBuilder +import dev.typr.dslkt.DeleteBuilderMock +import dev.typr.dslkt.DeleteParams +import dev.typr.dslkt.SelectBuilder +import dev.typr.dslkt.SelectBuilderMock +import dev.typr.dslkt.SelectParams +import dev.typr.dslkt.UpdateBuilder +import dev.typr.dslkt.UpdateBuilderMock +import dev.typr.dslkt.UpdateParams +import dev.typr.foundationskt.Connection +import dev.typr.foundationskt.ConnectionRead +import java.lang.RuntimeException +import java.util.ArrayList +import kotlin.collections.Iterator +import kotlin.collections.List +import kotlin.collections.Map +import kotlin.collections.MutableMap + +data class PrecisionTypesRepoMock(val map: MutableMap = mutableMapOf()) : PrecisionTypesRepo { + override fun delete(): DeleteBuilder = DeleteBuilderMock(PrecisionTypesFields.structure, { map.values.toList() }, DeleteParams.empty(), { row -> row.id }, { id -> map.remove(id) }) + + override fun deleteById( + id: PrecisionTypesId, + c: Connection + ): kotlin.Boolean = map.remove(id) != null + + override fun deleteByIds( + ids: List, + c: Connection + ): Int { + var count = 0 + for (id in ids) { + if (map.remove(id) != null) { + count = count + 1 + } + } + return count + } + + override fun insert( + unsaved: PrecisionTypesRow, + c: Connection + ): PrecisionTypesRow { + if (map.containsKey(unsaved.id)) { + throw RuntimeException("id " + unsaved.id + " already exists") + } + map[unsaved.id] = unsaved + return unsaved + } + + override fun select(): SelectBuilder = SelectBuilderMock(PrecisionTypesFields.structure, { map.values.toList() }, SelectParams.empty()) + + override fun selectAll(c: ConnectionRead): List = map.values.toList() + + override fun selectById( + id: PrecisionTypesId, + c: ConnectionRead + ): PrecisionTypesRow? = map[id] + + override fun selectByIds( + ids: List, + c: ConnectionRead + ): List { + val result = ArrayList() + for (id in ids) { + val opt = map[id] + if (opt != null) { + result.add(opt) + } + } + return result + } + + override fun selectByIdsTracked( + ids: List, + c: ConnectionRead + ): Map = selectByIds(ids, c).associateBy({ row: PrecisionTypesRow -> row.id }) + + override fun update(): UpdateBuilder = UpdateBuilderMock(PrecisionTypesFields.structure, { map.values.toList() }, UpdateParams.empty(), { row -> row }) + + override fun update( + row: PrecisionTypesRow, + c: Connection + ): kotlin.Boolean { + val shouldUpdate = map[row.id]?.takeIf({ oldRow -> (oldRow != row) }) != null + if (shouldUpdate) { + map[row.id] = row + } + return shouldUpdate + } + + override fun upsert( + unsaved: PrecisionTypesRow, + c: Connection + ): PrecisionTypesRow { + map[unsaved.id] = unsaved + return unsaved + } + + override fun upsertBatch( + unsaved: Iterator, + c: Connection + ): List { + val result = ArrayList() + while (unsaved.hasNext()) { + val row = unsaved.next() + map[row.id] = row + result.add(row) + } + return result + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/precision_types/PrecisionTypesRow.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/precision_types/PrecisionTypesRow.kt new file mode 100644 index 0000000000..e95bbefdf0 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/precision_types/PrecisionTypesRow.kt @@ -0,0 +1,68 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precision_types + +import com.fasterxml.jackson.annotation.JsonProperty +import dev.typr.dslkt.RowCodecs +import dev.typr.foundations.Tuple.Tuple12 +import dev.typr.foundationskt.RowCodec +import testdb.precisetypes.Decimal10_2 +import testdb.precisetypes.Decimal18_4 +import testdb.precisetypes.Decimal5_2 +import testdb.precisetypes.Int10 +import testdb.precisetypes.Int18 +import testdb.precisetypes.Int5 +import testdb.precisetypes.String10 +import testdb.precisetypes.String100 +import testdb.precisetypes.String20 +import testdb.precisetypes.String255 +import testdb.precisetypes.String50 + +/** Table: precision_types + * Primary key: id + */ +data class PrecisionTypesRow( + val id: PrecisionTypesId, + val string10: String10, + val string20: String20, + val string50: String50, + val string100: String100, + val string255: String255, + @field:JsonProperty("decimal5_2") val decimal52: Decimal5_2, + @field:JsonProperty("decimal10_2") val decimal102: Decimal10_2, + @field:JsonProperty("decimal18_4") val decimal184: Decimal18_4, + @field:JsonProperty("decimal5_0") val decimal50: Int5, + @field:JsonProperty("decimal10_0") val decimal100: Int10, + @field:JsonProperty("decimal18_0") val decimal180: Int18 +) : Tuple12 { + override fun _1(): PrecisionTypesId = id + + override fun _10(): Int5 = decimal50 + + override fun _11(): Int10 = decimal100 + + override fun _12(): Int18 = decimal180 + + override fun _2(): String10 = string10 + + override fun _3(): String20 = string20 + + override fun _4(): String50 = string50 + + override fun _5(): String100 = string100 + + override fun _6(): String255 = string255 + + override fun _7(): Decimal5_2 = decimal52 + + override fun _8(): Decimal10_2 = decimal102 + + override fun _9(): Decimal18_4 = decimal184 + + companion object { + val rowCodec: RowCodec = RowCodecs.of(PrecisionTypesId.sqliteType, String10.sqliteType, String20.sqliteType, String50.sqliteType, String100.sqliteType, String255.sqliteType, Decimal5_2.sqliteType, Decimal10_2.sqliteType, Decimal18_4.sqliteType, Int5.sqliteType, Int10.sqliteType, Int18.sqliteType, { t0: PrecisionTypesId, t1: String10, t2: String20, t3: String50, t4: String100, t5: String255, t6: Decimal5_2, t7: Decimal10_2, t8: Decimal18_4, t9: Int5, t10: Int10, t11: Int18 -> PrecisionTypesRow(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11) }, { row: PrecisionTypesRow -> arrayOf(row.id, row.string10, row.string20, row.string50, row.string100, row.string255, row.decimal52, row.decimal102, row.decimal184, row.decimal50, row.decimal100, row.decimal180) }) + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/precision_types_null/PrecisionTypesNullFields.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/precision_types_null/PrecisionTypesNullFields.kt new file mode 100644 index 0000000000..641312439c --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/precision_types_null/PrecisionTypesNullFields.kt @@ -0,0 +1,90 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precision_types_null + +import dev.typr.dsl.FieldsBase +import dev.typr.dsl.Path +import dev.typr.dsl.SqlExpr.FieldLike +import dev.typr.dslkt.RelationStructure +import dev.typr.dslkt.SqlExpr +import dev.typr.dslkt.SqlExpr.IdField +import dev.typr.dslkt.SqlExpr.OptField +import dev.typr.dslkt.TupleExpr12 +import dev.typr.foundations.RowCodec +import kotlin.collections.List +import testdb.precisetypes.Decimal10_2 +import testdb.precisetypes.Decimal18_4 +import testdb.precisetypes.Decimal5_2 +import testdb.precisetypes.Int10 +import testdb.precisetypes.Int18 +import testdb.precisetypes.Int5 +import testdb.precisetypes.String10 +import testdb.precisetypes.String100 +import testdb.precisetypes.String20 +import testdb.precisetypes.String255 +import testdb.precisetypes.String50 + +data class PrecisionTypesNullFields(val _path: List) : TupleExpr12, RelationStructure, FieldsBase { + override fun _1(): SqlExpr = id() + + override fun _10(): SqlExpr = decimal50() + + override fun _11(): SqlExpr = decimal100() + + override fun _12(): SqlExpr = decimal180() + + override fun _2(): SqlExpr = string10() + + override fun _3(): SqlExpr = string20() + + override fun _4(): SqlExpr = string50() + + override fun _5(): SqlExpr = string100() + + override fun _6(): SqlExpr = string255() + + override fun _7(): SqlExpr = decimal52() + + override fun _8(): SqlExpr = decimal102() + + override fun _9(): SqlExpr = decimal184() + + override fun _path(): List = _path + + override fun columns(): List> = listOf(this.id().underlying, this.string10().underlying, this.string20().underlying, this.string50().underlying, this.string100().underlying, this.string255().underlying, this.decimal52().underlying, this.decimal102().underlying, this.decimal184().underlying, this.decimal50().underlying, this.decimal100().underlying, this.decimal180().underlying) + + fun decimal100(): OptField = OptField(_path, "decimal10_0", PrecisionTypesNullRow::decimal100, null, null, { row, value -> row.copy(decimal100 = value) }, Int10.sqliteType.underlying) + + fun decimal102(): OptField = OptField(_path, "decimal10_2", PrecisionTypesNullRow::decimal102, null, null, { row, value -> row.copy(decimal102 = value) }, Decimal10_2.sqliteType.underlying) + + fun decimal180(): OptField = OptField(_path, "decimal18_0", PrecisionTypesNullRow::decimal180, null, null, { row, value -> row.copy(decimal180 = value) }, Int18.sqliteType.underlying) + + fun decimal184(): OptField = OptField(_path, "decimal18_4", PrecisionTypesNullRow::decimal184, null, null, { row, value -> row.copy(decimal184 = value) }, Decimal18_4.sqliteType.underlying) + + fun decimal50(): OptField = OptField(_path, "decimal5_0", PrecisionTypesNullRow::decimal50, null, null, { row, value -> row.copy(decimal50 = value) }, Int5.sqliteType.underlying) + + fun decimal52(): OptField = OptField(_path, "decimal5_2", PrecisionTypesNullRow::decimal52, null, null, { row, value -> row.copy(decimal52 = value) }, Decimal5_2.sqliteType.underlying) + + fun id(): IdField = IdField(_path, "id", PrecisionTypesNullRow::id, null, null, { row, value -> row.copy(id = value) }, PrecisionTypesNullId.sqliteType.underlying) + + override fun rowCodec(): RowCodec = PrecisionTypesNullRow.rowCodec.underlying + + fun string10(): OptField = OptField(_path, "string10", PrecisionTypesNullRow::string10, null, null, { row, value -> row.copy(string10 = value) }, String10.sqliteType.underlying) + + fun string100(): OptField = OptField(_path, "string100", PrecisionTypesNullRow::string100, null, null, { row, value -> row.copy(string100 = value) }, String100.sqliteType.underlying) + + fun string20(): OptField = OptField(_path, "string20", PrecisionTypesNullRow::string20, null, null, { row, value -> row.copy(string20 = value) }, String20.sqliteType.underlying) + + fun string255(): OptField = OptField(_path, "string255", PrecisionTypesNullRow::string255, null, null, { row, value -> row.copy(string255 = value) }, String255.sqliteType.underlying) + + fun string50(): OptField = OptField(_path, "string50", PrecisionTypesNullRow::string50, null, null, { row, value -> row.copy(string50 = value) }, String50.sqliteType.underlying) + + override fun withPaths(_path: List): RelationStructure = PrecisionTypesNullFields(_path) + + companion object { + val structure: PrecisionTypesNullFields = PrecisionTypesNullFields(emptyList()) + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/precision_types_null/PrecisionTypesNullId.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/precision_types_null/PrecisionTypesNullId.kt new file mode 100644 index 0000000000..3713c9fe7e --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/precision_types_null/PrecisionTypesNullId.kt @@ -0,0 +1,26 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precision_types_null + +import com.fasterxml.jackson.annotation.JsonValue +import dev.typr.foundationskt.Bijection +import dev.typr.foundationskt.SqliteType +import dev.typr.foundationskt.SqliteTypes + +/** Type for the primary key of table `precision_types_null` */ +data class PrecisionTypesNullId(@field:JsonValue val value: kotlin.Long) { + override fun toString(): kotlin.String { + return value.toString() + } + + companion object { + val bijection: Bijection = + Bijection.of(PrecisionTypesNullId::value, ::PrecisionTypesNullId) + + val sqliteType: SqliteType = + SqliteTypes.integer.to(Bijection.of(::PrecisionTypesNullId, PrecisionTypesNullId::value)) + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/precision_types_null/PrecisionTypesNullRepo.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/precision_types_null/PrecisionTypesNullRepo.kt new file mode 100644 index 0000000000..678ed5ffa4 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/precision_types_null/PrecisionTypesNullRepo.kt @@ -0,0 +1,70 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precision_types_null + +import dev.typr.dslkt.DeleteBuilder +import dev.typr.dslkt.SelectBuilder +import dev.typr.dslkt.UpdateBuilder +import dev.typr.foundationskt.Connection +import dev.typr.foundationskt.ConnectionRead +import kotlin.collections.Iterator +import kotlin.collections.List +import kotlin.collections.Map + +interface PrecisionTypesNullRepo { + abstract fun delete(): DeleteBuilder + + abstract fun deleteById( + id: PrecisionTypesNullId, + c: Connection + ): kotlin.Boolean + + abstract fun deleteByIds( + ids: List, + c: Connection + ): Int + + abstract fun insert( + unsaved: PrecisionTypesNullRow, + c: Connection + ): PrecisionTypesNullRow + + abstract fun select(): SelectBuilder + + abstract fun selectAll(c: ConnectionRead): List + + abstract fun selectById( + id: PrecisionTypesNullId, + c: ConnectionRead + ): PrecisionTypesNullRow? + + abstract fun selectByIds( + ids: List, + c: ConnectionRead + ): List + + abstract fun selectByIdsTracked( + ids: List, + c: ConnectionRead + ): Map + + abstract fun update(): UpdateBuilder + + abstract fun update( + row: PrecisionTypesNullRow, + c: Connection + ): kotlin.Boolean + + abstract fun upsert( + unsaved: PrecisionTypesNullRow, + c: Connection + ): PrecisionTypesNullRow + + abstract fun upsertBatch( + unsaved: Iterator, + c: Connection + ): List +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/precision_types_null/PrecisionTypesNullRepoImpl.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/precision_types_null/PrecisionTypesNullRepoImpl.kt new file mode 100644 index 0000000000..3cb9c6c58f --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/precision_types_null/PrecisionTypesNullRepoImpl.kt @@ -0,0 +1,105 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precision_types_null + +import dev.typr.dslkt.DeleteBuilder +import dev.typr.dslkt.Dialect +import dev.typr.dslkt.SelectBuilder +import dev.typr.dslkt.UpdateBuilder +import dev.typr.foundationskt.Connection +import dev.typr.foundationskt.ConnectionRead +import dev.typr.foundationskt.Fragment +import java.util.ArrayList +import kotlin.collections.Iterator +import kotlin.collections.List +import kotlin.collections.Map +import kotlin.collections.MutableMap +import testdb.precisetypes.Decimal10_2 +import testdb.precisetypes.Decimal18_4 +import testdb.precisetypes.Decimal5_2 +import testdb.precisetypes.Int10 +import testdb.precisetypes.Int18 +import testdb.precisetypes.Int5 +import testdb.precisetypes.String10 +import testdb.precisetypes.String100 +import testdb.precisetypes.String20 +import testdb.precisetypes.String255 +import testdb.precisetypes.String50 + +class PrecisionTypesNullRepoImpl() : PrecisionTypesNullRepo { + override fun delete(): DeleteBuilder = DeleteBuilder.of("\"precision_types_null\"", PrecisionTypesNullFields.structure, Dialect.SQLITE) + + override fun deleteById( + id: PrecisionTypesNullId, + c: Connection + ): kotlin.Boolean = Fragment.concat(Fragment.of("delete from \"precision_types_null\" where \"id\" = "), Fragment.encode(PrecisionTypesNullId.sqliteType, id), Fragment.of("")).update().run(c) > 0 + + override fun deleteByIds( + ids: List, + c: Connection + ): Int { + val fragments: ArrayList = ArrayList() + for (id in ids) { fragments.add(Fragment.encode(PrecisionTypesNullId.sqliteType, id)) } + return Fragment.concat(Fragment.of("delete from \"precision_types_null\" where \"id\" in ("), Fragment.comma(fragments.toMutableList()), Fragment.of(")")).update().run(c) + } + + override fun insert( + unsaved: PrecisionTypesNullRow, + c: Connection + ): PrecisionTypesNullRow = Fragment.concat(Fragment.of("insert into \"precision_types_null\"(\"id\", \"string10\", \"string20\", \"string50\", \"string100\", \"string255\", \"decimal5_2\", \"decimal10_2\", \"decimal18_4\", \"decimal5_0\", \"decimal10_0\", \"decimal18_0\")\nvalues ("), Fragment.encode(PrecisionTypesNullId.sqliteType, unsaved.id), Fragment.of(", "), Fragment.encode(String10.sqliteType.opt(), unsaved.string10), Fragment.of(", "), Fragment.encode(String20.sqliteType.opt(), unsaved.string20), Fragment.of(", "), Fragment.encode(String50.sqliteType.opt(), unsaved.string50), Fragment.of(", "), Fragment.encode(String100.sqliteType.opt(), unsaved.string100), Fragment.of(", "), Fragment.encode(String255.sqliteType.opt(), unsaved.string255), Fragment.of(", "), Fragment.encode(Decimal5_2.sqliteType.opt(), unsaved.decimal52), Fragment.of(", "), Fragment.encode(Decimal10_2.sqliteType.opt(), unsaved.decimal102), Fragment.of(", "), Fragment.encode(Decimal18_4.sqliteType.opt(), unsaved.decimal184), Fragment.of(", "), Fragment.encode(Int5.sqliteType.opt(), unsaved.decimal50), Fragment.of(", "), Fragment.encode(Int10.sqliteType.opt(), unsaved.decimal100), Fragment.of(", "), Fragment.encode(Int18.sqliteType.opt(), unsaved.decimal180), Fragment.of(")\nRETURNING \"id\", \"string10\", \"string20\", \"string50\", \"string100\", \"string255\", \"decimal5_2\", \"decimal10_2\", \"decimal18_4\", \"decimal5_0\", \"decimal10_0\", \"decimal18_0\"\n")) + .updateReturning(PrecisionTypesNullRow.rowCodec.exactlyOne()).run(c) + + override fun select(): SelectBuilder = SelectBuilder.of("\"precision_types_null\"", PrecisionTypesNullFields.structure, PrecisionTypesNullRow.rowCodec, Dialect.SQLITE) + + override fun selectAll(c: ConnectionRead): List = Fragment.concat(Fragment.of("select \"id\", \"string10\", \"string20\", \"string50\", \"string100\", \"string255\", \"decimal5_2\", \"decimal10_2\", \"decimal18_4\", \"decimal5_0\", \"decimal10_0\", \"decimal18_0\"\nfrom \"precision_types_null\"\n")).query(PrecisionTypesNullRow.rowCodec.all()).run(c) + + override fun selectById( + id: PrecisionTypesNullId, + c: ConnectionRead + ): PrecisionTypesNullRow? = Fragment.concat(Fragment.of("select \"id\", \"string10\", \"string20\", \"string50\", \"string100\", \"string255\", \"decimal5_2\", \"decimal10_2\", \"decimal18_4\", \"decimal5_0\", \"decimal10_0\", \"decimal18_0\"\nfrom \"precision_types_null\"\nwhere \"id\" = "), Fragment.encode(PrecisionTypesNullId.sqliteType, id), Fragment.of("")).query(PrecisionTypesNullRow.rowCodec.first()).run(c) + + override fun selectByIds( + ids: List, + c: ConnectionRead + ): List { + val fragments: ArrayList = ArrayList() + for (id in ids) { fragments.add(Fragment.encode(PrecisionTypesNullId.sqliteType, id)) } + return Fragment.concat(Fragment.of("select \"id\", \"string10\", \"string20\", \"string50\", \"string100\", \"string255\", \"decimal5_2\", \"decimal10_2\", \"decimal18_4\", \"decimal5_0\", \"decimal10_0\", \"decimal18_0\" from \"precision_types_null\" where \"id\" in ("), Fragment.comma(fragments.toMutableList()), Fragment.of(")")).query(PrecisionTypesNullRow.rowCodec.all()).run(c) + } + + override fun selectByIdsTracked( + ids: List, + c: ConnectionRead + ): Map { + val ret: MutableMap = mutableMapOf() + selectByIds(ids, c).forEach({ row -> ret.put(row.id, row) }) + return ret.toMap() + } + + override fun update(): UpdateBuilder = UpdateBuilder.of("\"precision_types_null\"", PrecisionTypesNullFields.structure, PrecisionTypesNullRow.rowCodec, Dialect.SQLITE) + + override fun update( + row: PrecisionTypesNullRow, + c: Connection + ): kotlin.Boolean { + val id: PrecisionTypesNullId = row.id + return Fragment.concat(Fragment.of("update \"precision_types_null\"\nset \"string10\" = "), Fragment.encode(String10.sqliteType.opt(), row.string10), Fragment.of(",\n\"string20\" = "), Fragment.encode(String20.sqliteType.opt(), row.string20), Fragment.of(",\n\"string50\" = "), Fragment.encode(String50.sqliteType.opt(), row.string50), Fragment.of(",\n\"string100\" = "), Fragment.encode(String100.sqliteType.opt(), row.string100), Fragment.of(",\n\"string255\" = "), Fragment.encode(String255.sqliteType.opt(), row.string255), Fragment.of(",\n\"decimal5_2\" = "), Fragment.encode(Decimal5_2.sqliteType.opt(), row.decimal52), Fragment.of(",\n\"decimal10_2\" = "), Fragment.encode(Decimal10_2.sqliteType.opt(), row.decimal102), Fragment.of(",\n\"decimal18_4\" = "), Fragment.encode(Decimal18_4.sqliteType.opt(), row.decimal184), Fragment.of(",\n\"decimal5_0\" = "), Fragment.encode(Int5.sqliteType.opt(), row.decimal50), Fragment.of(",\n\"decimal10_0\" = "), Fragment.encode(Int10.sqliteType.opt(), row.decimal100), Fragment.of(",\n\"decimal18_0\" = "), Fragment.encode(Int18.sqliteType.opt(), row.decimal180), Fragment.of("\nwhere \"id\" = "), Fragment.encode(PrecisionTypesNullId.sqliteType, id), Fragment.of("")).update().run(c) > 0 + } + + override fun upsert( + unsaved: PrecisionTypesNullRow, + c: Connection + ): PrecisionTypesNullRow = Fragment.concat(Fragment.of("INSERT INTO \"precision_types_null\"(\"id\", \"string10\", \"string20\", \"string50\", \"string100\", \"string255\", \"decimal5_2\", \"decimal10_2\", \"decimal18_4\", \"decimal5_0\", \"decimal10_0\", \"decimal18_0\")\nVALUES ("), Fragment.encode(PrecisionTypesNullId.sqliteType, unsaved.id), Fragment.of(", "), Fragment.encode(String10.sqliteType.opt(), unsaved.string10), Fragment.of(", "), Fragment.encode(String20.sqliteType.opt(), unsaved.string20), Fragment.of(", "), Fragment.encode(String50.sqliteType.opt(), unsaved.string50), Fragment.of(", "), Fragment.encode(String100.sqliteType.opt(), unsaved.string100), Fragment.of(", "), Fragment.encode(String255.sqliteType.opt(), unsaved.string255), Fragment.of(", "), Fragment.encode(Decimal5_2.sqliteType.opt(), unsaved.decimal52), Fragment.of(", "), Fragment.encode(Decimal10_2.sqliteType.opt(), unsaved.decimal102), Fragment.of(", "), Fragment.encode(Decimal18_4.sqliteType.opt(), unsaved.decimal184), Fragment.of(", "), Fragment.encode(Int5.sqliteType.opt(), unsaved.decimal50), Fragment.of(", "), Fragment.encode(Int10.sqliteType.opt(), unsaved.decimal100), Fragment.of(", "), Fragment.encode(Int18.sqliteType.opt(), unsaved.decimal180), Fragment.of(")\nON CONFLICT (\"id\")\nDO UPDATE SET\n \"string10\" = EXCLUDED.\"string10\",\n\"string20\" = EXCLUDED.\"string20\",\n\"string50\" = EXCLUDED.\"string50\",\n\"string100\" = EXCLUDED.\"string100\",\n\"string255\" = EXCLUDED.\"string255\",\n\"decimal5_2\" = EXCLUDED.\"decimal5_2\",\n\"decimal10_2\" = EXCLUDED.\"decimal10_2\",\n\"decimal18_4\" = EXCLUDED.\"decimal18_4\",\n\"decimal5_0\" = EXCLUDED.\"decimal5_0\",\n\"decimal10_0\" = EXCLUDED.\"decimal10_0\",\n\"decimal18_0\" = EXCLUDED.\"decimal18_0\"\nRETURNING \"id\", \"string10\", \"string20\", \"string50\", \"string100\", \"string255\", \"decimal5_2\", \"decimal10_2\", \"decimal18_4\", \"decimal5_0\", \"decimal10_0\", \"decimal18_0\"")) + .updateReturning(PrecisionTypesNullRow.rowCodec.exactlyOne()) + .run(c) + + override fun upsertBatch( + unsaved: Iterator, + c: Connection + ): List = Fragment.concat(Fragment.of("INSERT INTO \"precision_types_null\"(\"id\", \"string10\", \"string20\", \"string50\", \"string100\", \"string255\", \"decimal5_2\", \"decimal10_2\", \"decimal18_4\", \"decimal5_0\", \"decimal10_0\", \"decimal18_0\")\nVALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\nON CONFLICT (\"id\")\nDO UPDATE SET\n \"string10\" = EXCLUDED.\"string10\",\n\"string20\" = EXCLUDED.\"string20\",\n\"string50\" = EXCLUDED.\"string50\",\n\"string100\" = EXCLUDED.\"string100\",\n\"string255\" = EXCLUDED.\"string255\",\n\"decimal5_2\" = EXCLUDED.\"decimal5_2\",\n\"decimal10_2\" = EXCLUDED.\"decimal10_2\",\n\"decimal18_4\" = EXCLUDED.\"decimal18_4\",\n\"decimal5_0\" = EXCLUDED.\"decimal5_0\",\n\"decimal10_0\" = EXCLUDED.\"decimal10_0\",\n\"decimal18_0\" = EXCLUDED.\"decimal18_0\"\nRETURNING \"id\", \"string10\", \"string20\", \"string50\", \"string100\", \"string255\", \"decimal5_2\", \"decimal10_2\", \"decimal18_4\", \"decimal5_0\", \"decimal10_0\", \"decimal18_0\"")) + .updateReturningEach(PrecisionTypesNullRow.rowCodec, unsaved) + .run(c) +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/precision_types_null/PrecisionTypesNullRepoMock.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/precision_types_null/PrecisionTypesNullRepoMock.kt new file mode 100644 index 0000000000..df9ddb5c84 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/precision_types_null/PrecisionTypesNullRepoMock.kt @@ -0,0 +1,119 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precision_types_null + +import dev.typr.dslkt.DeleteBuilder +import dev.typr.dslkt.DeleteBuilderMock +import dev.typr.dslkt.DeleteParams +import dev.typr.dslkt.SelectBuilder +import dev.typr.dslkt.SelectBuilderMock +import dev.typr.dslkt.SelectParams +import dev.typr.dslkt.UpdateBuilder +import dev.typr.dslkt.UpdateBuilderMock +import dev.typr.dslkt.UpdateParams +import dev.typr.foundationskt.Connection +import dev.typr.foundationskt.ConnectionRead +import java.lang.RuntimeException +import java.util.ArrayList +import kotlin.collections.Iterator +import kotlin.collections.List +import kotlin.collections.Map +import kotlin.collections.MutableMap + +data class PrecisionTypesNullRepoMock(val map: MutableMap = mutableMapOf()) : PrecisionTypesNullRepo { + override fun delete(): DeleteBuilder = DeleteBuilderMock(PrecisionTypesNullFields.structure, { map.values.toList() }, DeleteParams.empty(), { row -> row.id }, { id -> map.remove(id) }) + + override fun deleteById( + id: PrecisionTypesNullId, + c: Connection + ): kotlin.Boolean = map.remove(id) != null + + override fun deleteByIds( + ids: List, + c: Connection + ): Int { + var count = 0 + for (id in ids) { + if (map.remove(id) != null) { + count = count + 1 + } + } + return count + } + + override fun insert( + unsaved: PrecisionTypesNullRow, + c: Connection + ): PrecisionTypesNullRow { + if (map.containsKey(unsaved.id)) { + throw RuntimeException("id " + unsaved.id + " already exists") + } + map[unsaved.id] = unsaved + return unsaved + } + + override fun select(): SelectBuilder = SelectBuilderMock(PrecisionTypesNullFields.structure, { map.values.toList() }, SelectParams.empty()) + + override fun selectAll(c: ConnectionRead): List = map.values.toList() + + override fun selectById( + id: PrecisionTypesNullId, + c: ConnectionRead + ): PrecisionTypesNullRow? = map[id] + + override fun selectByIds( + ids: List, + c: ConnectionRead + ): List { + val result = ArrayList() + for (id in ids) { + val opt = map[id] + if (opt != null) { + result.add(opt) + } + } + return result + } + + override fun selectByIdsTracked( + ids: List, + c: ConnectionRead + ): Map = selectByIds(ids, c).associateBy({ row: PrecisionTypesNullRow -> row.id }) + + override fun update(): UpdateBuilder = UpdateBuilderMock(PrecisionTypesNullFields.structure, { map.values.toList() }, UpdateParams.empty(), { row -> row }) + + override fun update( + row: PrecisionTypesNullRow, + c: Connection + ): kotlin.Boolean { + val shouldUpdate = map[row.id]?.takeIf({ oldRow -> (oldRow != row) }) != null + if (shouldUpdate) { + map[row.id] = row + } + return shouldUpdate + } + + override fun upsert( + unsaved: PrecisionTypesNullRow, + c: Connection + ): PrecisionTypesNullRow { + map[unsaved.id] = unsaved + return unsaved + } + + override fun upsertBatch( + unsaved: Iterator, + c: Connection + ): List { + val result = ArrayList() + while (unsaved.hasNext()) { + val row = unsaved.next() + map[row.id] = row + result.add(row) + } + return result + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/precision_types_null/PrecisionTypesNullRow.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/precision_types_null/PrecisionTypesNullRow.kt new file mode 100644 index 0000000000..a5d1b363b2 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/precision_types_null/PrecisionTypesNullRow.kt @@ -0,0 +1,68 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precision_types_null + +import com.fasterxml.jackson.annotation.JsonProperty +import dev.typr.dslkt.RowCodecs +import dev.typr.foundations.Tuple.Tuple12 +import dev.typr.foundationskt.RowCodec +import testdb.precisetypes.Decimal10_2 +import testdb.precisetypes.Decimal18_4 +import testdb.precisetypes.Decimal5_2 +import testdb.precisetypes.Int10 +import testdb.precisetypes.Int18 +import testdb.precisetypes.Int5 +import testdb.precisetypes.String10 +import testdb.precisetypes.String100 +import testdb.precisetypes.String20 +import testdb.precisetypes.String255 +import testdb.precisetypes.String50 + +/** Table: precision_types_null + * Primary key: id + */ +data class PrecisionTypesNullRow( + val id: PrecisionTypesNullId, + val string10: String10?, + val string20: String20?, + val string50: String50?, + val string100: String100?, + val string255: String255?, + @field:JsonProperty("decimal5_2") val decimal52: Decimal5_2?, + @field:JsonProperty("decimal10_2") val decimal102: Decimal10_2?, + @field:JsonProperty("decimal18_4") val decimal184: Decimal18_4?, + @field:JsonProperty("decimal5_0") val decimal50: Int5?, + @field:JsonProperty("decimal10_0") val decimal100: Int10?, + @field:JsonProperty("decimal18_0") val decimal180: Int18? +) : Tuple12 { + override fun _1(): PrecisionTypesNullId = id + + override fun _10(): Int5? = decimal50 + + override fun _11(): Int10? = decimal100 + + override fun _12(): Int18? = decimal180 + + override fun _2(): String10? = string10 + + override fun _3(): String20? = string20 + + override fun _4(): String50? = string50 + + override fun _5(): String100? = string100 + + override fun _6(): String255? = string255 + + override fun _7(): Decimal5_2? = decimal52 + + override fun _8(): Decimal10_2? = decimal102 + + override fun _9(): Decimal18_4? = decimal184 + + companion object { + val rowCodec: RowCodec = RowCodecs.of(PrecisionTypesNullId.sqliteType, String10.sqliteType.opt(), String20.sqliteType.opt(), String50.sqliteType.opt(), String100.sqliteType.opt(), String255.sqliteType.opt(), Decimal5_2.sqliteType.opt(), Decimal10_2.sqliteType.opt(), Decimal18_4.sqliteType.opt(), Int5.sqliteType.opt(), Int10.sqliteType.opt(), Int18.sqliteType.opt(), { t0: PrecisionTypesNullId, t1: String10?, t2: String20?, t3: String50?, t4: String100?, t5: String255?, t6: Decimal5_2?, t7: Decimal10_2?, t8: Decimal18_4?, t9: Int5?, t10: Int10?, t11: Int18? -> PrecisionTypesNullRow(t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11) }, { row: PrecisionTypesNullRow -> arrayOf(row.id, row.string10, row.string20, row.string50, row.string100, row.string255, row.decimal52, row.decimal102, row.decimal184, row.decimal50, row.decimal100, row.decimal180) }) + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/product_details_with_sales/ProductDetailsWithSalesSqlRepo.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/product_details_with_sales/ProductDetailsWithSalesSqlRepo.kt new file mode 100644 index 0000000000..9012d0feb9 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/product_details_with_sales/ProductDetailsWithSalesSqlRepo.kt @@ -0,0 +1,17 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.product_details_with_sales + +import dev.typr.foundationskt.ConnectionRead +import java.math.BigDecimal +import kotlin.collections.List + +interface ProductDetailsWithSalesSqlRepo { + abstract fun apply( + minPrice: BigDecimal?, + c: ConnectionRead + ): List +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/product_details_with_sales/ProductDetailsWithSalesSqlRepoImpl.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/product_details_with_sales/ProductDetailsWithSalesSqlRepoImpl.kt new file mode 100644 index 0000000000..6c1074756f --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/product_details_with_sales/ProductDetailsWithSalesSqlRepoImpl.kt @@ -0,0 +1,19 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.product_details_with_sales + +import dev.typr.foundationskt.ConnectionRead +import dev.typr.foundationskt.Fragment +import dev.typr.foundationskt.SqliteTypes +import java.math.BigDecimal +import kotlin.collections.List + +class ProductDetailsWithSalesSqlRepoImpl() : ProductDetailsWithSalesSqlRepo { + override fun apply( + minPrice: BigDecimal?, + c: ConnectionRead + ): List = Fragment.concat(Fragment.of("-- Product details enriched with cumulative sales numbers.\n-- Tests: subquery in SELECT, joining on FK, ordering by computed column.\n\nSELECT\n p.product_id,\n p.sku,\n p.name AS product_name,\n p.price,\n COALESCE(SUM(oi.quantity), 0) AS total_units_sold,\n COALESCE(SUM(oi.quantity * oi.unit_price), 0) AS total_revenue\nFROM products p\nLEFT JOIN order_items oi ON p.product_id = oi.product_id\nWHERE ("), Fragment.encode(SqliteTypes.numeric.opt(), minPrice), Fragment.of(" IS NULL OR p.price >= "), Fragment.encode(SqliteTypes.numeric.opt(), minPrice), Fragment.of(")\nGROUP BY p.product_id, p.sku, p.name, p.price\nORDER BY total_revenue DESC, p.product_id")).query(ProductDetailsWithSalesSqlRow.rowCodec.all()).run(c) +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/product_details_with_sales/ProductDetailsWithSalesSqlRow.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/product_details_with_sales/ProductDetailsWithSalesSqlRow.kt new file mode 100644 index 0000000000..f46f89fadf --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/product_details_with_sales/ProductDetailsWithSalesSqlRow.kt @@ -0,0 +1,46 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.product_details_with_sales + +import com.fasterxml.jackson.annotation.JsonProperty +import dev.typr.dslkt.RowCodecs +import dev.typr.foundations.Tuple.Tuple6 +import dev.typr.foundationskt.RowCodec +import dev.typr.foundationskt.SqliteTypes +import java.math.BigDecimal +import testdb.products.ProductsId + +/** SQL file: product_details_with_sales.sql */ +data class ProductDetailsWithSalesSqlRow( + /** Points to [testdb.products.ProductsRow.productId] */ + @field:JsonProperty("product_id") val productId: ProductsId, + /** Points to [testdb.products.ProductsRow.sku] */ + val sku: kotlin.String, + /** Points to [testdb.products.ProductsRow.name] */ + @field:JsonProperty("product_name") val productName: kotlin.String, + /** Points to [testdb.products.ProductsRow.price] */ + val price: BigDecimal, + /** Points to [testdb.order_items.OrderItemsRow.quantity] */ + @field:JsonProperty("total_units_sold") val totalUnitsSold: kotlin.Long?, + /** Points to [testdb.order_items.OrderItemsRow.unitPrice] */ + @field:JsonProperty("total_revenue") val totalRevenue: BigDecimal? +) : Tuple6 { + override fun _1(): ProductsId = productId + + override fun _2(): kotlin.String = sku + + override fun _3(): kotlin.String = productName + + override fun _4(): BigDecimal = price + + override fun _5(): kotlin.Long? = totalUnitsSold + + override fun _6(): BigDecimal? = totalRevenue + + companion object { + val rowCodec: RowCodec = RowCodecs.of(ProductsId.sqliteType, SqliteTypes.varchar, SqliteTypes.text, SqliteTypes.numeric, SqliteTypes.bigint.opt(), SqliteTypes.numeric.opt(), { t0: ProductsId, t1: kotlin.String, t2: kotlin.String, t3: BigDecimal, t4: kotlin.Long?, t5: BigDecimal? -> ProductDetailsWithSalesSqlRow(t0, t1, t2, t3, t4, t5) }, { row: ProductDetailsWithSalesSqlRow -> arrayOf(row.productId, row.sku, row.productName, row.price, row.totalUnitsSold, row.totalRevenue) }) + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/products/ProductsFields.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/products/ProductsFields.kt new file mode 100644 index 0000000000..5d07bad9af --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/products/ProductsFields.kt @@ -0,0 +1,55 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.products + +import dev.typr.dsl.FieldsBase +import dev.typr.dsl.Path +import dev.typr.dsl.SqlExpr.FieldLike +import dev.typr.dslkt.RelationStructure +import dev.typr.dslkt.SqlExpr +import dev.typr.dslkt.SqlExpr.Field +import dev.typr.dslkt.SqlExpr.IdField +import dev.typr.dslkt.SqlExpr.OptField +import dev.typr.dslkt.TupleExpr5 +import dev.typr.foundations.RowCodec +import dev.typr.foundations.data.Json +import dev.typr.foundationskt.SqliteTypes +import java.math.BigDecimal +import kotlin.collections.List + +data class ProductsFields(val _path: List) : TupleExpr5, RelationStructure, FieldsBase { + override fun _1(): SqlExpr = productId() + + override fun _2(): SqlExpr = sku() + + override fun _3(): SqlExpr = name() + + override fun _4(): SqlExpr = price() + + override fun _5(): SqlExpr = metadata() + + override fun _path(): List = _path + + override fun columns(): List> = listOf(this.productId().underlying, this.sku().underlying, this.name().underlying, this.price().underlying, this.metadata().underlying) + + fun metadata(): OptField = OptField(_path, "metadata", ProductsRow::metadata, null, null, { row, value -> row.copy(metadata = value) }, SqliteTypes.json.underlying) + + fun name(): Field = Field(_path, "name", ProductsRow::name, null, null, { row, value -> row.copy(name = value) }, SqliteTypes.text.underlying) + + fun price(): Field = Field(_path, "price", ProductsRow::price, null, null, { row, value -> row.copy(price = value) }, SqliteTypes.numeric.underlying) + + fun productId(): IdField = IdField(_path, "product_id", ProductsRow::productId, null, null, { row, value -> row.copy(productId = value) }, ProductsId.sqliteType.underlying) + + override fun rowCodec(): RowCodec = ProductsRow.rowCodec.underlying + + fun sku(): Field = Field(_path, "sku", ProductsRow::sku, null, null, { row, value -> row.copy(sku = value) }, SqliteTypes.varchar.underlying) + + override fun withPaths(_path: List): RelationStructure = ProductsFields(_path) + + companion object { + val structure: ProductsFields = ProductsFields(emptyList()) + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/products/ProductsId.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/products/ProductsId.kt new file mode 100644 index 0000000000..61aeb6284a --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/products/ProductsId.kt @@ -0,0 +1,26 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.products + +import com.fasterxml.jackson.annotation.JsonValue +import dev.typr.foundationskt.Bijection +import dev.typr.foundationskt.SqliteType +import dev.typr.foundationskt.SqliteTypes + +/** Type for the primary key of table `products` */ +data class ProductsId(@field:JsonValue val value: kotlin.Long) { + override fun toString(): kotlin.String { + return value.toString() + } + + companion object { + val bijection: Bijection = + Bijection.of(ProductsId::value, ::ProductsId) + + val sqliteType: SqliteType = + SqliteTypes.integer.to(Bijection.of(::ProductsId, ProductsId::value)) + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/products/ProductsRepo.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/products/ProductsRepo.kt new file mode 100644 index 0000000000..4eafdfea32 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/products/ProductsRepo.kt @@ -0,0 +1,75 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.products + +import dev.typr.dslkt.DeleteBuilder +import dev.typr.dslkt.SelectBuilder +import dev.typr.dslkt.UpdateBuilder +import dev.typr.foundationskt.Connection +import dev.typr.foundationskt.ConnectionRead +import kotlin.collections.Iterator +import kotlin.collections.List +import kotlin.collections.Map + +interface ProductsRepo { + abstract fun delete(): DeleteBuilder + + abstract fun deleteById( + productId: ProductsId, + c: Connection + ): kotlin.Boolean + + abstract fun deleteByIds( + productIds: List, + c: Connection + ): Int + + abstract fun insert( + unsaved: ProductsRow, + c: Connection + ): ProductsRow + + abstract fun select(): SelectBuilder + + abstract fun selectAll(c: ConnectionRead): List + + abstract fun selectById( + productId: ProductsId, + c: ConnectionRead + ): ProductsRow? + + abstract fun selectByIds( + productIds: List, + c: ConnectionRead + ): List + + abstract fun selectByIdsTracked( + productIds: List, + c: ConnectionRead + ): Map + + abstract fun selectByUniqueSku( + sku: kotlin.String, + c: ConnectionRead + ): ProductsRow? + + abstract fun update(): UpdateBuilder + + abstract fun update( + row: ProductsRow, + c: Connection + ): kotlin.Boolean + + abstract fun upsert( + unsaved: ProductsRow, + c: Connection + ): ProductsRow + + abstract fun upsertBatch( + unsaved: Iterator, + c: Connection + ): List +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/products/ProductsRepoImpl.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/products/ProductsRepoImpl.kt new file mode 100644 index 0000000000..4b487dcd6c --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/products/ProductsRepoImpl.kt @@ -0,0 +1,100 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.products + +import dev.typr.dslkt.DeleteBuilder +import dev.typr.dslkt.Dialect +import dev.typr.dslkt.SelectBuilder +import dev.typr.dslkt.UpdateBuilder +import dev.typr.foundationskt.Connection +import dev.typr.foundationskt.ConnectionRead +import dev.typr.foundationskt.Fragment +import dev.typr.foundationskt.SqliteTypes +import java.util.ArrayList +import kotlin.collections.Iterator +import kotlin.collections.List +import kotlin.collections.Map +import kotlin.collections.MutableMap + +class ProductsRepoImpl() : ProductsRepo { + override fun delete(): DeleteBuilder = DeleteBuilder.of("\"products\"", ProductsFields.structure, Dialect.SQLITE) + + override fun deleteById( + productId: ProductsId, + c: Connection + ): kotlin.Boolean = Fragment.concat(Fragment.of("delete from \"products\" where \"product_id\" = "), Fragment.encode(ProductsId.sqliteType, productId), Fragment.of("")).update().run(c) > 0 + + override fun deleteByIds( + productIds: List, + c: Connection + ): Int { + val fragments: ArrayList = ArrayList() + for (id in productIds) { fragments.add(Fragment.encode(ProductsId.sqliteType, id)) } + return Fragment.concat(Fragment.of("delete from \"products\" where \"product_id\" in ("), Fragment.comma(fragments.toMutableList()), Fragment.of(")")).update().run(c) + } + + override fun insert( + unsaved: ProductsRow, + c: Connection + ): ProductsRow = Fragment.concat(Fragment.of("insert into \"products\"(\"product_id\", \"sku\", \"name\", \"price\", \"metadata\")\nvalues ("), Fragment.encode(ProductsId.sqliteType, unsaved.productId), Fragment.of(", "), Fragment.encode(SqliteTypes.varchar, unsaved.sku), Fragment.of(", "), Fragment.encode(SqliteTypes.text, unsaved.name), Fragment.of(", "), Fragment.encode(SqliteTypes.numeric, unsaved.price), Fragment.of(", "), Fragment.encode(SqliteTypes.json.opt(), unsaved.metadata), Fragment.of(")\nRETURNING \"product_id\", \"sku\", \"name\", \"price\", \"metadata\"\n")) + .updateReturning(ProductsRow.rowCodec.exactlyOne()).run(c) + + override fun select(): SelectBuilder = SelectBuilder.of("\"products\"", ProductsFields.structure, ProductsRow.rowCodec, Dialect.SQLITE) + + override fun selectAll(c: ConnectionRead): List = Fragment.concat(Fragment.of("select \"product_id\", \"sku\", \"name\", \"price\", \"metadata\"\nfrom \"products\"\n")).query(ProductsRow.rowCodec.all()).run(c) + + override fun selectById( + productId: ProductsId, + c: ConnectionRead + ): ProductsRow? = Fragment.concat(Fragment.of("select \"product_id\", \"sku\", \"name\", \"price\", \"metadata\"\nfrom \"products\"\nwhere \"product_id\" = "), Fragment.encode(ProductsId.sqliteType, productId), Fragment.of("")).query(ProductsRow.rowCodec.first()).run(c) + + override fun selectByIds( + productIds: List, + c: ConnectionRead + ): List { + val fragments: ArrayList = ArrayList() + for (id in productIds) { fragments.add(Fragment.encode(ProductsId.sqliteType, id)) } + return Fragment.concat(Fragment.of("select \"product_id\", \"sku\", \"name\", \"price\", \"metadata\" from \"products\" where \"product_id\" in ("), Fragment.comma(fragments.toMutableList()), Fragment.of(")")).query(ProductsRow.rowCodec.all()).run(c) + } + + override fun selectByIdsTracked( + productIds: List, + c: ConnectionRead + ): Map { + val ret: MutableMap = mutableMapOf() + selectByIds(productIds, c).forEach({ row -> ret.put(row.productId, row) }) + return ret.toMap() + } + + override fun selectByUniqueSku( + sku: kotlin.String, + c: ConnectionRead + ): ProductsRow? = Fragment.concat(Fragment.of("select \"product_id\", \"sku\", \"name\", \"price\", \"metadata\"\nfrom \"products\"\nwhere \"sku\" = "), Fragment.encode(SqliteTypes.varchar, sku), Fragment.of("\n")).query(ProductsRow.rowCodec.first()).run(c) + + override fun update(): UpdateBuilder = UpdateBuilder.of("\"products\"", ProductsFields.structure, ProductsRow.rowCodec, Dialect.SQLITE) + + override fun update( + row: ProductsRow, + c: Connection + ): kotlin.Boolean { + val productId: ProductsId = row.productId + return Fragment.concat(Fragment.of("update \"products\"\nset \"sku\" = "), Fragment.encode(SqliteTypes.varchar, row.sku), Fragment.of(",\n\"name\" = "), Fragment.encode(SqliteTypes.text, row.name), Fragment.of(",\n\"price\" = "), Fragment.encode(SqliteTypes.numeric, row.price), Fragment.of(",\n\"metadata\" = "), Fragment.encode(SqliteTypes.json.opt(), row.metadata), Fragment.of("\nwhere \"product_id\" = "), Fragment.encode(ProductsId.sqliteType, productId), Fragment.of("")).update().run(c) > 0 + } + + override fun upsert( + unsaved: ProductsRow, + c: Connection + ): ProductsRow = Fragment.concat(Fragment.of("INSERT INTO \"products\"(\"product_id\", \"sku\", \"name\", \"price\", \"metadata\")\nVALUES ("), Fragment.encode(ProductsId.sqliteType, unsaved.productId), Fragment.of(", "), Fragment.encode(SqliteTypes.varchar, unsaved.sku), Fragment.of(", "), Fragment.encode(SqliteTypes.text, unsaved.name), Fragment.of(", "), Fragment.encode(SqliteTypes.numeric, unsaved.price), Fragment.of(", "), Fragment.encode(SqliteTypes.json.opt(), unsaved.metadata), Fragment.of(")\nON CONFLICT (\"product_id\")\nDO UPDATE SET\n \"sku\" = EXCLUDED.\"sku\",\n\"name\" = EXCLUDED.\"name\",\n\"price\" = EXCLUDED.\"price\",\n\"metadata\" = EXCLUDED.\"metadata\"\nRETURNING \"product_id\", \"sku\", \"name\", \"price\", \"metadata\"")) + .updateReturning(ProductsRow.rowCodec.exactlyOne()) + .run(c) + + override fun upsertBatch( + unsaved: Iterator, + c: Connection + ): List = Fragment.concat(Fragment.of("INSERT INTO \"products\"(\"product_id\", \"sku\", \"name\", \"price\", \"metadata\")\nVALUES (?, ?, ?, ?, ?)\nON CONFLICT (\"product_id\")\nDO UPDATE SET\n \"sku\" = EXCLUDED.\"sku\",\n\"name\" = EXCLUDED.\"name\",\n\"price\" = EXCLUDED.\"price\",\n\"metadata\" = EXCLUDED.\"metadata\"\nRETURNING \"product_id\", \"sku\", \"name\", \"price\", \"metadata\"")) + .updateReturningEach(ProductsRow.rowCodec, unsaved) + .run(c) +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/products/ProductsRepoMock.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/products/ProductsRepoMock.kt new file mode 100644 index 0000000000..cbbc7fdcde --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/products/ProductsRepoMock.kt @@ -0,0 +1,124 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.products + +import dev.typr.dslkt.DeleteBuilder +import dev.typr.dslkt.DeleteBuilderMock +import dev.typr.dslkt.DeleteParams +import dev.typr.dslkt.SelectBuilder +import dev.typr.dslkt.SelectBuilderMock +import dev.typr.dslkt.SelectParams +import dev.typr.dslkt.UpdateBuilder +import dev.typr.dslkt.UpdateBuilderMock +import dev.typr.dslkt.UpdateParams +import dev.typr.foundationskt.Connection +import dev.typr.foundationskt.ConnectionRead +import java.lang.RuntimeException +import java.util.ArrayList +import kotlin.collections.Iterator +import kotlin.collections.List +import kotlin.collections.Map +import kotlin.collections.MutableMap + +data class ProductsRepoMock(val map: MutableMap = mutableMapOf()) : ProductsRepo { + override fun delete(): DeleteBuilder = DeleteBuilderMock(ProductsFields.structure, { map.values.toList() }, DeleteParams.empty(), { row -> row.productId }, { id -> map.remove(id) }) + + override fun deleteById( + productId: ProductsId, + c: Connection + ): kotlin.Boolean = map.remove(productId) != null + + override fun deleteByIds( + productIds: List, + c: Connection + ): Int { + var count = 0 + for (id in productIds) { + if (map.remove(id) != null) { + count = count + 1 + } + } + return count + } + + override fun insert( + unsaved: ProductsRow, + c: Connection + ): ProductsRow { + if (map.containsKey(unsaved.productId)) { + throw RuntimeException("id " + unsaved.productId + " already exists") + } + map[unsaved.productId] = unsaved + return unsaved + } + + override fun select(): SelectBuilder = SelectBuilderMock(ProductsFields.structure, { map.values.toList() }, SelectParams.empty()) + + override fun selectAll(c: ConnectionRead): List = map.values.toList() + + override fun selectById( + productId: ProductsId, + c: ConnectionRead + ): ProductsRow? = map[productId] + + override fun selectByIds( + productIds: List, + c: ConnectionRead + ): List { + val result = ArrayList() + for (id in productIds) { + val opt = map[id] + if (opt != null) { + result.add(opt) + } + } + return result + } + + override fun selectByIdsTracked( + productIds: List, + c: ConnectionRead + ): Map = selectByIds(productIds, c).associateBy({ row: ProductsRow -> row.productId }) + + override fun selectByUniqueSku( + sku: kotlin.String, + c: ConnectionRead + ): ProductsRow? = map.values.toList().find({ v -> (sku == v.sku) }) + + override fun update(): UpdateBuilder = UpdateBuilderMock(ProductsFields.structure, { map.values.toList() }, UpdateParams.empty(), { row -> row }) + + override fun update( + row: ProductsRow, + c: Connection + ): kotlin.Boolean { + val shouldUpdate = map[row.productId]?.takeIf({ oldRow -> (oldRow != row) }) != null + if (shouldUpdate) { + map[row.productId] = row + } + return shouldUpdate + } + + override fun upsert( + unsaved: ProductsRow, + c: Connection + ): ProductsRow { + map[unsaved.productId] = unsaved + return unsaved + } + + override fun upsertBatch( + unsaved: Iterator, + c: Connection + ): List { + val result = ArrayList() + while (unsaved.hasNext()) { + val row = unsaved.next() + map[row.productId] = row + result.add(row) + } + return result + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/products/ProductsRow.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/products/ProductsRow.kt new file mode 100644 index 0000000000..ad226db66e --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/products/ProductsRow.kt @@ -0,0 +1,41 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.products + +import com.fasterxml.jackson.annotation.JsonProperty +import dev.typr.dslkt.RowCodecs +import dev.typr.foundations.Tuple.Tuple5 +import dev.typr.foundations.data.Json +import dev.typr.foundationskt.RowCodec +import dev.typr.foundationskt.SqliteTypes +import java.math.BigDecimal + +/** Table: products + * Primary key: product_id + */ +data class ProductsRow( + @field:JsonProperty("product_id") val productId: ProductsId, + val sku: kotlin.String, + val name: kotlin.String, + val price: BigDecimal, + val metadata: Json? +) : Tuple5 { + override fun _1(): ProductsId = productId + + override fun _2(): kotlin.String = sku + + override fun _3(): kotlin.String = name + + override fun _4(): BigDecimal = price + + override fun _5(): Json? = metadata + + fun id(): ProductsId = productId + + companion object { + val rowCodec: RowCodec = RowCodecs.of(ProductsId.sqliteType, SqliteTypes.varchar, SqliteTypes.text, SqliteTypes.numeric, SqliteTypes.json.opt(), { t0: ProductsId, t1: kotlin.String, t2: kotlin.String, t3: BigDecimal, t4: Json? -> ProductsRow(t0, t1, t2, t3, t4) }, { row: ProductsRow -> arrayOf(row.productId, row.sku, row.name, row.price, row.metadata) }) + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/userdefined/Email.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/userdefined/Email.kt new file mode 100644 index 0000000000..d234055a9d --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/userdefined/Email.kt @@ -0,0 +1,28 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.userdefined + +import com.fasterxml.jackson.annotation.JsonValue +import dev.typr.foundationskt.Bijection +import dev.typr.foundationskt.SqliteType +import dev.typr.foundationskt.SqliteTypes + +/** Shared type `Email` + * Generated from TypeDefinitions matching + */ +data class Email(@field:JsonValue val value: kotlin.String) { + override fun toString(): kotlin.String { + return value + } + + companion object { + val bijection: Bijection = + Bijection.of(Email::value, ::Email) + + val sqliteType: SqliteType = + SqliteTypes.varchar.to(Bijection.of(::Email, Email::value)) + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/users/UsersFields.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/users/UsersFields.kt new file mode 100644 index 0000000000..cc9459698b --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/users/UsersFields.kt @@ -0,0 +1,45 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.users + +import dev.typr.dsl.FieldsBase +import dev.typr.dsl.Path +import dev.typr.dsl.SqlExpr.FieldLike +import dev.typr.dslkt.RelationStructure +import dev.typr.dslkt.SqlExpr +import dev.typr.dslkt.SqlExpr.Field +import dev.typr.dslkt.SqlExpr.IdField +import dev.typr.dslkt.TupleExpr3 +import dev.typr.foundations.RowCodec +import dev.typr.foundationskt.SqliteTypes +import kotlin.collections.List +import testdb.userdefined.Email + +data class UsersFields(val _path: List) : TupleExpr3, RelationStructure, FieldsBase { + override fun _1(): SqlExpr = userId() + + override fun _2(): SqlExpr = username() + + override fun _3(): SqlExpr = email() + + override fun _path(): List = _path + + override fun columns(): List> = listOf(this.userId().underlying, this.username().underlying, this.email().underlying) + + fun email(): Field = Field(_path, "email", UsersRow::email, null, null, { row, value -> row.copy(email = value) }, Email.sqliteType.underlying) + + override fun rowCodec(): RowCodec = UsersRow.rowCodec.underlying + + fun userId(): IdField = IdField(_path, "user_id", UsersRow::userId, null, null, { row, value -> row.copy(userId = value) }, UsersId.sqliteType.underlying) + + fun username(): Field = Field(_path, "username", UsersRow::username, null, null, { row, value -> row.copy(username = value) }, SqliteTypes.varchar.underlying) + + override fun withPaths(_path: List): RelationStructure = UsersFields(_path) + + companion object { + val structure: UsersFields = UsersFields(emptyList()) + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/users/UsersId.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/users/UsersId.kt new file mode 100644 index 0000000000..192ff585e6 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/users/UsersId.kt @@ -0,0 +1,26 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.users + +import com.fasterxml.jackson.annotation.JsonValue +import dev.typr.foundationskt.Bijection +import dev.typr.foundationskt.SqliteType +import dev.typr.foundationskt.SqliteTypes + +/** Type for the primary key of table `users` */ +data class UsersId(@field:JsonValue val value: kotlin.Long) { + override fun toString(): kotlin.String { + return value.toString() + } + + companion object { + val bijection: Bijection = + Bijection.of(UsersId::value, ::UsersId) + + val sqliteType: SqliteType = + SqliteTypes.integer.to(Bijection.of(::UsersId, UsersId::value)) + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/users/UsersRepo.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/users/UsersRepo.kt new file mode 100644 index 0000000000..372e59f076 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/users/UsersRepo.kt @@ -0,0 +1,81 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.users + +import dev.typr.dslkt.DeleteBuilder +import dev.typr.dslkt.SelectBuilder +import dev.typr.dslkt.UpdateBuilder +import dev.typr.foundationskt.Connection +import dev.typr.foundationskt.ConnectionRead +import kotlin.collections.Iterator +import kotlin.collections.List +import kotlin.collections.Map +import testdb.userdefined.Email + +interface UsersRepo { + abstract fun delete(): DeleteBuilder + + abstract fun deleteById( + userId: UsersId, + c: Connection + ): kotlin.Boolean + + abstract fun deleteByIds( + userIds: List, + c: Connection + ): Int + + abstract fun insert( + unsaved: UsersRow, + c: Connection + ): UsersRow + + abstract fun select(): SelectBuilder + + abstract fun selectAll(c: ConnectionRead): List + + abstract fun selectById( + userId: UsersId, + c: ConnectionRead + ): UsersRow? + + abstract fun selectByIds( + userIds: List, + c: ConnectionRead + ): List + + abstract fun selectByIdsTracked( + userIds: List, + c: ConnectionRead + ): Map + + abstract fun selectByUniqueEmail( + email: /* user-picked */ Email, + c: ConnectionRead + ): UsersRow? + + abstract fun selectByUniqueUsername( + username: kotlin.String, + c: ConnectionRead + ): UsersRow? + + abstract fun update(): UpdateBuilder + + abstract fun update( + row: UsersRow, + c: Connection + ): kotlin.Boolean + + abstract fun upsert( + unsaved: UsersRow, + c: Connection + ): UsersRow + + abstract fun upsertBatch( + unsaved: Iterator, + c: Connection + ): List +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/users/UsersRepoImpl.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/users/UsersRepoImpl.kt new file mode 100644 index 0000000000..fe17946814 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/users/UsersRepoImpl.kt @@ -0,0 +1,106 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.users + +import dev.typr.dslkt.DeleteBuilder +import dev.typr.dslkt.Dialect +import dev.typr.dslkt.SelectBuilder +import dev.typr.dslkt.UpdateBuilder +import dev.typr.foundationskt.Connection +import dev.typr.foundationskt.ConnectionRead +import dev.typr.foundationskt.Fragment +import dev.typr.foundationskt.SqliteTypes +import java.util.ArrayList +import kotlin.collections.Iterator +import kotlin.collections.List +import kotlin.collections.Map +import kotlin.collections.MutableMap +import testdb.userdefined.Email + +class UsersRepoImpl() : UsersRepo { + override fun delete(): DeleteBuilder = DeleteBuilder.of("\"users\"", UsersFields.structure, Dialect.SQLITE) + + override fun deleteById( + userId: UsersId, + c: Connection + ): kotlin.Boolean = Fragment.concat(Fragment.of("delete from \"users\" where \"user_id\" = "), Fragment.encode(UsersId.sqliteType, userId), Fragment.of("")).update().run(c) > 0 + + override fun deleteByIds( + userIds: List, + c: Connection + ): Int { + val fragments: ArrayList = ArrayList() + for (id in userIds) { fragments.add(Fragment.encode(UsersId.sqliteType, id)) } + return Fragment.concat(Fragment.of("delete from \"users\" where \"user_id\" in ("), Fragment.comma(fragments.toMutableList()), Fragment.of(")")).update().run(c) + } + + override fun insert( + unsaved: UsersRow, + c: Connection + ): UsersRow = Fragment.concat(Fragment.of("insert into \"users\"(\"user_id\", \"username\", \"email\")\nvalues ("), Fragment.encode(UsersId.sqliteType, unsaved.userId), Fragment.of(", "), Fragment.encode(SqliteTypes.varchar, unsaved.username), Fragment.of(", "), Fragment.encode(Email.sqliteType, unsaved.email), Fragment.of(")\nRETURNING \"user_id\", \"username\", \"email\"\n")) + .updateReturning(UsersRow.rowCodec.exactlyOne()).run(c) + + override fun select(): SelectBuilder = SelectBuilder.of("\"users\"", UsersFields.structure, UsersRow.rowCodec, Dialect.SQLITE) + + override fun selectAll(c: ConnectionRead): List = Fragment.concat(Fragment.of("select \"user_id\", \"username\", \"email\"\nfrom \"users\"\n")).query(UsersRow.rowCodec.all()).run(c) + + override fun selectById( + userId: UsersId, + c: ConnectionRead + ): UsersRow? = Fragment.concat(Fragment.of("select \"user_id\", \"username\", \"email\"\nfrom \"users\"\nwhere \"user_id\" = "), Fragment.encode(UsersId.sqliteType, userId), Fragment.of("")).query(UsersRow.rowCodec.first()).run(c) + + override fun selectByIds( + userIds: List, + c: ConnectionRead + ): List { + val fragments: ArrayList = ArrayList() + for (id in userIds) { fragments.add(Fragment.encode(UsersId.sqliteType, id)) } + return Fragment.concat(Fragment.of("select \"user_id\", \"username\", \"email\" from \"users\" where \"user_id\" in ("), Fragment.comma(fragments.toMutableList()), Fragment.of(")")).query(UsersRow.rowCodec.all()).run(c) + } + + override fun selectByIdsTracked( + userIds: List, + c: ConnectionRead + ): Map { + val ret: MutableMap = mutableMapOf() + selectByIds(userIds, c).forEach({ row -> ret.put(row.userId, row) }) + return ret.toMap() + } + + override fun selectByUniqueEmail( + email: /* user-picked */ Email, + c: ConnectionRead + ): UsersRow? = Fragment.concat(Fragment.of("select \"user_id\", \"username\", \"email\"\nfrom \"users\"\nwhere \"email\" = "), Fragment.encode(Email.sqliteType, email), Fragment.of("\n")).query(UsersRow.rowCodec.first()).run(c) + + override fun selectByUniqueUsername( + username: kotlin.String, + c: ConnectionRead + ): UsersRow? = Fragment.concat(Fragment.of("select \"user_id\", \"username\", \"email\"\nfrom \"users\"\nwhere \"username\" = "), Fragment.encode(SqliteTypes.varchar, username), Fragment.of("\n")).query(UsersRow.rowCodec.first()).run(c) + + override fun update(): UpdateBuilder = UpdateBuilder.of("\"users\"", UsersFields.structure, UsersRow.rowCodec, Dialect.SQLITE) + + override fun update( + row: UsersRow, + c: Connection + ): kotlin.Boolean { + val userId: UsersId = row.userId + return Fragment.concat(Fragment.of("update \"users\"\nset \"username\" = "), Fragment.encode(SqliteTypes.varchar, row.username), Fragment.of(",\n\"email\" = "), Fragment.encode(Email.sqliteType, row.email), Fragment.of("\nwhere \"user_id\" = "), Fragment.encode(UsersId.sqliteType, userId), Fragment.of("")).update().run(c) > 0 + } + + override fun upsert( + unsaved: UsersRow, + c: Connection + ): UsersRow = Fragment.concat(Fragment.of("INSERT INTO \"users\"(\"user_id\", \"username\", \"email\")\nVALUES ("), Fragment.encode(UsersId.sqliteType, unsaved.userId), Fragment.of(", "), Fragment.encode(SqliteTypes.varchar, unsaved.username), Fragment.of(", "), Fragment.encode(Email.sqliteType, unsaved.email), Fragment.of(")\nON CONFLICT (\"user_id\")\nDO UPDATE SET\n \"username\" = EXCLUDED.\"username\",\n\"email\" = EXCLUDED.\"email\"\nRETURNING \"user_id\", \"username\", \"email\"")) + .updateReturning(UsersRow.rowCodec.exactlyOne()) + .run(c) + + override fun upsertBatch( + unsaved: Iterator, + c: Connection + ): List = Fragment.concat(Fragment.of("INSERT INTO \"users\"(\"user_id\", \"username\", \"email\")\nVALUES (?, ?, ?)\nON CONFLICT (\"user_id\")\nDO UPDATE SET\n \"username\" = EXCLUDED.\"username\",\n\"email\" = EXCLUDED.\"email\"\nRETURNING \"user_id\", \"username\", \"email\"")) + .updateReturningEach(UsersRow.rowCodec, unsaved) + .run(c) +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/users/UsersRepoMock.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/users/UsersRepoMock.kt new file mode 100644 index 0000000000..586325ab71 --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/users/UsersRepoMock.kt @@ -0,0 +1,130 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.users + +import dev.typr.dslkt.DeleteBuilder +import dev.typr.dslkt.DeleteBuilderMock +import dev.typr.dslkt.DeleteParams +import dev.typr.dslkt.SelectBuilder +import dev.typr.dslkt.SelectBuilderMock +import dev.typr.dslkt.SelectParams +import dev.typr.dslkt.UpdateBuilder +import dev.typr.dslkt.UpdateBuilderMock +import dev.typr.dslkt.UpdateParams +import dev.typr.foundationskt.Connection +import dev.typr.foundationskt.ConnectionRead +import java.lang.RuntimeException +import java.util.ArrayList +import kotlin.collections.Iterator +import kotlin.collections.List +import kotlin.collections.Map +import kotlin.collections.MutableMap +import testdb.userdefined.Email + +data class UsersRepoMock(val map: MutableMap = mutableMapOf()) : UsersRepo { + override fun delete(): DeleteBuilder = DeleteBuilderMock(UsersFields.structure, { map.values.toList() }, DeleteParams.empty(), { row -> row.userId }, { id -> map.remove(id) }) + + override fun deleteById( + userId: UsersId, + c: Connection + ): kotlin.Boolean = map.remove(userId) != null + + override fun deleteByIds( + userIds: List, + c: Connection + ): Int { + var count = 0 + for (id in userIds) { + if (map.remove(id) != null) { + count = count + 1 + } + } + return count + } + + override fun insert( + unsaved: UsersRow, + c: Connection + ): UsersRow { + if (map.containsKey(unsaved.userId)) { + throw RuntimeException("id " + unsaved.userId + " already exists") + } + map[unsaved.userId] = unsaved + return unsaved + } + + override fun select(): SelectBuilder = SelectBuilderMock(UsersFields.structure, { map.values.toList() }, SelectParams.empty()) + + override fun selectAll(c: ConnectionRead): List = map.values.toList() + + override fun selectById( + userId: UsersId, + c: ConnectionRead + ): UsersRow? = map[userId] + + override fun selectByIds( + userIds: List, + c: ConnectionRead + ): List { + val result = ArrayList() + for (id in userIds) { + val opt = map[id] + if (opt != null) { + result.add(opt) + } + } + return result + } + + override fun selectByIdsTracked( + userIds: List, + c: ConnectionRead + ): Map = selectByIds(userIds, c).associateBy({ row: UsersRow -> row.userId }) + + override fun selectByUniqueEmail( + email: /* user-picked */ Email, + c: ConnectionRead + ): UsersRow? = map.values.toList().find({ v -> (email == v.email) }) + + override fun selectByUniqueUsername( + username: kotlin.String, + c: ConnectionRead + ): UsersRow? = map.values.toList().find({ v -> (username == v.username) }) + + override fun update(): UpdateBuilder = UpdateBuilderMock(UsersFields.structure, { map.values.toList() }, UpdateParams.empty(), { row -> row }) + + override fun update( + row: UsersRow, + c: Connection + ): kotlin.Boolean { + val shouldUpdate = map[row.userId]?.takeIf({ oldRow -> (oldRow != row) }) != null + if (shouldUpdate) { + map[row.userId] = row + } + return shouldUpdate + } + + override fun upsert( + unsaved: UsersRow, + c: Connection + ): UsersRow { + map[unsaved.userId] = unsaved + return unsaved + } + + override fun upsertBatch( + unsaved: Iterator, + c: Connection + ): List { + val result = ArrayList() + while (unsaved.hasNext()) { + val row = unsaved.next() + map[row.userId] = row + result.add(row) + } + return result + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/generated-and-checked-in/testdb/users/UsersRow.kt b/testers/sqlite/kotlin/generated-and-checked-in/testdb/users/UsersRow.kt new file mode 100644 index 0000000000..983a0e826a --- /dev/null +++ b/testers/sqlite/kotlin/generated-and-checked-in/testdb/users/UsersRow.kt @@ -0,0 +1,34 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.users + +import com.fasterxml.jackson.annotation.JsonProperty +import dev.typr.dslkt.RowCodecs +import dev.typr.foundations.Tuple.Tuple3 +import dev.typr.foundationskt.RowCodec +import dev.typr.foundationskt.SqliteTypes +import testdb.userdefined.Email + +/** Table: users + * Primary key: user_id + */ +data class UsersRow( + @field:JsonProperty("user_id") val userId: UsersId, + val username: kotlin.String, + val email: /* user-picked */ Email +) : Tuple3 { + override fun _1(): UsersId = userId + + override fun _2(): kotlin.String = username + + override fun _3(): /* user-picked */ Email = email + + fun id(): UsersId = userId + + companion object { + val rowCodec: RowCodec = RowCodecs.of(UsersId.sqliteType, SqliteTypes.varchar, Email.sqliteType, { t0: UsersId, t1: kotlin.String, t2: /* user-picked */ Email -> UsersRow(t0, t1, t2) }, { row: UsersRow -> arrayOf(row.userId, row.username, row.email) }) + } +} \ No newline at end of file diff --git a/testers/sqlite/kotlin/src/kotlin/testdb/AllTypesTest.kt b/testers/sqlite/kotlin/src/kotlin/testdb/AllTypesTest.kt new file mode 100644 index 0000000000..b821890dec --- /dev/null +++ b/testers/sqlite/kotlin/src/kotlin/testdb/AllTypesTest.kt @@ -0,0 +1,205 @@ +package testdb + +import dev.typr.foundations.data.Json +import org.junit.Assert.* +import org.junit.Test +import testdb.all_scalar_types.* +import java.math.BigDecimal +import java.time.LocalDate +import java.time.LocalDateTime +import java.time.LocalTime +import java.util.UUID + +class AllTypesTest { + private val repo = AllScalarTypesRepoImpl() + + private fun createSampleRow(id: Long): AllScalarTypesRow = AllScalarTypesRow( + AllScalarTypesId(id), + 42.toByte(), + 1000.toShort(), + 100000, + 10000000000L, + 9223372036854775000L, + true, + 3.14159, + 2.718281828, + 1.5f, + BigDecimal("12345.67"), + BigDecimal("999.999"), + "text content", + "varchar_value", + "char5", + "clob content", + byteArrayOf(1, 2, 3, 4, 5), + byteArrayOf(0x0A, 0x0B, 0x0C), + LocalDate.of(2025, 1, 15), + LocalTime.of(14, 30, 45), + LocalDateTime.of(2025, 1, 15, 14, 30, 45), + LocalDateTime.of(2025, 6, 1, 9, 0, 0), + UUID.fromString("550e8400-e29b-41d4-a716-446655440000"), + Json("{\"key\": \"value\"}"), + "required_value" + ) + + @Test + fun testInsertAndSelectAllTypes() { + SqliteTestHelper.run { c -> + val row = createSampleRow(1001L) + val inserted = repo.insert(row, c) + assertEquals(row.id, inserted.id) + assertEquals(row.colTinyint, inserted.colTinyint) + assertEquals(row.colBoolean, inserted.colBoolean) + assertEquals(row.colVarchar, inserted.colVarchar) + assertEquals(row.colDate, inserted.colDate) + assertEquals(row.colUuid, inserted.colUuid) + assertEquals(row.colNotNull, inserted.colNotNull) + assertNotNull(repo.selectById(inserted.id, c)) + } + } + + @Test + fun testUpdateAllTypes() { + SqliteTestHelper.run { c -> + val row = createSampleRow(1002L) + val inserted = repo.insert(row, c) + val updated = inserted.copy( + colVarchar = "updated_varchar", + colDecimal = BigDecimal("999.99"), + colBoolean = false + ) + assertTrue(repo.update(updated, c)) + val found = repo.selectById(inserted.id, c)!! + assertEquals("updated_varchar", found.colVarchar) + assertEquals(false, found.colBoolean) + } + } + + @Test + fun testDeleteAllTypes() { + SqliteTestHelper.run { c -> + val inserted = repo.insert(createSampleRow(1003L), c) + assertTrue(repo.deleteById(inserted.id, c)) + assertNull(repo.selectById(inserted.id, c)) + } + } + + @Test + fun testInsertWithNulls() { + SqliteTestHelper.run { c -> + val row = AllScalarTypesRow( + AllScalarTypesId(1004L), + null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, + null, null, null, null, null, null, null, null, + "required_only" + ) + val inserted = repo.insert(row, c) + assertEquals("required_only", inserted.colNotNull) + assertNull(inserted.colTinyint) + assertNull(inserted.colUuid) + assertNull(inserted.colJson) + } + } + + @Test + fun testIntegerTypes() { + SqliteTestHelper.run { c -> + val inserted = repo.insert(createSampleRow(1010L), c) + assertEquals(42.toByte(), inserted.colTinyint) + assertEquals(1000.toShort(), inserted.colSmallint) + assertEquals(100000, inserted.colInt) + assertEquals(10000000000L, inserted.colInteger) + assertEquals(9223372036854775000L, inserted.colBigint) + } + } + + @Test + fun testBooleanType() { + SqliteTestHelper.run { c -> + val inserted = repo.insert(createSampleRow(1011L), c) + assertEquals(true, inserted.colBoolean) + repo.update(inserted.copy(colBoolean = false), c) + assertEquals(false, repo.selectById(inserted.id, c)!!.colBoolean) + } + } + + @Test + fun testFloatingPointTypes() { + SqliteTestHelper.run { c -> + val inserted = repo.insert(createSampleRow(1012L), c) + assertEquals(3.14159, inserted.colReal!!, 0.0) + assertEquals(2.718281828, inserted.colDouble!!, 0.0) + assertEquals(1.5f, inserted.colFloat!!, 0.0f) + } + } + + @Test + fun testDecimalAndNumeric() { + SqliteTestHelper.run { c -> + val inserted = repo.insert(createSampleRow(1013L), c) + assertEquals(0, BigDecimal("12345.67").compareTo(inserted.colDecimal!!)) + assertEquals(0, BigDecimal("999.999").compareTo(inserted.colNumeric!!)) + } + } + + @Test + fun testTextTypes() { + SqliteTestHelper.run { c -> + val inserted = repo.insert(createSampleRow(1014L), c) + assertEquals("text content", inserted.colText) + assertEquals("varchar_value", inserted.colVarchar) + assertEquals("char5", inserted.colChar) + assertEquals("clob content", inserted.colClob) + } + } + + @Test + fun testBlobAndBinary() { + SqliteTestHelper.run { c -> + val blob = byteArrayOf(0, 1, 2, -1, -2) + val bin = byteArrayOf(-54, -2, -70, -66) + val inserted = repo.insert(createSampleRow(1015L).copy(colBlob = blob, colBinary = bin), c) + assertArrayEquals(blob, inserted.colBlob) + assertArrayEquals(bin, inserted.colBinary) + } + } + + @Test + fun testDateTimeTypes() { + SqliteTestHelper.run { c -> + val inserted = repo.insert(createSampleRow(1016L), c) + assertEquals(LocalDate.of(2025, 1, 15), inserted.colDate) + assertEquals(LocalTime.of(14, 30, 45), inserted.colTime) + assertEquals(LocalDateTime.of(2025, 1, 15, 14, 30, 45), inserted.colDatetime) + assertEquals(LocalDateTime.of(2025, 6, 1, 9, 0, 0), inserted.colTimestamp) + } + } + + @Test + fun testUuid() { + SqliteTestHelper.run { c -> + val uuid = UUID.randomUUID() + val inserted = repo.insert(createSampleRow(1017L).copy(colUuid = uuid), c) + assertEquals(uuid, inserted.colUuid) + } + } + + @Test + fun testSelectAllReturnsInsertedRow() { + SqliteTestHelper.run { c -> + val row = createSampleRow(1019L) + repo.insert(row, c) + val all = repo.selectAll(c) + assertTrue(all.size >= 2) + assertTrue(all.any { it.id.value == 1019L }) + } + } + + @Test + fun testJson() { + SqliteTestHelper.run { c -> + val json = Json("{\"name\":\"test\"}") + val inserted = repo.insert(createSampleRow(1018L).copy(colJson = json), c) + assertTrue(inserted.colJson!!.value().contains("name")) + } + } +} diff --git a/testers/sqlite/kotlin/src/kotlin/testdb/BasicCrudTest.kt b/testers/sqlite/kotlin/src/kotlin/testdb/BasicCrudTest.kt new file mode 100644 index 0000000000..b8c6ba763f --- /dev/null +++ b/testers/sqlite/kotlin/src/kotlin/testdb/BasicCrudTest.kt @@ -0,0 +1,48 @@ +package testdb + +import org.junit.Assert.assertEquals +import org.junit.Assert.assertNotNull +import org.junit.Assert.assertTrue +import org.junit.Test +import testdb.customers.CustomersId +import testdb.customers.CustomersRepoImpl +import testdb.customers.CustomersRowUnsaved +import testdb.customtypes.Defaulted +import testdb.products.ProductsRepoImpl + +class BasicCrudTest { + private val customers = CustomersRepoImpl() + private val products = ProductsRepoImpl() + + @Test + fun selectAllCustomersFromSeedData() { + val rows = SqliteTestHelper.applyRead { customers.selectAll(it) } + assertEquals(2, rows.size) + } + + @Test + fun findCustomerById() { + val row = SqliteTestHelper.applyRead { customers.selectById(CustomersId(1L), it) } + assertNotNull(row) + assertEquals("John Doe", row!!.name) + } + + @Test + fun deleteCustomerById() { + val deleted = SqliteTestHelper.apply { conn -> + val inserted = customers.insert( + CustomersRowUnsaved(CustomersId(999L), "Disposable", null, Defaulted.UseDefault()), conn + ) + customers.deleteById(inserted.customerId, conn) + } + assertTrue(deleted) + } + + @Test + fun productsHaveExpectedPrices() { + val ps = SqliteTestHelper.applyRead { products.selectAll(it) } + assertEquals(2, ps.size) + val skus = ps.map { it.sku }.sorted() + assertEquals(listOf("PROD-001", "PROD-002"), skus) + } +} diff --git a/testers/sqlite/kotlin/src/kotlin/testdb/CompositeKeyTest.kt b/testers/sqlite/kotlin/src/kotlin/testdb/CompositeKeyTest.kt new file mode 100644 index 0000000000..c9fe20e6d2 --- /dev/null +++ b/testers/sqlite/kotlin/src/kotlin/testdb/CompositeKeyTest.kt @@ -0,0 +1,155 @@ +package testdb + +import org.junit.Assert.* +import org.junit.Test +import testdb.departments.* +import testdb.employees.* +import java.math.BigDecimal +import java.time.LocalDate + +class CompositeKeyTest { + private val departments = DepartmentsRepoImpl() + private val employees = EmployeesRepoImpl() + + @Test + fun departmentsInsert() { + SqliteTestHelper.run { c -> + val d = DepartmentsRow("ENG", "EU-NORTH", "Engineering EU", BigDecimal("750000")) + val inserted = departments.insert(d, c) + assertEquals("Engineering EU", inserted.deptName) + } + } + + @Test + fun departmentsSelectBySeedId() { + SqliteTestHelper.run { c -> + val found = departments.selectById(DepartmentsId("IT", "US-WEST"), c) + assertNotNull(found) + assertEquals("Information Technology", found!!.deptName) + } + } + + @Test + fun departmentsCompositeIdFromRow() { + SqliteTestHelper.run { c -> + val inserted = departments.insert( + DepartmentsRow("SALES", "APAC", "Sales APAC", BigDecimal("500000")), c + ) + val id = inserted.compositeId() + assertEquals("SALES", id.deptCode) + assertEquals(inserted, departments.selectById(id, c)) + } + } + + @Test + fun departmentsUpdate() { + SqliteTestHelper.run { c -> + val inserted = departments.insert( + DepartmentsRow("FINANCE", "US-CENTRAL", "Finance", BigDecimal("800000")), c + ) + assertTrue(departments.update(inserted.copy(budget = BigDecimal("900000")), c)) + assertEquals( + 0, + BigDecimal("900000").compareTo(departments.selectById(inserted.compositeId(), c)!!.budget!!) + ) + } + } + + @Test + fun departmentsDelete() { + SqliteTestHelper.run { c -> + val inserted = departments.insert(DepartmentsRow("TEMP", "TEMP-REGION", "Temporary", null), c) + assertTrue(departments.deleteById(inserted.compositeId(), c)) + assertNull(departments.selectById(inserted.compositeId(), c)) + } + } + + @Test + fun departmentsMultipleSameCode() { + SqliteTestHelper.run { c -> + departments.insert(DepartmentsRow("ENG2", "US", "Eng US", null), c) + departments.insert(DepartmentsRow("ENG2", "EU", "Eng EU", null), c) + departments.insert(DepartmentsRow("ENG2", "APAC", "Eng APAC", null), c) + assertNotNull(departments.selectById(DepartmentsId("ENG2", "US"), c)) + assertNotNull(departments.selectById(DepartmentsId("ENG2", "EU"), c)) + assertNotNull(departments.selectById(DepartmentsId("ENG2", "APAC"), c)) + } + } + + @Test + fun employeesInsert() { + SqliteTestHelper.run { c -> + val emp = EmployeesRow(2001L, "A", "IT", "US-WEST", "Alice", BigDecimal("95000"), LocalDate.of(2025, 1, 15)) + val inserted = employees.insert(emp, c) + assertEquals(2001L, inserted.empNumber) + } + } + + @Test + fun employeesSelectBySeedId() { + SqliteTestHelper.run { c -> + val found = employees.selectById(EmployeesId(1001L, "A"), c) + assertNotNull(found) + assertEquals("Alice Johnson", found!!.empName) + } + } + + @Test + fun employeesCompositeIdFromRow() { + SqliteTestHelper.run { c -> + val inserted = employees.insert( + EmployeesRow(3001L, "C", "HR", "US-EAST", "Carol", null, LocalDate.of(2025, 3, 1)), c + ) + assertEquals(3001L, inserted.compositeId().empNumber) + assertEquals("C", inserted.compositeId().empSuffix) + } + } + + @Test + fun employeesUpdate() { + SqliteTestHelper.run { c -> + val inserted = employees.insert( + EmployeesRow(4001L, "D", "IT", "US-WEST", "David", BigDecimal("120000"), LocalDate.of(2025, 4, 1)), c + ) + employees.update(inserted.copy(salary = BigDecimal("130000")), c) + assertEquals( + 0, + BigDecimal("130000").compareTo(employees.selectById(inserted.compositeId(), c)!!.salary!!) + ) + } + } + + @Test + fun employeesDelete() { + SqliteTestHelper.run { c -> + val inserted = employees.insert( + EmployeesRow(5001L, "X", "IT", "US-WEST", "Disposable", null, LocalDate.of(2025, 5, 1)), c + ) + assertTrue(employees.deleteById(inserted.compositeId(), c)) + } + } + + @Test + fun employeesMultipleSameNumber() { + SqliteTestHelper.run { c -> + employees.insert(EmployeesRow(9999L, "A", "IT", "US-WEST", "A", null, LocalDate.of(2025, 1, 1)), c) + employees.insert(EmployeesRow(9999L, "B", "IT", "US-WEST", "B", null, LocalDate.of(2025, 1, 1)), c) + employees.insert(EmployeesRow(9999L, "C", "IT", "US-WEST", "C", null, LocalDate.of(2025, 1, 1)), c) + assertNotNull(employees.selectById(EmployeesId(9999L, "A"), c)) + assertNotNull(employees.selectById(EmployeesId(9999L, "B"), c)) + assertNotNull(employees.selectById(EmployeesId(9999L, "C"), c)) + } + } + + @Test + fun employeeDepartmentForeignKey() { + SqliteTestHelper.run { c -> + departments.insert(DepartmentsRow("FK_TEST", "FK_REGION", "FK Dept", BigDecimal("500000")), c) + val emp = employees.insert( + EmployeesRow(6001L, "F", "FK_TEST", "FK_REGION", "FK Emp", BigDecimal("60000"), LocalDate.of(2025, 6, 1)), c + ) + assertEquals("FK_TEST", emp.deptCode) + assertNotNull(departments.selectById(DepartmentsId(emp.deptCode, emp.deptRegion), c)) + } + } +} diff --git a/testers/sqlite/kotlin/src/kotlin/testdb/DSLTest.kt b/testers/sqlite/kotlin/src/kotlin/testdb/DSLTest.kt new file mode 100644 index 0000000000..5c4bcef1c9 --- /dev/null +++ b/testers/sqlite/kotlin/src/kotlin/testdb/DSLTest.kt @@ -0,0 +1,131 @@ +package testdb + +import org.junit.Assert.* +import org.junit.Test +import testdb.customers.* +import java.time.LocalDateTime + +class DSLTest { + private val repo = CustomersRepoImpl() + private fun row(id: Long, name: String) = + CustomersRow(CustomersId(id), name, null, LocalDateTime.of(2025, 1, 1, 0, 0)) + + @Test + fun selectWithWhere() { + SqliteTestHelper.run { c -> + repo.insert(row(5001L, "DSL Test User"), c) + val results = repo.select().where { it.name().isEqual("DSL Test User") }.toList(c) + assertEquals(1, results.size) + } + } + + @Test + fun selectWithOrderByAsc() { + SqliteTestHelper.run { c -> + repo.insert(row(5002L, "Zebra"), c) + repo.insert(row(5003L, "Alpha"), c) + repo.insert(row(5004L, "Mike"), c) + val r = repo.select() + .where { it.customerId().greaterThan(CustomersId(5001L)) } + .orderBy { it.name().asc() } + .toList(c) + assertEquals("Alpha", r[0].name) + assertEquals("Zebra", r.last().name) + } + } + + @Test + fun selectWithOrderByDesc() { + SqliteTestHelper.run { c -> + repo.insert(row(5005L, "DescA"), c) + repo.insert(row(5006L, "DescB"), c) + repo.insert(row(5007L, "DescC"), c) + val r = repo.select() + .where { it.name().like("Desc%") } + .orderBy { it.name().desc() } + .toList(c) + assertEquals("DescC", r[0].name) + } + } + + @Test + fun selectWithLimit() { + SqliteTestHelper.run { c -> + (0 until 10).forEach { i -> repo.insert(row(5100L + i, "Limit$i"), c) } + val r = repo.select().where { it.name().like("Limit%") }.limit(3).toList(c) + assertEquals(3, r.size) + } + } + + @Test + fun selectWithOffset() { + SqliteTestHelper.run { c -> + repo.insert(row(5200L, "OffsetA"), c) + repo.insert(row(5201L, "OffsetB"), c) + repo.insert(row(5202L, "OffsetC"), c) + repo.insert(row(5203L, "OffsetD"), c) + val r = repo.select() + .where { it.name().like("Offset%") } + .orderBy { it.name().asc() } + .offset(2).limit(10).toList(c) + assertEquals(listOf("OffsetC", "OffsetD"), r.map { it.name }) + } + } + + @Test + fun selectWithCount() { + SqliteTestHelper.run { c -> + repo.insert(row(5300L, "CountA"), c) + repo.insert(row(5301L, "CountB"), c) + repo.insert(row(5302L, "CountC"), c) + val count = repo.select().where { it.name().like("Count%") }.count(c) + assertEquals(3, count) + } + } + + @Test + fun selectWithLike() { + SqliteTestHelper.run { c -> + repo.insert(row(5400L, "LikeTest_ABC"), c) + repo.insert(row(5401L, "LikeTest_XYZ"), c) + repo.insert(row(5402L, "Other"), c) + val r = repo.select().where { it.name().like("LikeTest%") }.toList(c) + assertEquals(2, r.size) + } + } + + @Test + fun selectWithIn() { + SqliteTestHelper.run { c -> + repo.insert(row(5500L, "In1"), c) + repo.insert(row(5501L, "In2"), c) + repo.insert(row(5502L, "In3"), c) + val r = repo.select().where { it.customerId().`in`(CustomersId(5500L), CustomersId(5502L)) }.toList(c) + assertEquals(2, r.size) + } + } + + @Test + fun updateBuilder() { + SqliteTestHelper.run { c -> + repo.insert(row(5600L, "UpdateMe"), c) + val n = repo.update() + .where { it.customerId().isEqual(CustomersId(5600L)) } + .setValue({ it.name() }, "Updated") + .execute(c) + assertEquals(1, n) + assertEquals("Updated", repo.selectById(CustomersId(5600L), c)!!.name) + } + } + + @Test + fun deleteBuilder() { + SqliteTestHelper.run { c -> + repo.insert(row(5700L, "DeleteA"), c) + repo.insert(row(5701L, "DeleteB"), c) + repo.insert(row(5702L, "DeleteC"), c) + val n = repo.delete().where { cust -> cust.name().like("Delete%") }.execute(c) + assertEquals(3, n) + } + } +} diff --git a/testers/sqlite/kotlin/src/kotlin/testdb/DatabaseFeaturesTest.kt b/testers/sqlite/kotlin/src/kotlin/testdb/DatabaseFeaturesTest.kt new file mode 100644 index 0000000000..7fa853f880 --- /dev/null +++ b/testers/sqlite/kotlin/src/kotlin/testdb/DatabaseFeaturesTest.kt @@ -0,0 +1,127 @@ +package testdb + +import dev.typr.foundations.data.Json +import org.junit.Assert.* +import org.junit.Test +import testdb.customer_orders.CustomerOrdersViewRepoImpl +import testdb.customers.* +import testdb.customtypes.Defaulted +import testdb.order_details.OrderDetailsViewRepoImpl +import testdb.orders.* +import testdb.products.* +import testdb.userdefined.Email +import java.math.BigDecimal +import java.time.LocalDate +import java.time.LocalDateTime +import java.util.UUID + +class DatabaseFeaturesTest { + private val customers = CustomersRepoImpl() + private val products = ProductsRepoImpl() + private val orders = OrdersRepoImpl() + private val customerOrdersRepo = CustomerOrdersViewRepoImpl() + private val orderDetailsRepo = OrderDetailsViewRepoImpl() + + @Test + fun insertReturningPopulatesGeneratedColumns() { + SqliteTestHelper.run { c -> + val unsaved = CustomersRowUnsaved(CustomersId(10001L), "Returning Test") + val inserted = customers.insert(unsaved, c) + assertEquals(10001L, inserted.customerId.value) + assertNotNull(inserted.createdAt) + } + } + + @Test + fun insertWithProvidedDefault() { + SqliteTestHelper.run { c -> + val explicit = LocalDateTime.of(2020, 5, 1, 12, 0) + val unsaved = CustomersRowUnsaved( + CustomersId(10002L), "Explicit", Email("u@x.com"), Defaulted.Provided(explicit) + ) + assertEquals(explicit, customers.insert(unsaved, c).createdAt) + } + } + + @Test + fun upsertInsertsNew() { + SqliteTestHelper.run { c -> + val row = CustomersRow(CustomersId(20001L), "Upsert Insert", null, LocalDateTime.of(2025, 1, 1, 0, 0)) + assertEquals("Upsert Insert", customers.upsert(row, c).name) + } + } + + @Test + fun upsertUpdatesOnConflict() { + SqliteTestHelper.run { c -> + val row = CustomersRow(CustomersId(20002L), "Original", Email("a@x.com"), LocalDateTime.of(2025, 1, 1, 0, 0)) + customers.insert(row, c) + val updated = row.copy(name = "Updated via Upsert", email = Email("b@x.com")) + val result = customers.upsert(updated, c) + assertEquals("Updated via Upsert", result.name) + assertEquals("Updated via Upsert", customers.selectById(CustomersId(20002L), c)!!.name) + } + } + + @Test + fun uuidJsonRoundTrip() { + SqliteTestHelper.run { c -> + val uuid = UUID.randomUUID() + val product = ProductsRow( + ProductsId(30001L), "SKU-UUID-$uuid", "UUID Product", BigDecimal("1.00"), + Json("{\"uuid\":\"$uuid\"}") + ) + val inserted = products.insert(product, c) + assertTrue(inserted.metadata!!.value().contains(uuid.toString())) + } + } + + @Test + fun customerOrdersView() { + SqliteTestHelper.applyRead { c -> + val rows = customerOrdersRepo.selectAll(c) + assertEquals(2, rows.size) + assertTrue(rows.any { it.customerName == "John Doe" }) + assertTrue(rows.any { it.customerName == "Jane Smith" }) + } + } + + @Test + fun orderDetailsView() { + SqliteTestHelper.applyRead { c -> + val rows = orderDetailsRepo.selectAll(c) + assertEquals(3, rows.size) + rows.forEach { r -> + val s = r.lineTotal!! + assertTrue(BigDecimal(s) > BigDecimal.ZERO) + } + } + } + + @Test + fun selectByIdsReturnsRequested() { + SqliteTestHelper.applyRead { c -> + val found = customers.selectByIds(listOf(CustomersId(1L), CustomersId(2L)), c) + assertEquals(2, found.size) + } + } + + @Test + fun insertWithExplicitId() { + SqliteTestHelper.run { c -> + val row = CustomersRow(CustomersId(50001L), "Explicit ID", null, LocalDateTime.of(2025, 1, 1, 0, 0)) + val inserted = customers.insert(row, c) + assertEquals(50001L, inserted.customerId.value) + } + } + + @Test + fun orderInsertWithForeignKeyValue() { + SqliteTestHelper.run { c -> + val ord = orders.insert( + OrdersRow(OrdersId(70001L), CustomersId(1L), LocalDate.of(2025, 7, 1), BigDecimal("250.00"), "pending"), c + ) + assertEquals(70001L, ord.orderId.value) + } + } +} diff --git a/testers/sqlite/kotlin/src/kotlin/testdb/ForeignKeyTest.kt b/testers/sqlite/kotlin/src/kotlin/testdb/ForeignKeyTest.kt new file mode 100644 index 0000000000..889a09ed5e --- /dev/null +++ b/testers/sqlite/kotlin/src/kotlin/testdb/ForeignKeyTest.kt @@ -0,0 +1,94 @@ +package testdb + +import org.junit.Assert.* +import org.junit.Test +import testdb.customers.* +import testdb.order_items.* +import testdb.orders.* +import testdb.products.* +import testdb.userdefined.Email +import java.math.BigDecimal +import java.time.LocalDate +import java.time.LocalDateTime + +class ForeignKeyTest { + private val customers = CustomersRepoImpl() + private val products = ProductsRepoImpl() + private val orders = OrdersRepoImpl() + private val orderItems = OrderItemsRepoImpl() + + @Test + fun customerInsert() { + SqliteTestHelper.run { c -> + val inserted = customers.insert( + CustomersRow(CustomersId(100L), "John", Email("john@x.com"), LocalDateTime.of(2025, 1, 1, 0, 0)), c + ) + assertEquals("John", inserted.name) + } + } + + @Test + fun productInsert() { + SqliteTestHelper.run { c -> + val inserted = products.insert( + ProductsRow(ProductsId(100L), "PROD-100", "Widget", BigDecimal("29.99"), null), c + ) + assertEquals("PROD-100", inserted.sku) + } + } + + @Test + fun orderWithCustomerFK() { + SqliteTestHelper.run { c -> + val cust = customers.insert( + CustomersRow(CustomersId(101L), "Jane", Email("jane@x.com"), LocalDateTime.of(2025, 1, 2, 0, 0)), c + ) + val ord = orders.insert( + OrdersRow(OrdersId(101L), cust.customerId, LocalDate.of(2025, 1, 15), BigDecimal("99.99"), "pending"), c + ) + assertEquals(cust.customerId, ord.customerId) + } + } + + @Test + fun orderItemWithCompositePK() { + SqliteTestHelper.run { c -> + customers.insert(CustomersRow(CustomersId(102L), "x", null, LocalDateTime.of(2025, 1, 1, 0, 0)), c) + val prod = products.insert(ProductsRow(ProductsId(102L), "PROD-102", "W", BigDecimal("49.99"), null), c) + val ord = orders.insert( + OrdersRow(OrdersId(102L), CustomersId(102L), LocalDate.of(2025, 1, 16), BigDecimal("149.97"), "pending"), c + ) + val item = orderItems.insert(OrderItemsRow(ord.orderId, prod.productId, 3L, BigDecimal("49.99")), c) + assertEquals(3L, item.quantity) + } + } + + @Test + fun foreignKeyEnforced() { + var threw = false + try { + SqliteTestHelper.run { c -> + orders.insert( + OrdersRow(OrdersId(9999L), CustomersId(99999L), LocalDate.of(2025, 1, 1), null, "pending"), c + ) + } + } catch (e: Exception) { + val msg = e.message ?: "" + threw = msg.contains("FOREIGN KEY") || msg.lowercase().contains("foreign key") + } + assertTrue("Expected FK violation", threw) + } + + @Test + fun typeSafeIds() { + SqliteTestHelper.run { c -> + val cid = CustomersId(200L); val pid = ProductsId(200L); val oid = OrdersId(200L) + customers.insert(CustomersRow(cid, "TS", null, LocalDateTime.of(2025, 1, 1, 0, 0)), c) + products.insert(ProductsRow(pid, "SKU-200", "TS Prod", BigDecimal("1.00"), null), c) + orders.insert(OrdersRow(oid, cid, LocalDate.of(2025, 1, 1), null, "pending"), c) + assertNotNull(customers.selectById(cid, c)) + assertNotNull(products.selectById(pid, c)) + assertNotNull(orders.selectById(oid, c)) + } + } +} diff --git a/testers/sqlite/kotlin/src/kotlin/testdb/MockRepoTest.kt b/testers/sqlite/kotlin/src/kotlin/testdb/MockRepoTest.kt new file mode 100644 index 0000000000..30818c2ee0 --- /dev/null +++ b/testers/sqlite/kotlin/src/kotlin/testdb/MockRepoTest.kt @@ -0,0 +1,118 @@ +package testdb + +import dev.typr.dslkt.MockConnection +import org.junit.Assert.* +import org.junit.Test +import testdb.customers.* +import testdb.departments.* +import testdb.userdefined.Email +import java.math.BigDecimal +import java.time.LocalDateTime + +class MockRepoTest { + + private fun mkCustomersMock(): CustomersRepoMock = CustomersRepoMock({ unsaved -> + CustomersRow( + customerId = unsaved.customerId, + name = unsaved.name, + email = unsaved.email, + createdAt = unsaved.createdAt.getOrElse { LocalDateTime.of(2025, 1, 1, 0, 0) } + ) + }) + + @Test + fun testMockInsertAndSelect() { + val mock = mkCustomersMock() + val customer = CustomersRow(CustomersId(1L), "Mock User", Email("mock@test.com"), LocalDateTime.of(2025, 1, 1, 0, 0)) + val inserted = mock.insert(customer, MockConnection.instance) + assertEquals("Mock User", inserted.name) + val found = mock.selectById(CustomersId(1L), MockConnection.instance) + assertNotNull(found) + assertEquals("Mock User", found!!.name) + } + + @Test + fun testMockUpdate() { + val mock = mkCustomersMock() + val customer = CustomersRow(CustomersId(2L), "Original", null, LocalDateTime.of(2025, 1, 1, 0, 0)) + mock.insert(customer, MockConnection.instance) + mock.update(customer.copy(name = "Updated"), MockConnection.instance) + assertEquals("Updated", mock.selectById(CustomersId(2L), MockConnection.instance)!!.name) + } + + @Test + fun testMockDelete() { + val mock = mkCustomersMock() + mock.insert(CustomersRow(CustomersId(3L), "Del", null, LocalDateTime.of(2025, 1, 1, 0, 0)), MockConnection.instance) + assertNotNull(mock.selectById(CustomersId(3L), MockConnection.instance)) + mock.deleteById(CustomersId(3L), MockConnection.instance) + assertNull(mock.selectById(CustomersId(3L), MockConnection.instance)) + } + + @Test + fun testMockSelectAll() { + val mock = mkCustomersMock() + mock.insert(CustomersRow(CustomersId(10L), "U1", null, LocalDateTime.of(2025, 1, 1, 0, 0)), MockConnection.instance) + mock.insert(CustomersRow(CustomersId(11L), "U2", null, LocalDateTime.of(2025, 1, 1, 0, 0)), MockConnection.instance) + mock.insert(CustomersRow(CustomersId(12L), "U3", null, LocalDateTime.of(2025, 1, 1, 0, 0)), MockConnection.instance) + assertEquals(3, mock.selectAll(MockConnection.instance).size) + } + + @Test + fun testMockDSLLimit() { + val mock = mkCustomersMock() + for (i in 0 until 10) { + mock.insert(CustomersRow(CustomersId(300L + i), "Limit$i", null, LocalDateTime.of(2025, 1, 1, 0, 0)), MockConnection.instance) + } + val results = mock.select().where { it.name().like("Limit%") }.limit(5).toList(MockConnection.instance) + assertEquals(5, results.size) + } + + @Test + fun testMockWithCompositeKey() { + val mock = DepartmentsRepoMock() + mock.insert(DepartmentsRow("MOCK_IT", "MOCK_US", "Mock IT US", BigDecimal("500000")), MockConnection.instance) + val found = mock.selectById(DepartmentsId("MOCK_IT", "MOCK_US"), MockConnection.instance) + assertNotNull(found) + assertEquals("Mock IT US", found!!.deptName) + } + + @Test + fun testMockDSLQuery() { + val mock = mkCustomersMock() + mock.insert(CustomersRow(CustomersId(100L), "Alice", null, LocalDateTime.of(2025, 1, 1, 0, 0)), MockConnection.instance) + mock.insert(CustomersRow(CustomersId(101L), "Bob", null, LocalDateTime.of(2025, 1, 1, 0, 0)), MockConnection.instance) + mock.insert(CustomersRow(CustomersId(102L), "Charlie", null, LocalDateTime.of(2025, 1, 1, 0, 0)), MockConnection.instance) + + val results = mock.select() + .where { it.customerId().greaterThan(CustomersId(100L)) } + .orderBy { it.name().asc() } + .toList(MockConnection.instance) + + assertEquals(2, results.size) + assertEquals("Bob", results[0].name) + assertEquals("Charlie", results[1].name) + } + + @Test + fun testMockDSLCount() { + val mock = mkCustomersMock() + mock.insert(CustomersRow(CustomersId(200L), "Count1", null, LocalDateTime.of(2025, 1, 1, 0, 0)), MockConnection.instance) + mock.insert(CustomersRow(CustomersId(201L), "Count2", null, LocalDateTime.of(2025, 1, 1, 0, 0)), MockConnection.instance) + mock.insert(CustomersRow(CustomersId(202L), "Other", null, LocalDateTime.of(2025, 1, 1, 0, 0)), MockConnection.instance) + + val count = mock.select() + .where { it.name().like("Count%") } + .count(MockConnection.instance) + assertEquals(2, count) + } + + @Test + fun testMockIsolation() { + val mock1 = mkCustomersMock() + val mock2 = mkCustomersMock() + mock1.insert(CustomersRow(CustomersId(400L), "M1", null, LocalDateTime.of(2025, 1, 1, 0, 0)), MockConnection.instance) + assertNotNull(mock1.selectById(CustomersId(400L), MockConnection.instance)) + assertNull(mock2.selectById(CustomersId(400L), MockConnection.instance)) + } +} diff --git a/testers/sqlite/kotlin/src/kotlin/testdb/SqlScriptTest.kt b/testers/sqlite/kotlin/src/kotlin/testdb/SqlScriptTest.kt new file mode 100644 index 0000000000..f698a27f78 --- /dev/null +++ b/testers/sqlite/kotlin/src/kotlin/testdb/SqlScriptTest.kt @@ -0,0 +1,146 @@ +package testdb + +import org.junit.Assert.* +import org.junit.Test +import testdb.all_scalar_types_search.AllScalarTypesSearchSqlRepoImpl +import testdb.customer_search.CustomerSearchSqlRepoImpl +import testdb.delete_old_orders.DeleteOldOrdersSqlRepoImpl +import testdb.order_summary_by_customer.OrderSummaryByCustomerSqlRepoImpl +import testdb.product_details_with_sales.ProductDetailsWithSalesSqlRepoImpl +import java.math.BigDecimal +import java.time.LocalDate +import java.time.LocalDateTime + +class SqlScriptTest { + private val customerSearch = CustomerSearchSqlRepoImpl() + private val orderSummary = OrderSummaryByCustomerSqlRepoImpl() + private val productDetails = ProductDetailsWithSalesSqlRepoImpl() + private val scalarSearch = AllScalarTypesSearchSqlRepoImpl() + private val deleteOld = DeleteOldOrdersSqlRepoImpl() + + @Test + fun customerSearchAll() { + SqliteTestHelper.applyRead { c -> + val rows = customerSearch.apply(null, null, null, 100L, c) + assertEquals(2, rows.size) + } + } + + @Test + fun customerSearchByName() { + SqliteTestHelper.applyRead { c -> + val rows = customerSearch.apply("John%", null, null, 100L, c) + assertEquals(1, rows.size) + assertEquals("John Doe", rows[0].name) + } + } + + @Test + fun customerSearchByEmail() { + SqliteTestHelper.applyRead { c -> + val rows = customerSearch.apply(null, "%jane%", null, 100L, c) + assertEquals(1, rows.size) + } + } + + @Test + fun customerSearchLimit() { + SqliteTestHelper.applyRead { c -> + val rows = customerSearch.apply(null, null, null, 1L, c) + assertEquals(1, rows.size) + } + } + + @Test + fun customerSearchByCreatedAfter() { + SqliteTestHelper.applyRead { c -> + val rows = customerSearch.apply(null, null, LocalDateTime.of(2099, 1, 1, 0, 0), 100L, c) + assertEquals(0, rows.size) + } + } + + @Test + fun orderSummaryInRange() { + SqliteTestHelper.applyRead { c -> + val rows = orderSummary.apply(LocalDate.of(2025, 1, 1), LocalDate.of(2025, 12, 31), c) + assertEquals(2, rows.size) + val total = rows.mapNotNull { it.totalRevenue }.fold(BigDecimal.ZERO) { a, b -> a.add(b) } + assertEquals(0, BigDecimal("109.97").compareTo(total)) + } + } + + @Test + fun orderSummaryEmptyRange() { + SqliteTestHelper.applyRead { c -> + val rows = orderSummary.apply(LocalDate.of(2099, 1, 1), LocalDate.of(2099, 12, 31), c) + assertEquals(0, rows.size) + } + } + + @Test + fun productDetailsAll() { + SqliteTestHelper.applyRead { c -> + val rows = productDetails.apply(null, c) + assertEquals(2, rows.size) + } + } + + @Test + fun productDetailsMinPrice() { + SqliteTestHelper.applyRead { c -> + val rows = productDetails.apply(BigDecimal("40.00"), c) + assertEquals(1, rows.size) + assertEquals("Widget B", rows[0].productName) + } + } + + @Test + fun allScalarSearchAll() { + SqliteTestHelper.applyRead { c -> + val rows = scalarSearch.apply(null, null, null, c) + assertEquals(1, rows.size) + } + } + + @Test + fun allScalarSearchMinId() { + SqliteTestHelper.applyRead { c -> + val rows = scalarSearch.apply(100L, null, null, c) + assertEquals(0, rows.size) + } + } + + @Test + fun allScalarSearchByText() { + SqliteTestHelper.applyRead { c -> + val rows = scalarSearch.apply(null, "hel%", null, c) + assertEquals(1, rows.size) + } + } + + @Test + fun deleteOldOrders() { + SqliteTestHelper.run { c -> + val ordersRepo = testdb.orders.OrdersRepoImpl() + ordersRepo.insert( + testdb.orders.OrdersRow( + testdb.orders.OrdersId(9001L), + testdb.customers.CustomersId(1L), + LocalDate.of(2020, 1, 1), + BigDecimal("10.00"), + "completed" + ), c + ) + val deleted = deleteOld.apply(LocalDate.of(2025, 1, 1), c) + assertEquals(1, deleted) + } + } + + @Test + fun deleteOldOrdersNoneMatch() { + SqliteTestHelper.run { c -> + val deleted = deleteOld.apply(LocalDate.of(1900, 1, 1), c) + assertEquals(0, deleted) + } + } +} diff --git a/testers/sqlite/kotlin/src/kotlin/testdb/SqliteTestHelper.kt b/testers/sqlite/kotlin/src/kotlin/testdb/SqliteTestHelper.kt new file mode 100644 index 0000000000..dc9b763630 --- /dev/null +++ b/testers/sqlite/kotlin/src/kotlin/testdb/SqliteTestHelper.kt @@ -0,0 +1,77 @@ +package testdb + +import dev.typr.foundationskt.Connection +import dev.typr.foundationskt.ConnectionRead +import dev.typr.foundationskt.Transactor +import dev.typr.foundationskt.connect.ConnectionSettings +import dev.typr.foundationskt.connect.SqliteConfig +import java.nio.file.Files +import java.nio.file.Path +import java.util.concurrent.atomic.AtomicBoolean + +/** + * SQLite in-memory test helper. xerial driver doesn't support multi-statement execute(), so we + * split the schema and run statements one at a time during a one-time init; per-test transactions + * are then rollback-only on the same connection. + */ +object SqliteTestHelper { + private val CONFIG: SqliteConfig = SqliteConfig.inMemory().foreignKeys(true).build() + private val BASE: Transactor = Transactor.create(CONFIG, ConnectionSettings.EMPTY) + private val TRANSACTOR: Transactor = BASE.rollbackOnly() + private val INITIALISED = AtomicBoolean(false) + + private fun splitStatements(sql: String): List { + val out = mutableListOf() + val cur = StringBuilder() + var inString = false + var i = 0 + while (i < sql.length) { + val c = sql[i] + when { + !inString && c == '-' && i + 1 < sql.length && sql[i + 1] == '-' -> { + while (i < sql.length && sql[i] != '\n') i++ + } + c == '\'' -> { + cur.append(c); inString = !inString; i++ + } + c == ';' && !inString -> { + out.add(cur.toString()); cur.clear(); i++ + } + else -> { + cur.append(c); i++ + } + } + } + out.add(cur.toString()) + return out + } + + private fun ensureInitialised() { + if (INITIALISED.compareAndSet(false, true)) { + val schema = Files.readString(Path.of("sql-init/sqlite/00-schema.sql")) + BASE.transact { conn -> + conn.unwrap().createStatement().use { stmt -> + for (chunk in splitStatements(schema)) { + val s = chunk.trim() + if (s.isNotEmpty()) stmt.execute(s) + } + } + } + } + } + + fun apply(f: (Connection) -> T): T { + ensureInitialised() + return TRANSACTOR.transact(f) + } + + fun run(f: (Connection) -> Unit) { + ensureInitialised() + TRANSACTOR.transact { conn -> f(conn) } + } + + fun applyRead(f: (ConnectionRead) -> T): T { + ensureInitialised() + return TRANSACTOR.transactRead(f) + } +} diff --git a/testers/sqlite/kotlin/src/kotlin/testdb/TestInsertTest.kt b/testers/sqlite/kotlin/src/kotlin/testdb/TestInsertTest.kt new file mode 100644 index 0000000000..37786bca1b --- /dev/null +++ b/testers/sqlite/kotlin/src/kotlin/testdb/TestInsertTest.kt @@ -0,0 +1,99 @@ +package testdb + +import org.junit.Assert.* +import org.junit.Test +import java.math.BigDecimal +import java.util.Random + +class TestInsertTest { + private val testInsert = TestInsert(Random(1794141443)) + + @Test + fun customersInsert() { + SqliteTestHelper.run { c -> + val row = testInsert.Customers(name = "Test Customer", c = c) + assertNotNull(row.customerId) + assertEquals("Test Customer", row.name) + } + } + + @Test + fun departmentsInsert() { + SqliteTestHelper.run { c -> + val row = testInsert.Departments( + deptCode = "DEPT1", deptRegion = "NORTH", deptName = "Test Department", c = c + ) + assertEquals("DEPT1", row.deptCode) + assertEquals("NORTH", row.deptRegion) + } + } + + @Test + fun productsInsert() { + SqliteTestHelper.run { c -> + val row = testInsert.Products( + sku = "SKU001", name = "Test Product", price = BigDecimal("99.99"), c = c + ) + assertNotNull(row.productId) + assertEquals("SKU001", row.sku) + } + } + + @Test + fun allScalarTypesInsert() { + SqliteTestHelper.run { c -> + val row = testInsert.AllScalarTypes(colNotNull = "required_value", c = c) + assertNotNull(row.id) + assertEquals("required_value", row.colNotNull) + } + } + + @Test + fun employeesWithDepartmentFK() { + SqliteTestHelper.run { c -> + val dept = testInsert.Departments( + deptCode = "EMP_DEPT", deptRegion = "WEST", deptName = "Employee Dept", c = c + ) + val emp = testInsert.Employees( + DepartmentsId = dept.compositeId(), empSuffix = "Jr", empName = "John Doe", c = c + ) + assertEquals(dept.deptCode, emp.deptCode) + assertEquals(dept.deptRegion, emp.deptRegion) + } + } + + @Test + fun ordersWithCustomerFK() { + SqliteTestHelper.run { c -> + val customer = testInsert.Customers(name = "Order Customer", c = c) + val order = testInsert.Orders(customerId = customer.customerId, c = c) + assertEquals(customer.customerId, order.customerId) + } + } + + @Test + fun customersWithCustomization() { + SqliteTestHelper.run { c -> + val row = testInsert.Customers(name = "Custom Name", c = c) + assertEquals("Custom Name", row.name) + } + } + + @Test + fun seededRandomReproducible() { + val id1 = SqliteTestHelper.apply { TestInsert(Random(123)).Customers(name = "x", c = it).customerId.value } + val id2 = SqliteTestHelper.apply { TestInsert(Random(123)).Customers(name = "x", c = it).customerId.value } + assertEquals(id1, id2) + } + + @Test + fun multipleInserts() { + SqliteTestHelper.run { c -> + val r1 = testInsert.Customers(name = "C1", c = c) + val r2 = testInsert.Customers(name = "C2", c = c) + val r3 = testInsert.Customers(name = "C3", c = c) + assertNotEquals(r1.customerId, r2.customerId) + assertNotEquals(r2.customerId, r3.customerId) + } + } +} diff --git a/testers/sqlite/kotlin/src/kotlin/testdb/TupleInTest.kt b/testers/sqlite/kotlin/src/kotlin/testdb/TupleInTest.kt new file mode 100644 index 0000000000..557abf2e75 --- /dev/null +++ b/testers/sqlite/kotlin/src/kotlin/testdb/TupleInTest.kt @@ -0,0 +1,70 @@ +package testdb + +import org.junit.Assert.* +import org.junit.Test +import testdb.departments.* +import java.math.BigDecimal + +class TupleInTest { + private val repo = DepartmentsRepoImpl() + + @Test + fun compositeIdInMultiple() { + SqliteTestHelper.run { c -> + val d1 = repo.insert(DepartmentsRow("TI_A", "US", "A US", null), c) + repo.insert(DepartmentsRow("TI_A", "EU", "A EU", null), c) + val d3 = repo.insert(DepartmentsRow("TI_B", "US", "B US", null), c) + repo.insert(DepartmentsRow("TI_B", "EU", "B EU", null), c) + + val result = repo.select() + .where { it.compositeIdIn(listOf(d1.compositeId(), d3.compositeId())) } + .toList(c) + assertEquals(2, result.size) + val ids = result.map { it.compositeId() }.toSet() + assertEquals(setOf(d1.compositeId(), d3.compositeId()), ids) + } + } + + @Test + fun compositeIdInSingle() { + SqliteTestHelper.run { c -> + val d1 = repo.insert(DepartmentsRow("TI_S", "APAC", "S APAC", null), c) + repo.insert(DepartmentsRow("TI_S", "EMEA", "S EMEA", null), c) + val result = repo.select().where { it.compositeIdIn(listOf(d1.compositeId())) }.toList(c) + assertEquals(1, result.size) + assertEquals(d1, result[0]) + } + } + + @Test + fun compositeIdInEmpty() { + SqliteTestHelper.run { c -> + val result = repo.select().where { it.compositeIdIn(emptyList()) }.toList(c) + assertTrue(result.isEmpty()) + } + } + + @Test + fun compositeIdInNonExistent() { + SqliteTestHelper.run { c -> + val result = repo.select().where { + it.compositeIdIn(listOf(DepartmentsId("NOPE", "NEVER"), DepartmentsId("ALSO", "MISSING"))) + }.toList(c) + assertTrue(result.isEmpty()) + } + } + + @Test + fun compositeIdInCombinedWithOther() { + SqliteTestHelper.run { c -> + val d1 = repo.insert(DepartmentsRow("TI_C", "US", "Combined US", BigDecimal("100000")), c) + val d2 = repo.insert(DepartmentsRow("TI_C", "EU", "Combined EU", BigDecimal("50000")), c) + val result = repo.select() + .where { it.compositeIdIn(listOf(d1.compositeId(), d2.compositeId())) } + .where { it.budget().greaterThan(BigDecimal("75000")) } + .toList(c) + assertEquals(1, result.size) + assertEquals(d1, result[0]) + } + } +} diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/DefaultedDeserializer.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/DefaultedDeserializer.scala new file mode 100644 index 0000000000..2916fd6b61 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/DefaultedDeserializer.scala @@ -0,0 +1,63 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb + +import com.fasterxml.jackson.core.JsonParser +import com.fasterxml.jackson.core.JsonToken +import com.fasterxml.jackson.databind.BeanProperty +import com.fasterxml.jackson.databind.DeserializationContext +import com.fasterxml.jackson.databind.JavaType +import com.fasterxml.jackson.databind.JsonDeserializer +import com.fasterxml.jackson.databind.deser.ContextualDeserializer +import java.io.IOException +import java.lang.Class +import java.lang.RuntimeException +import testdb.customtypes.Defaulted +import testdb.customtypes.Defaulted.Provided +import testdb.customtypes.Defaulted.UseDefault + +/** Jackson deserializer for Defaulted types */ +class DefaultedDeserializer( + val valueType: JavaType, + val defaultedClass: Class[?] +) extends JsonDeserializer[Defaulted[?]] with ContextualDeserializer { + override def createContextual( + ctxt: DeserializationContext, + property: BeanProperty + ): JsonDeserializer[?] = { + val contextType: JavaType = ctxt.getContextualType() + val `type`: JavaType = (if (contextType == null && property != null) property.getType() else contextType) + if (`type` != null && `type`.containedTypeCount() > 0) { + return new DefaultedDeserializer(`type`.containedType(0), `type`.getRawClass()); + } + throw new RuntimeException("unexpected") + } + + @throws[IOException] + override def deserialize( + p: JsonParser, + ctxt: DeserializationContext + ): Defaulted[?] = { + if (p.currentToken() == JsonToken.VALUE_STRING) { + val text: String = p.getText(); + if ("defaulted".equals(text)) { + return new UseDefault[Any](); + } + throw new IOException("Expected 'defaulted' but got: " + text); + } + if (p.currentToken() == JsonToken.START_OBJECT) { + p.nextToken(); + if (p.currentToken() == JsonToken.FIELD_NAME && "provided".equals(p.currentName())) { + p.nextToken(); + val value: Any = ctxt.readValue(p, valueType); + p.nextToken(); + return new Provided[Any](value); + } + + } + throw new IOException("Expected 'provided' field but got: " + p.currentName()) + } +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/DefaultedSerializer.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/DefaultedSerializer.scala new file mode 100644 index 0000000000..a7778d2a72 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/DefaultedSerializer.scala @@ -0,0 +1,35 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb + +import com.fasterxml.jackson.core.JsonGenerator +import com.fasterxml.jackson.databind.JsonSerializer +import com.fasterxml.jackson.databind.SerializerProvider +import java.io.IOException +import testdb.customtypes.Defaulted +import testdb.customtypes.Defaulted.Provided +import testdb.customtypes.Defaulted.UseDefault + +/** Jackson serializer for Defaulted types */ +class DefaultedSerializer extends JsonSerializer[Defaulted[?]] { + @throws[IOException] + override def serialize( + value: Defaulted[?], + gen: JsonGenerator, + serializers: SerializerProvider + ): Unit = { + value match { + case null => gen.writeNull() + case u: UseDefault[?] => gen.writeString("defaulted") + case p: Provided[?] => { + gen.writeStartObject(); + gen.writeFieldName("provided"); + serializers.defaultSerializeValue(p.value, gen); + gen.writeEndObject(); + } + } + } +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/TestInsert.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/TestInsert.scala new file mode 100644 index 0000000000..c85c392556 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/TestInsert.scala @@ -0,0 +1,279 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb + +import dev.typr.foundations.data.Json +import dev.typr.foundationssc.Connection +import java.math.BigInteger +import java.time.LocalDate +import java.time.LocalDateTime +import java.time.LocalTime +import java.util.UUID +import scala.util.Random +import testdb.all_scalar_types.AllScalarTypesId +import testdb.all_scalar_types.AllScalarTypesRepoImpl +import testdb.all_scalar_types.AllScalarTypesRow +import testdb.customers.CustomersId +import testdb.customers.CustomersRepoImpl +import testdb.customers.CustomersRow +import testdb.customers.CustomersRowUnsaved +import testdb.customtypes.Defaulted +import testdb.customtypes.Defaulted.UseDefault +import testdb.departments.DepartmentsId +import testdb.departments.DepartmentsRepoImpl +import testdb.departments.DepartmentsRow +import testdb.employees.EmployeesRepoImpl +import testdb.employees.EmployeesRow +import testdb.employees.EmployeesRowUnsaved +import testdb.order_items.OrderItemsRepoImpl +import testdb.order_items.OrderItemsRow +import testdb.order_items.OrderItemsRowUnsaved +import testdb.orders.OrdersId +import testdb.orders.OrdersRepoImpl +import testdb.orders.OrdersRow +import testdb.orders.OrdersRowUnsaved +import testdb.precisetypes.Decimal10_2 +import testdb.precisetypes.Decimal18_4 +import testdb.precisetypes.Decimal5_2 +import testdb.precisetypes.Int10 +import testdb.precisetypes.Int18 +import testdb.precisetypes.Int5 +import testdb.precisetypes.String10 +import testdb.precisetypes.String100 +import testdb.precisetypes.String20 +import testdb.precisetypes.String255 +import testdb.precisetypes.String50 +import testdb.precision_types.PrecisionTypesId +import testdb.precision_types.PrecisionTypesRepoImpl +import testdb.precision_types.PrecisionTypesRow +import testdb.precision_types_null.PrecisionTypesNullId +import testdb.precision_types_null.PrecisionTypesNullRepoImpl +import testdb.precision_types_null.PrecisionTypesNullRow +import testdb.products.ProductsId +import testdb.products.ProductsRepoImpl +import testdb.products.ProductsRow +import testdb.userdefined.Email +import testdb.users.UsersId +import testdb.users.UsersRepoImpl +import testdb.users.UsersRow + +/** Methods to generate random data for `Ident(TestInsert)` */ +case class TestInsert(random: Random) { + def AllScalarTypes( + id: AllScalarTypesId = new AllScalarTypesId(random.nextLong()), + colTinyint: Option[Byte] = (if (random.nextBoolean()) None else Some(random.nextInt(Byte.MaxValue).toByte)), + colSmallint: Option[Short] = (if (random.nextBoolean()) None else Some(random.nextInt(Short.MaxValue).toShort)), + colInt: Option[Int] = (if (random.nextBoolean()) None else Some(random.nextInt())), + colInteger: Option[Long] = (if (random.nextBoolean()) None else Some(random.nextLong())), + colBigint: Option[Long] = (if (random.nextBoolean()) None else Some(random.nextLong())), + colBoolean: Option[Boolean] = (if (random.nextBoolean()) None else Some(random.nextBoolean())), + colReal: Option[Double] = (if (random.nextBoolean()) None else Some(random.nextDouble())), + colDouble: Option[Double] = (if (random.nextBoolean()) None else Some(random.nextDouble())), + colFloat: Option[Float] = (if (random.nextBoolean()) None else Some(random.nextFloat())), + colDecimal: Option[BigDecimal] = (if (random.nextBoolean()) None else Some(BigDecimal.decimal(random.nextDouble()))), + colNumeric: Option[BigDecimal] = (if (random.nextBoolean()) None else Some(BigDecimal.decimal(random.nextDouble()))), + colText: Option[String] = (if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString)), + colVarchar: Option[String] = (if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString)), + colChar: Option[String] = (if (random.nextBoolean()) None else Some(random.alphanumeric.take(5).mkString)), + colClob: Option[String] = (if (random.nextBoolean()) None else Some(random.alphanumeric.take(20).mkString)), + colBlob: Option[Array[Byte]] = None, + colBinary: Option[Array[Byte]] = None, + colDate: Option[LocalDate] = (if (random.nextBoolean()) None else Some(LocalDate.ofEpochDay(random.nextInt(30000).toLong))), + colTime: Option[LocalTime] = (if (random.nextBoolean()) None else Some(LocalTime.ofSecondOfDay(random.nextInt(24 * 60 * 60).toLong))), + colDatetime: Option[LocalDateTime] = (if (random.nextBoolean()) None else Some(LocalDateTime.of(LocalDate.ofEpochDay(random.nextInt(30000).toLong), LocalTime.ofSecondOfDay(random.nextInt(24 * 60 * 60).toLong)))), + colTimestamp: Option[LocalDateTime] = (if (random.nextBoolean()) None else Some(LocalDateTime.of(LocalDate.ofEpochDay(random.nextInt(30000).toLong), LocalTime.ofSecondOfDay(random.nextInt(24 * 60 * 60).toLong)))), + colUuid: Option[UUID] = (if (random.nextBoolean()) None else Some(UUID.nameUUIDFromBytes{val bs = Array.ofDim[Byte](16); random.nextBytes(bs); bs})), + colJson: Option[Json] = (if (random.nextBoolean()) None else Some(new Json("{}"))), + colNotNull: String = random.alphanumeric.take(20).mkString + )(using c: Connection): AllScalarTypesRow = { + (new AllScalarTypesRepoImpl()).insert(new AllScalarTypesRow( + id = id, + colTinyint = colTinyint, + colSmallint = colSmallint, + colInt = colInt, + colInteger = colInteger, + colBigint = colBigint, + colBoolean = colBoolean, + colReal = colReal, + colDouble = colDouble, + colFloat = colFloat, + colDecimal = colDecimal, + colNumeric = colNumeric, + colText = colText, + colVarchar = colVarchar, + colChar = colChar, + colClob = colClob, + colBlob = colBlob, + colBinary = colBinary, + colDate = colDate, + colTime = colTime, + colDatetime = colDatetime, + colTimestamp = colTimestamp, + colUuid = colUuid, + colJson = colJson, + colNotNull = colNotNull + ))(using c) + } + + def Customers( + customerId: CustomersId = new CustomersId(random.nextLong()), + name: String = random.alphanumeric.take(20).mkString, + email: Option[/* user-picked */ Email] = (if (random.nextBoolean()) None else Some(new Email(random.alphanumeric.take(20).mkString))), + createdAt: Defaulted[LocalDateTime] = new UseDefault() + )(using c: Connection): CustomersRow = { + (new CustomersRepoImpl()).insert(new CustomersRowUnsaved( + customerId = customerId, + name = name, + email = email, + createdAt = createdAt + ))(using c) + } + + def Departments( + deptCode: String = random.alphanumeric.take(10).mkString, + deptRegion: String = random.alphanumeric.take(10).mkString, + deptName: String = random.alphanumeric.take(20).mkString, + budget: Option[BigDecimal] = (if (random.nextBoolean()) None else Some(BigDecimal.decimal(random.nextDouble()))) + )(using c: Connection): DepartmentsRow = { + (new DepartmentsRepoImpl()).insert(new DepartmentsRow( + deptCode = deptCode, + deptRegion = deptRegion, + deptName = deptName, + budget = budget + ))(using c) + } + + def Employees( + DepartmentsId: DepartmentsId, + empNumber: Long = random.nextLong(), + empSuffix: String = random.alphanumeric.take(5).mkString, + empName: String = random.alphanumeric.take(20).mkString, + salary: Option[BigDecimal] = (if (random.nextBoolean()) None else Some(BigDecimal.decimal(random.nextDouble()))), + hireDate: Defaulted[LocalDate] = new UseDefault() + )(using c: Connection): EmployeesRow = { + (new EmployeesRepoImpl()).insert(new EmployeesRowUnsaved( + empNumber = empNumber, + empSuffix = empSuffix, + deptCode = DepartmentsId.deptCode, + deptRegion = DepartmentsId.deptRegion, + empName = empName, + salary = salary, + hireDate = hireDate + ))(using c) + } + + def OrderItems( + orderId: OrdersId, + productId: ProductsId, + unitPrice: BigDecimal = BigDecimal.decimal(random.nextDouble()), + quantity: Defaulted[Long] = new UseDefault() + )(using c: Connection): OrderItemsRow = { + (new OrderItemsRepoImpl()).insert(new OrderItemsRowUnsaved( + orderId = orderId, + productId = productId, + unitPrice = unitPrice, + quantity = quantity + ))(using c) + } + + def Orders( + customerId: CustomersId, + orderId: OrdersId = new OrdersId(random.nextLong()), + orderDate: LocalDate = LocalDate.ofEpochDay(random.nextInt(30000).toLong), + totalAmount: Option[BigDecimal] = (if (random.nextBoolean()) None else Some(BigDecimal.decimal(random.nextDouble()))), + status: Defaulted[String] = new UseDefault() + )(using c: Connection): OrdersRow = { + (new OrdersRepoImpl()).insert(new OrdersRowUnsaved( + orderId = orderId, + customerId = customerId, + orderDate = orderDate, + totalAmount = totalAmount, + status = status + ))(using c) + } + + def PrecisionTypes( + id: PrecisionTypesId = new PrecisionTypesId(random.nextLong()), + string10: String10 = String10.truncate(random.alphanumeric.take(10).mkString), + string20: String20 = String20.truncate(random.alphanumeric.take(20).mkString), + string50: String50 = String50.truncate(random.alphanumeric.take(20).mkString), + string100: String100 = String100.truncate(random.alphanumeric.take(20).mkString), + string255: String255 = String255.truncate(random.alphanumeric.take(20).mkString), + decimal52: Decimal5_2 = Decimal5_2.unsafeForce(java.math.BigDecimal.valueOf(Math.abs(random.nextInt()) % 1000.toLong).add(java.math.BigDecimal.valueOf(Math.abs(random.nextInt()) % 100.toLong).movePointLeft(2))), + decimal102: Decimal10_2 = Decimal10_2.unsafeForce(java.math.BigDecimal.valueOf(Math.abs(random.nextInt()) % 1000000.toLong).add(java.math.BigDecimal.valueOf(Math.abs(random.nextInt()) % 100.toLong).movePointLeft(2))), + decimal184: Decimal18_4 = Decimal18_4.unsafeForce(java.math.BigDecimal.valueOf(Math.abs(random.nextInt()) % 1000000.toLong).add(java.math.BigDecimal.valueOf(Math.abs(random.nextInt()) % 10000.toLong).movePointLeft(4))), + decimal50: Int5 = Int5.unsafeForce(BigInteger.valueOf(Math.abs(random.nextInt()) % 100000.toLong)), + decimal100: Int10 = Int10.unsafeForce(BigInteger.valueOf(Math.abs(random.nextInt()) % 1000000000.toLong)), + decimal180: Int18 = Int18.unsafeForce(BigInteger.valueOf(Math.abs(random.nextInt()) % 1000000000.toLong)) + )(using c: Connection): PrecisionTypesRow = { + (new PrecisionTypesRepoImpl()).insert(new PrecisionTypesRow( + id = id, + string10 = string10, + string20 = string20, + string50 = string50, + string100 = string100, + string255 = string255, + decimal52 = decimal52, + decimal102 = decimal102, + decimal184 = decimal184, + decimal50 = decimal50, + decimal100 = decimal100, + decimal180 = decimal180 + ))(using c) + } + + def PrecisionTypesNull( + id: PrecisionTypesNullId = new PrecisionTypesNullId(random.nextLong()), + string10: Option[String10] = (if (random.nextBoolean()) None else Some(String10.truncate(random.alphanumeric.take(10).mkString))), + string20: Option[String20] = (if (random.nextBoolean()) None else Some(String20.truncate(random.alphanumeric.take(20).mkString))), + string50: Option[String50] = (if (random.nextBoolean()) None else Some(String50.truncate(random.alphanumeric.take(20).mkString))), + string100: Option[String100] = (if (random.nextBoolean()) None else Some(String100.truncate(random.alphanumeric.take(20).mkString))), + string255: Option[String255] = (if (random.nextBoolean()) None else Some(String255.truncate(random.alphanumeric.take(20).mkString))), + decimal52: Option[Decimal5_2] = (if (random.nextBoolean()) None else Some(Decimal5_2.unsafeForce(java.math.BigDecimal.valueOf(Math.abs(random.nextInt()) % 1000.toLong).add(java.math.BigDecimal.valueOf(Math.abs(random.nextInt()) % 100.toLong).movePointLeft(2))))), + decimal102: Option[Decimal10_2] = (if (random.nextBoolean()) None else Some(Decimal10_2.unsafeForce(java.math.BigDecimal.valueOf(Math.abs(random.nextInt()) % 1000000.toLong).add(java.math.BigDecimal.valueOf(Math.abs(random.nextInt()) % 100.toLong).movePointLeft(2))))), + decimal184: Option[Decimal18_4] = (if (random.nextBoolean()) None else Some(Decimal18_4.unsafeForce(java.math.BigDecimal.valueOf(Math.abs(random.nextInt()) % 1000000.toLong).add(java.math.BigDecimal.valueOf(Math.abs(random.nextInt()) % 10000.toLong).movePointLeft(4))))), + decimal50: Option[Int5] = (if (random.nextBoolean()) None else Some(Int5.unsafeForce(BigInteger.valueOf(Math.abs(random.nextInt()) % 100000.toLong)))), + decimal100: Option[Int10] = (if (random.nextBoolean()) None else Some(Int10.unsafeForce(BigInteger.valueOf(Math.abs(random.nextInt()) % 1000000000.toLong)))), + decimal180: Option[Int18] = (if (random.nextBoolean()) None else Some(Int18.unsafeForce(BigInteger.valueOf(Math.abs(random.nextInt()) % 1000000000.toLong)))) + )(using c: Connection): PrecisionTypesNullRow = { + (new PrecisionTypesNullRepoImpl()).insert(new PrecisionTypesNullRow( + id = id, + string10 = string10, + string20 = string20, + string50 = string50, + string100 = string100, + string255 = string255, + decimal52 = decimal52, + decimal102 = decimal102, + decimal184 = decimal184, + decimal50 = decimal50, + decimal100 = decimal100, + decimal180 = decimal180 + ))(using c) + } + + def Products( + productId: ProductsId = new ProductsId(random.nextLong()), + sku: String = random.alphanumeric.take(20).mkString, + name: String = random.alphanumeric.take(20).mkString, + price: BigDecimal = BigDecimal.decimal(random.nextDouble()), + metadata: Option[Json] = (if (random.nextBoolean()) None else Some(new Json("{}"))) + )(using c: Connection): ProductsRow = { + (new ProductsRepoImpl()).insert(new ProductsRow( + productId = productId, + sku = sku, + name = name, + price = price, + metadata = metadata + ))(using c) + } + + def Users( + userId: UsersId = new UsersId(random.nextLong()), + username: String = random.alphanumeric.take(20).mkString, + email: /* user-picked */ Email = new Email(random.alphanumeric.take(20).mkString) + )(using c: Connection): UsersRow = (new UsersRepoImpl()).insert(new UsersRow(userId = userId, username = username, email = email))(using c) +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/all_scalar_types/AllScalarTypesFields.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/all_scalar_types/AllScalarTypesFields.scala new file mode 100644 index 0000000000..95ff829dc4 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/all_scalar_types/AllScalarTypesFields.scala @@ -0,0 +1,385 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.all_scalar_types + +import dev.typr.dsl.FieldsBase +import dev.typr.dsl.Path +import dev.typr.dsl.SqlExpr.FieldLike +import dev.typr.dslsc.RelationStructure +import dev.typr.dslsc.SqlExpr +import dev.typr.dslsc.SqlExpr.Field +import dev.typr.dslsc.SqlExpr.IdField +import dev.typr.dslsc.SqlExpr.OptField +import dev.typr.dslsc.TupleExpr25 +import dev.typr.foundations.RowCodec +import dev.typr.foundations.data.Json +import dev.typr.foundationssc.SqliteTypes +import java.time.LocalDate +import java.time.LocalDateTime +import java.time.LocalTime +import java.util.UUID + +class AllScalarTypesFields(val `_path`: java.util.List[Path]) extends TupleExpr25[AllScalarTypesId, Byte, Short, Int, Long, Long, Boolean, Double, Double, Float, BigDecimal, BigDecimal, String, String, String, String, Array[Byte], Array[Byte], LocalDate, LocalTime, LocalDateTime, LocalDateTime, UUID, Json, String] with RelationStructure[AllScalarTypesFields, AllScalarTypesRow] with FieldsBase[AllScalarTypesRow] { + def id: IdField[AllScalarTypesId, AllScalarTypesRow] = { + new IdField[AllScalarTypesId, AllScalarTypesRow]( + _path, + "id", + _.id, + None, + None, + (row, value) => row.copy(id = value), + AllScalarTypesId.sqliteType.underlying + ) + } + + def colTinyint: OptField[Byte, AllScalarTypesRow] = { + new OptField[Byte, AllScalarTypesRow]( + _path, + "col_tinyint", + _.colTinyint, + None, + None, + (row, value) => row.copy(colTinyint = value), + SqliteTypes.tinyint.underlying + ) + } + + def colSmallint: OptField[Short, AllScalarTypesRow] = { + new OptField[Short, AllScalarTypesRow]( + _path, + "col_smallint", + _.colSmallint, + None, + None, + (row, value) => row.copy(colSmallint = value), + SqliteTypes.smallint.underlying + ) + } + + def colInt: OptField[Int, AllScalarTypesRow] = { + new OptField[Int, AllScalarTypesRow]( + _path, + "col_int", + _.colInt, + None, + None, + (row, value) => row.copy(colInt = value), + SqliteTypes.int_.underlying + ) + } + + def colInteger: OptField[Long, AllScalarTypesRow] = { + new OptField[Long, AllScalarTypesRow]( + _path, + "col_integer", + _.colInteger, + None, + None, + (row, value) => row.copy(colInteger = value), + SqliteTypes.integer.underlying + ) + } + + def colBigint: OptField[Long, AllScalarTypesRow] = { + new OptField[Long, AllScalarTypesRow]( + _path, + "col_bigint", + _.colBigint, + None, + None, + (row, value) => row.copy(colBigint = value), + SqliteTypes.bigint.underlying + ) + } + + def colBoolean: OptField[Boolean, AllScalarTypesRow] = { + new OptField[Boolean, AllScalarTypesRow]( + _path, + "col_boolean", + _.colBoolean, + None, + None, + (row, value) => row.copy(colBoolean = value), + SqliteTypes.boolean_.underlying + ) + } + + def colReal: OptField[Double, AllScalarTypesRow] = { + new OptField[Double, AllScalarTypesRow]( + _path, + "col_real", + _.colReal, + None, + None, + (row, value) => row.copy(colReal = value), + SqliteTypes.real.underlying + ) + } + + def colDouble: OptField[Double, AllScalarTypesRow] = { + new OptField[Double, AllScalarTypesRow]( + _path, + "col_double", + _.colDouble, + None, + None, + (row, value) => row.copy(colDouble = value), + SqliteTypes.double_.underlying + ) + } + + def colFloat: OptField[Float, AllScalarTypesRow] = { + new OptField[Float, AllScalarTypesRow]( + _path, + "col_float", + _.colFloat, + None, + None, + (row, value) => row.copy(colFloat = value), + SqliteTypes.float_.underlying + ) + } + + def colDecimal: OptField[BigDecimal, AllScalarTypesRow] = { + new OptField[BigDecimal, AllScalarTypesRow]( + _path, + "col_decimal", + _.colDecimal, + None, + None, + (row, value) => row.copy(colDecimal = value), + SqliteTypes.numeric.underlying + ) + } + + def colNumeric: OptField[BigDecimal, AllScalarTypesRow] = { + new OptField[BigDecimal, AllScalarTypesRow]( + _path, + "col_numeric", + _.colNumeric, + None, + None, + (row, value) => row.copy(colNumeric = value), + SqliteTypes.numeric.underlying + ) + } + + def colText: OptField[String, AllScalarTypesRow] = { + new OptField[String, AllScalarTypesRow]( + _path, + "col_text", + _.colText, + None, + None, + (row, value) => row.copy(colText = value), + SqliteTypes.text.underlying + ) + } + + def colVarchar: OptField[String, AllScalarTypesRow] = { + new OptField[String, AllScalarTypesRow]( + _path, + "col_varchar", + _.colVarchar, + None, + None, + (row, value) => row.copy(colVarchar = value), + SqliteTypes.varchar.underlying + ) + } + + def colChar: OptField[String, AllScalarTypesRow] = { + new OptField[String, AllScalarTypesRow]( + _path, + "col_char", + _.colChar, + None, + None, + (row, value) => row.copy(colChar = value), + SqliteTypes.char_.underlying + ) + } + + def colClob: OptField[String, AllScalarTypesRow] = { + new OptField[String, AllScalarTypesRow]( + _path, + "col_clob", + _.colClob, + None, + None, + (row, value) => row.copy(colClob = value), + SqliteTypes.clob.underlying + ) + } + + def colBlob: OptField[Array[Byte], AllScalarTypesRow] = { + new OptField[Array[Byte], AllScalarTypesRow]( + _path, + "col_blob", + _.colBlob, + None, + None, + (row, value) => row.copy(colBlob = value), + SqliteTypes.blob.underlying + ) + } + + def colBinary: OptField[Array[Byte], AllScalarTypesRow] = { + new OptField[Array[Byte], AllScalarTypesRow]( + _path, + "col_binary", + _.colBinary, + None, + None, + (row, value) => row.copy(colBinary = value), + SqliteTypes.binary.underlying + ) + } + + def colDate: OptField[LocalDate, AllScalarTypesRow] = { + new OptField[LocalDate, AllScalarTypesRow]( + _path, + "col_date", + _.colDate, + None, + None, + (row, value) => row.copy(colDate = value), + SqliteTypes.date.underlying + ) + } + + def colTime: OptField[LocalTime, AllScalarTypesRow] = { + new OptField[LocalTime, AllScalarTypesRow]( + _path, + "col_time", + _.colTime, + None, + None, + (row, value) => row.copy(colTime = value), + SqliteTypes.time.underlying + ) + } + + def colDatetime: OptField[LocalDateTime, AllScalarTypesRow] = { + new OptField[LocalDateTime, AllScalarTypesRow]( + _path, + "col_datetime", + _.colDatetime, + None, + None, + (row, value) => row.copy(colDatetime = value), + SqliteTypes.timestamp.underlying + ) + } + + def colTimestamp: OptField[LocalDateTime, AllScalarTypesRow] = { + new OptField[LocalDateTime, AllScalarTypesRow]( + _path, + "col_timestamp", + _.colTimestamp, + None, + None, + (row, value) => row.copy(colTimestamp = value), + SqliteTypes.timestamp.underlying + ) + } + + def colUuid: OptField[UUID, AllScalarTypesRow] = { + new OptField[UUID, AllScalarTypesRow]( + _path, + "col_uuid", + _.colUuid, + None, + None, + (row, value) => row.copy(colUuid = value), + SqliteTypes.uuid.underlying + ) + } + + def colJson: OptField[Json, AllScalarTypesRow] = { + new OptField[Json, AllScalarTypesRow]( + _path, + "col_json", + _.colJson, + None, + None, + (row, value) => row.copy(colJson = value), + SqliteTypes.json.underlying + ) + } + + def colNotNull: Field[String, AllScalarTypesRow] = { + new Field[String, AllScalarTypesRow]( + _path, + "col_not_null", + _.colNotNull, + None, + None, + (row, value) => row.copy(colNotNull = value), + SqliteTypes.text.underlying + ) + } + + override def columns: java.util.List[FieldLike[?, AllScalarTypesRow]] = java.util.List.of(this.id.underlying, this.colTinyint.underlying, this.colSmallint.underlying, this.colInt.underlying, this.colInteger.underlying, this.colBigint.underlying, this.colBoolean.underlying, this.colReal.underlying, this.colDouble.underlying, this.colFloat.underlying, this.colDecimal.underlying, this.colNumeric.underlying, this.colText.underlying, this.colVarchar.underlying, this.colChar.underlying, this.colClob.underlying, this.colBlob.underlying, this.colBinary.underlying, this.colDate.underlying, this.colTime.underlying, this.colDatetime.underlying, this.colTimestamp.underlying, this.colUuid.underlying, this.colJson.underlying, this.colNotNull.underlying) + + override def rowCodec: RowCodec[AllScalarTypesRow] = AllScalarTypesRow.rowCodec.underlying + + override def withPaths(`_path`: java.util.List[Path]): RelationStructure[AllScalarTypesFields, AllScalarTypesRow] = new AllScalarTypesFields(`_path`) + + override def `_1`: SqlExpr[AllScalarTypesId] = id + + override def `_2`: SqlExpr[Byte] = colTinyint + + override def `_3`: SqlExpr[Short] = colSmallint + + override def `_4`: SqlExpr[Int] = colInt + + override def `_5`: SqlExpr[Long] = colInteger + + override def `_6`: SqlExpr[Long] = colBigint + + override def `_7`: SqlExpr[Boolean] = colBoolean + + override def `_8`: SqlExpr[Double] = colReal + + override def `_9`: SqlExpr[Double] = colDouble + + override def `_10`: SqlExpr[Float] = colFloat + + override def `_11`: SqlExpr[BigDecimal] = colDecimal + + override def `_12`: SqlExpr[BigDecimal] = colNumeric + + override def `_13`: SqlExpr[String] = colText + + override def `_14`: SqlExpr[String] = colVarchar + + override def `_15`: SqlExpr[String] = colChar + + override def `_16`: SqlExpr[String] = colClob + + override def `_17`: SqlExpr[Array[Byte]] = colBlob + + override def `_18`: SqlExpr[Array[Byte]] = colBinary + + override def `_19`: SqlExpr[LocalDate] = colDate + + override def `_20`: SqlExpr[LocalTime] = colTime + + override def `_21`: SqlExpr[LocalDateTime] = colDatetime + + override def `_22`: SqlExpr[LocalDateTime] = colTimestamp + + override def `_23`: SqlExpr[UUID] = colUuid + + override def `_24`: SqlExpr[Json] = colJson + + override def `_25`: SqlExpr[String] = colNotNull +} + +object AllScalarTypesFields { + val structure: AllScalarTypesFields = new AllScalarTypesFields(java.util.Collections.emptyList()) +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/all_scalar_types/AllScalarTypesId.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/all_scalar_types/AllScalarTypesId.scala new file mode 100644 index 0000000000..facf9ac1d7 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/all_scalar_types/AllScalarTypesId.scala @@ -0,0 +1,20 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.all_scalar_types + +import com.fasterxml.jackson.annotation.JsonValue +import dev.typr.dslsc.Bijection +import dev.typr.foundationssc.SqliteType +import dev.typr.foundationssc.SqliteTypes + +/** Type for the primary key of table `all_scalar_types` */ +case class AllScalarTypesId(@JsonValue value: Long) extends scala.AnyVal + +object AllScalarTypesId { + given bijection: Bijection[AllScalarTypesId, Long] = Bijection.of[AllScalarTypesId, Long](_.value, AllScalarTypesId.apply) + + given sqliteType: SqliteType[AllScalarTypesId] = SqliteTypes.integer.to(Bijection.of(AllScalarTypesId.apply, _.value)) +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/all_scalar_types/AllScalarTypesRepo.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/all_scalar_types/AllScalarTypesRepo.scala new file mode 100644 index 0000000000..2c9c24a9a5 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/all_scalar_types/AllScalarTypesRepo.scala @@ -0,0 +1,40 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.all_scalar_types + +import dev.typr.dslsc.DeleteBuilder +import dev.typr.dslsc.SelectBuilder +import dev.typr.dslsc.UpdateBuilder +import dev.typr.foundationssc.Connection +import dev.typr.foundationssc.ConnectionRead + +trait AllScalarTypesRepo { + def delete: DeleteBuilder[AllScalarTypesFields, AllScalarTypesRow] + + def deleteById(id: AllScalarTypesId)(using c: Connection): Boolean + + def deleteByIds(ids: List[AllScalarTypesId])(using c: Connection): Int + + def insert(unsaved: AllScalarTypesRow)(using c: Connection): AllScalarTypesRow + + def select: SelectBuilder[AllScalarTypesFields, AllScalarTypesRow] + + def selectAll(using c: ConnectionRead): List[AllScalarTypesRow] + + def selectById(id: AllScalarTypesId)(using c: ConnectionRead): Option[AllScalarTypesRow] + + def selectByIds(ids: List[AllScalarTypesId])(using c: ConnectionRead): List[AllScalarTypesRow] + + def selectByIdsTracked(ids: List[AllScalarTypesId])(using c: ConnectionRead): Map[AllScalarTypesId, AllScalarTypesRow] + + def update: UpdateBuilder[AllScalarTypesFields, AllScalarTypesRow] + + def update(row: AllScalarTypesRow)(using c: Connection): Boolean + + def upsert(unsaved: AllScalarTypesRow)(using c: Connection): AllScalarTypesRow + + def upsertBatch(unsaved: Iterator[AllScalarTypesRow])(using c: Connection): List[AllScalarTypesRow] +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/all_scalar_types/AllScalarTypesRepoImpl.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/all_scalar_types/AllScalarTypesRepoImpl.scala new file mode 100644 index 0000000000..c89ebeb17e --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/all_scalar_types/AllScalarTypesRepoImpl.scala @@ -0,0 +1,163 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.all_scalar_types + +import dev.typr.dslsc.DeleteBuilder +import dev.typr.dslsc.Dialect +import dev.typr.dslsc.SelectBuilder +import dev.typr.dslsc.UpdateBuilder +import dev.typr.foundationssc.Connection +import dev.typr.foundationssc.ConnectionRead +import dev.typr.foundationssc.Fragment +import dev.typr.foundationssc.SqliteTypes +import scala.collection.mutable.ListBuffer +import dev.typr.foundationssc.Fragment.sql + +class AllScalarTypesRepoImpl extends AllScalarTypesRepo { + override def delete: DeleteBuilder[AllScalarTypesFields, AllScalarTypesRow] = DeleteBuilder.of(""""all_scalar_types"""", AllScalarTypesFields.structure, Dialect.SQLITE) + + override def deleteById(id: AllScalarTypesId)(using c: Connection): Boolean = sql"""delete from "all_scalar_types" where "id" = ${Fragment.encode(AllScalarTypesId.sqliteType, id)}""".update().run(using c) > 0 + + override def deleteByIds(ids: List[AllScalarTypesId])(using c: Connection): Int = { + val fragments: ListBuffer[Fragment] = ListBuffer() + ids.foreach { id => fragments.addOne(Fragment.encode(AllScalarTypesId.sqliteType, id)): @scala.annotation.nowarn } + return Fragment.concat(Fragment.of("""delete from "all_scalar_types" where "id" in ("""), Fragment.comma(fragments), Fragment.of(")")).update().run(using c) + } + + override def insert(unsaved: AllScalarTypesRow)(using c: Connection): AllScalarTypesRow = { + sql"""insert into "all_scalar_types"("id", "col_tinyint", "col_smallint", "col_int", "col_integer", "col_bigint", "col_boolean", "col_real", "col_double", "col_float", "col_decimal", "col_numeric", "col_text", "col_varchar", "col_char", "col_clob", "col_blob", "col_binary", "col_date", "col_time", "col_datetime", "col_timestamp", "col_uuid", "col_json", "col_not_null") + values (${Fragment.encode(AllScalarTypesId.sqliteType, unsaved.id)}, ${Fragment.encode(SqliteTypes.tinyint.opt, unsaved.colTinyint)}, ${Fragment.encode(SqliteTypes.smallint.opt, unsaved.colSmallint)}, ${Fragment.encode(SqliteTypes.int_.opt, unsaved.colInt)}, ${Fragment.encode(SqliteTypes.integer.opt, unsaved.colInteger)}, ${Fragment.encode(SqliteTypes.bigint.opt, unsaved.colBigint)}, ${Fragment.encode(SqliteTypes.boolean_.opt, unsaved.colBoolean)}, ${Fragment.encode(SqliteTypes.real.opt, unsaved.colReal)}, ${Fragment.encode(SqliteTypes.double_.opt, unsaved.colDouble)}, ${Fragment.encode(SqliteTypes.float_.opt, unsaved.colFloat)}, ${Fragment.encode(SqliteTypes.numeric.opt, unsaved.colDecimal)}, ${Fragment.encode(SqliteTypes.numeric.opt, unsaved.colNumeric)}, ${Fragment.encode(SqliteTypes.text.opt, unsaved.colText)}, ${Fragment.encode(SqliteTypes.varchar.opt, unsaved.colVarchar)}, ${Fragment.encode(SqliteTypes.char_.opt, unsaved.colChar)}, ${Fragment.encode(SqliteTypes.clob.opt, unsaved.colClob)}, ${Fragment.encode(SqliteTypes.blob.opt, unsaved.colBlob)}, ${Fragment.encode(SqliteTypes.binary.opt, unsaved.colBinary)}, ${Fragment.encode(SqliteTypes.date.opt, unsaved.colDate)}, ${Fragment.encode(SqliteTypes.time.opt, unsaved.colTime)}, ${Fragment.encode(SqliteTypes.timestamp.opt, unsaved.colDatetime)}, ${Fragment.encode(SqliteTypes.timestamp.opt, unsaved.colTimestamp)}, ${Fragment.encode(SqliteTypes.uuid.opt, unsaved.colUuid)}, ${Fragment.encode(SqliteTypes.json.opt, unsaved.colJson)}, ${Fragment.encode(SqliteTypes.text, unsaved.colNotNull)}) + RETURNING "id", "col_tinyint", "col_smallint", "col_int", "col_integer", "col_bigint", "col_boolean", "col_real", "col_double", "col_float", "col_decimal", "col_numeric", "col_text", "col_varchar", "col_char", "col_clob", "col_blob", "col_binary", "col_date", "col_time", "col_datetime", "col_timestamp", "col_uuid", "col_json", "col_not_null" + """ + .updateReturning(AllScalarTypesRow.rowCodec.exactlyOne()).run(using c) + } + + override def select: SelectBuilder[AllScalarTypesFields, AllScalarTypesRow] = SelectBuilder.of(""""all_scalar_types"""", AllScalarTypesFields.structure, AllScalarTypesRow.rowCodec, Dialect.SQLITE) + + override def selectAll(using c: ConnectionRead): List[AllScalarTypesRow] = { + sql"""select "id", "col_tinyint", "col_smallint", "col_int", "col_integer", "col_bigint", "col_boolean", "col_real", "col_double", "col_float", "col_decimal", "col_numeric", "col_text", "col_varchar", "col_char", "col_clob", "col_blob", "col_binary", "col_date", "col_time", "col_datetime", "col_timestamp", "col_uuid", "col_json", "col_not_null" + from "all_scalar_types" + """.query(AllScalarTypesRow.rowCodec.all()).run(using c) + } + + override def selectById(id: AllScalarTypesId)(using c: ConnectionRead): Option[AllScalarTypesRow] = { + sql"""select "id", "col_tinyint", "col_smallint", "col_int", "col_integer", "col_bigint", "col_boolean", "col_real", "col_double", "col_float", "col_decimal", "col_numeric", "col_text", "col_varchar", "col_char", "col_clob", "col_blob", "col_binary", "col_date", "col_time", "col_datetime", "col_timestamp", "col_uuid", "col_json", "col_not_null" + from "all_scalar_types" + where "id" = ${Fragment.encode(AllScalarTypesId.sqliteType, id)}""".query(AllScalarTypesRow.rowCodec.first()).run(using c) + } + + override def selectByIds(ids: List[AllScalarTypesId])(using c: ConnectionRead): List[AllScalarTypesRow] = { + val fragments: ListBuffer[Fragment] = ListBuffer() + ids.foreach { id => fragments.addOne(Fragment.encode(AllScalarTypesId.sqliteType, id)): @scala.annotation.nowarn } + return Fragment.concat(Fragment.of("""select "id", "col_tinyint", "col_smallint", "col_int", "col_integer", "col_bigint", "col_boolean", "col_real", "col_double", "col_float", "col_decimal", "col_numeric", "col_text", "col_varchar", "col_char", "col_clob", "col_blob", "col_binary", "col_date", "col_time", "col_datetime", "col_timestamp", "col_uuid", "col_json", "col_not_null" from "all_scalar_types" where "id" in ("""), Fragment.comma(fragments), Fragment.of(")")).query(AllScalarTypesRow.rowCodec.all()).run(using c) + } + + override def selectByIdsTracked(ids: List[AllScalarTypesId])(using c: ConnectionRead): Map[AllScalarTypesId, AllScalarTypesRow] = { + val ret: scala.collection.mutable.Map[AllScalarTypesId, AllScalarTypesRow] = scala.collection.mutable.Map.empty[AllScalarTypesId, AllScalarTypesRow] + selectByIds(ids)(using c).foreach(row => ret.put(row.id, row): @scala.annotation.nowarn) + return ret.toMap + } + + override def update: UpdateBuilder[AllScalarTypesFields, AllScalarTypesRow] = UpdateBuilder.of(""""all_scalar_types"""", AllScalarTypesFields.structure, AllScalarTypesRow.rowCodec, Dialect.SQLITE) + + override def update(row: AllScalarTypesRow)(using c: Connection): Boolean = { + val id: AllScalarTypesId = row.id + return sql"""update "all_scalar_types" + set "col_tinyint" = ${Fragment.encode(SqliteTypes.tinyint.opt, row.colTinyint)}, + "col_smallint" = ${Fragment.encode(SqliteTypes.smallint.opt, row.colSmallint)}, + "col_int" = ${Fragment.encode(SqliteTypes.int_.opt, row.colInt)}, + "col_integer" = ${Fragment.encode(SqliteTypes.integer.opt, row.colInteger)}, + "col_bigint" = ${Fragment.encode(SqliteTypes.bigint.opt, row.colBigint)}, + "col_boolean" = ${Fragment.encode(SqliteTypes.boolean_.opt, row.colBoolean)}, + "col_real" = ${Fragment.encode(SqliteTypes.real.opt, row.colReal)}, + "col_double" = ${Fragment.encode(SqliteTypes.double_.opt, row.colDouble)}, + "col_float" = ${Fragment.encode(SqliteTypes.float_.opt, row.colFloat)}, + "col_decimal" = ${Fragment.encode(SqliteTypes.numeric.opt, row.colDecimal)}, + "col_numeric" = ${Fragment.encode(SqliteTypes.numeric.opt, row.colNumeric)}, + "col_text" = ${Fragment.encode(SqliteTypes.text.opt, row.colText)}, + "col_varchar" = ${Fragment.encode(SqliteTypes.varchar.opt, row.colVarchar)}, + "col_char" = ${Fragment.encode(SqliteTypes.char_.opt, row.colChar)}, + "col_clob" = ${Fragment.encode(SqliteTypes.clob.opt, row.colClob)}, + "col_blob" = ${Fragment.encode(SqliteTypes.blob.opt, row.colBlob)}, + "col_binary" = ${Fragment.encode(SqliteTypes.binary.opt, row.colBinary)}, + "col_date" = ${Fragment.encode(SqliteTypes.date.opt, row.colDate)}, + "col_time" = ${Fragment.encode(SqliteTypes.time.opt, row.colTime)}, + "col_datetime" = ${Fragment.encode(SqliteTypes.timestamp.opt, row.colDatetime)}, + "col_timestamp" = ${Fragment.encode(SqliteTypes.timestamp.opt, row.colTimestamp)}, + "col_uuid" = ${Fragment.encode(SqliteTypes.uuid.opt, row.colUuid)}, + "col_json" = ${Fragment.encode(SqliteTypes.json.opt, row.colJson)}, + "col_not_null" = ${Fragment.encode(SqliteTypes.text, row.colNotNull)} + where "id" = ${Fragment.encode(AllScalarTypesId.sqliteType, id)}""".update().run(using c) > 0 + } + + override def upsert(unsaved: AllScalarTypesRow)(using c: Connection): AllScalarTypesRow = { + sql"""INSERT INTO "all_scalar_types"("id", "col_tinyint", "col_smallint", "col_int", "col_integer", "col_bigint", "col_boolean", "col_real", "col_double", "col_float", "col_decimal", "col_numeric", "col_text", "col_varchar", "col_char", "col_clob", "col_blob", "col_binary", "col_date", "col_time", "col_datetime", "col_timestamp", "col_uuid", "col_json", "col_not_null") + VALUES (${Fragment.encode(AllScalarTypesId.sqliteType, unsaved.id)}, ${Fragment.encode(SqliteTypes.tinyint.opt, unsaved.colTinyint)}, ${Fragment.encode(SqliteTypes.smallint.opt, unsaved.colSmallint)}, ${Fragment.encode(SqliteTypes.int_.opt, unsaved.colInt)}, ${Fragment.encode(SqliteTypes.integer.opt, unsaved.colInteger)}, ${Fragment.encode(SqliteTypes.bigint.opt, unsaved.colBigint)}, ${Fragment.encode(SqliteTypes.boolean_.opt, unsaved.colBoolean)}, ${Fragment.encode(SqliteTypes.real.opt, unsaved.colReal)}, ${Fragment.encode(SqliteTypes.double_.opt, unsaved.colDouble)}, ${Fragment.encode(SqliteTypes.float_.opt, unsaved.colFloat)}, ${Fragment.encode(SqliteTypes.numeric.opt, unsaved.colDecimal)}, ${Fragment.encode(SqliteTypes.numeric.opt, unsaved.colNumeric)}, ${Fragment.encode(SqliteTypes.text.opt, unsaved.colText)}, ${Fragment.encode(SqliteTypes.varchar.opt, unsaved.colVarchar)}, ${Fragment.encode(SqliteTypes.char_.opt, unsaved.colChar)}, ${Fragment.encode(SqliteTypes.clob.opt, unsaved.colClob)}, ${Fragment.encode(SqliteTypes.blob.opt, unsaved.colBlob)}, ${Fragment.encode(SqliteTypes.binary.opt, unsaved.colBinary)}, ${Fragment.encode(SqliteTypes.date.opt, unsaved.colDate)}, ${Fragment.encode(SqliteTypes.time.opt, unsaved.colTime)}, ${Fragment.encode(SqliteTypes.timestamp.opt, unsaved.colDatetime)}, ${Fragment.encode(SqliteTypes.timestamp.opt, unsaved.colTimestamp)}, ${Fragment.encode(SqliteTypes.uuid.opt, unsaved.colUuid)}, ${Fragment.encode(SqliteTypes.json.opt, unsaved.colJson)}, ${Fragment.encode(SqliteTypes.text, unsaved.colNotNull)}) + ON CONFLICT ("id") + DO UPDATE SET + "col_tinyint" = EXCLUDED."col_tinyint", + "col_smallint" = EXCLUDED."col_smallint", + "col_int" = EXCLUDED."col_int", + "col_integer" = EXCLUDED."col_integer", + "col_bigint" = EXCLUDED."col_bigint", + "col_boolean" = EXCLUDED."col_boolean", + "col_real" = EXCLUDED."col_real", + "col_double" = EXCLUDED."col_double", + "col_float" = EXCLUDED."col_float", + "col_decimal" = EXCLUDED."col_decimal", + "col_numeric" = EXCLUDED."col_numeric", + "col_text" = EXCLUDED."col_text", + "col_varchar" = EXCLUDED."col_varchar", + "col_char" = EXCLUDED."col_char", + "col_clob" = EXCLUDED."col_clob", + "col_blob" = EXCLUDED."col_blob", + "col_binary" = EXCLUDED."col_binary", + "col_date" = EXCLUDED."col_date", + "col_time" = EXCLUDED."col_time", + "col_datetime" = EXCLUDED."col_datetime", + "col_timestamp" = EXCLUDED."col_timestamp", + "col_uuid" = EXCLUDED."col_uuid", + "col_json" = EXCLUDED."col_json", + "col_not_null" = EXCLUDED."col_not_null" + RETURNING "id", "col_tinyint", "col_smallint", "col_int", "col_integer", "col_bigint", "col_boolean", "col_real", "col_double", "col_float", "col_decimal", "col_numeric", "col_text", "col_varchar", "col_char", "col_clob", "col_blob", "col_binary", "col_date", "col_time", "col_datetime", "col_timestamp", "col_uuid", "col_json", "col_not_null"""" + .updateReturning(AllScalarTypesRow.rowCodec.exactlyOne()) + .run(using c) + } + + override def upsertBatch(unsaved: Iterator[AllScalarTypesRow])(using c: Connection): List[AllScalarTypesRow] = { + sql"""INSERT INTO "all_scalar_types"("id", "col_tinyint", "col_smallint", "col_int", "col_integer", "col_bigint", "col_boolean", "col_real", "col_double", "col_float", "col_decimal", "col_numeric", "col_text", "col_varchar", "col_char", "col_clob", "col_blob", "col_binary", "col_date", "col_time", "col_datetime", "col_timestamp", "col_uuid", "col_json", "col_not_null") + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + ON CONFLICT ("id") + DO UPDATE SET + "col_tinyint" = EXCLUDED."col_tinyint", + "col_smallint" = EXCLUDED."col_smallint", + "col_int" = EXCLUDED."col_int", + "col_integer" = EXCLUDED."col_integer", + "col_bigint" = EXCLUDED."col_bigint", + "col_boolean" = EXCLUDED."col_boolean", + "col_real" = EXCLUDED."col_real", + "col_double" = EXCLUDED."col_double", + "col_float" = EXCLUDED."col_float", + "col_decimal" = EXCLUDED."col_decimal", + "col_numeric" = EXCLUDED."col_numeric", + "col_text" = EXCLUDED."col_text", + "col_varchar" = EXCLUDED."col_varchar", + "col_char" = EXCLUDED."col_char", + "col_clob" = EXCLUDED."col_clob", + "col_blob" = EXCLUDED."col_blob", + "col_binary" = EXCLUDED."col_binary", + "col_date" = EXCLUDED."col_date", + "col_time" = EXCLUDED."col_time", + "col_datetime" = EXCLUDED."col_datetime", + "col_timestamp" = EXCLUDED."col_timestamp", + "col_uuid" = EXCLUDED."col_uuid", + "col_json" = EXCLUDED."col_json", + "col_not_null" = EXCLUDED."col_not_null" + RETURNING "id", "col_tinyint", "col_smallint", "col_int", "col_integer", "col_bigint", "col_boolean", "col_real", "col_double", "col_float", "col_decimal", "col_numeric", "col_text", "col_varchar", "col_char", "col_clob", "col_blob", "col_binary", "col_date", "col_time", "col_datetime", "col_timestamp", "col_uuid", "col_json", "col_not_null"""" + .updateReturningEach(AllScalarTypesRow.rowCodec, unsaved) + .run(using c) + } +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/all_scalar_types/AllScalarTypesRepoMock.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/all_scalar_types/AllScalarTypesRepoMock.scala new file mode 100644 index 0000000000..fcac51cad1 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/all_scalar_types/AllScalarTypesRepoMock.scala @@ -0,0 +1,73 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.all_scalar_types + +import dev.typr.dslsc.DeleteBuilder +import dev.typr.dslsc.DeleteBuilderMock +import dev.typr.dslsc.DeleteParams +import dev.typr.dslsc.SelectBuilder +import dev.typr.dslsc.SelectBuilderMock +import dev.typr.dslsc.SelectParams +import dev.typr.dslsc.UpdateBuilder +import dev.typr.dslsc.UpdateBuilderMock +import dev.typr.dslsc.UpdateParams +import dev.typr.foundationssc.Connection +import dev.typr.foundationssc.ConnectionRead +import java.lang.RuntimeException + +case class AllScalarTypesRepoMock(map: scala.collection.mutable.Map[AllScalarTypesId, AllScalarTypesRow] = scala.collection.mutable.Map.empty[AllScalarTypesId, AllScalarTypesRow]) extends AllScalarTypesRepo { + override def delete: DeleteBuilder[AllScalarTypesFields, AllScalarTypesRow] = DeleteBuilderMock(AllScalarTypesFields.structure, () => map.values.toList, DeleteParams.empty(), row => row.id, id => map.remove(id): @scala.annotation.nowarn) + + override def deleteById(id: AllScalarTypesId)(using c: Connection): Boolean = map.remove(id).isDefined + + override def deleteByIds(ids: List[AllScalarTypesId])(using c: Connection): Int = { + var count = 0 + ids.foreach { id => if (map.remove(id).isDefined) { + count = count + 1 + } } + return count + } + + override def insert(unsaved: AllScalarTypesRow)(using c: Connection): AllScalarTypesRow = { + if (map.contains(unsaved.id)) { + throw new RuntimeException(s"id ${unsaved.id} already exists") + } + map.put(unsaved.id, unsaved): @scala.annotation.nowarn + return unsaved + } + + override def select: SelectBuilder[AllScalarTypesFields, AllScalarTypesRow] = SelectBuilderMock(AllScalarTypesFields.structure, () => map.values.toList, SelectParams.empty()) + + override def selectAll(using c: ConnectionRead): List[AllScalarTypesRow] = map.values.toList + + override def selectById(id: AllScalarTypesId)(using c: ConnectionRead): Option[AllScalarTypesRow] = map.get(id) + + override def selectByIds(ids: List[AllScalarTypesId])(using c: ConnectionRead): List[AllScalarTypesRow] = ids.flatMap(map.get(_)).toList + + override def selectByIdsTracked(ids: List[AllScalarTypesId])(using c: ConnectionRead): Map[AllScalarTypesId, AllScalarTypesRow] = selectByIds(ids)(using c).map(x => (((row: AllScalarTypesRow) => row.id).apply(x), x)).toMap + + override def update: UpdateBuilder[AllScalarTypesFields, AllScalarTypesRow] = UpdateBuilderMock(AllScalarTypesFields.structure, () => map.values.toList, UpdateParams.empty(), row => row) + + override def update(row: AllScalarTypesRow)(using c: Connection): Boolean = { + val shouldUpdate = map.get(row.id).filter(oldRow => (oldRow != row)).isDefined + if (shouldUpdate) { + map.put(row.id, row): @scala.annotation.nowarn + } + return shouldUpdate + } + + override def upsert(unsaved: AllScalarTypesRow)(using c: Connection): AllScalarTypesRow = { + map.put(unsaved.id, unsaved): @scala.annotation.nowarn + return unsaved + } + + override def upsertBatch(unsaved: Iterator[AllScalarTypesRow])(using c: Connection): List[AllScalarTypesRow] = { + unsaved.map { row => + map.put(row.id, row): @scala.annotation.nowarn + row + }.toList + } +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/all_scalar_types/AllScalarTypesRow.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/all_scalar_types/AllScalarTypesRow.scala new file mode 100644 index 0000000000..e2037277c1 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/all_scalar_types/AllScalarTypesRow.scala @@ -0,0 +1,102 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.all_scalar_types + +import com.fasterxml.jackson.annotation.JsonProperty +import dev.typr.dslsc.RowCodecs +import dev.typr.foundations.Tuple.Tuple25 +import dev.typr.foundations.data.Json +import dev.typr.foundationssc.RowCodec +import dev.typr.foundationssc.SqliteTypes +import java.time.LocalDate +import java.time.LocalDateTime +import java.time.LocalTime +import java.util.UUID + +/** Table: all_scalar_types + * Primary key: id + */ +case class AllScalarTypesRow( + id: AllScalarTypesId, + @JsonProperty("col_tinyint") colTinyint: Option[Byte], + @JsonProperty("col_smallint") colSmallint: Option[Short], + @JsonProperty("col_int") colInt: Option[Int], + @JsonProperty("col_integer") colInteger: Option[Long], + @JsonProperty("col_bigint") colBigint: Option[Long], + @JsonProperty("col_boolean") colBoolean: Option[Boolean], + @JsonProperty("col_real") colReal: Option[Double], + @JsonProperty("col_double") colDouble: Option[Double], + @JsonProperty("col_float") colFloat: Option[Float], + @JsonProperty("col_decimal") colDecimal: Option[BigDecimal], + @JsonProperty("col_numeric") colNumeric: Option[BigDecimal], + @JsonProperty("col_text") colText: Option[String], + @JsonProperty("col_varchar") colVarchar: Option[String], + @JsonProperty("col_char") colChar: Option[String], + @JsonProperty("col_clob") colClob: Option[String], + @JsonProperty("col_blob") colBlob: Option[Array[Byte]], + @JsonProperty("col_binary") colBinary: Option[Array[Byte]], + @JsonProperty("col_date") colDate: Option[LocalDate], + @JsonProperty("col_time") colTime: Option[LocalTime], + @JsonProperty("col_datetime") colDatetime: Option[LocalDateTime], + @JsonProperty("col_timestamp") colTimestamp: Option[LocalDateTime], + @JsonProperty("col_uuid") colUuid: Option[UUID], + @JsonProperty("col_json") colJson: Option[Json], + @JsonProperty("col_not_null") colNotNull: String +) extends Tuple25[AllScalarTypesId, Option[Byte], Option[Short], Option[Int], Option[Long], Option[Long], Option[Boolean], Option[Double], Option[Double], Option[Float], Option[BigDecimal], Option[BigDecimal], Option[String], Option[String], Option[String], Option[String], Option[Array[Byte]], Option[Array[Byte]], Option[LocalDate], Option[LocalTime], Option[LocalDateTime], Option[LocalDateTime], Option[UUID], Option[Json], String] { + override def `_1`: AllScalarTypesId = id + + override def `_2`: Option[Byte] = colTinyint + + override def `_3`: Option[Short] = colSmallint + + override def `_4`: Option[Int] = colInt + + override def `_5`: Option[Long] = colInteger + + override def `_6`: Option[Long] = colBigint + + override def `_7`: Option[Boolean] = colBoolean + + override def `_8`: Option[Double] = colReal + + override def `_9`: Option[Double] = colDouble + + override def `_10`: Option[Float] = colFloat + + override def `_11`: Option[BigDecimal] = colDecimal + + override def `_12`: Option[BigDecimal] = colNumeric + + override def `_13`: Option[String] = colText + + override def `_14`: Option[String] = colVarchar + + override def `_15`: Option[String] = colChar + + override def `_16`: Option[String] = colClob + + override def `_17`: Option[Array[Byte]] = colBlob + + override def `_18`: Option[Array[Byte]] = colBinary + + override def `_19`: Option[LocalDate] = colDate + + override def `_20`: Option[LocalTime] = colTime + + override def `_21`: Option[LocalDateTime] = colDatetime + + override def `_22`: Option[LocalDateTime] = colTimestamp + + override def `_23`: Option[UUID] = colUuid + + override def `_24`: Option[Json] = colJson + + override def `_25`: String = colNotNull +} + +object AllScalarTypesRow { + val rowCodec: RowCodec[AllScalarTypesRow] = RowCodecs.of(AllScalarTypesId.sqliteType, SqliteTypes.tinyint.opt, SqliteTypes.smallint.opt, SqliteTypes.int_.opt, SqliteTypes.integer.opt, SqliteTypes.bigint.opt, SqliteTypes.boolean_.opt, SqliteTypes.real.opt, SqliteTypes.double_.opt, SqliteTypes.float_.opt, SqliteTypes.numeric.opt, SqliteTypes.numeric.opt, SqliteTypes.text.opt, SqliteTypes.varchar.opt, SqliteTypes.char_.opt, SqliteTypes.clob.opt, SqliteTypes.blob.opt, SqliteTypes.binary.opt, SqliteTypes.date.opt, SqliteTypes.time.opt, SqliteTypes.timestamp.opt, SqliteTypes.timestamp.opt, SqliteTypes.uuid.opt, SqliteTypes.json.opt, SqliteTypes.text)(AllScalarTypesRow.apply)(row => Array[Any](row.id, row.colTinyint, row.colSmallint, row.colInt, row.colInteger, row.colBigint, row.colBoolean, row.colReal, row.colDouble, row.colFloat, row.colDecimal, row.colNumeric, row.colText, row.colVarchar, row.colChar, row.colClob, row.colBlob, row.colBinary, row.colDate, row.colTime, row.colDatetime, row.colTimestamp, row.colUuid, row.colJson, row.colNotNull)) +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/all_scalar_types_search/AllScalarTypesSearchSqlRepo.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/all_scalar_types_search/AllScalarTypesSearchSqlRepo.scala new file mode 100644 index 0000000000..f75dc78b62 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/all_scalar_types_search/AllScalarTypesSearchSqlRepo.scala @@ -0,0 +1,17 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.all_scalar_types_search + +import dev.typr.foundationssc.ConnectionRead +import java.time.LocalDate + +trait AllScalarTypesSearchSqlRepo { + def apply( + minId: Option[Long], + textPattern: Option[String], + afterDate: Option[LocalDate] + )(using c: ConnectionRead): List[AllScalarTypesSearchSqlRow] +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/all_scalar_types_search/AllScalarTypesSearchSqlRepoImpl.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/all_scalar_types_search/AllScalarTypesSearchSqlRepoImpl.scala new file mode 100644 index 0000000000..faf4383ac3 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/all_scalar_types_search/AllScalarTypesSearchSqlRepoImpl.scala @@ -0,0 +1,43 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.all_scalar_types_search + +import dev.typr.foundationssc.ConnectionRead +import dev.typr.foundationssc.Fragment +import dev.typr.foundationssc.SqliteTypes +import java.time.LocalDate +import dev.typr.foundationssc.Fragment.sql + +class AllScalarTypesSearchSqlRepoImpl extends AllScalarTypesSearchSqlRepo { + override def apply( + minId: Option[Long], + textPattern: Option[String], + afterDate: Option[LocalDate] + )(using c: ConnectionRead): List[AllScalarTypesSearchSqlRow] = { + sql"""-- Filter the all_scalar_types table by a handful of columns. + -- Tests: a parameter for each affinity (INTEGER, REAL, TEXT, DATE). + + SELECT + id, + col_tinyint, + col_smallint, + col_integer, + col_bigint, + col_real, + col_double, + col_decimal, + col_text, + col_date, + col_uuid, + col_json + FROM all_scalar_types + WHERE + (${Fragment.encode(SqliteTypes.integer.opt, minId)} IS NULL OR id >= ${Fragment.encode(SqliteTypes.integer.opt, minId)}) + AND (${Fragment.encode(SqliteTypes.text.opt, textPattern)} IS NULL OR col_text LIKE ${Fragment.encode(SqliteTypes.text.opt, textPattern)}) + AND (${Fragment.encode(SqliteTypes.date.opt, afterDate)} IS NULL OR col_date >= ${Fragment.encode(SqliteTypes.date.opt, afterDate)}) + ORDER BY id""".query(AllScalarTypesSearchSqlRow.rowCodec.all()).run(using c) + } +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/all_scalar_types_search/AllScalarTypesSearchSqlRow.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/all_scalar_types_search/AllScalarTypesSearchSqlRow.scala new file mode 100644 index 0000000000..1f954f327b --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/all_scalar_types_search/AllScalarTypesSearchSqlRow.scala @@ -0,0 +1,72 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.all_scalar_types_search + +import com.fasterxml.jackson.annotation.JsonProperty +import dev.typr.dslsc.RowCodecs +import dev.typr.foundations.Tuple.Tuple12 +import dev.typr.foundations.data.Json +import dev.typr.foundationssc.RowCodec +import dev.typr.foundationssc.SqliteTypes +import java.time.LocalDate +import java.util.UUID +import testdb.all_scalar_types.AllScalarTypesId + +/** SQL file: all_scalar_types_search.sql */ +case class AllScalarTypesSearchSqlRow( + /** Points to [[testdb.all_scalar_types.AllScalarTypesRow.id]] */ + id: AllScalarTypesId, + /** Points to [[testdb.all_scalar_types.AllScalarTypesRow.colTinyint]] */ + @JsonProperty("col_tinyint") colTinyint: Option[Byte], + /** Points to [[testdb.all_scalar_types.AllScalarTypesRow.colSmallint]] */ + @JsonProperty("col_smallint") colSmallint: Option[Short], + /** Points to [[testdb.all_scalar_types.AllScalarTypesRow.colInteger]] */ + @JsonProperty("col_integer") colInteger: Option[Long], + /** Points to [[testdb.all_scalar_types.AllScalarTypesRow.colBigint]] */ + @JsonProperty("col_bigint") colBigint: Option[Long], + /** Points to [[testdb.all_scalar_types.AllScalarTypesRow.colReal]] */ + @JsonProperty("col_real") colReal: Option[Double], + /** Points to [[testdb.all_scalar_types.AllScalarTypesRow.colDouble]] */ + @JsonProperty("col_double") colDouble: Option[Double], + /** Points to [[testdb.all_scalar_types.AllScalarTypesRow.colDecimal]] */ + @JsonProperty("col_decimal") colDecimal: Option[BigDecimal], + /** Points to [[testdb.all_scalar_types.AllScalarTypesRow.colText]] */ + @JsonProperty("col_text") colText: Option[String], + /** Points to [[testdb.all_scalar_types.AllScalarTypesRow.colDate]] */ + @JsonProperty("col_date") colDate: Option[LocalDate], + /** Points to [[testdb.all_scalar_types.AllScalarTypesRow.colUuid]] */ + @JsonProperty("col_uuid") colUuid: Option[UUID], + /** Points to [[testdb.all_scalar_types.AllScalarTypesRow.colJson]] */ + @JsonProperty("col_json") colJson: Option[Json] +) extends Tuple12[AllScalarTypesId, Option[Byte], Option[Short], Option[Long], Option[Long], Option[Double], Option[Double], Option[BigDecimal], Option[String], Option[LocalDate], Option[UUID], Option[Json]] { + override def `_1`: AllScalarTypesId = id + + override def `_2`: Option[Byte] = colTinyint + + override def `_3`: Option[Short] = colSmallint + + override def `_4`: Option[Long] = colInteger + + override def `_5`: Option[Long] = colBigint + + override def `_6`: Option[Double] = colReal + + override def `_7`: Option[Double] = colDouble + + override def `_8`: Option[BigDecimal] = colDecimal + + override def `_9`: Option[String] = colText + + override def `_10`: Option[LocalDate] = colDate + + override def `_11`: Option[UUID] = colUuid + + override def `_12`: Option[Json] = colJson +} + +object AllScalarTypesSearchSqlRow { + val rowCodec: RowCodec[AllScalarTypesSearchSqlRow] = RowCodecs.of(AllScalarTypesId.sqliteType, SqliteTypes.tinyint.opt, SqliteTypes.smallint.opt, SqliteTypes.integer.opt, SqliteTypes.bigint.opt, SqliteTypes.real.opt, SqliteTypes.double_.opt, SqliteTypes.numeric.opt, SqliteTypes.text.opt, SqliteTypes.date.opt, SqliteTypes.uuid.opt, SqliteTypes.json.opt)(AllScalarTypesSearchSqlRow.apply)(row => Array[Any](row.id, row.colTinyint, row.colSmallint, row.colInteger, row.colBigint, row.colReal, row.colDouble, row.colDecimal, row.colText, row.colDate, row.colUuid, row.colJson)) +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/bridge/Customer.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/bridge/Customer.scala new file mode 100644 index 0000000000..7fb6797fcb --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/bridge/Customer.scala @@ -0,0 +1,15 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.bridge + + + +/** Bridge composite type: Customer */ +case class Customer( + created_at: Option[String], + customer_id: String, + email: Option[String] +) \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/customer_orders/CustomerOrdersViewFields.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/customer_orders/CustomerOrdersViewFields.scala new file mode 100644 index 0000000000..21410305b5 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/customer_orders/CustomerOrdersViewFields.scala @@ -0,0 +1,130 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.customer_orders + +import dev.typr.dsl.FieldsBase +import dev.typr.dsl.Path +import dev.typr.dsl.SqlExpr.FieldLike +import dev.typr.dslsc.RelationStructure +import dev.typr.dslsc.SqlExpr +import dev.typr.dslsc.SqlExpr.OptField +import dev.typr.dslsc.TupleExpr7 +import dev.typr.foundations.RowCodec +import dev.typr.foundationssc.SqliteTypes +import java.time.LocalDate +import testdb.customers.CustomersId +import testdb.orders.OrdersId +import testdb.userdefined.Email + +class CustomerOrdersViewFields(val `_path`: java.util.List[Path]) extends TupleExpr7[CustomersId, String, /* user-picked */ Email, OrdersId, LocalDate, BigDecimal, String] with RelationStructure[CustomerOrdersViewFields, CustomerOrdersViewRow] with FieldsBase[CustomerOrdersViewRow] { + def customerId: OptField[CustomersId, CustomerOrdersViewRow] = { + new OptField[CustomersId, CustomerOrdersViewRow]( + _path, + "customer_id", + _.customerId, + None, + None, + (row, value) => row.copy(customerId = value), + CustomersId.sqliteType.underlying + ) + } + + def customerName: OptField[String, CustomerOrdersViewRow] = { + new OptField[String, CustomerOrdersViewRow]( + _path, + "customer_name", + _.customerName, + None, + None, + (row, value) => row.copy(customerName = value), + SqliteTypes.text.underlying + ) + } + + def email: OptField[/* user-picked */ Email, CustomerOrdersViewRow] = { + new OptField[/* user-picked */ Email, CustomerOrdersViewRow]( + _path, + "email", + _.email, + None, + None, + (row, value) => row.copy(email = value), + Email.sqliteType.underlying + ) + } + + def orderId: OptField[OrdersId, CustomerOrdersViewRow] = { + new OptField[OrdersId, CustomerOrdersViewRow]( + _path, + "order_id", + _.orderId, + None, + None, + (row, value) => row.copy(orderId = value), + OrdersId.sqliteType.underlying + ) + } + + def orderDate: OptField[LocalDate, CustomerOrdersViewRow] = { + new OptField[LocalDate, CustomerOrdersViewRow]( + _path, + "order_date", + _.orderDate, + None, + None, + (row, value) => row.copy(orderDate = value), + SqliteTypes.date.underlying + ) + } + + def totalAmount: OptField[BigDecimal, CustomerOrdersViewRow] = { + new OptField[BigDecimal, CustomerOrdersViewRow]( + _path, + "total_amount", + _.totalAmount, + None, + None, + (row, value) => row.copy(totalAmount = value), + SqliteTypes.numeric.underlying + ) + } + + def status: OptField[String, CustomerOrdersViewRow] = { + new OptField[String, CustomerOrdersViewRow]( + _path, + "status", + _.status, + None, + None, + (row, value) => row.copy(status = value), + SqliteTypes.text.underlying + ) + } + + override def columns: java.util.List[FieldLike[?, CustomerOrdersViewRow]] = java.util.List.of(this.customerId.underlying, this.customerName.underlying, this.email.underlying, this.orderId.underlying, this.orderDate.underlying, this.totalAmount.underlying, this.status.underlying) + + override def rowCodec: RowCodec[CustomerOrdersViewRow] = CustomerOrdersViewRow.rowCodec.underlying + + override def withPaths(`_path`: java.util.List[Path]): RelationStructure[CustomerOrdersViewFields, CustomerOrdersViewRow] = new CustomerOrdersViewFields(`_path`) + + override def `_1`: SqlExpr[CustomersId] = customerId + + override def `_2`: SqlExpr[String] = customerName + + override def `_3`: SqlExpr[/* user-picked */ Email] = email + + override def `_4`: SqlExpr[OrdersId] = orderId + + override def `_5`: SqlExpr[LocalDate] = orderDate + + override def `_6`: SqlExpr[BigDecimal] = totalAmount + + override def `_7`: SqlExpr[String] = status +} + +object CustomerOrdersViewFields { + val structure: CustomerOrdersViewFields = new CustomerOrdersViewFields(java.util.Collections.emptyList()) +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/customer_orders/CustomerOrdersViewRepo.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/customer_orders/CustomerOrdersViewRepo.scala new file mode 100644 index 0000000000..2f9ceac757 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/customer_orders/CustomerOrdersViewRepo.scala @@ -0,0 +1,15 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.customer_orders + +import dev.typr.dslsc.SelectBuilder +import dev.typr.foundationssc.ConnectionRead + +trait CustomerOrdersViewRepo { + def select: SelectBuilder[CustomerOrdersViewFields, CustomerOrdersViewRow] + + def selectAll(using c: ConnectionRead): List[CustomerOrdersViewRow] +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/customer_orders/CustomerOrdersViewRepoImpl.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/customer_orders/CustomerOrdersViewRepoImpl.scala new file mode 100644 index 0000000000..5103e14ae2 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/customer_orders/CustomerOrdersViewRepoImpl.scala @@ -0,0 +1,21 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.customer_orders + +import dev.typr.dslsc.Dialect +import dev.typr.dslsc.SelectBuilder +import dev.typr.foundationssc.ConnectionRead +import dev.typr.foundationssc.Fragment.sql + +class CustomerOrdersViewRepoImpl extends CustomerOrdersViewRepo { + override def select: SelectBuilder[CustomerOrdersViewFields, CustomerOrdersViewRow] = SelectBuilder.of(""""customer_orders"""", CustomerOrdersViewFields.structure, CustomerOrdersViewRow.rowCodec, Dialect.SQLITE) + + override def selectAll(using c: ConnectionRead): List[CustomerOrdersViewRow] = { + sql"""select "customer_id", "customer_name", "email", "order_id", "order_date", "total_amount", "status" + from "customer_orders" + """.query(CustomerOrdersViewRow.rowCodec.all()).run(using c) + } +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/customer_orders/CustomerOrdersViewRow.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/customer_orders/CustomerOrdersViewRow.scala new file mode 100644 index 0000000000..2d0881b2e2 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/customer_orders/CustomerOrdersViewRow.scala @@ -0,0 +1,52 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.customer_orders + +import com.fasterxml.jackson.annotation.JsonProperty +import dev.typr.dslsc.RowCodecs +import dev.typr.foundations.Tuple.Tuple7 +import dev.typr.foundationssc.RowCodec +import dev.typr.foundationssc.SqliteTypes +import java.time.LocalDate +import testdb.customers.CustomersId +import testdb.orders.OrdersId +import testdb.userdefined.Email + +/** View: customer_orders */ +case class CustomerOrdersViewRow( + /** Points to [[testdb.customers.CustomersRow.customerId]] */ + @JsonProperty("customer_id") customerId: Option[CustomersId], + /** Points to [[testdb.customers.CustomersRow.customerName]] */ + @JsonProperty("customer_name") customerName: Option[String], + /** Points to [[testdb.customers.CustomersRow.email]] */ + email: Option[/* user-picked */ Email], + /** Points to [[testdb.orders.OrdersRow.orderId]] */ + @JsonProperty("order_id") orderId: Option[OrdersId], + /** Points to [[testdb.orders.OrdersRow.orderDate]] */ + @JsonProperty("order_date") orderDate: Option[LocalDate], + /** Points to [[testdb.orders.OrdersRow.totalAmount]] */ + @JsonProperty("total_amount") totalAmount: Option[BigDecimal], + /** Points to [[testdb.orders.OrdersRow.status]] */ + status: Option[String] +) extends Tuple7[Option[CustomersId], Option[String], Option[/* user-picked */ Email], Option[OrdersId], Option[LocalDate], Option[BigDecimal], Option[String]] { + override def `_1`: Option[CustomersId] = customerId + + override def `_2`: Option[String] = customerName + + override def `_3`: Option[/* user-picked */ Email] = email + + override def `_4`: Option[OrdersId] = orderId + + override def `_5`: Option[LocalDate] = orderDate + + override def `_6`: Option[BigDecimal] = totalAmount + + override def `_7`: Option[String] = status +} + +object CustomerOrdersViewRow { + val rowCodec: RowCodec[CustomerOrdersViewRow] = RowCodecs.of(CustomersId.sqliteType.opt, SqliteTypes.text.opt, Email.sqliteType.opt, OrdersId.sqliteType.opt, SqliteTypes.date.opt, SqliteTypes.numeric.opt, SqliteTypes.text.opt)(CustomerOrdersViewRow.apply)(row => Array[Any](row.customerId, row.customerName, row.email, row.orderId, row.orderDate, row.totalAmount, row.status)) +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/customer_search/CustomerSearchSqlRepo.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/customer_search/CustomerSearchSqlRepo.scala new file mode 100644 index 0000000000..f546878e5a --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/customer_search/CustomerSearchSqlRepo.scala @@ -0,0 +1,18 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.customer_search + +import dev.typr.foundationssc.ConnectionRead +import java.time.LocalDateTime + +trait CustomerSearchSqlRepo { + def apply( + namePattern: Option[String], + emailPattern: Option[String], + createdAfter: Option[LocalDateTime], + maxResults: Long + )(using c: ConnectionRead): List[CustomerSearchSqlRow] +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/customer_search/CustomerSearchSqlRepoImpl.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/customer_search/CustomerSearchSqlRepoImpl.scala new file mode 100644 index 0000000000..01d05614f0 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/customer_search/CustomerSearchSqlRepoImpl.scala @@ -0,0 +1,37 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.customer_search + +import dev.typr.foundationssc.ConnectionRead +import dev.typr.foundationssc.Fragment +import dev.typr.foundationssc.SqliteTypes +import java.time.LocalDateTime +import dev.typr.foundationssc.Fragment.sql + +class CustomerSearchSqlRepoImpl extends CustomerSearchSqlRepo { + override def apply( + namePattern: Option[String], + emailPattern: Option[String], + createdAfter: Option[LocalDateTime], + maxResults: Long + )(using c: ConnectionRead): List[CustomerSearchSqlRow] = { + sql"""-- Customer search with multiple optional filters. + -- Tests: optional parameters, LIKE patterns, complex WHERE, ORDER BY/LIMIT. + + SELECT + customer_id, + name, + email, + created_at + FROM customers + WHERE + (${Fragment.encode(SqliteTypes.text.opt, namePattern)} IS NULL OR name LIKE ${Fragment.encode(SqliteTypes.text.opt, namePattern)}) + AND (${Fragment.encode(SqliteTypes.text.opt, emailPattern)} IS NULL OR email LIKE ${Fragment.encode(SqliteTypes.text.opt, emailPattern)}) + AND (${Fragment.encode(SqliteTypes.timestamp.opt, createdAfter)} IS NULL OR created_at >= ${Fragment.encode(SqliteTypes.timestamp.opt, createdAfter)}) + ORDER BY created_at DESC, customer_id + LIMIT ${Fragment.encode(SqliteTypes.bigint, maxResults)}""".query(CustomerSearchSqlRow.rowCodec.all()).run(using c) + } +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/customer_search/CustomerSearchSqlRow.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/customer_search/CustomerSearchSqlRow.scala new file mode 100644 index 0000000000..c3227df4a0 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/customer_search/CustomerSearchSqlRow.scala @@ -0,0 +1,39 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.customer_search + +import com.fasterxml.jackson.annotation.JsonProperty +import dev.typr.dslsc.RowCodecs +import dev.typr.foundations.Tuple.Tuple4 +import dev.typr.foundationssc.RowCodec +import dev.typr.foundationssc.SqliteTypes +import java.time.LocalDateTime +import testdb.customers.CustomersId +import testdb.userdefined.Email + +/** SQL file: customer_search.sql */ +case class CustomerSearchSqlRow( + /** Points to [[testdb.customers.CustomersRow.customerId]] */ + @JsonProperty("customer_id") customerId: CustomersId, + /** Points to [[testdb.customers.CustomersRow.name]] */ + name: String, + /** Points to [[testdb.customers.CustomersRow.email]] */ + email: Option[/* user-picked */ Email], + /** Points to [[testdb.customers.CustomersRow.createdAt]] */ + @JsonProperty("created_at") createdAt: LocalDateTime +) extends Tuple4[CustomersId, String, Option[/* user-picked */ Email], LocalDateTime] { + override def `_1`: CustomersId = customerId + + override def `_2`: String = name + + override def `_3`: Option[/* user-picked */ Email] = email + + override def `_4`: LocalDateTime = createdAt +} + +object CustomerSearchSqlRow { + val rowCodec: RowCodec[CustomerSearchSqlRow] = RowCodecs.of(CustomersId.sqliteType, SqliteTypes.text, Email.sqliteType.opt, SqliteTypes.timestamp)(CustomerSearchSqlRow.apply)(row => Array[Any](row.customerId, row.name, row.email, row.createdAt)) +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/customers/CustomersFields.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/customers/CustomersFields.scala new file mode 100644 index 0000000000..cd91977ae2 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/customers/CustomersFields.scala @@ -0,0 +1,88 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.customers + +import dev.typr.dsl.FieldsBase +import dev.typr.dsl.Path +import dev.typr.dsl.SqlExpr.FieldLike +import dev.typr.dslsc.RelationStructure +import dev.typr.dslsc.SqlExpr +import dev.typr.dslsc.SqlExpr.Field +import dev.typr.dslsc.SqlExpr.IdField +import dev.typr.dslsc.SqlExpr.OptField +import dev.typr.dslsc.TupleExpr4 +import dev.typr.foundations.RowCodec +import dev.typr.foundationssc.SqliteTypes +import java.time.LocalDateTime +import testdb.userdefined.Email + +class CustomersFields(val `_path`: java.util.List[Path]) extends TupleExpr4[CustomersId, String, /* user-picked */ Email, LocalDateTime] with RelationStructure[CustomersFields, CustomersRow] with FieldsBase[CustomersRow] { + def customerId: IdField[CustomersId, CustomersRow] = { + new IdField[CustomersId, CustomersRow]( + _path, + "customer_id", + _.customerId, + None, + None, + (row, value) => row.copy(customerId = value), + CustomersId.sqliteType.underlying + ) + } + + def name: Field[String, CustomersRow] = { + new Field[String, CustomersRow]( + _path, + "name", + _.name, + None, + None, + (row, value) => row.copy(name = value), + SqliteTypes.text.underlying + ) + } + + def email: OptField[/* user-picked */ Email, CustomersRow] = { + new OptField[/* user-picked */ Email, CustomersRow]( + _path, + "email", + _.email, + None, + None, + (row, value) => row.copy(email = value), + Email.sqliteType.underlying + ) + } + + def createdAt: Field[LocalDateTime, CustomersRow] = { + new Field[LocalDateTime, CustomersRow]( + _path, + "created_at", + _.createdAt, + None, + None, + (row, value) => row.copy(createdAt = value), + SqliteTypes.timestamp.underlying + ) + } + + override def columns: java.util.List[FieldLike[?, CustomersRow]] = java.util.List.of(this.customerId.underlying, this.name.underlying, this.email.underlying, this.createdAt.underlying) + + override def rowCodec: RowCodec[CustomersRow] = CustomersRow.rowCodec.underlying + + override def withPaths(`_path`: java.util.List[Path]): RelationStructure[CustomersFields, CustomersRow] = new CustomersFields(`_path`) + + override def `_1`: SqlExpr[CustomersId] = customerId + + override def `_2`: SqlExpr[String] = name + + override def `_3`: SqlExpr[/* user-picked */ Email] = email + + override def `_4`: SqlExpr[LocalDateTime] = createdAt +} + +object CustomersFields { + val structure: CustomersFields = new CustomersFields(java.util.Collections.emptyList()) +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/customers/CustomersId.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/customers/CustomersId.scala new file mode 100644 index 0000000000..dfb049fbee --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/customers/CustomersId.scala @@ -0,0 +1,20 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.customers + +import com.fasterxml.jackson.annotation.JsonValue +import dev.typr.dslsc.Bijection +import dev.typr.foundationssc.SqliteType +import dev.typr.foundationssc.SqliteTypes + +/** Type for the primary key of table `customers` */ +case class CustomersId(@JsonValue value: Long) extends scala.AnyVal + +object CustomersId { + given bijection: Bijection[CustomersId, Long] = Bijection.of[CustomersId, Long](_.value, CustomersId.apply) + + given sqliteType: SqliteType[CustomersId] = SqliteTypes.integer.to(Bijection.of(CustomersId.apply, _.value)) +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/customers/CustomersRepo.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/customers/CustomersRepo.scala new file mode 100644 index 0000000000..1d893ed26b --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/customers/CustomersRepo.scala @@ -0,0 +1,42 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.customers + +import dev.typr.dslsc.DeleteBuilder +import dev.typr.dslsc.SelectBuilder +import dev.typr.dslsc.UpdateBuilder +import dev.typr.foundationssc.Connection +import dev.typr.foundationssc.ConnectionRead + +trait CustomersRepo { + def delete: DeleteBuilder[CustomersFields, CustomersRow] + + def deleteById(customerId: CustomersId)(using c: Connection): Boolean + + def deleteByIds(customerIds: List[CustomersId])(using c: Connection): Int + + def insert(unsaved: CustomersRow)(using c: Connection): CustomersRow + + def insert(unsaved: CustomersRowUnsaved)(using c: Connection): CustomersRow + + def select: SelectBuilder[CustomersFields, CustomersRow] + + def selectAll(using c: ConnectionRead): List[CustomersRow] + + def selectById(customerId: CustomersId)(using c: ConnectionRead): Option[CustomersRow] + + def selectByIds(customerIds: List[CustomersId])(using c: ConnectionRead): List[CustomersRow] + + def selectByIdsTracked(customerIds: List[CustomersId])(using c: ConnectionRead): Map[CustomersId, CustomersRow] + + def update: UpdateBuilder[CustomersFields, CustomersRow] + + def update(row: CustomersRow)(using c: Connection): Boolean + + def upsert(unsaved: CustomersRow)(using c: Connection): CustomersRow + + def upsertBatch(unsaved: Iterator[CustomersRow])(using c: Connection): List[CustomersRow] +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/customers/CustomersRepoImpl.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/customers/CustomersRepoImpl.scala new file mode 100644 index 0000000000..24f44d6172 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/customers/CustomersRepoImpl.scala @@ -0,0 +1,123 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.customers + +import dev.typr.dslsc.DeleteBuilder +import dev.typr.dslsc.Dialect +import dev.typr.dslsc.SelectBuilder +import dev.typr.dslsc.UpdateBuilder +import dev.typr.foundationssc.Connection +import dev.typr.foundationssc.ConnectionRead +import dev.typr.foundationssc.Fragment +import dev.typr.foundationssc.SqliteTypes +import scala.collection.mutable.ListBuffer +import testdb.userdefined.Email +import dev.typr.foundationssc.Fragment.sql + +class CustomersRepoImpl extends CustomersRepo { + override def delete: DeleteBuilder[CustomersFields, CustomersRow] = DeleteBuilder.of(""""customers"""", CustomersFields.structure, Dialect.SQLITE) + + override def deleteById(customerId: CustomersId)(using c: Connection): Boolean = sql"""delete from "customers" where "customer_id" = ${Fragment.encode(CustomersId.sqliteType, customerId)}""".update().run(using c) > 0 + + override def deleteByIds(customerIds: List[CustomersId])(using c: Connection): Int = { + val fragments: ListBuffer[Fragment] = ListBuffer() + customerIds.foreach { id => fragments.addOne(Fragment.encode(CustomersId.sqliteType, id)): @scala.annotation.nowarn } + return Fragment.concat(Fragment.of("""delete from "customers" where "customer_id" in ("""), Fragment.comma(fragments), Fragment.of(")")).update().run(using c) + } + + override def insert(unsaved: CustomersRow)(using c: Connection): CustomersRow = { + sql"""insert into "customers"("customer_id", "name", "email", "created_at") + values (${Fragment.encode(CustomersId.sqliteType, unsaved.customerId)}, ${Fragment.encode(SqliteTypes.text, unsaved.name)}, ${Fragment.encode(Email.sqliteType.opt, unsaved.email)}, ${Fragment.encode(SqliteTypes.timestamp, unsaved.createdAt)}) + RETURNING "customer_id", "name", "email", "created_at" + """ + .updateReturning(CustomersRow.rowCodec.exactlyOne()).run(using c) + } + + override def insert(unsaved: CustomersRowUnsaved)(using c: Connection): CustomersRow = { + val columns: ListBuffer[Fragment] = ListBuffer() + val values: ListBuffer[Fragment] = ListBuffer() + columns.addOne(Fragment.of(""""customer_id"""")): @scala.annotation.nowarn + values.addOne(sql"${Fragment.encode(CustomersId.sqliteType, unsaved.customerId)}"): @scala.annotation.nowarn + columns.addOne(Fragment.of(""""name"""")): @scala.annotation.nowarn + values.addOne(sql"${Fragment.encode(SqliteTypes.text, unsaved.name)}"): @scala.annotation.nowarn + columns.addOne(Fragment.of(""""email"""")): @scala.annotation.nowarn + values.addOne(sql"${Fragment.encode(Email.sqliteType.opt, unsaved.email)}"): @scala.annotation.nowarn + unsaved.createdAt.visit( + { }, + value => { columns.addOne(Fragment.of(""""created_at"""")): @scala.annotation.nowarn; values.addOne(sql"${Fragment.encode(SqliteTypes.timestamp, value)}"): @scala.annotation.nowarn } + ); + val q: Fragment = { + sql"""insert into "customers"(${Fragment.comma(columns)}) + values (${Fragment.comma(values)}) + RETURNING "customer_id", "name", "email", "created_at" + """ + } + return q.updateReturning(CustomersRow.rowCodec.exactlyOne()).run(using c) + } + + override def select: SelectBuilder[CustomersFields, CustomersRow] = SelectBuilder.of(""""customers"""", CustomersFields.structure, CustomersRow.rowCodec, Dialect.SQLITE) + + override def selectAll(using c: ConnectionRead): List[CustomersRow] = { + sql"""select "customer_id", "name", "email", "created_at" + from "customers" + """.query(CustomersRow.rowCodec.all()).run(using c) + } + + override def selectById(customerId: CustomersId)(using c: ConnectionRead): Option[CustomersRow] = { + sql"""select "customer_id", "name", "email", "created_at" + from "customers" + where "customer_id" = ${Fragment.encode(CustomersId.sqliteType, customerId)}""".query(CustomersRow.rowCodec.first()).run(using c) + } + + override def selectByIds(customerIds: List[CustomersId])(using c: ConnectionRead): List[CustomersRow] = { + val fragments: ListBuffer[Fragment] = ListBuffer() + customerIds.foreach { id => fragments.addOne(Fragment.encode(CustomersId.sqliteType, id)): @scala.annotation.nowarn } + return Fragment.concat(Fragment.of("""select "customer_id", "name", "email", "created_at" from "customers" where "customer_id" in ("""), Fragment.comma(fragments), Fragment.of(")")).query(CustomersRow.rowCodec.all()).run(using c) + } + + override def selectByIdsTracked(customerIds: List[CustomersId])(using c: ConnectionRead): Map[CustomersId, CustomersRow] = { + val ret: scala.collection.mutable.Map[CustomersId, CustomersRow] = scala.collection.mutable.Map.empty[CustomersId, CustomersRow] + selectByIds(customerIds)(using c).foreach(row => ret.put(row.customerId, row): @scala.annotation.nowarn) + return ret.toMap + } + + override def update: UpdateBuilder[CustomersFields, CustomersRow] = UpdateBuilder.of(""""customers"""", CustomersFields.structure, CustomersRow.rowCodec, Dialect.SQLITE) + + override def update(row: CustomersRow)(using c: Connection): Boolean = { + val customerId: CustomersId = row.customerId + return sql"""update "customers" + set "name" = ${Fragment.encode(SqliteTypes.text, row.name)}, + "email" = ${Fragment.encode(Email.sqliteType.opt, row.email)}, + "created_at" = ${Fragment.encode(SqliteTypes.timestamp, row.createdAt)} + where "customer_id" = ${Fragment.encode(CustomersId.sqliteType, customerId)}""".update().run(using c) > 0 + } + + override def upsert(unsaved: CustomersRow)(using c: Connection): CustomersRow = { + sql"""INSERT INTO "customers"("customer_id", "name", "email", "created_at") + VALUES (${Fragment.encode(CustomersId.sqliteType, unsaved.customerId)}, ${Fragment.encode(SqliteTypes.text, unsaved.name)}, ${Fragment.encode(Email.sqliteType.opt, unsaved.email)}, ${Fragment.encode(SqliteTypes.timestamp, unsaved.createdAt)}) + ON CONFLICT ("customer_id") + DO UPDATE SET + "name" = EXCLUDED."name", + "email" = EXCLUDED."email", + "created_at" = EXCLUDED."created_at" + RETURNING "customer_id", "name", "email", "created_at"""" + .updateReturning(CustomersRow.rowCodec.exactlyOne()) + .run(using c) + } + + override def upsertBatch(unsaved: Iterator[CustomersRow])(using c: Connection): List[CustomersRow] = { + sql"""INSERT INTO "customers"("customer_id", "name", "email", "created_at") + VALUES (?, ?, ?, ?) + ON CONFLICT ("customer_id") + DO UPDATE SET + "name" = EXCLUDED."name", + "email" = EXCLUDED."email", + "created_at" = EXCLUDED."created_at" + RETURNING "customer_id", "name", "email", "created_at"""" + .updateReturningEach(CustomersRow.rowCodec, unsaved) + .run(using c) + } +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/customers/CustomersRepoMock.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/customers/CustomersRepoMock.scala new file mode 100644 index 0000000000..5cfac3b029 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/customers/CustomersRepoMock.scala @@ -0,0 +1,78 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.customers + +import dev.typr.dslsc.DeleteBuilder +import dev.typr.dslsc.DeleteBuilderMock +import dev.typr.dslsc.DeleteParams +import dev.typr.dslsc.SelectBuilder +import dev.typr.dslsc.SelectBuilderMock +import dev.typr.dslsc.SelectParams +import dev.typr.dslsc.UpdateBuilder +import dev.typr.dslsc.UpdateBuilderMock +import dev.typr.dslsc.UpdateParams +import dev.typr.foundationssc.Connection +import dev.typr.foundationssc.ConnectionRead +import java.lang.RuntimeException + +case class CustomersRepoMock( + toRow: CustomersRowUnsaved => CustomersRow, + map: scala.collection.mutable.Map[CustomersId, CustomersRow] = scala.collection.mutable.Map.empty[CustomersId, CustomersRow] +) extends CustomersRepo { + override def delete: DeleteBuilder[CustomersFields, CustomersRow] = DeleteBuilderMock(CustomersFields.structure, () => map.values.toList, DeleteParams.empty(), row => row.customerId, id => map.remove(id): @scala.annotation.nowarn) + + override def deleteById(customerId: CustomersId)(using c: Connection): Boolean = map.remove(customerId).isDefined + + override def deleteByIds(customerIds: List[CustomersId])(using c: Connection): Int = { + var count = 0 + customerIds.foreach { id => if (map.remove(id).isDefined) { + count = count + 1 + } } + return count + } + + override def insert(unsaved: CustomersRow)(using c: Connection): CustomersRow = { + if (map.contains(unsaved.customerId)) { + throw new RuntimeException(s"id ${unsaved.customerId} already exists") + } + map.put(unsaved.customerId, unsaved): @scala.annotation.nowarn + return unsaved + } + + override def insert(unsaved: CustomersRowUnsaved)(using c: Connection): CustomersRow = insert(toRow(unsaved))(using c) + + override def select: SelectBuilder[CustomersFields, CustomersRow] = SelectBuilderMock(CustomersFields.structure, () => map.values.toList, SelectParams.empty()) + + override def selectAll(using c: ConnectionRead): List[CustomersRow] = map.values.toList + + override def selectById(customerId: CustomersId)(using c: ConnectionRead): Option[CustomersRow] = map.get(customerId) + + override def selectByIds(customerIds: List[CustomersId])(using c: ConnectionRead): List[CustomersRow] = customerIds.flatMap(map.get(_)).toList + + override def selectByIdsTracked(customerIds: List[CustomersId])(using c: ConnectionRead): Map[CustomersId, CustomersRow] = selectByIds(customerIds)(using c).map(x => (((row: CustomersRow) => row.customerId).apply(x), x)).toMap + + override def update: UpdateBuilder[CustomersFields, CustomersRow] = UpdateBuilderMock(CustomersFields.structure, () => map.values.toList, UpdateParams.empty(), row => row) + + override def update(row: CustomersRow)(using c: Connection): Boolean = { + val shouldUpdate = map.get(row.customerId).filter(oldRow => (oldRow != row)).isDefined + if (shouldUpdate) { + map.put(row.customerId, row): @scala.annotation.nowarn + } + return shouldUpdate + } + + override def upsert(unsaved: CustomersRow)(using c: Connection): CustomersRow = { + map.put(unsaved.customerId, unsaved): @scala.annotation.nowarn + return unsaved + } + + override def upsertBatch(unsaved: Iterator[CustomersRow])(using c: Connection): List[CustomersRow] = { + unsaved.map { row => + map.put(row.customerId, row): @scala.annotation.nowarn + row + }.toList + } +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/customers/CustomersRow.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/customers/CustomersRow.scala new file mode 100644 index 0000000000..73fc173a7d --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/customers/CustomersRow.scala @@ -0,0 +1,49 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.customers + +import com.fasterxml.jackson.annotation.JsonProperty +import dev.typr.dslsc.RowCodecs +import dev.typr.foundations.Tuple.Tuple4 +import dev.typr.foundationssc.RowCodec +import dev.typr.foundationssc.SqliteTypes +import java.time.LocalDateTime +import testdb.customtypes.Defaulted +import testdb.userdefined.Email + +/** Table: customers + * Primary key: customer_id + */ +case class CustomersRow( + @JsonProperty("customer_id") customerId: CustomersId, + name: String, + email: Option[/* user-picked */ Email], + /** Default: CURRENT_TIMESTAMP */ + @JsonProperty("created_at") createdAt: LocalDateTime +) extends Tuple4[CustomersId, String, Option[/* user-picked */ Email], LocalDateTime] { + def id: CustomersId = customerId + + def toUnsavedRow(createdAt: Defaulted[LocalDateTime] = Defaulted.Provided(this.createdAt)): CustomersRowUnsaved = { + new CustomersRowUnsaved( + customerId, + name, + email, + createdAt + ) + } + + override def `_1`: CustomersId = customerId + + override def `_2`: String = name + + override def `_3`: Option[/* user-picked */ Email] = email + + override def `_4`: LocalDateTime = createdAt +} + +object CustomersRow { + val rowCodec: RowCodec[CustomersRow] = RowCodecs.of(CustomersId.sqliteType, SqliteTypes.text, Email.sqliteType.opt, SqliteTypes.timestamp)(CustomersRow.apply)(row => Array[Any](row.customerId, row.name, row.email, row.createdAt)) +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/customers/CustomersRowUnsaved.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/customers/CustomersRowUnsaved.scala new file mode 100644 index 0000000000..352347ce96 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/customers/CustomersRowUnsaved.scala @@ -0,0 +1,30 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.customers + +import com.fasterxml.jackson.annotation.JsonProperty +import java.time.LocalDateTime +import testdb.customtypes.Defaulted +import testdb.customtypes.Defaulted.UseDefault +import testdb.userdefined.Email + +/** This class corresponds to a row in table `customers` which has not been persisted yet */ +case class CustomersRowUnsaved( + @JsonProperty("customer_id") customerId: CustomersId, + name: String, + email: Option[/* user-picked */ Email] = None, + /** Default: CURRENT_TIMESTAMP */ + @JsonProperty("created_at") createdAt: Defaulted[LocalDateTime] = new UseDefault() +) { + def toRow(createdAtDefault: => LocalDateTime): CustomersRow = { + new CustomersRow( + customerId = customerId, + name = name, + email = email, + createdAt = createdAt.getOrElse(createdAtDefault) + ) + } +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/customtypes/Defaulted.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/customtypes/Defaulted.scala new file mode 100644 index 0000000000..9bacd71f1f --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/customtypes/Defaulted.scala @@ -0,0 +1,58 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.customtypes + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize +import com.fasterxml.jackson.databind.annotation.JsonSerialize +import testdb.DefaultedDeserializer +import testdb.DefaultedSerializer + +@JsonSerialize(`using` = classOf[DefaultedSerializer]) +@JsonDeserialize(`using` = classOf[DefaultedDeserializer]) +/** This signals a value where if you don't provide it, postgres will generate it for you */ +sealed trait Defaulted[T] { + def fold[U]( + onDefault: => U, + onProvided: T => U + ): U + + def getOrElse(onDefault: => T): T + + def visit( + onDefault: => Unit, + onProvided: T => Unit + ): Unit +} + +object Defaulted { + case class Provided[T](value: T) extends Defaulted[T] { + override def fold[U]( + onDefault: => U, + onProvided: T => U + ): U = onProvided(value) + + override def getOrElse(onDefault: => T): T = value + + override def visit( + onDefault: => Unit, + onProvided: T => Unit + ): Unit = onProvided(value) + } + + case class UseDefault[T]() extends Defaulted[T] { + override def fold[U]( + onDefault: => U, + onProvided: T => U + ): U = onDefault + + override def getOrElse(onDefault: => T): T = onDefault + + override def visit( + onDefault: => Unit, + onProvided: T => Unit + ): Unit = onDefault + } +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/delete_old_orders/DeleteOldOrdersSqlRepo.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/delete_old_orders/DeleteOldOrdersSqlRepo.scala new file mode 100644 index 0000000000..6f3cf281b2 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/delete_old_orders/DeleteOldOrdersSqlRepo.scala @@ -0,0 +1,13 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.delete_old_orders + +import dev.typr.foundationssc.Connection +import java.time.LocalDate + +trait DeleteOldOrdersSqlRepo { + def apply(cutoffDate: LocalDate)(using c: Connection): Int +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/delete_old_orders/DeleteOldOrdersSqlRepoImpl.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/delete_old_orders/DeleteOldOrdersSqlRepoImpl.scala new file mode 100644 index 0000000000..e6495c920c --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/delete_old_orders/DeleteOldOrdersSqlRepoImpl.scala @@ -0,0 +1,27 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.delete_old_orders + +import dev.typr.foundationssc.Connection +import dev.typr.foundationssc.Fragment +import dev.typr.foundationssc.SqliteTypes +import java.time.LocalDate +import dev.typr.foundationssc.Fragment.sql + +class DeleteOldOrdersSqlRepoImpl extends DeleteOldOrdersSqlRepo { + override def apply(cutoffDate: LocalDate)(using c: Connection): Int = { + sql"""-- Delete completed orders older than a cutoff date. + -- Tests: DELETE statement with required date param, no result columns. + -- + -- SQLite stores DATE as ISO-8601 TEXT, so sqlglot can't infer that + -- order_date < :cutoff_date wants a LocalDate. We pin the type + -- explicitly with the `:name:Type!` annotation — same opt-in pattern + -- as the other dialects use for parameters not otherwise resolvable + -- from schema lineage. + DELETE FROM orders + WHERE status = 'completed' AND order_date < ${Fragment.encode(SqliteTypes.date, cutoffDate)}""".update().run(using c) + } +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/departments/DepartmentsFields.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/departments/DepartmentsFields.scala new file mode 100644 index 0000000000..e2574eeea7 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/departments/DepartmentsFields.scala @@ -0,0 +1,91 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.departments + +import dev.typr.dsl.FieldsBase +import dev.typr.dsl.Path +import dev.typr.dsl.SqlExpr.FieldLike +import dev.typr.dslsc.RelationStructure +import dev.typr.dslsc.SqlExpr +import dev.typr.dslsc.SqlExpr.Field +import dev.typr.dslsc.SqlExpr.IdField +import dev.typr.dslsc.SqlExpr.OptField +import dev.typr.dslsc.TupleExpr +import dev.typr.dslsc.TupleExpr4 +import dev.typr.foundations.RowCodec +import dev.typr.foundationssc.SqliteTypes + +class DepartmentsFields(val `_path`: java.util.List[Path]) extends TupleExpr4[String, String, String, BigDecimal] with RelationStructure[DepartmentsFields, DepartmentsRow] with FieldsBase[DepartmentsRow] { + def deptCode: IdField[String, DepartmentsRow] = { + new IdField[String, DepartmentsRow]( + _path, + "dept_code", + _.deptCode, + None, + None, + (row, value) => row.copy(deptCode = value), + SqliteTypes.varchar.underlying + ) + } + + def deptRegion: IdField[String, DepartmentsRow] = { + new IdField[String, DepartmentsRow]( + _path, + "dept_region", + _.deptRegion, + None, + None, + (row, value) => row.copy(deptRegion = value), + SqliteTypes.varchar.underlying + ) + } + + def deptName: Field[String, DepartmentsRow] = { + new Field[String, DepartmentsRow]( + _path, + "dept_name", + _.deptName, + None, + None, + (row, value) => row.copy(deptName = value), + SqliteTypes.text.underlying + ) + } + + def budget: OptField[BigDecimal, DepartmentsRow] = { + new OptField[BigDecimal, DepartmentsRow]( + _path, + "budget", + _.budget, + None, + None, + (row, value) => row.copy(budget = value), + SqliteTypes.numeric.underlying + ) + } + + def compositeIdIs(compositeId: DepartmentsId): SqlExpr[Boolean] = SqlExpr.all(deptCode.isEqual(compositeId.deptCode), deptRegion.isEqual(compositeId.deptRegion)) + + def compositeIdIn(compositeIds: List[DepartmentsId]): SqlExpr[Boolean] = TupleExpr.of(deptCode, deptRegion).among(compositeIds) + + override def columns: java.util.List[FieldLike[?, DepartmentsRow]] = java.util.List.of(this.deptCode.underlying, this.deptRegion.underlying, this.deptName.underlying, this.budget.underlying) + + override def rowCodec: RowCodec[DepartmentsRow] = DepartmentsRow.rowCodec.underlying + + override def withPaths(`_path`: java.util.List[Path]): RelationStructure[DepartmentsFields, DepartmentsRow] = new DepartmentsFields(`_path`) + + override def `_1`: SqlExpr[String] = deptCode + + override def `_2`: SqlExpr[String] = deptRegion + + override def `_3`: SqlExpr[String] = deptName + + override def `_4`: SqlExpr[BigDecimal] = budget +} + +object DepartmentsFields { + val structure: DepartmentsFields = new DepartmentsFields(java.util.Collections.emptyList()) +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/departments/DepartmentsId.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/departments/DepartmentsId.scala new file mode 100644 index 0000000000..21eae13dd4 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/departments/DepartmentsId.scala @@ -0,0 +1,26 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.departments + +import com.fasterxml.jackson.annotation.JsonProperty +import dev.typr.dslsc.RowCodecs +import dev.typr.foundations.Tuple.Tuple2 +import dev.typr.foundationssc.RowCodec +import dev.typr.foundationssc.SqliteTypes + +/** Type for the composite primary key of table `departments` */ +case class DepartmentsId( + @JsonProperty("dept_code") deptCode: String, + @JsonProperty("dept_region") deptRegion: String +) extends Tuple2[String, String] { + override def `_1`: String = deptCode + + override def `_2`: String = deptRegion +} + +object DepartmentsId { + val rowCodec: RowCodec[DepartmentsId] = RowCodecs.of(SqliteTypes.varchar, SqliteTypes.varchar)(DepartmentsId.apply)(row => Array[Any](row.deptCode, row.deptRegion)) +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/departments/DepartmentsRepo.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/departments/DepartmentsRepo.scala new file mode 100644 index 0000000000..4c0183942e --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/departments/DepartmentsRepo.scala @@ -0,0 +1,40 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.departments + +import dev.typr.dslsc.DeleteBuilder +import dev.typr.dslsc.SelectBuilder +import dev.typr.dslsc.UpdateBuilder +import dev.typr.foundationssc.Connection +import dev.typr.foundationssc.ConnectionRead + +trait DepartmentsRepo { + def delete: DeleteBuilder[DepartmentsFields, DepartmentsRow] + + def deleteById(compositeId: DepartmentsId)(using c: Connection): Boolean + + def deleteByIds(compositeIds: List[DepartmentsId])(using c: Connection): Int + + def insert(unsaved: DepartmentsRow)(using c: Connection): DepartmentsRow + + def select: SelectBuilder[DepartmentsFields, DepartmentsRow] + + def selectAll(using c: ConnectionRead): List[DepartmentsRow] + + def selectById(compositeId: DepartmentsId)(using c: ConnectionRead): Option[DepartmentsRow] + + def selectByIds(compositeIds: List[DepartmentsId])(using c: ConnectionRead): List[DepartmentsRow] + + def selectByIdsTracked(compositeIds: List[DepartmentsId])(using c: ConnectionRead): Map[DepartmentsId, DepartmentsRow] + + def update: UpdateBuilder[DepartmentsFields, DepartmentsRow] + + def update(row: DepartmentsRow)(using c: Connection): Boolean + + def upsert(unsaved: DepartmentsRow)(using c: Connection): DepartmentsRow + + def upsertBatch(unsaved: Iterator[DepartmentsRow])(using c: Connection): List[DepartmentsRow] +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/departments/DepartmentsRepoImpl.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/departments/DepartmentsRepoImpl.scala new file mode 100644 index 0000000000..4c8669c643 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/departments/DepartmentsRepoImpl.scala @@ -0,0 +1,97 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.departments + +import dev.typr.dslsc.DeleteBuilder +import dev.typr.dslsc.Dialect +import dev.typr.dslsc.SelectBuilder +import dev.typr.dslsc.UpdateBuilder +import dev.typr.foundationssc.Connection +import dev.typr.foundationssc.ConnectionRead +import dev.typr.foundationssc.Fragment +import dev.typr.foundationssc.SqliteTypes +import scala.collection.mutable.ListBuffer +import dev.typr.foundationssc.Fragment.sql + +class DepartmentsRepoImpl extends DepartmentsRepo { + override def delete: DeleteBuilder[DepartmentsFields, DepartmentsRow] = DeleteBuilder.of(""""departments"""", DepartmentsFields.structure, Dialect.SQLITE) + + override def deleteById(compositeId: DepartmentsId)(using c: Connection): Boolean = sql"""delete from "departments" where "dept_code" = ${Fragment.encode(SqliteTypes.varchar, compositeId.deptCode)} AND "dept_region" = ${Fragment.encode(SqliteTypes.varchar, compositeId.deptRegion)}""".update().run(using c) > 0 + + override def deleteByIds(compositeIds: List[DepartmentsId])(using c: Connection): Int = { + val fragments: ListBuffer[Fragment] = ListBuffer() + compositeIds.foreach { id => fragments.addOne(Fragment.concat(Fragment.of("("), Fragment.encode(SqliteTypes.varchar, id.deptCode), Fragment.of(", "), Fragment.encode(SqliteTypes.varchar, id.deptRegion), Fragment.of(")"))): @scala.annotation.nowarn } + return Fragment.concat(Fragment.of("""delete from "departments" where ("dept_code", "dept_region") in ("""), Fragment.comma(fragments), Fragment.of(")")).update().run(using c) + } + + override def insert(unsaved: DepartmentsRow)(using c: Connection): DepartmentsRow = { + sql"""insert into "departments"("dept_code", "dept_region", "dept_name", "budget") + values (${Fragment.encode(SqliteTypes.varchar, unsaved.deptCode)}, ${Fragment.encode(SqliteTypes.varchar, unsaved.deptRegion)}, ${Fragment.encode(SqliteTypes.text, unsaved.deptName)}, ${Fragment.encode(SqliteTypes.numeric.opt, unsaved.budget)}) + RETURNING "dept_code", "dept_region", "dept_name", "budget" + """ + .updateReturning(DepartmentsRow.rowCodec.exactlyOne()).run(using c) + } + + override def select: SelectBuilder[DepartmentsFields, DepartmentsRow] = SelectBuilder.of(""""departments"""", DepartmentsFields.structure, DepartmentsRow.rowCodec, Dialect.SQLITE) + + override def selectAll(using c: ConnectionRead): List[DepartmentsRow] = { + sql"""select "dept_code", "dept_region", "dept_name", "budget" + from "departments" + """.query(DepartmentsRow.rowCodec.all()).run(using c) + } + + override def selectById(compositeId: DepartmentsId)(using c: ConnectionRead): Option[DepartmentsRow] = { + sql"""select "dept_code", "dept_region", "dept_name", "budget" + from "departments" + where "dept_code" = ${Fragment.encode(SqliteTypes.varchar, compositeId.deptCode)} AND "dept_region" = ${Fragment.encode(SqliteTypes.varchar, compositeId.deptRegion)}""".query(DepartmentsRow.rowCodec.first()).run(using c) + } + + override def selectByIds(compositeIds: List[DepartmentsId])(using c: ConnectionRead): List[DepartmentsRow] = { + val fragments: ListBuffer[Fragment] = ListBuffer() + compositeIds.foreach { id => fragments.addOne(Fragment.concat(Fragment.of("("), Fragment.encode(SqliteTypes.varchar, id.deptCode), Fragment.of(", "), Fragment.encode(SqliteTypes.varchar, id.deptRegion), Fragment.of(")"))): @scala.annotation.nowarn } + return Fragment.concat(Fragment.of("""select "dept_code", "dept_region", "dept_name", "budget" from "departments" where ("dept_code", "dept_region") in ("""), Fragment.comma(fragments), Fragment.of(")")).query(DepartmentsRow.rowCodec.all()).run(using c) + } + + override def selectByIdsTracked(compositeIds: List[DepartmentsId])(using c: ConnectionRead): Map[DepartmentsId, DepartmentsRow] = { + val ret: scala.collection.mutable.Map[DepartmentsId, DepartmentsRow] = scala.collection.mutable.Map.empty[DepartmentsId, DepartmentsRow] + selectByIds(compositeIds)(using c).foreach(row => ret.put(row.compositeId, row): @scala.annotation.nowarn) + return ret.toMap + } + + override def update: UpdateBuilder[DepartmentsFields, DepartmentsRow] = UpdateBuilder.of(""""departments"""", DepartmentsFields.structure, DepartmentsRow.rowCodec, Dialect.SQLITE) + + override def update(row: DepartmentsRow)(using c: Connection): Boolean = { + val compositeId: DepartmentsId = row.compositeId + return sql"""update "departments" + set "dept_name" = ${Fragment.encode(SqliteTypes.text, row.deptName)}, + "budget" = ${Fragment.encode(SqliteTypes.numeric.opt, row.budget)} + where "dept_code" = ${Fragment.encode(SqliteTypes.varchar, compositeId.deptCode)} AND "dept_region" = ${Fragment.encode(SqliteTypes.varchar, compositeId.deptRegion)}""".update().run(using c) > 0 + } + + override def upsert(unsaved: DepartmentsRow)(using c: Connection): DepartmentsRow = { + sql"""INSERT INTO "departments"("dept_code", "dept_region", "dept_name", "budget") + VALUES (${Fragment.encode(SqliteTypes.varchar, unsaved.deptCode)}, ${Fragment.encode(SqliteTypes.varchar, unsaved.deptRegion)}, ${Fragment.encode(SqliteTypes.text, unsaved.deptName)}, ${Fragment.encode(SqliteTypes.numeric.opt, unsaved.budget)}) + ON CONFLICT ("dept_code", "dept_region") + DO UPDATE SET + "dept_name" = EXCLUDED."dept_name", + "budget" = EXCLUDED."budget" + RETURNING "dept_code", "dept_region", "dept_name", "budget"""" + .updateReturning(DepartmentsRow.rowCodec.exactlyOne()) + .run(using c) + } + + override def upsertBatch(unsaved: Iterator[DepartmentsRow])(using c: Connection): List[DepartmentsRow] = { + sql"""INSERT INTO "departments"("dept_code", "dept_region", "dept_name", "budget") + VALUES (?, ?, ?, ?) + ON CONFLICT ("dept_code", "dept_region") + DO UPDATE SET + "dept_name" = EXCLUDED."dept_name", + "budget" = EXCLUDED."budget" + RETURNING "dept_code", "dept_region", "dept_name", "budget"""" + .updateReturningEach(DepartmentsRow.rowCodec, unsaved) + .run(using c) + } +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/departments/DepartmentsRepoMock.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/departments/DepartmentsRepoMock.scala new file mode 100644 index 0000000000..b2a7e9ff14 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/departments/DepartmentsRepoMock.scala @@ -0,0 +1,73 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.departments + +import dev.typr.dslsc.DeleteBuilder +import dev.typr.dslsc.DeleteBuilderMock +import dev.typr.dslsc.DeleteParams +import dev.typr.dslsc.SelectBuilder +import dev.typr.dslsc.SelectBuilderMock +import dev.typr.dslsc.SelectParams +import dev.typr.dslsc.UpdateBuilder +import dev.typr.dslsc.UpdateBuilderMock +import dev.typr.dslsc.UpdateParams +import dev.typr.foundationssc.Connection +import dev.typr.foundationssc.ConnectionRead +import java.lang.RuntimeException + +case class DepartmentsRepoMock(map: scala.collection.mutable.Map[DepartmentsId, DepartmentsRow] = scala.collection.mutable.Map.empty[DepartmentsId, DepartmentsRow]) extends DepartmentsRepo { + override def delete: DeleteBuilder[DepartmentsFields, DepartmentsRow] = DeleteBuilderMock(DepartmentsFields.structure, () => map.values.toList, DeleteParams.empty(), row => row.compositeId, id => map.remove(id): @scala.annotation.nowarn) + + override def deleteById(compositeId: DepartmentsId)(using c: Connection): Boolean = map.remove(compositeId).isDefined + + override def deleteByIds(compositeIds: List[DepartmentsId])(using c: Connection): Int = { + var count = 0 + compositeIds.foreach { id => if (map.remove(id).isDefined) { + count = count + 1 + } } + return count + } + + override def insert(unsaved: DepartmentsRow)(using c: Connection): DepartmentsRow = { + if (map.contains(unsaved.compositeId)) { + throw new RuntimeException(s"id ${unsaved.compositeId} already exists") + } + map.put(unsaved.compositeId, unsaved): @scala.annotation.nowarn + return unsaved + } + + override def select: SelectBuilder[DepartmentsFields, DepartmentsRow] = SelectBuilderMock(DepartmentsFields.structure, () => map.values.toList, SelectParams.empty()) + + override def selectAll(using c: ConnectionRead): List[DepartmentsRow] = map.values.toList + + override def selectById(compositeId: DepartmentsId)(using c: ConnectionRead): Option[DepartmentsRow] = map.get(compositeId) + + override def selectByIds(compositeIds: List[DepartmentsId])(using c: ConnectionRead): List[DepartmentsRow] = compositeIds.flatMap(map.get(_)).toList + + override def selectByIdsTracked(compositeIds: List[DepartmentsId])(using c: ConnectionRead): Map[DepartmentsId, DepartmentsRow] = selectByIds(compositeIds)(using c).map(x => (((row: DepartmentsRow) => row.compositeId).apply(x), x)).toMap + + override def update: UpdateBuilder[DepartmentsFields, DepartmentsRow] = UpdateBuilderMock(DepartmentsFields.structure, () => map.values.toList, UpdateParams.empty(), row => row) + + override def update(row: DepartmentsRow)(using c: Connection): Boolean = { + val shouldUpdate = map.get(row.compositeId).filter(oldRow => (oldRow != row)).isDefined + if (shouldUpdate) { + map.put(row.compositeId, row): @scala.annotation.nowarn + } + return shouldUpdate + } + + override def upsert(unsaved: DepartmentsRow)(using c: Connection): DepartmentsRow = { + map.put(unsaved.compositeId, unsaved): @scala.annotation.nowarn + return unsaved + } + + override def upsertBatch(unsaved: Iterator[DepartmentsRow])(using c: Connection): List[DepartmentsRow] = { + unsaved.map { row => + map.put(row.compositeId, row): @scala.annotation.nowarn + row + }.toList + } +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/departments/DepartmentsRow.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/departments/DepartmentsRow.scala new file mode 100644 index 0000000000..4d269b144e --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/departments/DepartmentsRow.scala @@ -0,0 +1,51 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.departments + +import com.fasterxml.jackson.annotation.JsonProperty +import dev.typr.dslsc.RowCodecs +import dev.typr.foundations.Tuple.Tuple4 +import dev.typr.foundationssc.RowCodec +import dev.typr.foundationssc.SqliteTypes + +/** Table: departments + * Composite primary key: dept_code, dept_region + */ +case class DepartmentsRow( + @JsonProperty("dept_code") deptCode: String, + @JsonProperty("dept_region") deptRegion: String, + @JsonProperty("dept_name") deptName: String, + budget: Option[BigDecimal] +) extends Tuple4[String, String, String, Option[BigDecimal]] { + def compositeId: DepartmentsId = new DepartmentsId(deptCode, deptRegion) + + def id: DepartmentsId = this.compositeId + + override def `_1`: String = deptCode + + override def `_2`: String = deptRegion + + override def `_3`: String = deptName + + override def `_4`: Option[BigDecimal] = budget +} + +object DepartmentsRow { + def apply( + compositeId: DepartmentsId, + deptName: String, + budget: Option[BigDecimal] + ): DepartmentsRow = { + new DepartmentsRow( + compositeId.deptCode, + compositeId.deptRegion, + deptName, + budget + ) + } + + val rowCodec: RowCodec[DepartmentsRow] = RowCodecs.of(SqliteTypes.varchar, SqliteTypes.varchar, SqliteTypes.text, SqliteTypes.numeric.opt)(DepartmentsRow.apply)(row => Array[Any](row.deptCode, row.deptRegion, row.deptName, row.budget)) +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/employees/EmployeesFields.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/employees/EmployeesFields.scala new file mode 100644 index 0000000000..147e80c986 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/employees/EmployeesFields.scala @@ -0,0 +1,144 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.employees + +import dev.typr.dsl.FieldsBase +import dev.typr.dsl.Path +import dev.typr.dsl.SqlExpr.FieldLike +import dev.typr.dslsc.ForeignKey +import dev.typr.dslsc.RelationStructure +import dev.typr.dslsc.SqlExpr +import dev.typr.dslsc.SqlExpr.Field +import dev.typr.dslsc.SqlExpr.IdField +import dev.typr.dslsc.SqlExpr.OptField +import dev.typr.dslsc.TupleExpr +import dev.typr.dslsc.TupleExpr7 +import dev.typr.foundations.RowCodec +import dev.typr.foundationssc.SqliteTypes +import java.time.LocalDate +import testdb.departments.DepartmentsFields +import testdb.departments.DepartmentsId +import testdb.departments.DepartmentsRow + +class EmployeesFields(val `_path`: java.util.List[Path]) extends TupleExpr7[Long, String, String, String, String, BigDecimal, LocalDate] with RelationStructure[EmployeesFields, EmployeesRow] with FieldsBase[EmployeesRow] { + def empNumber: IdField[Long, EmployeesRow] = { + new IdField[Long, EmployeesRow]( + _path, + "emp_number", + _.empNumber, + None, + None, + (row, value) => row.copy(empNumber = value), + SqliteTypes.integer.underlying + ) + } + + def empSuffix: IdField[String, EmployeesRow] = { + new IdField[String, EmployeesRow]( + _path, + "emp_suffix", + _.empSuffix, + None, + None, + (row, value) => row.copy(empSuffix = value), + SqliteTypes.varchar.underlying + ) + } + + def deptCode: Field[String, EmployeesRow] = { + new Field[String, EmployeesRow]( + _path, + "dept_code", + _.deptCode, + None, + None, + (row, value) => row.copy(deptCode = value), + SqliteTypes.varchar.underlying + ) + } + + def deptRegion: Field[String, EmployeesRow] = { + new Field[String, EmployeesRow]( + _path, + "dept_region", + _.deptRegion, + None, + None, + (row, value) => row.copy(deptRegion = value), + SqliteTypes.varchar.underlying + ) + } + + def empName: Field[String, EmployeesRow] = { + new Field[String, EmployeesRow]( + _path, + "emp_name", + _.empName, + None, + None, + (row, value) => row.copy(empName = value), + SqliteTypes.text.underlying + ) + } + + def salary: OptField[BigDecimal, EmployeesRow] = { + new OptField[BigDecimal, EmployeesRow]( + _path, + "salary", + _.salary, + None, + None, + (row, value) => row.copy(salary = value), + SqliteTypes.numeric.underlying + ) + } + + def hireDate: Field[LocalDate, EmployeesRow] = { + new Field[LocalDate, EmployeesRow]( + _path, + "hire_date", + _.hireDate, + None, + None, + (row, value) => row.copy(hireDate = value), + SqliteTypes.date.underlying + ) + } + + def fkDepartments: ForeignKey[DepartmentsFields, DepartmentsRow] = ForeignKey.of[DepartmentsFields, DepartmentsRow]("employees_fk_0").withColumnPair[String](deptCode, _.deptCode).withColumnPair[String](deptRegion, _.deptRegion) + + def `extractIdent(DepartmentsId)Is`(id: DepartmentsId): SqlExpr[Boolean] = SqlExpr.all(deptCode.isEqual(id.deptCode), deptRegion.isEqual(id.deptRegion)) + + def `extractIdent(DepartmentsId)In`(ids: List[DepartmentsId]): SqlExpr[Boolean] = TupleExpr.of(deptCode, deptRegion).among(ids) + + def compositeIdIs(compositeId: EmployeesId): SqlExpr[Boolean] = SqlExpr.all(empNumber.isEqual(compositeId.empNumber), empSuffix.isEqual(compositeId.empSuffix)) + + def compositeIdIn(compositeIds: List[EmployeesId]): SqlExpr[Boolean] = TupleExpr.of(empNumber, empSuffix).among(compositeIds) + + override def columns: java.util.List[FieldLike[?, EmployeesRow]] = java.util.List.of(this.empNumber.underlying, this.empSuffix.underlying, this.deptCode.underlying, this.deptRegion.underlying, this.empName.underlying, this.salary.underlying, this.hireDate.underlying) + + override def rowCodec: RowCodec[EmployeesRow] = EmployeesRow.rowCodec.underlying + + override def withPaths(`_path`: java.util.List[Path]): RelationStructure[EmployeesFields, EmployeesRow] = new EmployeesFields(`_path`) + + override def `_1`: SqlExpr[Long] = empNumber + + override def `_2`: SqlExpr[String] = empSuffix + + override def `_3`: SqlExpr[String] = deptCode + + override def `_4`: SqlExpr[String] = deptRegion + + override def `_5`: SqlExpr[String] = empName + + override def `_6`: SqlExpr[BigDecimal] = salary + + override def `_7`: SqlExpr[LocalDate] = hireDate +} + +object EmployeesFields { + val structure: EmployeesFields = new EmployeesFields(java.util.Collections.emptyList()) +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/employees/EmployeesId.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/employees/EmployeesId.scala new file mode 100644 index 0000000000..7685199e74 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/employees/EmployeesId.scala @@ -0,0 +1,26 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.employees + +import com.fasterxml.jackson.annotation.JsonProperty +import dev.typr.dslsc.RowCodecs +import dev.typr.foundations.Tuple.Tuple2 +import dev.typr.foundationssc.RowCodec +import dev.typr.foundationssc.SqliteTypes + +/** Type for the composite primary key of table `employees` */ +case class EmployeesId( + @JsonProperty("emp_number") empNumber: Long, + @JsonProperty("emp_suffix") empSuffix: String +) extends Tuple2[Long, String] { + override def `_1`: Long = empNumber + + override def `_2`: String = empSuffix +} + +object EmployeesId { + val rowCodec: RowCodec[EmployeesId] = RowCodecs.of(SqliteTypes.integer, SqliteTypes.varchar)(EmployeesId.apply)(row => Array[Any](row.empNumber, row.empSuffix)) +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/employees/EmployeesRepo.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/employees/EmployeesRepo.scala new file mode 100644 index 0000000000..24c8b71123 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/employees/EmployeesRepo.scala @@ -0,0 +1,42 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.employees + +import dev.typr.dslsc.DeleteBuilder +import dev.typr.dslsc.SelectBuilder +import dev.typr.dslsc.UpdateBuilder +import dev.typr.foundationssc.Connection +import dev.typr.foundationssc.ConnectionRead + +trait EmployeesRepo { + def delete: DeleteBuilder[EmployeesFields, EmployeesRow] + + def deleteById(compositeId: EmployeesId)(using c: Connection): Boolean + + def deleteByIds(compositeIds: List[EmployeesId])(using c: Connection): Int + + def insert(unsaved: EmployeesRow)(using c: Connection): EmployeesRow + + def insert(unsaved: EmployeesRowUnsaved)(using c: Connection): EmployeesRow + + def select: SelectBuilder[EmployeesFields, EmployeesRow] + + def selectAll(using c: ConnectionRead): List[EmployeesRow] + + def selectById(compositeId: EmployeesId)(using c: ConnectionRead): Option[EmployeesRow] + + def selectByIds(compositeIds: List[EmployeesId])(using c: ConnectionRead): List[EmployeesRow] + + def selectByIdsTracked(compositeIds: List[EmployeesId])(using c: ConnectionRead): Map[EmployeesId, EmployeesRow] + + def update: UpdateBuilder[EmployeesFields, EmployeesRow] + + def update(row: EmployeesRow)(using c: Connection): Boolean + + def upsert(unsaved: EmployeesRow)(using c: Connection): EmployeesRow + + def upsertBatch(unsaved: Iterator[EmployeesRow])(using c: Connection): List[EmployeesRow] +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/employees/EmployeesRepoImpl.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/employees/EmployeesRepoImpl.scala new file mode 100644 index 0000000000..85493622b7 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/employees/EmployeesRepoImpl.scala @@ -0,0 +1,134 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.employees + +import dev.typr.dslsc.DeleteBuilder +import dev.typr.dslsc.Dialect +import dev.typr.dslsc.SelectBuilder +import dev.typr.dslsc.UpdateBuilder +import dev.typr.foundationssc.Connection +import dev.typr.foundationssc.ConnectionRead +import dev.typr.foundationssc.Fragment +import dev.typr.foundationssc.SqliteTypes +import scala.collection.mutable.ListBuffer +import dev.typr.foundationssc.Fragment.sql + +class EmployeesRepoImpl extends EmployeesRepo { + override def delete: DeleteBuilder[EmployeesFields, EmployeesRow] = DeleteBuilder.of(""""employees"""", EmployeesFields.structure, Dialect.SQLITE) + + override def deleteById(compositeId: EmployeesId)(using c: Connection): Boolean = sql"""delete from "employees" where "emp_number" = ${Fragment.encode(SqliteTypes.integer, compositeId.empNumber)} AND "emp_suffix" = ${Fragment.encode(SqliteTypes.varchar, compositeId.empSuffix)}""".update().run(using c) > 0 + + override def deleteByIds(compositeIds: List[EmployeesId])(using c: Connection): Int = { + val fragments: ListBuffer[Fragment] = ListBuffer() + compositeIds.foreach { id => fragments.addOne(Fragment.concat(Fragment.of("("), Fragment.encode(SqliteTypes.integer, id.empNumber), Fragment.of(", "), Fragment.encode(SqliteTypes.varchar, id.empSuffix), Fragment.of(")"))): @scala.annotation.nowarn } + return Fragment.concat(Fragment.of("""delete from "employees" where ("emp_number", "emp_suffix") in ("""), Fragment.comma(fragments), Fragment.of(")")).update().run(using c) + } + + override def insert(unsaved: EmployeesRow)(using c: Connection): EmployeesRow = { + sql"""insert into "employees"("emp_number", "emp_suffix", "dept_code", "dept_region", "emp_name", "salary", "hire_date") + values (${Fragment.encode(SqliteTypes.integer, unsaved.empNumber)}, ${Fragment.encode(SqliteTypes.varchar, unsaved.empSuffix)}, ${Fragment.encode(SqliteTypes.varchar, unsaved.deptCode)}, ${Fragment.encode(SqliteTypes.varchar, unsaved.deptRegion)}, ${Fragment.encode(SqliteTypes.text, unsaved.empName)}, ${Fragment.encode(SqliteTypes.numeric.opt, unsaved.salary)}, ${Fragment.encode(SqliteTypes.date, unsaved.hireDate)}) + RETURNING "emp_number", "emp_suffix", "dept_code", "dept_region", "emp_name", "salary", "hire_date" + """ + .updateReturning(EmployeesRow.rowCodec.exactlyOne()).run(using c) + } + + override def insert(unsaved: EmployeesRowUnsaved)(using c: Connection): EmployeesRow = { + val columns: ListBuffer[Fragment] = ListBuffer() + val values: ListBuffer[Fragment] = ListBuffer() + columns.addOne(Fragment.of(""""emp_number"""")): @scala.annotation.nowarn + values.addOne(sql"${Fragment.encode(SqliteTypes.integer, unsaved.empNumber)}"): @scala.annotation.nowarn + columns.addOne(Fragment.of(""""emp_suffix"""")): @scala.annotation.nowarn + values.addOne(sql"${Fragment.encode(SqliteTypes.varchar, unsaved.empSuffix)}"): @scala.annotation.nowarn + columns.addOne(Fragment.of(""""dept_code"""")): @scala.annotation.nowarn + values.addOne(sql"${Fragment.encode(SqliteTypes.varchar, unsaved.deptCode)}"): @scala.annotation.nowarn + columns.addOne(Fragment.of(""""dept_region"""")): @scala.annotation.nowarn + values.addOne(sql"${Fragment.encode(SqliteTypes.varchar, unsaved.deptRegion)}"): @scala.annotation.nowarn + columns.addOne(Fragment.of(""""emp_name"""")): @scala.annotation.nowarn + values.addOne(sql"${Fragment.encode(SqliteTypes.text, unsaved.empName)}"): @scala.annotation.nowarn + columns.addOne(Fragment.of(""""salary"""")): @scala.annotation.nowarn + values.addOne(sql"${Fragment.encode(SqliteTypes.numeric.opt, unsaved.salary)}"): @scala.annotation.nowarn + unsaved.hireDate.visit( + { }, + value => { columns.addOne(Fragment.of(""""hire_date"""")): @scala.annotation.nowarn; values.addOne(sql"${Fragment.encode(SqliteTypes.date, value)}"): @scala.annotation.nowarn } + ); + val q: Fragment = { + sql"""insert into "employees"(${Fragment.comma(columns)}) + values (${Fragment.comma(values)}) + RETURNING "emp_number", "emp_suffix", "dept_code", "dept_region", "emp_name", "salary", "hire_date" + """ + } + return q.updateReturning(EmployeesRow.rowCodec.exactlyOne()).run(using c) + } + + override def select: SelectBuilder[EmployeesFields, EmployeesRow] = SelectBuilder.of(""""employees"""", EmployeesFields.structure, EmployeesRow.rowCodec, Dialect.SQLITE) + + override def selectAll(using c: ConnectionRead): List[EmployeesRow] = { + sql"""select "emp_number", "emp_suffix", "dept_code", "dept_region", "emp_name", "salary", "hire_date" + from "employees" + """.query(EmployeesRow.rowCodec.all()).run(using c) + } + + override def selectById(compositeId: EmployeesId)(using c: ConnectionRead): Option[EmployeesRow] = { + sql"""select "emp_number", "emp_suffix", "dept_code", "dept_region", "emp_name", "salary", "hire_date" + from "employees" + where "emp_number" = ${Fragment.encode(SqliteTypes.integer, compositeId.empNumber)} AND "emp_suffix" = ${Fragment.encode(SqliteTypes.varchar, compositeId.empSuffix)}""".query(EmployeesRow.rowCodec.first()).run(using c) + } + + override def selectByIds(compositeIds: List[EmployeesId])(using c: ConnectionRead): List[EmployeesRow] = { + val fragments: ListBuffer[Fragment] = ListBuffer() + compositeIds.foreach { id => fragments.addOne(Fragment.concat(Fragment.of("("), Fragment.encode(SqliteTypes.integer, id.empNumber), Fragment.of(", "), Fragment.encode(SqliteTypes.varchar, id.empSuffix), Fragment.of(")"))): @scala.annotation.nowarn } + return Fragment.concat(Fragment.of("""select "emp_number", "emp_suffix", "dept_code", "dept_region", "emp_name", "salary", "hire_date" from "employees" where ("emp_number", "emp_suffix") in ("""), Fragment.comma(fragments), Fragment.of(")")).query(EmployeesRow.rowCodec.all()).run(using c) + } + + override def selectByIdsTracked(compositeIds: List[EmployeesId])(using c: ConnectionRead): Map[EmployeesId, EmployeesRow] = { + val ret: scala.collection.mutable.Map[EmployeesId, EmployeesRow] = scala.collection.mutable.Map.empty[EmployeesId, EmployeesRow] + selectByIds(compositeIds)(using c).foreach(row => ret.put(row.compositeId, row): @scala.annotation.nowarn) + return ret.toMap + } + + override def update: UpdateBuilder[EmployeesFields, EmployeesRow] = UpdateBuilder.of(""""employees"""", EmployeesFields.structure, EmployeesRow.rowCodec, Dialect.SQLITE) + + override def update(row: EmployeesRow)(using c: Connection): Boolean = { + val compositeId: EmployeesId = row.compositeId + return sql"""update "employees" + set "dept_code" = ${Fragment.encode(SqliteTypes.varchar, row.deptCode)}, + "dept_region" = ${Fragment.encode(SqliteTypes.varchar, row.deptRegion)}, + "emp_name" = ${Fragment.encode(SqliteTypes.text, row.empName)}, + "salary" = ${Fragment.encode(SqliteTypes.numeric.opt, row.salary)}, + "hire_date" = ${Fragment.encode(SqliteTypes.date, row.hireDate)} + where "emp_number" = ${Fragment.encode(SqliteTypes.integer, compositeId.empNumber)} AND "emp_suffix" = ${Fragment.encode(SqliteTypes.varchar, compositeId.empSuffix)}""".update().run(using c) > 0 + } + + override def upsert(unsaved: EmployeesRow)(using c: Connection): EmployeesRow = { + sql"""INSERT INTO "employees"("emp_number", "emp_suffix", "dept_code", "dept_region", "emp_name", "salary", "hire_date") + VALUES (${Fragment.encode(SqliteTypes.integer, unsaved.empNumber)}, ${Fragment.encode(SqliteTypes.varchar, unsaved.empSuffix)}, ${Fragment.encode(SqliteTypes.varchar, unsaved.deptCode)}, ${Fragment.encode(SqliteTypes.varchar, unsaved.deptRegion)}, ${Fragment.encode(SqliteTypes.text, unsaved.empName)}, ${Fragment.encode(SqliteTypes.numeric.opt, unsaved.salary)}, ${Fragment.encode(SqliteTypes.date, unsaved.hireDate)}) + ON CONFLICT ("emp_number", "emp_suffix") + DO UPDATE SET + "dept_code" = EXCLUDED."dept_code", + "dept_region" = EXCLUDED."dept_region", + "emp_name" = EXCLUDED."emp_name", + "salary" = EXCLUDED."salary", + "hire_date" = EXCLUDED."hire_date" + RETURNING "emp_number", "emp_suffix", "dept_code", "dept_region", "emp_name", "salary", "hire_date"""" + .updateReturning(EmployeesRow.rowCodec.exactlyOne()) + .run(using c) + } + + override def upsertBatch(unsaved: Iterator[EmployeesRow])(using c: Connection): List[EmployeesRow] = { + sql"""INSERT INTO "employees"("emp_number", "emp_suffix", "dept_code", "dept_region", "emp_name", "salary", "hire_date") + VALUES (?, ?, ?, ?, ?, ?, ?) + ON CONFLICT ("emp_number", "emp_suffix") + DO UPDATE SET + "dept_code" = EXCLUDED."dept_code", + "dept_region" = EXCLUDED."dept_region", + "emp_name" = EXCLUDED."emp_name", + "salary" = EXCLUDED."salary", + "hire_date" = EXCLUDED."hire_date" + RETURNING "emp_number", "emp_suffix", "dept_code", "dept_region", "emp_name", "salary", "hire_date"""" + .updateReturningEach(EmployeesRow.rowCodec, unsaved) + .run(using c) + } +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/employees/EmployeesRepoMock.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/employees/EmployeesRepoMock.scala new file mode 100644 index 0000000000..b234582315 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/employees/EmployeesRepoMock.scala @@ -0,0 +1,78 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.employees + +import dev.typr.dslsc.DeleteBuilder +import dev.typr.dslsc.DeleteBuilderMock +import dev.typr.dslsc.DeleteParams +import dev.typr.dslsc.SelectBuilder +import dev.typr.dslsc.SelectBuilderMock +import dev.typr.dslsc.SelectParams +import dev.typr.dslsc.UpdateBuilder +import dev.typr.dslsc.UpdateBuilderMock +import dev.typr.dslsc.UpdateParams +import dev.typr.foundationssc.Connection +import dev.typr.foundationssc.ConnectionRead +import java.lang.RuntimeException + +case class EmployeesRepoMock( + toRow: EmployeesRowUnsaved => EmployeesRow, + map: scala.collection.mutable.Map[EmployeesId, EmployeesRow] = scala.collection.mutable.Map.empty[EmployeesId, EmployeesRow] +) extends EmployeesRepo { + override def delete: DeleteBuilder[EmployeesFields, EmployeesRow] = DeleteBuilderMock(EmployeesFields.structure, () => map.values.toList, DeleteParams.empty(), row => row.compositeId, id => map.remove(id): @scala.annotation.nowarn) + + override def deleteById(compositeId: EmployeesId)(using c: Connection): Boolean = map.remove(compositeId).isDefined + + override def deleteByIds(compositeIds: List[EmployeesId])(using c: Connection): Int = { + var count = 0 + compositeIds.foreach { id => if (map.remove(id).isDefined) { + count = count + 1 + } } + return count + } + + override def insert(unsaved: EmployeesRow)(using c: Connection): EmployeesRow = { + if (map.contains(unsaved.compositeId)) { + throw new RuntimeException(s"id ${unsaved.compositeId} already exists") + } + map.put(unsaved.compositeId, unsaved): @scala.annotation.nowarn + return unsaved + } + + override def insert(unsaved: EmployeesRowUnsaved)(using c: Connection): EmployeesRow = insert(toRow(unsaved))(using c) + + override def select: SelectBuilder[EmployeesFields, EmployeesRow] = SelectBuilderMock(EmployeesFields.structure, () => map.values.toList, SelectParams.empty()) + + override def selectAll(using c: ConnectionRead): List[EmployeesRow] = map.values.toList + + override def selectById(compositeId: EmployeesId)(using c: ConnectionRead): Option[EmployeesRow] = map.get(compositeId) + + override def selectByIds(compositeIds: List[EmployeesId])(using c: ConnectionRead): List[EmployeesRow] = compositeIds.flatMap(map.get(_)).toList + + override def selectByIdsTracked(compositeIds: List[EmployeesId])(using c: ConnectionRead): Map[EmployeesId, EmployeesRow] = selectByIds(compositeIds)(using c).map(x => (((row: EmployeesRow) => row.compositeId).apply(x), x)).toMap + + override def update: UpdateBuilder[EmployeesFields, EmployeesRow] = UpdateBuilderMock(EmployeesFields.structure, () => map.values.toList, UpdateParams.empty(), row => row) + + override def update(row: EmployeesRow)(using c: Connection): Boolean = { + val shouldUpdate = map.get(row.compositeId).filter(oldRow => (oldRow != row)).isDefined + if (shouldUpdate) { + map.put(row.compositeId, row): @scala.annotation.nowarn + } + return shouldUpdate + } + + override def upsert(unsaved: EmployeesRow)(using c: Connection): EmployeesRow = { + map.put(unsaved.compositeId, unsaved): @scala.annotation.nowarn + return unsaved + } + + override def upsertBatch(unsaved: Iterator[EmployeesRow])(using c: Connection): List[EmployeesRow] = { + unsaved.map { row => + map.put(row.compositeId, row): @scala.annotation.nowarn + row + }.toList + } +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/employees/EmployeesRow.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/employees/EmployeesRow.scala new file mode 100644 index 0000000000..ae14f77aed --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/employees/EmployeesRow.scala @@ -0,0 +1,86 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.employees + +import com.fasterxml.jackson.annotation.JsonProperty +import dev.typr.dslsc.RowCodecs +import dev.typr.foundations.Tuple.Tuple7 +import dev.typr.foundationssc.RowCodec +import dev.typr.foundationssc.SqliteTypes +import java.time.LocalDate +import testdb.customtypes.Defaulted +import testdb.departments.DepartmentsId + +/** Table: employees + * Composite primary key: emp_number, emp_suffix + */ +case class EmployeesRow( + @JsonProperty("emp_number") empNumber: Long, + @JsonProperty("emp_suffix") empSuffix: String, + /** Points to [[testdb.departments.DepartmentsRow.deptCode]] */ + @JsonProperty("dept_code") deptCode: String, + /** Points to [[testdb.departments.DepartmentsRow.deptRegion]] */ + @JsonProperty("dept_region") deptRegion: String, + @JsonProperty("emp_name") empName: String, + salary: Option[BigDecimal], + /** Default: CURRENT_DATE */ + @JsonProperty("hire_date") hireDate: LocalDate +) extends Tuple7[Long, String, String, String, String, Option[BigDecimal], LocalDate] { + def compositeId: EmployeesId = new EmployeesId(empNumber, empSuffix) + + def id: EmployeesId = this.compositeId + + def extractDepartmentsId: DepartmentsId = new DepartmentsId(deptCode = deptCode, deptRegion = deptRegion) + + def toUnsavedRow(hireDate: Defaulted[LocalDate] = Defaulted.Provided(this.hireDate)): EmployeesRowUnsaved = { + new EmployeesRowUnsaved( + empNumber, + empSuffix, + deptCode, + deptRegion, + empName, + salary, + hireDate + ) + } + + override def `_1`: Long = empNumber + + override def `_2`: String = empSuffix + + override def `_3`: String = deptCode + + override def `_4`: String = deptRegion + + override def `_5`: String = empName + + override def `_6`: Option[BigDecimal] = salary + + override def `_7`: LocalDate = hireDate +} + +object EmployeesRow { + def apply( + compositeId: EmployeesId, + deptCode: String, + deptRegion: String, + empName: String, + salary: Option[BigDecimal], + hireDate: LocalDate + ): EmployeesRow = { + new EmployeesRow( + compositeId.empNumber, + compositeId.empSuffix, + deptCode, + deptRegion, + empName, + salary, + hireDate + ) + } + + val rowCodec: RowCodec[EmployeesRow] = RowCodecs.of(SqliteTypes.integer, SqliteTypes.varchar, SqliteTypes.varchar, SqliteTypes.varchar, SqliteTypes.text, SqliteTypes.numeric.opt, SqliteTypes.date)(EmployeesRow.apply)(row => Array[Any](row.empNumber, row.empSuffix, row.deptCode, row.deptRegion, row.empName, row.salary, row.hireDate)) +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/employees/EmployeesRowUnsaved.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/employees/EmployeesRowUnsaved.scala new file mode 100644 index 0000000000..1d39815769 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/employees/EmployeesRowUnsaved.scala @@ -0,0 +1,37 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.employees + +import com.fasterxml.jackson.annotation.JsonProperty +import java.time.LocalDate +import testdb.customtypes.Defaulted +import testdb.customtypes.Defaulted.UseDefault + +/** This class corresponds to a row in table `employees` which has not been persisted yet */ +case class EmployeesRowUnsaved( + @JsonProperty("emp_number") empNumber: Long, + @JsonProperty("emp_suffix") empSuffix: String, + /** Points to [[testdb.departments.DepartmentsRow.deptCode]] */ + @JsonProperty("dept_code") deptCode: String, + /** Points to [[testdb.departments.DepartmentsRow.deptRegion]] */ + @JsonProperty("dept_region") deptRegion: String, + @JsonProperty("emp_name") empName: String, + salary: Option[BigDecimal] = None, + /** Default: CURRENT_DATE */ + @JsonProperty("hire_date") hireDate: Defaulted[LocalDate] = new UseDefault() +) { + def toRow(hireDateDefault: => LocalDate): EmployeesRow = { + new EmployeesRow( + empNumber = empNumber, + empSuffix = empSuffix, + deptCode = deptCode, + deptRegion = deptRegion, + empName = empName, + salary = salary, + hireDate = hireDate.getOrElse(hireDateDefault) + ) + } +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/order_details/OrderDetailsViewFields.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/order_details/OrderDetailsViewFields.scala new file mode 100644 index 0000000000..447bfbf218 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/order_details/OrderDetailsViewFields.scala @@ -0,0 +1,128 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.order_details + +import dev.typr.dsl.FieldsBase +import dev.typr.dsl.Path +import dev.typr.dsl.SqlExpr.FieldLike +import dev.typr.dslsc.RelationStructure +import dev.typr.dslsc.SqlExpr +import dev.typr.dslsc.SqlExpr.OptField +import dev.typr.dslsc.TupleExpr7 +import dev.typr.foundations.RowCodec +import dev.typr.foundationssc.SqliteTypes +import java.time.LocalDate +import testdb.orders.OrdersId + +class OrderDetailsViewFields(val `_path`: java.util.List[Path]) extends TupleExpr7[OrdersId, LocalDate, String, String, Long, BigDecimal, String] with RelationStructure[OrderDetailsViewFields, OrderDetailsViewRow] with FieldsBase[OrderDetailsViewRow] { + def orderId: OptField[OrdersId, OrderDetailsViewRow] = { + new OptField[OrdersId, OrderDetailsViewRow]( + _path, + "order_id", + _.orderId, + None, + None, + (row, value) => row.copy(orderId = value), + OrdersId.sqliteType.underlying + ) + } + + def orderDate: OptField[LocalDate, OrderDetailsViewRow] = { + new OptField[LocalDate, OrderDetailsViewRow]( + _path, + "order_date", + _.orderDate, + None, + None, + (row, value) => row.copy(orderDate = value), + SqliteTypes.date.underlying + ) + } + + def customerName: OptField[String, OrderDetailsViewRow] = { + new OptField[String, OrderDetailsViewRow]( + _path, + "customer_name", + _.customerName, + None, + None, + (row, value) => row.copy(customerName = value), + SqliteTypes.text.underlying + ) + } + + def productName: OptField[String, OrderDetailsViewRow] = { + new OptField[String, OrderDetailsViewRow]( + _path, + "product_name", + _.productName, + None, + None, + (row, value) => row.copy(productName = value), + SqliteTypes.text.underlying + ) + } + + def quantity: OptField[Long, OrderDetailsViewRow] = { + new OptField[Long, OrderDetailsViewRow]( + _path, + "quantity", + _.quantity, + None, + None, + (row, value) => row.copy(quantity = value), + SqliteTypes.integer.underlying + ) + } + + def unitPrice: OptField[BigDecimal, OrderDetailsViewRow] = { + new OptField[BigDecimal, OrderDetailsViewRow]( + _path, + "unit_price", + _.unitPrice, + None, + None, + (row, value) => row.copy(unitPrice = value), + SqliteTypes.numeric.underlying + ) + } + + def lineTotal: OptField[String, OrderDetailsViewRow] = { + new OptField[String, OrderDetailsViewRow]( + _path, + "line_total", + _.lineTotal, + None, + None, + (row, value) => row.copy(lineTotal = value), + SqliteTypes.text.underlying + ) + } + + override def columns: java.util.List[FieldLike[?, OrderDetailsViewRow]] = java.util.List.of(this.orderId.underlying, this.orderDate.underlying, this.customerName.underlying, this.productName.underlying, this.quantity.underlying, this.unitPrice.underlying, this.lineTotal.underlying) + + override def rowCodec: RowCodec[OrderDetailsViewRow] = OrderDetailsViewRow.rowCodec.underlying + + override def withPaths(`_path`: java.util.List[Path]): RelationStructure[OrderDetailsViewFields, OrderDetailsViewRow] = new OrderDetailsViewFields(`_path`) + + override def `_1`: SqlExpr[OrdersId] = orderId + + override def `_2`: SqlExpr[LocalDate] = orderDate + + override def `_3`: SqlExpr[String] = customerName + + override def `_4`: SqlExpr[String] = productName + + override def `_5`: SqlExpr[Long] = quantity + + override def `_6`: SqlExpr[BigDecimal] = unitPrice + + override def `_7`: SqlExpr[String] = lineTotal +} + +object OrderDetailsViewFields { + val structure: OrderDetailsViewFields = new OrderDetailsViewFields(java.util.Collections.emptyList()) +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/order_details/OrderDetailsViewRepo.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/order_details/OrderDetailsViewRepo.scala new file mode 100644 index 0000000000..d6f069e63b --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/order_details/OrderDetailsViewRepo.scala @@ -0,0 +1,15 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.order_details + +import dev.typr.dslsc.SelectBuilder +import dev.typr.foundationssc.ConnectionRead + +trait OrderDetailsViewRepo { + def select: SelectBuilder[OrderDetailsViewFields, OrderDetailsViewRow] + + def selectAll(using c: ConnectionRead): List[OrderDetailsViewRow] +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/order_details/OrderDetailsViewRepoImpl.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/order_details/OrderDetailsViewRepoImpl.scala new file mode 100644 index 0000000000..7f9899b2db --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/order_details/OrderDetailsViewRepoImpl.scala @@ -0,0 +1,21 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.order_details + +import dev.typr.dslsc.Dialect +import dev.typr.dslsc.SelectBuilder +import dev.typr.foundationssc.ConnectionRead +import dev.typr.foundationssc.Fragment.sql + +class OrderDetailsViewRepoImpl extends OrderDetailsViewRepo { + override def select: SelectBuilder[OrderDetailsViewFields, OrderDetailsViewRow] = SelectBuilder.of(""""order_details"""", OrderDetailsViewFields.structure, OrderDetailsViewRow.rowCodec, Dialect.SQLITE) + + override def selectAll(using c: ConnectionRead): List[OrderDetailsViewRow] = { + sql"""select "order_id", "order_date", "customer_name", "product_name", "quantity", "unit_price", "line_total" + from "order_details" + """.query(OrderDetailsViewRow.rowCodec.all()).run(using c) + } +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/order_details/OrderDetailsViewRow.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/order_details/OrderDetailsViewRow.scala new file mode 100644 index 0000000000..3140a2f5fa --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/order_details/OrderDetailsViewRow.scala @@ -0,0 +1,49 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.order_details + +import com.fasterxml.jackson.annotation.JsonProperty +import dev.typr.dslsc.RowCodecs +import dev.typr.foundations.Tuple.Tuple7 +import dev.typr.foundationssc.RowCodec +import dev.typr.foundationssc.SqliteTypes +import java.time.LocalDate +import testdb.orders.OrdersId + +/** View: order_details */ +case class OrderDetailsViewRow( + /** Points to [[testdb.orders.OrdersRow.orderId]] */ + @JsonProperty("order_id") orderId: Option[OrdersId], + /** Points to [[testdb.orders.OrdersRow.orderDate]] */ + @JsonProperty("order_date") orderDate: Option[LocalDate], + /** Points to [[testdb.customers.CustomersRow.customerName]] */ + @JsonProperty("customer_name") customerName: Option[String], + /** Points to [[testdb.products.ProductsRow.productName]] */ + @JsonProperty("product_name") productName: Option[String], + /** Points to [[testdb.order_items.OrderItemsRow.quantity]] */ + quantity: Option[Long], + /** Points to [[testdb.order_items.OrderItemsRow.unitPrice]] */ + @JsonProperty("unit_price") unitPrice: Option[BigDecimal], + @JsonProperty("line_total") lineTotal: Option[String] +) extends Tuple7[Option[OrdersId], Option[LocalDate], Option[String], Option[String], Option[Long], Option[BigDecimal], Option[String]] { + override def `_1`: Option[OrdersId] = orderId + + override def `_2`: Option[LocalDate] = orderDate + + override def `_3`: Option[String] = customerName + + override def `_4`: Option[String] = productName + + override def `_5`: Option[Long] = quantity + + override def `_6`: Option[BigDecimal] = unitPrice + + override def `_7`: Option[String] = lineTotal +} + +object OrderDetailsViewRow { + val rowCodec: RowCodec[OrderDetailsViewRow] = RowCodecs.of(OrdersId.sqliteType.opt, SqliteTypes.date.opt, SqliteTypes.text.opt, SqliteTypes.text.opt, SqliteTypes.integer.opt, SqliteTypes.numeric.opt, SqliteTypes.text.opt)(OrderDetailsViewRow.apply)(row => Array[Any](row.orderId, row.orderDate, row.customerName, row.productName, row.quantity, row.unitPrice, row.lineTotal)) +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/order_items/OrderItemsFields.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/order_items/OrderItemsFields.scala new file mode 100644 index 0000000000..a5d4ea9dab --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/order_items/OrderItemsFields.scala @@ -0,0 +1,101 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.order_items + +import dev.typr.dsl.FieldsBase +import dev.typr.dsl.Path +import dev.typr.dsl.SqlExpr.FieldLike +import dev.typr.dslsc.ForeignKey +import dev.typr.dslsc.RelationStructure +import dev.typr.dslsc.SqlExpr +import dev.typr.dslsc.SqlExpr.Field +import dev.typr.dslsc.SqlExpr.IdField +import dev.typr.dslsc.TupleExpr +import dev.typr.dslsc.TupleExpr4 +import dev.typr.foundations.RowCodec +import dev.typr.foundationssc.SqliteTypes +import testdb.orders.OrdersFields +import testdb.orders.OrdersId +import testdb.orders.OrdersRow +import testdb.products.ProductsFields +import testdb.products.ProductsId +import testdb.products.ProductsRow + +class OrderItemsFields(val `_path`: java.util.List[Path]) extends TupleExpr4[OrdersId, ProductsId, Long, BigDecimal] with RelationStructure[OrderItemsFields, OrderItemsRow] with FieldsBase[OrderItemsRow] { + def orderId: IdField[OrdersId, OrderItemsRow] = { + new IdField[OrdersId, OrderItemsRow]( + _path, + "order_id", + _.orderId, + None, + None, + (row, value) => row.copy(orderId = value), + OrdersId.sqliteType.underlying + ) + } + + def productId: IdField[ProductsId, OrderItemsRow] = { + new IdField[ProductsId, OrderItemsRow]( + _path, + "product_id", + _.productId, + None, + None, + (row, value) => row.copy(productId = value), + ProductsId.sqliteType.underlying + ) + } + + def quantity: Field[Long, OrderItemsRow] = { + new Field[Long, OrderItemsRow]( + _path, + "quantity", + _.quantity, + None, + None, + (row, value) => row.copy(quantity = value), + SqliteTypes.integer.underlying + ) + } + + def unitPrice: Field[BigDecimal, OrderItemsRow] = { + new Field[BigDecimal, OrderItemsRow]( + _path, + "unit_price", + _.unitPrice, + None, + None, + (row, value) => row.copy(unitPrice = value), + SqliteTypes.numeric.underlying + ) + } + + def fkProducts: ForeignKey[ProductsFields, ProductsRow] = ForeignKey.of[ProductsFields, ProductsRow]("order_items_fk_0").withColumnPair[ProductsId](productId, _.productId) + + def fkOrders: ForeignKey[OrdersFields, OrdersRow] = ForeignKey.of[OrdersFields, OrdersRow]("order_items_fk_1").withColumnPair[OrdersId](orderId, _.orderId) + + def compositeIdIs(compositeId: OrderItemsId): SqlExpr[Boolean] = SqlExpr.all(orderId.isEqual(compositeId.orderId), productId.isEqual(compositeId.productId)) + + def compositeIdIn(compositeIds: List[OrderItemsId]): SqlExpr[Boolean] = TupleExpr.of(orderId, productId).among(compositeIds) + + override def columns: java.util.List[FieldLike[?, OrderItemsRow]] = java.util.List.of(this.orderId.underlying, this.productId.underlying, this.quantity.underlying, this.unitPrice.underlying) + + override def rowCodec: RowCodec[OrderItemsRow] = OrderItemsRow.rowCodec.underlying + + override def withPaths(`_path`: java.util.List[Path]): RelationStructure[OrderItemsFields, OrderItemsRow] = new OrderItemsFields(`_path`) + + override def `_1`: SqlExpr[OrdersId] = orderId + + override def `_2`: SqlExpr[ProductsId] = productId + + override def `_3`: SqlExpr[Long] = quantity + + override def `_4`: SqlExpr[BigDecimal] = unitPrice +} + +object OrderItemsFields { + val structure: OrderItemsFields = new OrderItemsFields(java.util.Collections.emptyList()) +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/order_items/OrderItemsId.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/order_items/OrderItemsId.scala new file mode 100644 index 0000000000..9bbf720862 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/order_items/OrderItemsId.scala @@ -0,0 +1,27 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.order_items + +import com.fasterxml.jackson.annotation.JsonProperty +import dev.typr.dslsc.RowCodecs +import dev.typr.foundations.Tuple.Tuple2 +import dev.typr.foundationssc.RowCodec +import testdb.orders.OrdersId +import testdb.products.ProductsId + +/** Type for the composite primary key of table `order_items` */ +case class OrderItemsId( + @JsonProperty("order_id") orderId: OrdersId, + @JsonProperty("product_id") productId: ProductsId +) extends Tuple2[OrdersId, ProductsId] { + override def `_1`: OrdersId = orderId + + override def `_2`: ProductsId = productId +} + +object OrderItemsId { + val rowCodec: RowCodec[OrderItemsId] = RowCodecs.of(OrdersId.sqliteType, ProductsId.sqliteType)(OrderItemsId.apply)(row => Array[Any](row.orderId, row.productId)) +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/order_items/OrderItemsRepo.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/order_items/OrderItemsRepo.scala new file mode 100644 index 0000000000..f5c0d29c4e --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/order_items/OrderItemsRepo.scala @@ -0,0 +1,42 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.order_items + +import dev.typr.dslsc.DeleteBuilder +import dev.typr.dslsc.SelectBuilder +import dev.typr.dslsc.UpdateBuilder +import dev.typr.foundationssc.Connection +import dev.typr.foundationssc.ConnectionRead + +trait OrderItemsRepo { + def delete: DeleteBuilder[OrderItemsFields, OrderItemsRow] + + def deleteById(compositeId: OrderItemsId)(using c: Connection): Boolean + + def deleteByIds(compositeIds: List[OrderItemsId])(using c: Connection): Int + + def insert(unsaved: OrderItemsRow)(using c: Connection): OrderItemsRow + + def insert(unsaved: OrderItemsRowUnsaved)(using c: Connection): OrderItemsRow + + def select: SelectBuilder[OrderItemsFields, OrderItemsRow] + + def selectAll(using c: ConnectionRead): List[OrderItemsRow] + + def selectById(compositeId: OrderItemsId)(using c: ConnectionRead): Option[OrderItemsRow] + + def selectByIds(compositeIds: List[OrderItemsId])(using c: ConnectionRead): List[OrderItemsRow] + + def selectByIdsTracked(compositeIds: List[OrderItemsId])(using c: ConnectionRead): Map[OrderItemsId, OrderItemsRow] + + def update: UpdateBuilder[OrderItemsFields, OrderItemsRow] + + def update(row: OrderItemsRow)(using c: Connection): Boolean + + def upsert(unsaved: OrderItemsRow)(using c: Connection): OrderItemsRow + + def upsertBatch(unsaved: Iterator[OrderItemsRow])(using c: Connection): List[OrderItemsRow] +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/order_items/OrderItemsRepoImpl.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/order_items/OrderItemsRepoImpl.scala new file mode 100644 index 0000000000..5bc8b633dd --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/order_items/OrderItemsRepoImpl.scala @@ -0,0 +1,121 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.order_items + +import dev.typr.dslsc.DeleteBuilder +import dev.typr.dslsc.Dialect +import dev.typr.dslsc.SelectBuilder +import dev.typr.dslsc.UpdateBuilder +import dev.typr.foundationssc.Connection +import dev.typr.foundationssc.ConnectionRead +import dev.typr.foundationssc.Fragment +import dev.typr.foundationssc.SqliteTypes +import scala.collection.mutable.ListBuffer +import testdb.orders.OrdersId +import testdb.products.ProductsId +import dev.typr.foundationssc.Fragment.sql + +class OrderItemsRepoImpl extends OrderItemsRepo { + override def delete: DeleteBuilder[OrderItemsFields, OrderItemsRow] = DeleteBuilder.of(""""order_items"""", OrderItemsFields.structure, Dialect.SQLITE) + + override def deleteById(compositeId: OrderItemsId)(using c: Connection): Boolean = sql"""delete from "order_items" where "order_id" = ${Fragment.encode(OrdersId.sqliteType, compositeId.orderId)} AND "product_id" = ${Fragment.encode(ProductsId.sqliteType, compositeId.productId)}""".update().run(using c) > 0 + + override def deleteByIds(compositeIds: List[OrderItemsId])(using c: Connection): Int = { + val fragments: ListBuffer[Fragment] = ListBuffer() + compositeIds.foreach { id => fragments.addOne(Fragment.concat(Fragment.of("("), Fragment.encode(OrdersId.sqliteType, id.orderId), Fragment.of(", "), Fragment.encode(ProductsId.sqliteType, id.productId), Fragment.of(")"))): @scala.annotation.nowarn } + return Fragment.concat(Fragment.of("""delete from "order_items" where ("order_id", "product_id") in ("""), Fragment.comma(fragments), Fragment.of(")")).update().run(using c) + } + + override def insert(unsaved: OrderItemsRow)(using c: Connection): OrderItemsRow = { + sql"""insert into "order_items"("order_id", "product_id", "quantity", "unit_price") + values (${Fragment.encode(OrdersId.sqliteType, unsaved.orderId)}, ${Fragment.encode(ProductsId.sqliteType, unsaved.productId)}, ${Fragment.encode(SqliteTypes.integer, unsaved.quantity)}, ${Fragment.encode(SqliteTypes.numeric, unsaved.unitPrice)}) + RETURNING "order_id", "product_id", "quantity", "unit_price" + """ + .updateReturning(OrderItemsRow.rowCodec.exactlyOne()).run(using c) + } + + override def insert(unsaved: OrderItemsRowUnsaved)(using c: Connection): OrderItemsRow = { + val columns: ListBuffer[Fragment] = ListBuffer() + val values: ListBuffer[Fragment] = ListBuffer() + columns.addOne(Fragment.of(""""order_id"""")): @scala.annotation.nowarn + values.addOne(sql"${Fragment.encode(OrdersId.sqliteType, unsaved.orderId)}"): @scala.annotation.nowarn + columns.addOne(Fragment.of(""""product_id"""")): @scala.annotation.nowarn + values.addOne(sql"${Fragment.encode(ProductsId.sqliteType, unsaved.productId)}"): @scala.annotation.nowarn + columns.addOne(Fragment.of(""""unit_price"""")): @scala.annotation.nowarn + values.addOne(sql"${Fragment.encode(SqliteTypes.numeric, unsaved.unitPrice)}"): @scala.annotation.nowarn + unsaved.quantity.visit( + { }, + value => { columns.addOne(Fragment.of(""""quantity"""")): @scala.annotation.nowarn; values.addOne(sql"${Fragment.encode(SqliteTypes.integer, value)}"): @scala.annotation.nowarn } + ); + val q: Fragment = { + sql"""insert into "order_items"(${Fragment.comma(columns)}) + values (${Fragment.comma(values)}) + RETURNING "order_id", "product_id", "quantity", "unit_price" + """ + } + return q.updateReturning(OrderItemsRow.rowCodec.exactlyOne()).run(using c) + } + + override def select: SelectBuilder[OrderItemsFields, OrderItemsRow] = SelectBuilder.of(""""order_items"""", OrderItemsFields.structure, OrderItemsRow.rowCodec, Dialect.SQLITE) + + override def selectAll(using c: ConnectionRead): List[OrderItemsRow] = { + sql"""select "order_id", "product_id", "quantity", "unit_price" + from "order_items" + """.query(OrderItemsRow.rowCodec.all()).run(using c) + } + + override def selectById(compositeId: OrderItemsId)(using c: ConnectionRead): Option[OrderItemsRow] = { + sql"""select "order_id", "product_id", "quantity", "unit_price" + from "order_items" + where "order_id" = ${Fragment.encode(OrdersId.sqliteType, compositeId.orderId)} AND "product_id" = ${Fragment.encode(ProductsId.sqliteType, compositeId.productId)}""".query(OrderItemsRow.rowCodec.first()).run(using c) + } + + override def selectByIds(compositeIds: List[OrderItemsId])(using c: ConnectionRead): List[OrderItemsRow] = { + val fragments: ListBuffer[Fragment] = ListBuffer() + compositeIds.foreach { id => fragments.addOne(Fragment.concat(Fragment.of("("), Fragment.encode(OrdersId.sqliteType, id.orderId), Fragment.of(", "), Fragment.encode(ProductsId.sqliteType, id.productId), Fragment.of(")"))): @scala.annotation.nowarn } + return Fragment.concat(Fragment.of("""select "order_id", "product_id", "quantity", "unit_price" from "order_items" where ("order_id", "product_id") in ("""), Fragment.comma(fragments), Fragment.of(")")).query(OrderItemsRow.rowCodec.all()).run(using c) + } + + override def selectByIdsTracked(compositeIds: List[OrderItemsId])(using c: ConnectionRead): Map[OrderItemsId, OrderItemsRow] = { + val ret: scala.collection.mutable.Map[OrderItemsId, OrderItemsRow] = scala.collection.mutable.Map.empty[OrderItemsId, OrderItemsRow] + selectByIds(compositeIds)(using c).foreach(row => ret.put(row.compositeId, row): @scala.annotation.nowarn) + return ret.toMap + } + + override def update: UpdateBuilder[OrderItemsFields, OrderItemsRow] = UpdateBuilder.of(""""order_items"""", OrderItemsFields.structure, OrderItemsRow.rowCodec, Dialect.SQLITE) + + override def update(row: OrderItemsRow)(using c: Connection): Boolean = { + val compositeId: OrderItemsId = row.compositeId + return sql"""update "order_items" + set "quantity" = ${Fragment.encode(SqliteTypes.integer, row.quantity)}, + "unit_price" = ${Fragment.encode(SqliteTypes.numeric, row.unitPrice)} + where "order_id" = ${Fragment.encode(OrdersId.sqliteType, compositeId.orderId)} AND "product_id" = ${Fragment.encode(ProductsId.sqliteType, compositeId.productId)}""".update().run(using c) > 0 + } + + override def upsert(unsaved: OrderItemsRow)(using c: Connection): OrderItemsRow = { + sql"""INSERT INTO "order_items"("order_id", "product_id", "quantity", "unit_price") + VALUES (${Fragment.encode(OrdersId.sqliteType, unsaved.orderId)}, ${Fragment.encode(ProductsId.sqliteType, unsaved.productId)}, ${Fragment.encode(SqliteTypes.integer, unsaved.quantity)}, ${Fragment.encode(SqliteTypes.numeric, unsaved.unitPrice)}) + ON CONFLICT ("order_id", "product_id") + DO UPDATE SET + "quantity" = EXCLUDED."quantity", + "unit_price" = EXCLUDED."unit_price" + RETURNING "order_id", "product_id", "quantity", "unit_price"""" + .updateReturning(OrderItemsRow.rowCodec.exactlyOne()) + .run(using c) + } + + override def upsertBatch(unsaved: Iterator[OrderItemsRow])(using c: Connection): List[OrderItemsRow] = { + sql"""INSERT INTO "order_items"("order_id", "product_id", "quantity", "unit_price") + VALUES (?, ?, ?, ?) + ON CONFLICT ("order_id", "product_id") + DO UPDATE SET + "quantity" = EXCLUDED."quantity", + "unit_price" = EXCLUDED."unit_price" + RETURNING "order_id", "product_id", "quantity", "unit_price"""" + .updateReturningEach(OrderItemsRow.rowCodec, unsaved) + .run(using c) + } +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/order_items/OrderItemsRepoMock.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/order_items/OrderItemsRepoMock.scala new file mode 100644 index 0000000000..4955f74ae0 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/order_items/OrderItemsRepoMock.scala @@ -0,0 +1,78 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.order_items + +import dev.typr.dslsc.DeleteBuilder +import dev.typr.dslsc.DeleteBuilderMock +import dev.typr.dslsc.DeleteParams +import dev.typr.dslsc.SelectBuilder +import dev.typr.dslsc.SelectBuilderMock +import dev.typr.dslsc.SelectParams +import dev.typr.dslsc.UpdateBuilder +import dev.typr.dslsc.UpdateBuilderMock +import dev.typr.dslsc.UpdateParams +import dev.typr.foundationssc.Connection +import dev.typr.foundationssc.ConnectionRead +import java.lang.RuntimeException + +case class OrderItemsRepoMock( + toRow: OrderItemsRowUnsaved => OrderItemsRow, + map: scala.collection.mutable.Map[OrderItemsId, OrderItemsRow] = scala.collection.mutable.Map.empty[OrderItemsId, OrderItemsRow] +) extends OrderItemsRepo { + override def delete: DeleteBuilder[OrderItemsFields, OrderItemsRow] = DeleteBuilderMock(OrderItemsFields.structure, () => map.values.toList, DeleteParams.empty(), row => row.compositeId, id => map.remove(id): @scala.annotation.nowarn) + + override def deleteById(compositeId: OrderItemsId)(using c: Connection): Boolean = map.remove(compositeId).isDefined + + override def deleteByIds(compositeIds: List[OrderItemsId])(using c: Connection): Int = { + var count = 0 + compositeIds.foreach { id => if (map.remove(id).isDefined) { + count = count + 1 + } } + return count + } + + override def insert(unsaved: OrderItemsRow)(using c: Connection): OrderItemsRow = { + if (map.contains(unsaved.compositeId)) { + throw new RuntimeException(s"id ${unsaved.compositeId} already exists") + } + map.put(unsaved.compositeId, unsaved): @scala.annotation.nowarn + return unsaved + } + + override def insert(unsaved: OrderItemsRowUnsaved)(using c: Connection): OrderItemsRow = insert(toRow(unsaved))(using c) + + override def select: SelectBuilder[OrderItemsFields, OrderItemsRow] = SelectBuilderMock(OrderItemsFields.structure, () => map.values.toList, SelectParams.empty()) + + override def selectAll(using c: ConnectionRead): List[OrderItemsRow] = map.values.toList + + override def selectById(compositeId: OrderItemsId)(using c: ConnectionRead): Option[OrderItemsRow] = map.get(compositeId) + + override def selectByIds(compositeIds: List[OrderItemsId])(using c: ConnectionRead): List[OrderItemsRow] = compositeIds.flatMap(map.get(_)).toList + + override def selectByIdsTracked(compositeIds: List[OrderItemsId])(using c: ConnectionRead): Map[OrderItemsId, OrderItemsRow] = selectByIds(compositeIds)(using c).map(x => (((row: OrderItemsRow) => row.compositeId).apply(x), x)).toMap + + override def update: UpdateBuilder[OrderItemsFields, OrderItemsRow] = UpdateBuilderMock(OrderItemsFields.structure, () => map.values.toList, UpdateParams.empty(), row => row) + + override def update(row: OrderItemsRow)(using c: Connection): Boolean = { + val shouldUpdate = map.get(row.compositeId).filter(oldRow => (oldRow != row)).isDefined + if (shouldUpdate) { + map.put(row.compositeId, row): @scala.annotation.nowarn + } + return shouldUpdate + } + + override def upsert(unsaved: OrderItemsRow)(using c: Connection): OrderItemsRow = { + map.put(unsaved.compositeId, unsaved): @scala.annotation.nowarn + return unsaved + } + + override def upsertBatch(unsaved: Iterator[OrderItemsRow])(using c: Connection): List[OrderItemsRow] = { + unsaved.map { row => + map.put(row.compositeId, row): @scala.annotation.nowarn + row + }.toList + } +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/order_items/OrderItemsRow.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/order_items/OrderItemsRow.scala new file mode 100644 index 0000000000..712ff5bbdc --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/order_items/OrderItemsRow.scala @@ -0,0 +1,66 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.order_items + +import com.fasterxml.jackson.annotation.JsonProperty +import dev.typr.dslsc.RowCodecs +import dev.typr.foundations.Tuple.Tuple4 +import dev.typr.foundationssc.RowCodec +import dev.typr.foundationssc.SqliteTypes +import testdb.customtypes.Defaulted +import testdb.orders.OrdersId +import testdb.products.ProductsId + +/** Table: order_items + * Composite primary key: order_id, product_id + */ +case class OrderItemsRow( + /** Points to [[testdb.orders.OrdersRow.orderId]] */ + @JsonProperty("order_id") orderId: OrdersId, + /** Points to [[testdb.products.ProductsRow.productId]] */ + @JsonProperty("product_id") productId: ProductsId, + /** Default: 1 */ + quantity: Long, + @JsonProperty("unit_price") unitPrice: BigDecimal +) extends Tuple4[OrdersId, ProductsId, Long, BigDecimal] { + def compositeId: OrderItemsId = new OrderItemsId(orderId, productId) + + def id: OrderItemsId = this.compositeId + + def toUnsavedRow(quantity: Defaulted[Long] = Defaulted.Provided(this.quantity)): OrderItemsRowUnsaved = { + new OrderItemsRowUnsaved( + orderId, + productId, + unitPrice, + quantity + ) + } + + override def `_1`: OrdersId = orderId + + override def `_2`: ProductsId = productId + + override def `_3`: Long = quantity + + override def `_4`: BigDecimal = unitPrice +} + +object OrderItemsRow { + def apply( + compositeId: OrderItemsId, + quantity: Long, + unitPrice: BigDecimal + ): OrderItemsRow = { + new OrderItemsRow( + compositeId.orderId, + compositeId.productId, + quantity, + unitPrice + ) + } + + val rowCodec: RowCodec[OrderItemsRow] = RowCodecs.of(OrdersId.sqliteType, ProductsId.sqliteType, SqliteTypes.integer, SqliteTypes.numeric)(OrderItemsRow.apply)(row => Array[Any](row.orderId, row.productId, row.quantity, row.unitPrice)) +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/order_items/OrderItemsRowUnsaved.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/order_items/OrderItemsRowUnsaved.scala new file mode 100644 index 0000000000..9982b042a7 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/order_items/OrderItemsRowUnsaved.scala @@ -0,0 +1,32 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.order_items + +import com.fasterxml.jackson.annotation.JsonProperty +import testdb.customtypes.Defaulted +import testdb.customtypes.Defaulted.UseDefault +import testdb.orders.OrdersId +import testdb.products.ProductsId + +/** This class corresponds to a row in table `order_items` which has not been persisted yet */ +case class OrderItemsRowUnsaved( + /** Points to [[testdb.orders.OrdersRow.orderId]] */ + @JsonProperty("order_id") orderId: OrdersId, + /** Points to [[testdb.products.ProductsRow.productId]] */ + @JsonProperty("product_id") productId: ProductsId, + @JsonProperty("unit_price") unitPrice: BigDecimal, + /** Default: 1 */ + quantity: Defaulted[Long] = new UseDefault() +) { + def toRow(quantityDefault: => Long): OrderItemsRow = { + new OrderItemsRow( + orderId = orderId, + productId = productId, + quantity = quantity.getOrElse(quantityDefault), + unitPrice = unitPrice + ) + } +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/order_summary_by_customer/OrderSummaryByCustomerSqlRepo.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/order_summary_by_customer/OrderSummaryByCustomerSqlRepo.scala new file mode 100644 index 0000000000..f262d20764 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/order_summary_by_customer/OrderSummaryByCustomerSqlRepo.scala @@ -0,0 +1,16 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.order_summary_by_customer + +import dev.typr.foundationssc.ConnectionRead +import java.time.LocalDate + +trait OrderSummaryByCustomerSqlRepo { + def apply( + fromDate: LocalDate, + toDate: LocalDate + )(using c: ConnectionRead): List[OrderSummaryByCustomerSqlRow] +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/order_summary_by_customer/OrderSummaryByCustomerSqlRepoImpl.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/order_summary_by_customer/OrderSummaryByCustomerSqlRepoImpl.scala new file mode 100644 index 0000000000..3990189f14 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/order_summary_by_customer/OrderSummaryByCustomerSqlRepoImpl.scala @@ -0,0 +1,35 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.order_summary_by_customer + +import dev.typr.foundationssc.ConnectionRead +import dev.typr.foundationssc.Fragment +import dev.typr.foundationssc.SqliteTypes +import java.time.LocalDate +import dev.typr.foundationssc.Fragment.sql + +class OrderSummaryByCustomerSqlRepoImpl extends OrderSummaryByCustomerSqlRepo { + override def apply( + fromDate: LocalDate, + toDate: LocalDate + )(using c: ConnectionRead): List[OrderSummaryByCustomerSqlRow] = { + sql"""-- Summary stats per customer over an order date range. + -- Tests: GROUP BY, aggregates with NULL-aware results, JOIN, date params. + + SELECT + c.customer_id, + c.name AS customer_name, + COUNT(o.order_id) AS order_count, + COALESCE(SUM(o.total_amount), 0) AS total_revenue, + MAX(o.order_date) AS last_order_date + FROM customers c + LEFT JOIN orders o ON c.customer_id = o.customer_id + WHERE o.order_date IS NULL + OR (o.order_date >= ${Fragment.encode(SqliteTypes.date, fromDate)} AND o.order_date <= ${Fragment.encode(SqliteTypes.date, toDate)}) + GROUP BY c.customer_id, c.name + ORDER BY total_revenue DESC, c.customer_id""".query(OrderSummaryByCustomerSqlRow.rowCodec.all()).run(using c) + } +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/order_summary_by_customer/OrderSummaryByCustomerSqlRow.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/order_summary_by_customer/OrderSummaryByCustomerSqlRow.scala new file mode 100644 index 0000000000..51de212441 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/order_summary_by_customer/OrderSummaryByCustomerSqlRow.scala @@ -0,0 +1,42 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.order_summary_by_customer + +import com.fasterxml.jackson.annotation.JsonProperty +import dev.typr.dslsc.RowCodecs +import dev.typr.foundations.Tuple.Tuple5 +import dev.typr.foundationssc.RowCodec +import dev.typr.foundationssc.SqliteTypes +import java.time.LocalDate +import testdb.customers.CustomersId + +/** SQL file: order_summary_by_customer.sql */ +case class OrderSummaryByCustomerSqlRow( + /** Points to [[testdb.customers.CustomersRow.customerId]] */ + @JsonProperty("customer_id") customerId: CustomersId, + /** Points to [[testdb.customers.CustomersRow.name]] */ + @JsonProperty("customer_name") customerName: String, + /** Points to [[testdb.orders.OrdersRow.orderId]] */ + @JsonProperty("order_count") orderCount: Option[Long], + /** Points to [[testdb.orders.OrdersRow.totalAmount]] */ + @JsonProperty("total_revenue") totalRevenue: Option[BigDecimal], + /** Points to [[testdb.orders.OrdersRow.orderDate]] */ + @JsonProperty("last_order_date") lastOrderDate: Option[LocalDate] +) extends Tuple5[CustomersId, String, Option[Long], Option[BigDecimal], Option[LocalDate]] { + override def `_1`: CustomersId = customerId + + override def `_2`: String = customerName + + override def `_3`: Option[Long] = orderCount + + override def `_4`: Option[BigDecimal] = totalRevenue + + override def `_5`: Option[LocalDate] = lastOrderDate +} + +object OrderSummaryByCustomerSqlRow { + val rowCodec: RowCodec[OrderSummaryByCustomerSqlRow] = RowCodecs.of(CustomersId.sqliteType, SqliteTypes.text, SqliteTypes.bigint.opt, SqliteTypes.numeric.opt, SqliteTypes.date.opt)(OrderSummaryByCustomerSqlRow.apply)(row => Array[Any](row.customerId, row.customerName, row.orderCount, row.totalRevenue, row.lastOrderDate)) +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/orders/OrdersFields.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/orders/OrdersFields.scala new file mode 100644 index 0000000000..d810e02142 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/orders/OrdersFields.scala @@ -0,0 +1,107 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.orders + +import dev.typr.dsl.FieldsBase +import dev.typr.dsl.Path +import dev.typr.dsl.SqlExpr.FieldLike +import dev.typr.dslsc.ForeignKey +import dev.typr.dslsc.RelationStructure +import dev.typr.dslsc.SqlExpr +import dev.typr.dslsc.SqlExpr.Field +import dev.typr.dslsc.SqlExpr.IdField +import dev.typr.dslsc.SqlExpr.OptField +import dev.typr.dslsc.TupleExpr5 +import dev.typr.foundations.RowCodec +import dev.typr.foundationssc.SqliteTypes +import java.time.LocalDate +import testdb.customers.CustomersFields +import testdb.customers.CustomersId +import testdb.customers.CustomersRow + +class OrdersFields(val `_path`: java.util.List[Path]) extends TupleExpr5[OrdersId, CustomersId, LocalDate, BigDecimal, String] with RelationStructure[OrdersFields, OrdersRow] with FieldsBase[OrdersRow] { + def orderId: IdField[OrdersId, OrdersRow] = { + new IdField[OrdersId, OrdersRow]( + _path, + "order_id", + _.orderId, + None, + None, + (row, value) => row.copy(orderId = value), + OrdersId.sqliteType.underlying + ) + } + + def customerId: Field[CustomersId, OrdersRow] = { + new Field[CustomersId, OrdersRow]( + _path, + "customer_id", + _.customerId, + None, + None, + (row, value) => row.copy(customerId = value), + CustomersId.sqliteType.underlying + ) + } + + def orderDate: Field[LocalDate, OrdersRow] = { + new Field[LocalDate, OrdersRow]( + _path, + "order_date", + _.orderDate, + None, + None, + (row, value) => row.copy(orderDate = value), + SqliteTypes.date.underlying + ) + } + + def totalAmount: OptField[BigDecimal, OrdersRow] = { + new OptField[BigDecimal, OrdersRow]( + _path, + "total_amount", + _.totalAmount, + None, + None, + (row, value) => row.copy(totalAmount = value), + SqliteTypes.numeric.underlying + ) + } + + def status: Field[String, OrdersRow] = { + new Field[String, OrdersRow]( + _path, + "status", + _.status, + None, + None, + (row, value) => row.copy(status = value), + SqliteTypes.text.underlying + ) + } + + def fkCustomers: ForeignKey[CustomersFields, CustomersRow] = ForeignKey.of[CustomersFields, CustomersRow]("orders_fk_0").withColumnPair[CustomersId](customerId, _.customerId) + + override def columns: java.util.List[FieldLike[?, OrdersRow]] = java.util.List.of(this.orderId.underlying, this.customerId.underlying, this.orderDate.underlying, this.totalAmount.underlying, this.status.underlying) + + override def rowCodec: RowCodec[OrdersRow] = OrdersRow.rowCodec.underlying + + override def withPaths(`_path`: java.util.List[Path]): RelationStructure[OrdersFields, OrdersRow] = new OrdersFields(`_path`) + + override def `_1`: SqlExpr[OrdersId] = orderId + + override def `_2`: SqlExpr[CustomersId] = customerId + + override def `_3`: SqlExpr[LocalDate] = orderDate + + override def `_4`: SqlExpr[BigDecimal] = totalAmount + + override def `_5`: SqlExpr[String] = status +} + +object OrdersFields { + val structure: OrdersFields = new OrdersFields(java.util.Collections.emptyList()) +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/orders/OrdersId.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/orders/OrdersId.scala new file mode 100644 index 0000000000..77ac1093a9 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/orders/OrdersId.scala @@ -0,0 +1,20 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.orders + +import com.fasterxml.jackson.annotation.JsonValue +import dev.typr.dslsc.Bijection +import dev.typr.foundationssc.SqliteType +import dev.typr.foundationssc.SqliteTypes + +/** Type for the primary key of table `orders` */ +case class OrdersId(@JsonValue value: Long) extends scala.AnyVal + +object OrdersId { + given bijection: Bijection[OrdersId, Long] = Bijection.of[OrdersId, Long](_.value, OrdersId.apply) + + given sqliteType: SqliteType[OrdersId] = SqliteTypes.integer.to(Bijection.of(OrdersId.apply, _.value)) +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/orders/OrdersRepo.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/orders/OrdersRepo.scala new file mode 100644 index 0000000000..36f1ef82d1 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/orders/OrdersRepo.scala @@ -0,0 +1,42 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.orders + +import dev.typr.dslsc.DeleteBuilder +import dev.typr.dslsc.SelectBuilder +import dev.typr.dslsc.UpdateBuilder +import dev.typr.foundationssc.Connection +import dev.typr.foundationssc.ConnectionRead + +trait OrdersRepo { + def delete: DeleteBuilder[OrdersFields, OrdersRow] + + def deleteById(orderId: OrdersId)(using c: Connection): Boolean + + def deleteByIds(orderIds: List[OrdersId])(using c: Connection): Int + + def insert(unsaved: OrdersRow)(using c: Connection): OrdersRow + + def insert(unsaved: OrdersRowUnsaved)(using c: Connection): OrdersRow + + def select: SelectBuilder[OrdersFields, OrdersRow] + + def selectAll(using c: ConnectionRead): List[OrdersRow] + + def selectById(orderId: OrdersId)(using c: ConnectionRead): Option[OrdersRow] + + def selectByIds(orderIds: List[OrdersId])(using c: ConnectionRead): List[OrdersRow] + + def selectByIdsTracked(orderIds: List[OrdersId])(using c: ConnectionRead): Map[OrdersId, OrdersRow] + + def update: UpdateBuilder[OrdersFields, OrdersRow] + + def update(row: OrdersRow)(using c: Connection): Boolean + + def upsert(unsaved: OrdersRow)(using c: Connection): OrdersRow + + def upsertBatch(unsaved: Iterator[OrdersRow])(using c: Connection): List[OrdersRow] +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/orders/OrdersRepoImpl.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/orders/OrdersRepoImpl.scala new file mode 100644 index 0000000000..f0fcc0f2e1 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/orders/OrdersRepoImpl.scala @@ -0,0 +1,128 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.orders + +import dev.typr.dslsc.DeleteBuilder +import dev.typr.dslsc.Dialect +import dev.typr.dslsc.SelectBuilder +import dev.typr.dslsc.UpdateBuilder +import dev.typr.foundationssc.Connection +import dev.typr.foundationssc.ConnectionRead +import dev.typr.foundationssc.Fragment +import dev.typr.foundationssc.SqliteTypes +import scala.collection.mutable.ListBuffer +import testdb.customers.CustomersId +import dev.typr.foundationssc.Fragment.sql + +class OrdersRepoImpl extends OrdersRepo { + override def delete: DeleteBuilder[OrdersFields, OrdersRow] = DeleteBuilder.of(""""orders"""", OrdersFields.structure, Dialect.SQLITE) + + override def deleteById(orderId: OrdersId)(using c: Connection): Boolean = sql"""delete from "orders" where "order_id" = ${Fragment.encode(OrdersId.sqliteType, orderId)}""".update().run(using c) > 0 + + override def deleteByIds(orderIds: List[OrdersId])(using c: Connection): Int = { + val fragments: ListBuffer[Fragment] = ListBuffer() + orderIds.foreach { id => fragments.addOne(Fragment.encode(OrdersId.sqliteType, id)): @scala.annotation.nowarn } + return Fragment.concat(Fragment.of("""delete from "orders" where "order_id" in ("""), Fragment.comma(fragments), Fragment.of(")")).update().run(using c) + } + + override def insert(unsaved: OrdersRow)(using c: Connection): OrdersRow = { + sql"""insert into "orders"("order_id", "customer_id", "order_date", "total_amount", "status") + values (${Fragment.encode(OrdersId.sqliteType, unsaved.orderId)}, ${Fragment.encode(CustomersId.sqliteType, unsaved.customerId)}, ${Fragment.encode(SqliteTypes.date, unsaved.orderDate)}, ${Fragment.encode(SqliteTypes.numeric.opt, unsaved.totalAmount)}, ${Fragment.encode(SqliteTypes.text, unsaved.status)}) + RETURNING "order_id", "customer_id", "order_date", "total_amount", "status" + """ + .updateReturning(OrdersRow.rowCodec.exactlyOne()).run(using c) + } + + override def insert(unsaved: OrdersRowUnsaved)(using c: Connection): OrdersRow = { + val columns: ListBuffer[Fragment] = ListBuffer() + val values: ListBuffer[Fragment] = ListBuffer() + columns.addOne(Fragment.of(""""order_id"""")): @scala.annotation.nowarn + values.addOne(sql"${Fragment.encode(OrdersId.sqliteType, unsaved.orderId)}"): @scala.annotation.nowarn + columns.addOne(Fragment.of(""""customer_id"""")): @scala.annotation.nowarn + values.addOne(sql"${Fragment.encode(CustomersId.sqliteType, unsaved.customerId)}"): @scala.annotation.nowarn + columns.addOne(Fragment.of(""""order_date"""")): @scala.annotation.nowarn + values.addOne(sql"${Fragment.encode(SqliteTypes.date, unsaved.orderDate)}"): @scala.annotation.nowarn + columns.addOne(Fragment.of(""""total_amount"""")): @scala.annotation.nowarn + values.addOne(sql"${Fragment.encode(SqliteTypes.numeric.opt, unsaved.totalAmount)}"): @scala.annotation.nowarn + unsaved.status.visit( + { }, + value => { columns.addOne(Fragment.of(""""status"""")): @scala.annotation.nowarn; values.addOne(sql"${Fragment.encode(SqliteTypes.text, value)}"): @scala.annotation.nowarn } + ); + val q: Fragment = { + sql"""insert into "orders"(${Fragment.comma(columns)}) + values (${Fragment.comma(values)}) + RETURNING "order_id", "customer_id", "order_date", "total_amount", "status" + """ + } + return q.updateReturning(OrdersRow.rowCodec.exactlyOne()).run(using c) + } + + override def select: SelectBuilder[OrdersFields, OrdersRow] = SelectBuilder.of(""""orders"""", OrdersFields.structure, OrdersRow.rowCodec, Dialect.SQLITE) + + override def selectAll(using c: ConnectionRead): List[OrdersRow] = { + sql"""select "order_id", "customer_id", "order_date", "total_amount", "status" + from "orders" + """.query(OrdersRow.rowCodec.all()).run(using c) + } + + override def selectById(orderId: OrdersId)(using c: ConnectionRead): Option[OrdersRow] = { + sql"""select "order_id", "customer_id", "order_date", "total_amount", "status" + from "orders" + where "order_id" = ${Fragment.encode(OrdersId.sqliteType, orderId)}""".query(OrdersRow.rowCodec.first()).run(using c) + } + + override def selectByIds(orderIds: List[OrdersId])(using c: ConnectionRead): List[OrdersRow] = { + val fragments: ListBuffer[Fragment] = ListBuffer() + orderIds.foreach { id => fragments.addOne(Fragment.encode(OrdersId.sqliteType, id)): @scala.annotation.nowarn } + return Fragment.concat(Fragment.of("""select "order_id", "customer_id", "order_date", "total_amount", "status" from "orders" where "order_id" in ("""), Fragment.comma(fragments), Fragment.of(")")).query(OrdersRow.rowCodec.all()).run(using c) + } + + override def selectByIdsTracked(orderIds: List[OrdersId])(using c: ConnectionRead): Map[OrdersId, OrdersRow] = { + val ret: scala.collection.mutable.Map[OrdersId, OrdersRow] = scala.collection.mutable.Map.empty[OrdersId, OrdersRow] + selectByIds(orderIds)(using c).foreach(row => ret.put(row.orderId, row): @scala.annotation.nowarn) + return ret.toMap + } + + override def update: UpdateBuilder[OrdersFields, OrdersRow] = UpdateBuilder.of(""""orders"""", OrdersFields.structure, OrdersRow.rowCodec, Dialect.SQLITE) + + override def update(row: OrdersRow)(using c: Connection): Boolean = { + val orderId: OrdersId = row.orderId + return sql"""update "orders" + set "customer_id" = ${Fragment.encode(CustomersId.sqliteType, row.customerId)}, + "order_date" = ${Fragment.encode(SqliteTypes.date, row.orderDate)}, + "total_amount" = ${Fragment.encode(SqliteTypes.numeric.opt, row.totalAmount)}, + "status" = ${Fragment.encode(SqliteTypes.text, row.status)} + where "order_id" = ${Fragment.encode(OrdersId.sqliteType, orderId)}""".update().run(using c) > 0 + } + + override def upsert(unsaved: OrdersRow)(using c: Connection): OrdersRow = { + sql"""INSERT INTO "orders"("order_id", "customer_id", "order_date", "total_amount", "status") + VALUES (${Fragment.encode(OrdersId.sqliteType, unsaved.orderId)}, ${Fragment.encode(CustomersId.sqliteType, unsaved.customerId)}, ${Fragment.encode(SqliteTypes.date, unsaved.orderDate)}, ${Fragment.encode(SqliteTypes.numeric.opt, unsaved.totalAmount)}, ${Fragment.encode(SqliteTypes.text, unsaved.status)}) + ON CONFLICT ("order_id") + DO UPDATE SET + "customer_id" = EXCLUDED."customer_id", + "order_date" = EXCLUDED."order_date", + "total_amount" = EXCLUDED."total_amount", + "status" = EXCLUDED."status" + RETURNING "order_id", "customer_id", "order_date", "total_amount", "status"""" + .updateReturning(OrdersRow.rowCodec.exactlyOne()) + .run(using c) + } + + override def upsertBatch(unsaved: Iterator[OrdersRow])(using c: Connection): List[OrdersRow] = { + sql"""INSERT INTO "orders"("order_id", "customer_id", "order_date", "total_amount", "status") + VALUES (?, ?, ?, ?, ?) + ON CONFLICT ("order_id") + DO UPDATE SET + "customer_id" = EXCLUDED."customer_id", + "order_date" = EXCLUDED."order_date", + "total_amount" = EXCLUDED."total_amount", + "status" = EXCLUDED."status" + RETURNING "order_id", "customer_id", "order_date", "total_amount", "status"""" + .updateReturningEach(OrdersRow.rowCodec, unsaved) + .run(using c) + } +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/orders/OrdersRepoMock.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/orders/OrdersRepoMock.scala new file mode 100644 index 0000000000..ee5061d7bd --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/orders/OrdersRepoMock.scala @@ -0,0 +1,78 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.orders + +import dev.typr.dslsc.DeleteBuilder +import dev.typr.dslsc.DeleteBuilderMock +import dev.typr.dslsc.DeleteParams +import dev.typr.dslsc.SelectBuilder +import dev.typr.dslsc.SelectBuilderMock +import dev.typr.dslsc.SelectParams +import dev.typr.dslsc.UpdateBuilder +import dev.typr.dslsc.UpdateBuilderMock +import dev.typr.dslsc.UpdateParams +import dev.typr.foundationssc.Connection +import dev.typr.foundationssc.ConnectionRead +import java.lang.RuntimeException + +case class OrdersRepoMock( + toRow: OrdersRowUnsaved => OrdersRow, + map: scala.collection.mutable.Map[OrdersId, OrdersRow] = scala.collection.mutable.Map.empty[OrdersId, OrdersRow] +) extends OrdersRepo { + override def delete: DeleteBuilder[OrdersFields, OrdersRow] = DeleteBuilderMock(OrdersFields.structure, () => map.values.toList, DeleteParams.empty(), row => row.orderId, id => map.remove(id): @scala.annotation.nowarn) + + override def deleteById(orderId: OrdersId)(using c: Connection): Boolean = map.remove(orderId).isDefined + + override def deleteByIds(orderIds: List[OrdersId])(using c: Connection): Int = { + var count = 0 + orderIds.foreach { id => if (map.remove(id).isDefined) { + count = count + 1 + } } + return count + } + + override def insert(unsaved: OrdersRow)(using c: Connection): OrdersRow = { + if (map.contains(unsaved.orderId)) { + throw new RuntimeException(s"id ${unsaved.orderId} already exists") + } + map.put(unsaved.orderId, unsaved): @scala.annotation.nowarn + return unsaved + } + + override def insert(unsaved: OrdersRowUnsaved)(using c: Connection): OrdersRow = insert(toRow(unsaved))(using c) + + override def select: SelectBuilder[OrdersFields, OrdersRow] = SelectBuilderMock(OrdersFields.structure, () => map.values.toList, SelectParams.empty()) + + override def selectAll(using c: ConnectionRead): List[OrdersRow] = map.values.toList + + override def selectById(orderId: OrdersId)(using c: ConnectionRead): Option[OrdersRow] = map.get(orderId) + + override def selectByIds(orderIds: List[OrdersId])(using c: ConnectionRead): List[OrdersRow] = orderIds.flatMap(map.get(_)).toList + + override def selectByIdsTracked(orderIds: List[OrdersId])(using c: ConnectionRead): Map[OrdersId, OrdersRow] = selectByIds(orderIds)(using c).map(x => (((row: OrdersRow) => row.orderId).apply(x), x)).toMap + + override def update: UpdateBuilder[OrdersFields, OrdersRow] = UpdateBuilderMock(OrdersFields.structure, () => map.values.toList, UpdateParams.empty(), row => row) + + override def update(row: OrdersRow)(using c: Connection): Boolean = { + val shouldUpdate = map.get(row.orderId).filter(oldRow => (oldRow != row)).isDefined + if (shouldUpdate) { + map.put(row.orderId, row): @scala.annotation.nowarn + } + return shouldUpdate + } + + override def upsert(unsaved: OrdersRow)(using c: Connection): OrdersRow = { + map.put(unsaved.orderId, unsaved): @scala.annotation.nowarn + return unsaved + } + + override def upsertBatch(unsaved: Iterator[OrdersRow])(using c: Connection): List[OrdersRow] = { + unsaved.map { row => + map.put(row.orderId, row): @scala.annotation.nowarn + row + }.toList + } +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/orders/OrdersRow.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/orders/OrdersRow.scala new file mode 100644 index 0000000000..0cb867f3be --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/orders/OrdersRow.scala @@ -0,0 +1,54 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.orders + +import com.fasterxml.jackson.annotation.JsonProperty +import dev.typr.dslsc.RowCodecs +import dev.typr.foundations.Tuple.Tuple5 +import dev.typr.foundationssc.RowCodec +import dev.typr.foundationssc.SqliteTypes +import java.time.LocalDate +import testdb.customers.CustomersId +import testdb.customtypes.Defaulted + +/** Table: orders + * Primary key: order_id + */ +case class OrdersRow( + @JsonProperty("order_id") orderId: OrdersId, + /** Points to [[testdb.customers.CustomersRow.customerId]] */ + @JsonProperty("customer_id") customerId: CustomersId, + @JsonProperty("order_date") orderDate: LocalDate, + @JsonProperty("total_amount") totalAmount: Option[BigDecimal], + /** Default: 'pending' */ + status: String +) extends Tuple5[OrdersId, CustomersId, LocalDate, Option[BigDecimal], String] { + def id: OrdersId = orderId + + def toUnsavedRow(status: Defaulted[String] = Defaulted.Provided(this.status)): OrdersRowUnsaved = { + new OrdersRowUnsaved( + orderId, + customerId, + orderDate, + totalAmount, + status + ) + } + + override def `_1`: OrdersId = orderId + + override def `_2`: CustomersId = customerId + + override def `_3`: LocalDate = orderDate + + override def `_4`: Option[BigDecimal] = totalAmount + + override def `_5`: String = status +} + +object OrdersRow { + val rowCodec: RowCodec[OrdersRow] = RowCodecs.of(OrdersId.sqliteType, CustomersId.sqliteType, SqliteTypes.date, SqliteTypes.numeric.opt, SqliteTypes.text)(OrdersRow.apply)(row => Array[Any](row.orderId, row.customerId, row.orderDate, row.totalAmount, row.status)) +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/orders/OrdersRowUnsaved.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/orders/OrdersRowUnsaved.scala new file mode 100644 index 0000000000..24c88d3c09 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/orders/OrdersRowUnsaved.scala @@ -0,0 +1,33 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.orders + +import com.fasterxml.jackson.annotation.JsonProperty +import java.time.LocalDate +import testdb.customers.CustomersId +import testdb.customtypes.Defaulted +import testdb.customtypes.Defaulted.UseDefault + +/** This class corresponds to a row in table `orders` which has not been persisted yet */ +case class OrdersRowUnsaved( + @JsonProperty("order_id") orderId: OrdersId, + /** Points to [[testdb.customers.CustomersRow.customerId]] */ + @JsonProperty("customer_id") customerId: CustomersId, + @JsonProperty("order_date") orderDate: LocalDate, + @JsonProperty("total_amount") totalAmount: Option[BigDecimal] = None, + /** Default: 'pending' */ + status: Defaulted[String] = new UseDefault() +) { + def toRow(statusDefault: => String): OrdersRow = { + new OrdersRow( + orderId = orderId, + customerId = customerId, + orderDate = orderDate, + totalAmount = totalAmount, + status = status.getOrElse(statusDefault) + ) + } +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/precisetypes/Decimal10_2.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/precisetypes/Decimal10_2.scala new file mode 100644 index 0000000000..b3f1d14a59 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/precisetypes/Decimal10_2.scala @@ -0,0 +1,47 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precisetypes + +import com.fasterxml.jackson.annotation.JsonValue +import dev.typr.dslsc.Bijection +import dev.typr.foundations.data.precise.DecimalN +import dev.typr.foundationssc.SqliteType +import dev.typr.foundationssc.SqliteTypes +import java.lang.IllegalArgumentException + +case class Decimal10_2 private(@JsonValue value: BigDecimal) extends DecimalN { + override def decimalValue: java.math.BigDecimal = value.bigDecimal + + override def precision: Int = 10 + + override def scale: Int = 2 + + override def semanticEquals(other: DecimalN): Boolean = (if (other == null) false else decimalValue().compareTo(other.decimalValue()) == 0) + + override def semanticHashCode: Int = decimalValue().stripTrailingZeros().hashCode() + + override def equals(that: Any): Boolean = (this eq that.asInstanceOf[AnyRef]) || (that match { case other: DecimalN => decimalValue().compareTo(other.decimalValue()) == 0; case _ => false }) + + override def hashCode: Int = decimalValue().stripTrailingZeros().hashCode() +} + +object Decimal10_2 { + given Zero: Decimal10_2 = new Decimal10_2(BigDecimal(0)) + + given bijection: Bijection[Decimal10_2, BigDecimal] = Bijection.of[Decimal10_2, BigDecimal](_.value, Decimal10_2.apply) + + def of(value: BigDecimal): Option[Decimal10_2] = { val scaled = value.setScale(2, BigDecimal.RoundingMode.HALF_UP); if (scaled.precision <= 10) Some(new Decimal10_2(scaled)) else None } + + def of(value: Int): Decimal10_2 = new Decimal10_2(BigDecimal(value.toLong)) + + def of(value: Long): Option[Decimal10_2] = Decimal10_2.of(BigDecimal(value)) + + def of(value: Double): Option[Decimal10_2] = Decimal10_2.of(BigDecimal(value)) + + given sqliteType: SqliteType[Decimal10_2] = SqliteTypes.numeric.to(Bijection.of(Decimal10_2.apply, _.value)) + + def unsafeForce(value: BigDecimal): Decimal10_2 = { val scaled = value.setScale(2, BigDecimal.RoundingMode.HALF_UP); if (scaled.precision > 10) throw new IllegalArgumentException("Value exceeds precision(10, 2)"); new Decimal10_2(scaled) } +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/precisetypes/Decimal18_4.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/precisetypes/Decimal18_4.scala new file mode 100644 index 0000000000..9484a5a61b --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/precisetypes/Decimal18_4.scala @@ -0,0 +1,47 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precisetypes + +import com.fasterxml.jackson.annotation.JsonValue +import dev.typr.dslsc.Bijection +import dev.typr.foundations.data.precise.DecimalN +import dev.typr.foundationssc.SqliteType +import dev.typr.foundationssc.SqliteTypes +import java.lang.IllegalArgumentException + +case class Decimal18_4 private(@JsonValue value: BigDecimal) extends DecimalN { + override def decimalValue: java.math.BigDecimal = value.bigDecimal + + override def precision: Int = 18 + + override def scale: Int = 4 + + override def semanticEquals(other: DecimalN): Boolean = (if (other == null) false else decimalValue().compareTo(other.decimalValue()) == 0) + + override def semanticHashCode: Int = decimalValue().stripTrailingZeros().hashCode() + + override def equals(that: Any): Boolean = (this eq that.asInstanceOf[AnyRef]) || (that match { case other: DecimalN => decimalValue().compareTo(other.decimalValue()) == 0; case _ => false }) + + override def hashCode: Int = decimalValue().stripTrailingZeros().hashCode() +} + +object Decimal18_4 { + given Zero: Decimal18_4 = new Decimal18_4(BigDecimal(0)) + + given bijection: Bijection[Decimal18_4, BigDecimal] = Bijection.of[Decimal18_4, BigDecimal](_.value, Decimal18_4.apply) + + def of(value: BigDecimal): Option[Decimal18_4] = { val scaled = value.setScale(4, BigDecimal.RoundingMode.HALF_UP); if (scaled.precision <= 18) Some(new Decimal18_4(scaled)) else None } + + def of(value: Int): Decimal18_4 = new Decimal18_4(BigDecimal(value.toLong)) + + def of(value: Long): Option[Decimal18_4] = Decimal18_4.of(BigDecimal(value)) + + def of(value: Double): Option[Decimal18_4] = Decimal18_4.of(BigDecimal(value)) + + given sqliteType: SqliteType[Decimal18_4] = SqliteTypes.numeric.to(Bijection.of(Decimal18_4.apply, _.value)) + + def unsafeForce(value: BigDecimal): Decimal18_4 = { val scaled = value.setScale(4, BigDecimal.RoundingMode.HALF_UP); if (scaled.precision > 18) throw new IllegalArgumentException("Value exceeds precision(18, 4)"); new Decimal18_4(scaled) } +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/precisetypes/Decimal5_2.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/precisetypes/Decimal5_2.scala new file mode 100644 index 0000000000..8912752057 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/precisetypes/Decimal5_2.scala @@ -0,0 +1,47 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precisetypes + +import com.fasterxml.jackson.annotation.JsonValue +import dev.typr.dslsc.Bijection +import dev.typr.foundations.data.precise.DecimalN +import dev.typr.foundationssc.SqliteType +import dev.typr.foundationssc.SqliteTypes +import java.lang.IllegalArgumentException + +case class Decimal5_2 private(@JsonValue value: BigDecimal) extends DecimalN { + override def decimalValue: java.math.BigDecimal = value.bigDecimal + + override def precision: Int = 5 + + override def scale: Int = 2 + + override def semanticEquals(other: DecimalN): Boolean = (if (other == null) false else decimalValue().compareTo(other.decimalValue()) == 0) + + override def semanticHashCode: Int = decimalValue().stripTrailingZeros().hashCode() + + override def equals(that: Any): Boolean = (this eq that.asInstanceOf[AnyRef]) || (that match { case other: DecimalN => decimalValue().compareTo(other.decimalValue()) == 0; case _ => false }) + + override def hashCode: Int = decimalValue().stripTrailingZeros().hashCode() +} + +object Decimal5_2 { + given Zero: Decimal5_2 = new Decimal5_2(BigDecimal(0)) + + given bijection: Bijection[Decimal5_2, BigDecimal] = Bijection.of[Decimal5_2, BigDecimal](_.value, Decimal5_2.apply) + + def of(value: BigDecimal): Option[Decimal5_2] = { val scaled = value.setScale(2, BigDecimal.RoundingMode.HALF_UP); if (scaled.precision <= 5) Some(new Decimal5_2(scaled)) else None } + + def of(value: Int): Decimal5_2 = new Decimal5_2(BigDecimal(value.toLong)) + + def of(value: Long): Option[Decimal5_2] = Decimal5_2.of(BigDecimal(value)) + + def of(value: Double): Option[Decimal5_2] = Decimal5_2.of(BigDecimal(value)) + + given sqliteType: SqliteType[Decimal5_2] = SqliteTypes.numeric.to(Bijection.of(Decimal5_2.apply, _.value)) + + def unsafeForce(value: BigDecimal): Decimal5_2 = { val scaled = value.setScale(2, BigDecimal.RoundingMode.HALF_UP); if (scaled.precision > 5) throw new IllegalArgumentException("Value exceeds precision(5, 2)"); new Decimal5_2(scaled) } +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/precisetypes/Int10.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/precisetypes/Int10.scala new file mode 100644 index 0000000000..10203a50f6 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/precisetypes/Int10.scala @@ -0,0 +1,51 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precisetypes + +import com.fasterxml.jackson.annotation.JsonValue +import dev.typr.dslsc.Bijection +import dev.typr.foundations.data.precise.DecimalN +import dev.typr.foundationssc.SqliteType +import dev.typr.foundationssc.SqliteTypes +import java.lang.IllegalArgumentException +import scala.math.BigInt + +case class Int10 private(@JsonValue value: BigInt) extends DecimalN { + override def decimalValue: java.math.BigDecimal = new java.math.BigDecimal(value.bigInteger) + + override def precision: Int = 10 + + override def scale: Int = 0 + + override def semanticEquals(other: DecimalN): Boolean = (if (other == null) false else decimalValue().compareTo(other.decimalValue()) == 0) + + override def semanticHashCode: Int = decimalValue().stripTrailingZeros().hashCode() + + override def equals(that: Any): Boolean = (this eq that.asInstanceOf[AnyRef]) || (that match { case other: DecimalN => decimalValue().compareTo(other.decimalValue()) == 0; case _ => false }) + + override def hashCode: Int = decimalValue().stripTrailingZeros().hashCode() +} + +object Int10 { + given Zero: Int10 = new Int10(BigInt(0)) + + given bijection: Bijection[Int10, BigInt] = Bijection.of[Int10, BigInt](_.value, Int10.apply) + + def of(value: BigInt): Option[Int10] = (if (value.bitLength <= 40) Some(new Int10(value)) else None) + + def of(value: Int): Int10 = new Int10(BigInt(value.toLong)) + + def of(value: Long): Option[Int10] = Int10.of(BigInt(value)) + + given sqliteType: SqliteType[Int10] = SqliteTypes.numeric.to(Bijection.of(bd => new Int10(BigInt(bd.bigDecimal.toBigIntegerExact())), v => BigDecimal(new java.math.BigDecimal(v.value.bigInteger)))) + + def unsafeForce(value: BigInt): Int10 = { + if (value.bitLength > 40) { + throw new IllegalArgumentException("Value exceeds precision(10, 0)") + } + return new Int10(value) + } +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/precisetypes/Int18.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/precisetypes/Int18.scala new file mode 100644 index 0000000000..c66f5c840b --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/precisetypes/Int18.scala @@ -0,0 +1,51 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precisetypes + +import com.fasterxml.jackson.annotation.JsonValue +import dev.typr.dslsc.Bijection +import dev.typr.foundations.data.precise.DecimalN +import dev.typr.foundationssc.SqliteType +import dev.typr.foundationssc.SqliteTypes +import java.lang.IllegalArgumentException +import scala.math.BigInt + +case class Int18 private(@JsonValue value: BigInt) extends DecimalN { + override def decimalValue: java.math.BigDecimal = new java.math.BigDecimal(value.bigInteger) + + override def precision: Int = 18 + + override def scale: Int = 0 + + override def semanticEquals(other: DecimalN): Boolean = (if (other == null) false else decimalValue().compareTo(other.decimalValue()) == 0) + + override def semanticHashCode: Int = decimalValue().stripTrailingZeros().hashCode() + + override def equals(that: Any): Boolean = (this eq that.asInstanceOf[AnyRef]) || (that match { case other: DecimalN => decimalValue().compareTo(other.decimalValue()) == 0; case _ => false }) + + override def hashCode: Int = decimalValue().stripTrailingZeros().hashCode() +} + +object Int18 { + given Zero: Int18 = new Int18(BigInt(0)) + + given bijection: Bijection[Int18, BigInt] = Bijection.of[Int18, BigInt](_.value, Int18.apply) + + def of(value: BigInt): Option[Int18] = (if (value.bitLength <= 72) Some(new Int18(value)) else None) + + def of(value: Int): Int18 = new Int18(BigInt(value.toLong)) + + def of(value: Long): Option[Int18] = Int18.of(BigInt(value)) + + given sqliteType: SqliteType[Int18] = SqliteTypes.numeric.to(Bijection.of(bd => new Int18(BigInt(bd.bigDecimal.toBigIntegerExact())), v => BigDecimal(new java.math.BigDecimal(v.value.bigInteger)))) + + def unsafeForce(value: BigInt): Int18 = { + if (value.bitLength > 72) { + throw new IllegalArgumentException("Value exceeds precision(18, 0)") + } + return new Int18(value) + } +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/precisetypes/Int5.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/precisetypes/Int5.scala new file mode 100644 index 0000000000..b9ee3a98a5 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/precisetypes/Int5.scala @@ -0,0 +1,51 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precisetypes + +import com.fasterxml.jackson.annotation.JsonValue +import dev.typr.dslsc.Bijection +import dev.typr.foundations.data.precise.DecimalN +import dev.typr.foundationssc.SqliteType +import dev.typr.foundationssc.SqliteTypes +import java.lang.IllegalArgumentException +import scala.math.BigInt + +case class Int5 private(@JsonValue value: BigInt) extends DecimalN { + override def decimalValue: java.math.BigDecimal = new java.math.BigDecimal(value.bigInteger) + + override def precision: Int = 5 + + override def scale: Int = 0 + + override def semanticEquals(other: DecimalN): Boolean = (if (other == null) false else decimalValue().compareTo(other.decimalValue()) == 0) + + override def semanticHashCode: Int = decimalValue().stripTrailingZeros().hashCode() + + override def equals(that: Any): Boolean = (this eq that.asInstanceOf[AnyRef]) || (that match { case other: DecimalN => decimalValue().compareTo(other.decimalValue()) == 0; case _ => false }) + + override def hashCode: Int = decimalValue().stripTrailingZeros().hashCode() +} + +object Int5 { + given Zero: Int5 = new Int5(BigInt(0)) + + given bijection: Bijection[Int5, BigInt] = Bijection.of[Int5, BigInt](_.value, Int5.apply) + + def of(value: BigInt): Option[Int5] = (if (value.bitLength <= 20) Some(new Int5(value)) else None) + + def of(value: Int): Int5 = new Int5(BigInt(value.toLong)) + + def of(value: Long): Option[Int5] = Int5.of(BigInt(value)) + + given sqliteType: SqliteType[Int5] = SqliteTypes.numeric.to(Bijection.of(bd => new Int5(BigInt(bd.bigDecimal.toBigIntegerExact())), v => BigDecimal(new java.math.BigDecimal(v.value.bigInteger)))) + + def unsafeForce(value: BigInt): Int5 = { + if (value.bitLength > 20) { + throw new IllegalArgumentException("Value exceeds precision(5, 0)") + } + return new Int5(value) + } +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/precisetypes/String10.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/precisetypes/String10.scala new file mode 100644 index 0000000000..3b5c928c72 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/precisetypes/String10.scala @@ -0,0 +1,44 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precisetypes + +import com.fasterxml.jackson.annotation.JsonValue +import dev.typr.dslsc.Bijection +import dev.typr.foundations.data.precise.StringN +import dev.typr.foundationssc.SqliteType +import dev.typr.foundationssc.SqliteTypes +import java.lang.IllegalArgumentException + +case class String10 private(@JsonValue value: String) extends StringN { + override def rawValue: String = value + + override def maxLength: Int = 10 + + override def semanticEquals(other: StringN): Boolean = (if (other == null) false else (value == other.rawValue())) + + override def semanticHashCode: Int = value.hashCode() + + override def equals(that: Any): Boolean = (this eq that.asInstanceOf[AnyRef]) || (that match { case other: StringN => value == other.rawValue(); case _ => false }) + + override def hashCode: Int = value.hashCode() +} + +object String10 { + given bijection: Bijection[String10, String] = Bijection.of[String10, String](_.value, String10.apply) + + def of(value: String): Option[String10] = (if (value.length <= 10) Some(new String10(value)) else None) + + given sqliteType: SqliteType[String10] = SqliteTypes.varchar.to(Bijection.of(String10.apply, _.value)) + + def truncate(value: String): String10 = new String10((if (value.length <= 10) value else value.substring(0, 10))) + + def unsafeForce(value: String): String10 = { + if (value.length > 10) { + throw new IllegalArgumentException(s"Value length ${value.length} exceeds maximum 10") + } + return new String10(value) + } +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/precisetypes/String100.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/precisetypes/String100.scala new file mode 100644 index 0000000000..b9e97fe428 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/precisetypes/String100.scala @@ -0,0 +1,44 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precisetypes + +import com.fasterxml.jackson.annotation.JsonValue +import dev.typr.dslsc.Bijection +import dev.typr.foundations.data.precise.StringN +import dev.typr.foundationssc.SqliteType +import dev.typr.foundationssc.SqliteTypes +import java.lang.IllegalArgumentException + +case class String100 private(@JsonValue value: String) extends StringN { + override def rawValue: String = value + + override def maxLength: Int = 100 + + override def semanticEquals(other: StringN): Boolean = (if (other == null) false else (value == other.rawValue())) + + override def semanticHashCode: Int = value.hashCode() + + override def equals(that: Any): Boolean = (this eq that.asInstanceOf[AnyRef]) || (that match { case other: StringN => value == other.rawValue(); case _ => false }) + + override def hashCode: Int = value.hashCode() +} + +object String100 { + given bijection: Bijection[String100, String] = Bijection.of[String100, String](_.value, String100.apply) + + def of(value: String): Option[String100] = (if (value.length <= 100) Some(new String100(value)) else None) + + given sqliteType: SqliteType[String100] = SqliteTypes.varchar.to(Bijection.of(String100.apply, _.value)) + + def truncate(value: String): String100 = new String100((if (value.length <= 100) value else value.substring(0, 100))) + + def unsafeForce(value: String): String100 = { + if (value.length > 100) { + throw new IllegalArgumentException(s"Value length ${value.length} exceeds maximum 100") + } + return new String100(value) + } +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/precisetypes/String20.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/precisetypes/String20.scala new file mode 100644 index 0000000000..c26b08e17b --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/precisetypes/String20.scala @@ -0,0 +1,44 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precisetypes + +import com.fasterxml.jackson.annotation.JsonValue +import dev.typr.dslsc.Bijection +import dev.typr.foundations.data.precise.StringN +import dev.typr.foundationssc.SqliteType +import dev.typr.foundationssc.SqliteTypes +import java.lang.IllegalArgumentException + +case class String20 private(@JsonValue value: String) extends StringN { + override def rawValue: String = value + + override def maxLength: Int = 20 + + override def semanticEquals(other: StringN): Boolean = (if (other == null) false else (value == other.rawValue())) + + override def semanticHashCode: Int = value.hashCode() + + override def equals(that: Any): Boolean = (this eq that.asInstanceOf[AnyRef]) || (that match { case other: StringN => value == other.rawValue(); case _ => false }) + + override def hashCode: Int = value.hashCode() +} + +object String20 { + given bijection: Bijection[String20, String] = Bijection.of[String20, String](_.value, String20.apply) + + def of(value: String): Option[String20] = (if (value.length <= 20) Some(new String20(value)) else None) + + given sqliteType: SqliteType[String20] = SqliteTypes.varchar.to(Bijection.of(String20.apply, _.value)) + + def truncate(value: String): String20 = new String20((if (value.length <= 20) value else value.substring(0, 20))) + + def unsafeForce(value: String): String20 = { + if (value.length > 20) { + throw new IllegalArgumentException(s"Value length ${value.length} exceeds maximum 20") + } + return new String20(value) + } +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/precisetypes/String255.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/precisetypes/String255.scala new file mode 100644 index 0000000000..ceae630c52 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/precisetypes/String255.scala @@ -0,0 +1,44 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precisetypes + +import com.fasterxml.jackson.annotation.JsonValue +import dev.typr.dslsc.Bijection +import dev.typr.foundations.data.precise.StringN +import dev.typr.foundationssc.SqliteType +import dev.typr.foundationssc.SqliteTypes +import java.lang.IllegalArgumentException + +case class String255 private(@JsonValue value: String) extends StringN { + override def rawValue: String = value + + override def maxLength: Int = 255 + + override def semanticEquals(other: StringN): Boolean = (if (other == null) false else (value == other.rawValue())) + + override def semanticHashCode: Int = value.hashCode() + + override def equals(that: Any): Boolean = (this eq that.asInstanceOf[AnyRef]) || (that match { case other: StringN => value == other.rawValue(); case _ => false }) + + override def hashCode: Int = value.hashCode() +} + +object String255 { + given bijection: Bijection[String255, String] = Bijection.of[String255, String](_.value, String255.apply) + + def of(value: String): Option[String255] = (if (value.length <= 255) Some(new String255(value)) else None) + + given sqliteType: SqliteType[String255] = SqliteTypes.varchar.to(Bijection.of(String255.apply, _.value)) + + def truncate(value: String): String255 = new String255((if (value.length <= 255) value else value.substring(0, 255))) + + def unsafeForce(value: String): String255 = { + if (value.length > 255) { + throw new IllegalArgumentException(s"Value length ${value.length} exceeds maximum 255") + } + return new String255(value) + } +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/precisetypes/String50.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/precisetypes/String50.scala new file mode 100644 index 0000000000..9504e0764a --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/precisetypes/String50.scala @@ -0,0 +1,44 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precisetypes + +import com.fasterxml.jackson.annotation.JsonValue +import dev.typr.dslsc.Bijection +import dev.typr.foundations.data.precise.StringN +import dev.typr.foundationssc.SqliteType +import dev.typr.foundationssc.SqliteTypes +import java.lang.IllegalArgumentException + +case class String50 private(@JsonValue value: String) extends StringN { + override def rawValue: String = value + + override def maxLength: Int = 50 + + override def semanticEquals(other: StringN): Boolean = (if (other == null) false else (value == other.rawValue())) + + override def semanticHashCode: Int = value.hashCode() + + override def equals(that: Any): Boolean = (this eq that.asInstanceOf[AnyRef]) || (that match { case other: StringN => value == other.rawValue(); case _ => false }) + + override def hashCode: Int = value.hashCode() +} + +object String50 { + given bijection: Bijection[String50, String] = Bijection.of[String50, String](_.value, String50.apply) + + def of(value: String): Option[String50] = (if (value.length <= 50) Some(new String50(value)) else None) + + given sqliteType: SqliteType[String50] = SqliteTypes.varchar.to(Bijection.of(String50.apply, _.value)) + + def truncate(value: String): String50 = new String50((if (value.length <= 50) value else value.substring(0, 50))) + + def unsafeForce(value: String): String50 = { + if (value.length > 50) { + throw new IllegalArgumentException(s"Value length ${value.length} exceeds maximum 50") + } + return new String50(value) + } +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/precision_types/PrecisionTypesFields.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/precision_types/PrecisionTypesFields.scala new file mode 100644 index 0000000000..6524ef6136 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/precision_types/PrecisionTypesFields.scala @@ -0,0 +1,207 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precision_types + +import dev.typr.dsl.FieldsBase +import dev.typr.dsl.Path +import dev.typr.dsl.SqlExpr.FieldLike +import dev.typr.dslsc.RelationStructure +import dev.typr.dslsc.SqlExpr +import dev.typr.dslsc.SqlExpr.Field +import dev.typr.dslsc.SqlExpr.IdField +import dev.typr.dslsc.TupleExpr12 +import dev.typr.foundations.RowCodec +import testdb.precisetypes.Decimal10_2 +import testdb.precisetypes.Decimal18_4 +import testdb.precisetypes.Decimal5_2 +import testdb.precisetypes.Int10 +import testdb.precisetypes.Int18 +import testdb.precisetypes.Int5 +import testdb.precisetypes.String10 +import testdb.precisetypes.String100 +import testdb.precisetypes.String20 +import testdb.precisetypes.String255 +import testdb.precisetypes.String50 + +class PrecisionTypesFields(val `_path`: java.util.List[Path]) extends TupleExpr12[PrecisionTypesId, String10, String20, String50, String100, String255, Decimal5_2, Decimal10_2, Decimal18_4, Int5, Int10, Int18] with RelationStructure[PrecisionTypesFields, PrecisionTypesRow] with FieldsBase[PrecisionTypesRow] { + def id: IdField[PrecisionTypesId, PrecisionTypesRow] = { + new IdField[PrecisionTypesId, PrecisionTypesRow]( + _path, + "id", + _.id, + None, + None, + (row, value) => row.copy(id = value), + PrecisionTypesId.sqliteType.underlying + ) + } + + def string10: Field[String10, PrecisionTypesRow] = { + new Field[String10, PrecisionTypesRow]( + _path, + "string10", + _.string10, + None, + None, + (row, value) => row.copy(string10 = value), + String10.sqliteType.underlying + ) + } + + def string20: Field[String20, PrecisionTypesRow] = { + new Field[String20, PrecisionTypesRow]( + _path, + "string20", + _.string20, + None, + None, + (row, value) => row.copy(string20 = value), + String20.sqliteType.underlying + ) + } + + def string50: Field[String50, PrecisionTypesRow] = { + new Field[String50, PrecisionTypesRow]( + _path, + "string50", + _.string50, + None, + None, + (row, value) => row.copy(string50 = value), + String50.sqliteType.underlying + ) + } + + def string100: Field[String100, PrecisionTypesRow] = { + new Field[String100, PrecisionTypesRow]( + _path, + "string100", + _.string100, + None, + None, + (row, value) => row.copy(string100 = value), + String100.sqliteType.underlying + ) + } + + def string255: Field[String255, PrecisionTypesRow] = { + new Field[String255, PrecisionTypesRow]( + _path, + "string255", + _.string255, + None, + None, + (row, value) => row.copy(string255 = value), + String255.sqliteType.underlying + ) + } + + def decimal52: Field[Decimal5_2, PrecisionTypesRow] = { + new Field[Decimal5_2, PrecisionTypesRow]( + _path, + "decimal5_2", + _.decimal52, + None, + None, + (row, value) => row.copy(decimal52 = value), + Decimal5_2.sqliteType.underlying + ) + } + + def decimal102: Field[Decimal10_2, PrecisionTypesRow] = { + new Field[Decimal10_2, PrecisionTypesRow]( + _path, + "decimal10_2", + _.decimal102, + None, + None, + (row, value) => row.copy(decimal102 = value), + Decimal10_2.sqliteType.underlying + ) + } + + def decimal184: Field[Decimal18_4, PrecisionTypesRow] = { + new Field[Decimal18_4, PrecisionTypesRow]( + _path, + "decimal18_4", + _.decimal184, + None, + None, + (row, value) => row.copy(decimal184 = value), + Decimal18_4.sqliteType.underlying + ) + } + + def decimal50: Field[Int5, PrecisionTypesRow] = { + new Field[Int5, PrecisionTypesRow]( + _path, + "decimal5_0", + _.decimal50, + None, + None, + (row, value) => row.copy(decimal50 = value), + Int5.sqliteType.underlying + ) + } + + def decimal100: Field[Int10, PrecisionTypesRow] = { + new Field[Int10, PrecisionTypesRow]( + _path, + "decimal10_0", + _.decimal100, + None, + None, + (row, value) => row.copy(decimal100 = value), + Int10.sqliteType.underlying + ) + } + + def decimal180: Field[Int18, PrecisionTypesRow] = { + new Field[Int18, PrecisionTypesRow]( + _path, + "decimal18_0", + _.decimal180, + None, + None, + (row, value) => row.copy(decimal180 = value), + Int18.sqliteType.underlying + ) + } + + override def columns: java.util.List[FieldLike[?, PrecisionTypesRow]] = java.util.List.of(this.id.underlying, this.string10.underlying, this.string20.underlying, this.string50.underlying, this.string100.underlying, this.string255.underlying, this.decimal52.underlying, this.decimal102.underlying, this.decimal184.underlying, this.decimal50.underlying, this.decimal100.underlying, this.decimal180.underlying) + + override def rowCodec: RowCodec[PrecisionTypesRow] = PrecisionTypesRow.rowCodec.underlying + + override def withPaths(`_path`: java.util.List[Path]): RelationStructure[PrecisionTypesFields, PrecisionTypesRow] = new PrecisionTypesFields(`_path`) + + override def `_1`: SqlExpr[PrecisionTypesId] = id + + override def `_2`: SqlExpr[String10] = string10 + + override def `_3`: SqlExpr[String20] = string20 + + override def `_4`: SqlExpr[String50] = string50 + + override def `_5`: SqlExpr[String100] = string100 + + override def `_6`: SqlExpr[String255] = string255 + + override def `_7`: SqlExpr[Decimal5_2] = decimal52 + + override def `_8`: SqlExpr[Decimal10_2] = decimal102 + + override def `_9`: SqlExpr[Decimal18_4] = decimal184 + + override def `_10`: SqlExpr[Int5] = decimal50 + + override def `_11`: SqlExpr[Int10] = decimal100 + + override def `_12`: SqlExpr[Int18] = decimal180 +} + +object PrecisionTypesFields { + val structure: PrecisionTypesFields = new PrecisionTypesFields(java.util.Collections.emptyList()) +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/precision_types/PrecisionTypesId.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/precision_types/PrecisionTypesId.scala new file mode 100644 index 0000000000..76ce292547 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/precision_types/PrecisionTypesId.scala @@ -0,0 +1,20 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precision_types + +import com.fasterxml.jackson.annotation.JsonValue +import dev.typr.dslsc.Bijection +import dev.typr.foundationssc.SqliteType +import dev.typr.foundationssc.SqliteTypes + +/** Type for the primary key of table `precision_types` */ +case class PrecisionTypesId(@JsonValue value: Long) extends scala.AnyVal + +object PrecisionTypesId { + given bijection: Bijection[PrecisionTypesId, Long] = Bijection.of[PrecisionTypesId, Long](_.value, PrecisionTypesId.apply) + + given sqliteType: SqliteType[PrecisionTypesId] = SqliteTypes.integer.to(Bijection.of(PrecisionTypesId.apply, _.value)) +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/precision_types/PrecisionTypesRepo.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/precision_types/PrecisionTypesRepo.scala new file mode 100644 index 0000000000..7adc81745e --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/precision_types/PrecisionTypesRepo.scala @@ -0,0 +1,40 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precision_types + +import dev.typr.dslsc.DeleteBuilder +import dev.typr.dslsc.SelectBuilder +import dev.typr.dslsc.UpdateBuilder +import dev.typr.foundationssc.Connection +import dev.typr.foundationssc.ConnectionRead + +trait PrecisionTypesRepo { + def delete: DeleteBuilder[PrecisionTypesFields, PrecisionTypesRow] + + def deleteById(id: PrecisionTypesId)(using c: Connection): Boolean + + def deleteByIds(ids: List[PrecisionTypesId])(using c: Connection): Int + + def insert(unsaved: PrecisionTypesRow)(using c: Connection): PrecisionTypesRow + + def select: SelectBuilder[PrecisionTypesFields, PrecisionTypesRow] + + def selectAll(using c: ConnectionRead): List[PrecisionTypesRow] + + def selectById(id: PrecisionTypesId)(using c: ConnectionRead): Option[PrecisionTypesRow] + + def selectByIds(ids: List[PrecisionTypesId])(using c: ConnectionRead): List[PrecisionTypesRow] + + def selectByIdsTracked(ids: List[PrecisionTypesId])(using c: ConnectionRead): Map[PrecisionTypesId, PrecisionTypesRow] + + def update: UpdateBuilder[PrecisionTypesFields, PrecisionTypesRow] + + def update(row: PrecisionTypesRow)(using c: Connection): Boolean + + def upsert(unsaved: PrecisionTypesRow)(using c: Connection): PrecisionTypesRow + + def upsertBatch(unsaved: Iterator[PrecisionTypesRow])(using c: Connection): List[PrecisionTypesRow] +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/precision_types/PrecisionTypesRepoImpl.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/precision_types/PrecisionTypesRepoImpl.scala new file mode 100644 index 0000000000..f88e364cf8 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/precision_types/PrecisionTypesRepoImpl.scala @@ -0,0 +1,134 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precision_types + +import dev.typr.dslsc.DeleteBuilder +import dev.typr.dslsc.Dialect +import dev.typr.dslsc.SelectBuilder +import dev.typr.dslsc.UpdateBuilder +import dev.typr.foundationssc.Connection +import dev.typr.foundationssc.ConnectionRead +import dev.typr.foundationssc.Fragment +import scala.collection.mutable.ListBuffer +import testdb.precisetypes.Decimal10_2 +import testdb.precisetypes.Decimal18_4 +import testdb.precisetypes.Decimal5_2 +import testdb.precisetypes.Int10 +import testdb.precisetypes.Int18 +import testdb.precisetypes.Int5 +import testdb.precisetypes.String10 +import testdb.precisetypes.String100 +import testdb.precisetypes.String20 +import testdb.precisetypes.String255 +import testdb.precisetypes.String50 +import dev.typr.foundationssc.Fragment.sql + +class PrecisionTypesRepoImpl extends PrecisionTypesRepo { + override def delete: DeleteBuilder[PrecisionTypesFields, PrecisionTypesRow] = DeleteBuilder.of(""""precision_types"""", PrecisionTypesFields.structure, Dialect.SQLITE) + + override def deleteById(id: PrecisionTypesId)(using c: Connection): Boolean = sql"""delete from "precision_types" where "id" = ${Fragment.encode(PrecisionTypesId.sqliteType, id)}""".update().run(using c) > 0 + + override def deleteByIds(ids: List[PrecisionTypesId])(using c: Connection): Int = { + val fragments: ListBuffer[Fragment] = ListBuffer() + ids.foreach { id => fragments.addOne(Fragment.encode(PrecisionTypesId.sqliteType, id)): @scala.annotation.nowarn } + return Fragment.concat(Fragment.of("""delete from "precision_types" where "id" in ("""), Fragment.comma(fragments), Fragment.of(")")).update().run(using c) + } + + override def insert(unsaved: PrecisionTypesRow)(using c: Connection): PrecisionTypesRow = { + sql"""insert into "precision_types"("id", "string10", "string20", "string50", "string100", "string255", "decimal5_2", "decimal10_2", "decimal18_4", "decimal5_0", "decimal10_0", "decimal18_0") + values (${Fragment.encode(PrecisionTypesId.sqliteType, unsaved.id)}, ${Fragment.encode(String10.sqliteType, unsaved.string10)}, ${Fragment.encode(String20.sqliteType, unsaved.string20)}, ${Fragment.encode(String50.sqliteType, unsaved.string50)}, ${Fragment.encode(String100.sqliteType, unsaved.string100)}, ${Fragment.encode(String255.sqliteType, unsaved.string255)}, ${Fragment.encode(Decimal5_2.sqliteType, unsaved.decimal52)}, ${Fragment.encode(Decimal10_2.sqliteType, unsaved.decimal102)}, ${Fragment.encode(Decimal18_4.sqliteType, unsaved.decimal184)}, ${Fragment.encode(Int5.sqliteType, unsaved.decimal50)}, ${Fragment.encode(Int10.sqliteType, unsaved.decimal100)}, ${Fragment.encode(Int18.sqliteType, unsaved.decimal180)}) + RETURNING "id", "string10", "string20", "string50", "string100", "string255", "decimal5_2", "decimal10_2", "decimal18_4", "decimal5_0", "decimal10_0", "decimal18_0" + """ + .updateReturning(PrecisionTypesRow.rowCodec.exactlyOne()).run(using c) + } + + override def select: SelectBuilder[PrecisionTypesFields, PrecisionTypesRow] = SelectBuilder.of(""""precision_types"""", PrecisionTypesFields.structure, PrecisionTypesRow.rowCodec, Dialect.SQLITE) + + override def selectAll(using c: ConnectionRead): List[PrecisionTypesRow] = { + sql"""select "id", "string10", "string20", "string50", "string100", "string255", "decimal5_2", "decimal10_2", "decimal18_4", "decimal5_0", "decimal10_0", "decimal18_0" + from "precision_types" + """.query(PrecisionTypesRow.rowCodec.all()).run(using c) + } + + override def selectById(id: PrecisionTypesId)(using c: ConnectionRead): Option[PrecisionTypesRow] = { + sql"""select "id", "string10", "string20", "string50", "string100", "string255", "decimal5_2", "decimal10_2", "decimal18_4", "decimal5_0", "decimal10_0", "decimal18_0" + from "precision_types" + where "id" = ${Fragment.encode(PrecisionTypesId.sqliteType, id)}""".query(PrecisionTypesRow.rowCodec.first()).run(using c) + } + + override def selectByIds(ids: List[PrecisionTypesId])(using c: ConnectionRead): List[PrecisionTypesRow] = { + val fragments: ListBuffer[Fragment] = ListBuffer() + ids.foreach { id => fragments.addOne(Fragment.encode(PrecisionTypesId.sqliteType, id)): @scala.annotation.nowarn } + return Fragment.concat(Fragment.of("""select "id", "string10", "string20", "string50", "string100", "string255", "decimal5_2", "decimal10_2", "decimal18_4", "decimal5_0", "decimal10_0", "decimal18_0" from "precision_types" where "id" in ("""), Fragment.comma(fragments), Fragment.of(")")).query(PrecisionTypesRow.rowCodec.all()).run(using c) + } + + override def selectByIdsTracked(ids: List[PrecisionTypesId])(using c: ConnectionRead): Map[PrecisionTypesId, PrecisionTypesRow] = { + val ret: scala.collection.mutable.Map[PrecisionTypesId, PrecisionTypesRow] = scala.collection.mutable.Map.empty[PrecisionTypesId, PrecisionTypesRow] + selectByIds(ids)(using c).foreach(row => ret.put(row.id, row): @scala.annotation.nowarn) + return ret.toMap + } + + override def update: UpdateBuilder[PrecisionTypesFields, PrecisionTypesRow] = UpdateBuilder.of(""""precision_types"""", PrecisionTypesFields.structure, PrecisionTypesRow.rowCodec, Dialect.SQLITE) + + override def update(row: PrecisionTypesRow)(using c: Connection): Boolean = { + val id: PrecisionTypesId = row.id + return sql"""update "precision_types" + set "string10" = ${Fragment.encode(String10.sqliteType, row.string10)}, + "string20" = ${Fragment.encode(String20.sqliteType, row.string20)}, + "string50" = ${Fragment.encode(String50.sqliteType, row.string50)}, + "string100" = ${Fragment.encode(String100.sqliteType, row.string100)}, + "string255" = ${Fragment.encode(String255.sqliteType, row.string255)}, + "decimal5_2" = ${Fragment.encode(Decimal5_2.sqliteType, row.decimal52)}, + "decimal10_2" = ${Fragment.encode(Decimal10_2.sqliteType, row.decimal102)}, + "decimal18_4" = ${Fragment.encode(Decimal18_4.sqliteType, row.decimal184)}, + "decimal5_0" = ${Fragment.encode(Int5.sqliteType, row.decimal50)}, + "decimal10_0" = ${Fragment.encode(Int10.sqliteType, row.decimal100)}, + "decimal18_0" = ${Fragment.encode(Int18.sqliteType, row.decimal180)} + where "id" = ${Fragment.encode(PrecisionTypesId.sqliteType, id)}""".update().run(using c) > 0 + } + + override def upsert(unsaved: PrecisionTypesRow)(using c: Connection): PrecisionTypesRow = { + sql"""INSERT INTO "precision_types"("id", "string10", "string20", "string50", "string100", "string255", "decimal5_2", "decimal10_2", "decimal18_4", "decimal5_0", "decimal10_0", "decimal18_0") + VALUES (${Fragment.encode(PrecisionTypesId.sqliteType, unsaved.id)}, ${Fragment.encode(String10.sqliteType, unsaved.string10)}, ${Fragment.encode(String20.sqliteType, unsaved.string20)}, ${Fragment.encode(String50.sqliteType, unsaved.string50)}, ${Fragment.encode(String100.sqliteType, unsaved.string100)}, ${Fragment.encode(String255.sqliteType, unsaved.string255)}, ${Fragment.encode(Decimal5_2.sqliteType, unsaved.decimal52)}, ${Fragment.encode(Decimal10_2.sqliteType, unsaved.decimal102)}, ${Fragment.encode(Decimal18_4.sqliteType, unsaved.decimal184)}, ${Fragment.encode(Int5.sqliteType, unsaved.decimal50)}, ${Fragment.encode(Int10.sqliteType, unsaved.decimal100)}, ${Fragment.encode(Int18.sqliteType, unsaved.decimal180)}) + ON CONFLICT ("id") + DO UPDATE SET + "string10" = EXCLUDED."string10", + "string20" = EXCLUDED."string20", + "string50" = EXCLUDED."string50", + "string100" = EXCLUDED."string100", + "string255" = EXCLUDED."string255", + "decimal5_2" = EXCLUDED."decimal5_2", + "decimal10_2" = EXCLUDED."decimal10_2", + "decimal18_4" = EXCLUDED."decimal18_4", + "decimal5_0" = EXCLUDED."decimal5_0", + "decimal10_0" = EXCLUDED."decimal10_0", + "decimal18_0" = EXCLUDED."decimal18_0" + RETURNING "id", "string10", "string20", "string50", "string100", "string255", "decimal5_2", "decimal10_2", "decimal18_4", "decimal5_0", "decimal10_0", "decimal18_0"""" + .updateReturning(PrecisionTypesRow.rowCodec.exactlyOne()) + .run(using c) + } + + override def upsertBatch(unsaved: Iterator[PrecisionTypesRow])(using c: Connection): List[PrecisionTypesRow] = { + sql"""INSERT INTO "precision_types"("id", "string10", "string20", "string50", "string100", "string255", "decimal5_2", "decimal10_2", "decimal18_4", "decimal5_0", "decimal10_0", "decimal18_0") + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + ON CONFLICT ("id") + DO UPDATE SET + "string10" = EXCLUDED."string10", + "string20" = EXCLUDED."string20", + "string50" = EXCLUDED."string50", + "string100" = EXCLUDED."string100", + "string255" = EXCLUDED."string255", + "decimal5_2" = EXCLUDED."decimal5_2", + "decimal10_2" = EXCLUDED."decimal10_2", + "decimal18_4" = EXCLUDED."decimal18_4", + "decimal5_0" = EXCLUDED."decimal5_0", + "decimal10_0" = EXCLUDED."decimal10_0", + "decimal18_0" = EXCLUDED."decimal18_0" + RETURNING "id", "string10", "string20", "string50", "string100", "string255", "decimal5_2", "decimal10_2", "decimal18_4", "decimal5_0", "decimal10_0", "decimal18_0"""" + .updateReturningEach(PrecisionTypesRow.rowCodec, unsaved) + .run(using c) + } +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/precision_types/PrecisionTypesRepoMock.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/precision_types/PrecisionTypesRepoMock.scala new file mode 100644 index 0000000000..51e2432fbe --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/precision_types/PrecisionTypesRepoMock.scala @@ -0,0 +1,73 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precision_types + +import dev.typr.dslsc.DeleteBuilder +import dev.typr.dslsc.DeleteBuilderMock +import dev.typr.dslsc.DeleteParams +import dev.typr.dslsc.SelectBuilder +import dev.typr.dslsc.SelectBuilderMock +import dev.typr.dslsc.SelectParams +import dev.typr.dslsc.UpdateBuilder +import dev.typr.dslsc.UpdateBuilderMock +import dev.typr.dslsc.UpdateParams +import dev.typr.foundationssc.Connection +import dev.typr.foundationssc.ConnectionRead +import java.lang.RuntimeException + +case class PrecisionTypesRepoMock(map: scala.collection.mutable.Map[PrecisionTypesId, PrecisionTypesRow] = scala.collection.mutable.Map.empty[PrecisionTypesId, PrecisionTypesRow]) extends PrecisionTypesRepo { + override def delete: DeleteBuilder[PrecisionTypesFields, PrecisionTypesRow] = DeleteBuilderMock(PrecisionTypesFields.structure, () => map.values.toList, DeleteParams.empty(), row => row.id, id => map.remove(id): @scala.annotation.nowarn) + + override def deleteById(id: PrecisionTypesId)(using c: Connection): Boolean = map.remove(id).isDefined + + override def deleteByIds(ids: List[PrecisionTypesId])(using c: Connection): Int = { + var count = 0 + ids.foreach { id => if (map.remove(id).isDefined) { + count = count + 1 + } } + return count + } + + override def insert(unsaved: PrecisionTypesRow)(using c: Connection): PrecisionTypesRow = { + if (map.contains(unsaved.id)) { + throw new RuntimeException(s"id ${unsaved.id} already exists") + } + map.put(unsaved.id, unsaved): @scala.annotation.nowarn + return unsaved + } + + override def select: SelectBuilder[PrecisionTypesFields, PrecisionTypesRow] = SelectBuilderMock(PrecisionTypesFields.structure, () => map.values.toList, SelectParams.empty()) + + override def selectAll(using c: ConnectionRead): List[PrecisionTypesRow] = map.values.toList + + override def selectById(id: PrecisionTypesId)(using c: ConnectionRead): Option[PrecisionTypesRow] = map.get(id) + + override def selectByIds(ids: List[PrecisionTypesId])(using c: ConnectionRead): List[PrecisionTypesRow] = ids.flatMap(map.get(_)).toList + + override def selectByIdsTracked(ids: List[PrecisionTypesId])(using c: ConnectionRead): Map[PrecisionTypesId, PrecisionTypesRow] = selectByIds(ids)(using c).map(x => (((row: PrecisionTypesRow) => row.id).apply(x), x)).toMap + + override def update: UpdateBuilder[PrecisionTypesFields, PrecisionTypesRow] = UpdateBuilderMock(PrecisionTypesFields.structure, () => map.values.toList, UpdateParams.empty(), row => row) + + override def update(row: PrecisionTypesRow)(using c: Connection): Boolean = { + val shouldUpdate = map.get(row.id).filter(oldRow => (oldRow != row)).isDefined + if (shouldUpdate) { + map.put(row.id, row): @scala.annotation.nowarn + } + return shouldUpdate + } + + override def upsert(unsaved: PrecisionTypesRow)(using c: Connection): PrecisionTypesRow = { + map.put(unsaved.id, unsaved): @scala.annotation.nowarn + return unsaved + } + + override def upsertBatch(unsaved: Iterator[PrecisionTypesRow])(using c: Connection): List[PrecisionTypesRow] = { + unsaved.map { row => + map.put(row.id, row): @scala.annotation.nowarn + row + }.toList + } +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/precision_types/PrecisionTypesRow.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/precision_types/PrecisionTypesRow.scala new file mode 100644 index 0000000000..c13176bf8f --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/precision_types/PrecisionTypesRow.scala @@ -0,0 +1,68 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precision_types + +import com.fasterxml.jackson.annotation.JsonProperty +import dev.typr.dslsc.RowCodecs +import dev.typr.foundations.Tuple.Tuple12 +import dev.typr.foundationssc.RowCodec +import testdb.precisetypes.Decimal10_2 +import testdb.precisetypes.Decimal18_4 +import testdb.precisetypes.Decimal5_2 +import testdb.precisetypes.Int10 +import testdb.precisetypes.Int18 +import testdb.precisetypes.Int5 +import testdb.precisetypes.String10 +import testdb.precisetypes.String100 +import testdb.precisetypes.String20 +import testdb.precisetypes.String255 +import testdb.precisetypes.String50 + +/** Table: precision_types + * Primary key: id + */ +case class PrecisionTypesRow( + id: PrecisionTypesId, + string10: String10, + string20: String20, + string50: String50, + string100: String100, + string255: String255, + @JsonProperty("decimal5_2") decimal52: Decimal5_2, + @JsonProperty("decimal10_2") decimal102: Decimal10_2, + @JsonProperty("decimal18_4") decimal184: Decimal18_4, + @JsonProperty("decimal5_0") decimal50: Int5, + @JsonProperty("decimal10_0") decimal100: Int10, + @JsonProperty("decimal18_0") decimal180: Int18 +) extends Tuple12[PrecisionTypesId, String10, String20, String50, String100, String255, Decimal5_2, Decimal10_2, Decimal18_4, Int5, Int10, Int18] { + override def `_1`: PrecisionTypesId = id + + override def `_2`: String10 = string10 + + override def `_3`: String20 = string20 + + override def `_4`: String50 = string50 + + override def `_5`: String100 = string100 + + override def `_6`: String255 = string255 + + override def `_7`: Decimal5_2 = decimal52 + + override def `_8`: Decimal10_2 = decimal102 + + override def `_9`: Decimal18_4 = decimal184 + + override def `_10`: Int5 = decimal50 + + override def `_11`: Int10 = decimal100 + + override def `_12`: Int18 = decimal180 +} + +object PrecisionTypesRow { + val rowCodec: RowCodec[PrecisionTypesRow] = RowCodecs.of(PrecisionTypesId.sqliteType, String10.sqliteType, String20.sqliteType, String50.sqliteType, String100.sqliteType, String255.sqliteType, Decimal5_2.sqliteType, Decimal10_2.sqliteType, Decimal18_4.sqliteType, Int5.sqliteType, Int10.sqliteType, Int18.sqliteType)(PrecisionTypesRow.apply)(row => Array[Any](row.id, row.string10, row.string20, row.string50, row.string100, row.string255, row.decimal52, row.decimal102, row.decimal184, row.decimal50, row.decimal100, row.decimal180)) +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/precision_types_null/PrecisionTypesNullFields.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/precision_types_null/PrecisionTypesNullFields.scala new file mode 100644 index 0000000000..1cfa8bc963 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/precision_types_null/PrecisionTypesNullFields.scala @@ -0,0 +1,207 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precision_types_null + +import dev.typr.dsl.FieldsBase +import dev.typr.dsl.Path +import dev.typr.dsl.SqlExpr.FieldLike +import dev.typr.dslsc.RelationStructure +import dev.typr.dslsc.SqlExpr +import dev.typr.dslsc.SqlExpr.IdField +import dev.typr.dslsc.SqlExpr.OptField +import dev.typr.dslsc.TupleExpr12 +import dev.typr.foundations.RowCodec +import testdb.precisetypes.Decimal10_2 +import testdb.precisetypes.Decimal18_4 +import testdb.precisetypes.Decimal5_2 +import testdb.precisetypes.Int10 +import testdb.precisetypes.Int18 +import testdb.precisetypes.Int5 +import testdb.precisetypes.String10 +import testdb.precisetypes.String100 +import testdb.precisetypes.String20 +import testdb.precisetypes.String255 +import testdb.precisetypes.String50 + +class PrecisionTypesNullFields(val `_path`: java.util.List[Path]) extends TupleExpr12[PrecisionTypesNullId, String10, String20, String50, String100, String255, Decimal5_2, Decimal10_2, Decimal18_4, Int5, Int10, Int18] with RelationStructure[PrecisionTypesNullFields, PrecisionTypesNullRow] with FieldsBase[PrecisionTypesNullRow] { + def id: IdField[PrecisionTypesNullId, PrecisionTypesNullRow] = { + new IdField[PrecisionTypesNullId, PrecisionTypesNullRow]( + _path, + "id", + _.id, + None, + None, + (row, value) => row.copy(id = value), + PrecisionTypesNullId.sqliteType.underlying + ) + } + + def string10: OptField[String10, PrecisionTypesNullRow] = { + new OptField[String10, PrecisionTypesNullRow]( + _path, + "string10", + _.string10, + None, + None, + (row, value) => row.copy(string10 = value), + String10.sqliteType.underlying + ) + } + + def string20: OptField[String20, PrecisionTypesNullRow] = { + new OptField[String20, PrecisionTypesNullRow]( + _path, + "string20", + _.string20, + None, + None, + (row, value) => row.copy(string20 = value), + String20.sqliteType.underlying + ) + } + + def string50: OptField[String50, PrecisionTypesNullRow] = { + new OptField[String50, PrecisionTypesNullRow]( + _path, + "string50", + _.string50, + None, + None, + (row, value) => row.copy(string50 = value), + String50.sqliteType.underlying + ) + } + + def string100: OptField[String100, PrecisionTypesNullRow] = { + new OptField[String100, PrecisionTypesNullRow]( + _path, + "string100", + _.string100, + None, + None, + (row, value) => row.copy(string100 = value), + String100.sqliteType.underlying + ) + } + + def string255: OptField[String255, PrecisionTypesNullRow] = { + new OptField[String255, PrecisionTypesNullRow]( + _path, + "string255", + _.string255, + None, + None, + (row, value) => row.copy(string255 = value), + String255.sqliteType.underlying + ) + } + + def decimal52: OptField[Decimal5_2, PrecisionTypesNullRow] = { + new OptField[Decimal5_2, PrecisionTypesNullRow]( + _path, + "decimal5_2", + _.decimal52, + None, + None, + (row, value) => row.copy(decimal52 = value), + Decimal5_2.sqliteType.underlying + ) + } + + def decimal102: OptField[Decimal10_2, PrecisionTypesNullRow] = { + new OptField[Decimal10_2, PrecisionTypesNullRow]( + _path, + "decimal10_2", + _.decimal102, + None, + None, + (row, value) => row.copy(decimal102 = value), + Decimal10_2.sqliteType.underlying + ) + } + + def decimal184: OptField[Decimal18_4, PrecisionTypesNullRow] = { + new OptField[Decimal18_4, PrecisionTypesNullRow]( + _path, + "decimal18_4", + _.decimal184, + None, + None, + (row, value) => row.copy(decimal184 = value), + Decimal18_4.sqliteType.underlying + ) + } + + def decimal50: OptField[Int5, PrecisionTypesNullRow] = { + new OptField[Int5, PrecisionTypesNullRow]( + _path, + "decimal5_0", + _.decimal50, + None, + None, + (row, value) => row.copy(decimal50 = value), + Int5.sqliteType.underlying + ) + } + + def decimal100: OptField[Int10, PrecisionTypesNullRow] = { + new OptField[Int10, PrecisionTypesNullRow]( + _path, + "decimal10_0", + _.decimal100, + None, + None, + (row, value) => row.copy(decimal100 = value), + Int10.sqliteType.underlying + ) + } + + def decimal180: OptField[Int18, PrecisionTypesNullRow] = { + new OptField[Int18, PrecisionTypesNullRow]( + _path, + "decimal18_0", + _.decimal180, + None, + None, + (row, value) => row.copy(decimal180 = value), + Int18.sqliteType.underlying + ) + } + + override def columns: java.util.List[FieldLike[?, PrecisionTypesNullRow]] = java.util.List.of(this.id.underlying, this.string10.underlying, this.string20.underlying, this.string50.underlying, this.string100.underlying, this.string255.underlying, this.decimal52.underlying, this.decimal102.underlying, this.decimal184.underlying, this.decimal50.underlying, this.decimal100.underlying, this.decimal180.underlying) + + override def rowCodec: RowCodec[PrecisionTypesNullRow] = PrecisionTypesNullRow.rowCodec.underlying + + override def withPaths(`_path`: java.util.List[Path]): RelationStructure[PrecisionTypesNullFields, PrecisionTypesNullRow] = new PrecisionTypesNullFields(`_path`) + + override def `_1`: SqlExpr[PrecisionTypesNullId] = id + + override def `_2`: SqlExpr[String10] = string10 + + override def `_3`: SqlExpr[String20] = string20 + + override def `_4`: SqlExpr[String50] = string50 + + override def `_5`: SqlExpr[String100] = string100 + + override def `_6`: SqlExpr[String255] = string255 + + override def `_7`: SqlExpr[Decimal5_2] = decimal52 + + override def `_8`: SqlExpr[Decimal10_2] = decimal102 + + override def `_9`: SqlExpr[Decimal18_4] = decimal184 + + override def `_10`: SqlExpr[Int5] = decimal50 + + override def `_11`: SqlExpr[Int10] = decimal100 + + override def `_12`: SqlExpr[Int18] = decimal180 +} + +object PrecisionTypesNullFields { + val structure: PrecisionTypesNullFields = new PrecisionTypesNullFields(java.util.Collections.emptyList()) +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/precision_types_null/PrecisionTypesNullId.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/precision_types_null/PrecisionTypesNullId.scala new file mode 100644 index 0000000000..c8a69912ad --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/precision_types_null/PrecisionTypesNullId.scala @@ -0,0 +1,20 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precision_types_null + +import com.fasterxml.jackson.annotation.JsonValue +import dev.typr.dslsc.Bijection +import dev.typr.foundationssc.SqliteType +import dev.typr.foundationssc.SqliteTypes + +/** Type for the primary key of table `precision_types_null` */ +case class PrecisionTypesNullId(@JsonValue value: Long) extends scala.AnyVal + +object PrecisionTypesNullId { + given bijection: Bijection[PrecisionTypesNullId, Long] = Bijection.of[PrecisionTypesNullId, Long](_.value, PrecisionTypesNullId.apply) + + given sqliteType: SqliteType[PrecisionTypesNullId] = SqliteTypes.integer.to(Bijection.of(PrecisionTypesNullId.apply, _.value)) +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/precision_types_null/PrecisionTypesNullRepo.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/precision_types_null/PrecisionTypesNullRepo.scala new file mode 100644 index 0000000000..1b6f160b4e --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/precision_types_null/PrecisionTypesNullRepo.scala @@ -0,0 +1,40 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precision_types_null + +import dev.typr.dslsc.DeleteBuilder +import dev.typr.dslsc.SelectBuilder +import dev.typr.dslsc.UpdateBuilder +import dev.typr.foundationssc.Connection +import dev.typr.foundationssc.ConnectionRead + +trait PrecisionTypesNullRepo { + def delete: DeleteBuilder[PrecisionTypesNullFields, PrecisionTypesNullRow] + + def deleteById(id: PrecisionTypesNullId)(using c: Connection): Boolean + + def deleteByIds(ids: List[PrecisionTypesNullId])(using c: Connection): Int + + def insert(unsaved: PrecisionTypesNullRow)(using c: Connection): PrecisionTypesNullRow + + def select: SelectBuilder[PrecisionTypesNullFields, PrecisionTypesNullRow] + + def selectAll(using c: ConnectionRead): List[PrecisionTypesNullRow] + + def selectById(id: PrecisionTypesNullId)(using c: ConnectionRead): Option[PrecisionTypesNullRow] + + def selectByIds(ids: List[PrecisionTypesNullId])(using c: ConnectionRead): List[PrecisionTypesNullRow] + + def selectByIdsTracked(ids: List[PrecisionTypesNullId])(using c: ConnectionRead): Map[PrecisionTypesNullId, PrecisionTypesNullRow] + + def update: UpdateBuilder[PrecisionTypesNullFields, PrecisionTypesNullRow] + + def update(row: PrecisionTypesNullRow)(using c: Connection): Boolean + + def upsert(unsaved: PrecisionTypesNullRow)(using c: Connection): PrecisionTypesNullRow + + def upsertBatch(unsaved: Iterator[PrecisionTypesNullRow])(using c: Connection): List[PrecisionTypesNullRow] +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/precision_types_null/PrecisionTypesNullRepoImpl.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/precision_types_null/PrecisionTypesNullRepoImpl.scala new file mode 100644 index 0000000000..02abcfdbeb --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/precision_types_null/PrecisionTypesNullRepoImpl.scala @@ -0,0 +1,134 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precision_types_null + +import dev.typr.dslsc.DeleteBuilder +import dev.typr.dslsc.Dialect +import dev.typr.dslsc.SelectBuilder +import dev.typr.dslsc.UpdateBuilder +import dev.typr.foundationssc.Connection +import dev.typr.foundationssc.ConnectionRead +import dev.typr.foundationssc.Fragment +import scala.collection.mutable.ListBuffer +import testdb.precisetypes.Decimal10_2 +import testdb.precisetypes.Decimal18_4 +import testdb.precisetypes.Decimal5_2 +import testdb.precisetypes.Int10 +import testdb.precisetypes.Int18 +import testdb.precisetypes.Int5 +import testdb.precisetypes.String10 +import testdb.precisetypes.String100 +import testdb.precisetypes.String20 +import testdb.precisetypes.String255 +import testdb.precisetypes.String50 +import dev.typr.foundationssc.Fragment.sql + +class PrecisionTypesNullRepoImpl extends PrecisionTypesNullRepo { + override def delete: DeleteBuilder[PrecisionTypesNullFields, PrecisionTypesNullRow] = DeleteBuilder.of(""""precision_types_null"""", PrecisionTypesNullFields.structure, Dialect.SQLITE) + + override def deleteById(id: PrecisionTypesNullId)(using c: Connection): Boolean = sql"""delete from "precision_types_null" where "id" = ${Fragment.encode(PrecisionTypesNullId.sqliteType, id)}""".update().run(using c) > 0 + + override def deleteByIds(ids: List[PrecisionTypesNullId])(using c: Connection): Int = { + val fragments: ListBuffer[Fragment] = ListBuffer() + ids.foreach { id => fragments.addOne(Fragment.encode(PrecisionTypesNullId.sqliteType, id)): @scala.annotation.nowarn } + return Fragment.concat(Fragment.of("""delete from "precision_types_null" where "id" in ("""), Fragment.comma(fragments), Fragment.of(")")).update().run(using c) + } + + override def insert(unsaved: PrecisionTypesNullRow)(using c: Connection): PrecisionTypesNullRow = { + sql"""insert into "precision_types_null"("id", "string10", "string20", "string50", "string100", "string255", "decimal5_2", "decimal10_2", "decimal18_4", "decimal5_0", "decimal10_0", "decimal18_0") + values (${Fragment.encode(PrecisionTypesNullId.sqliteType, unsaved.id)}, ${Fragment.encode(String10.sqliteType.opt, unsaved.string10)}, ${Fragment.encode(String20.sqliteType.opt, unsaved.string20)}, ${Fragment.encode(String50.sqliteType.opt, unsaved.string50)}, ${Fragment.encode(String100.sqliteType.opt, unsaved.string100)}, ${Fragment.encode(String255.sqliteType.opt, unsaved.string255)}, ${Fragment.encode(Decimal5_2.sqliteType.opt, unsaved.decimal52)}, ${Fragment.encode(Decimal10_2.sqliteType.opt, unsaved.decimal102)}, ${Fragment.encode(Decimal18_4.sqliteType.opt, unsaved.decimal184)}, ${Fragment.encode(Int5.sqliteType.opt, unsaved.decimal50)}, ${Fragment.encode(Int10.sqliteType.opt, unsaved.decimal100)}, ${Fragment.encode(Int18.sqliteType.opt, unsaved.decimal180)}) + RETURNING "id", "string10", "string20", "string50", "string100", "string255", "decimal5_2", "decimal10_2", "decimal18_4", "decimal5_0", "decimal10_0", "decimal18_0" + """ + .updateReturning(PrecisionTypesNullRow.rowCodec.exactlyOne()).run(using c) + } + + override def select: SelectBuilder[PrecisionTypesNullFields, PrecisionTypesNullRow] = SelectBuilder.of(""""precision_types_null"""", PrecisionTypesNullFields.structure, PrecisionTypesNullRow.rowCodec, Dialect.SQLITE) + + override def selectAll(using c: ConnectionRead): List[PrecisionTypesNullRow] = { + sql"""select "id", "string10", "string20", "string50", "string100", "string255", "decimal5_2", "decimal10_2", "decimal18_4", "decimal5_0", "decimal10_0", "decimal18_0" + from "precision_types_null" + """.query(PrecisionTypesNullRow.rowCodec.all()).run(using c) + } + + override def selectById(id: PrecisionTypesNullId)(using c: ConnectionRead): Option[PrecisionTypesNullRow] = { + sql"""select "id", "string10", "string20", "string50", "string100", "string255", "decimal5_2", "decimal10_2", "decimal18_4", "decimal5_0", "decimal10_0", "decimal18_0" + from "precision_types_null" + where "id" = ${Fragment.encode(PrecisionTypesNullId.sqliteType, id)}""".query(PrecisionTypesNullRow.rowCodec.first()).run(using c) + } + + override def selectByIds(ids: List[PrecisionTypesNullId])(using c: ConnectionRead): List[PrecisionTypesNullRow] = { + val fragments: ListBuffer[Fragment] = ListBuffer() + ids.foreach { id => fragments.addOne(Fragment.encode(PrecisionTypesNullId.sqliteType, id)): @scala.annotation.nowarn } + return Fragment.concat(Fragment.of("""select "id", "string10", "string20", "string50", "string100", "string255", "decimal5_2", "decimal10_2", "decimal18_4", "decimal5_0", "decimal10_0", "decimal18_0" from "precision_types_null" where "id" in ("""), Fragment.comma(fragments), Fragment.of(")")).query(PrecisionTypesNullRow.rowCodec.all()).run(using c) + } + + override def selectByIdsTracked(ids: List[PrecisionTypesNullId])(using c: ConnectionRead): Map[PrecisionTypesNullId, PrecisionTypesNullRow] = { + val ret: scala.collection.mutable.Map[PrecisionTypesNullId, PrecisionTypesNullRow] = scala.collection.mutable.Map.empty[PrecisionTypesNullId, PrecisionTypesNullRow] + selectByIds(ids)(using c).foreach(row => ret.put(row.id, row): @scala.annotation.nowarn) + return ret.toMap + } + + override def update: UpdateBuilder[PrecisionTypesNullFields, PrecisionTypesNullRow] = UpdateBuilder.of(""""precision_types_null"""", PrecisionTypesNullFields.structure, PrecisionTypesNullRow.rowCodec, Dialect.SQLITE) + + override def update(row: PrecisionTypesNullRow)(using c: Connection): Boolean = { + val id: PrecisionTypesNullId = row.id + return sql"""update "precision_types_null" + set "string10" = ${Fragment.encode(String10.sqliteType.opt, row.string10)}, + "string20" = ${Fragment.encode(String20.sqliteType.opt, row.string20)}, + "string50" = ${Fragment.encode(String50.sqliteType.opt, row.string50)}, + "string100" = ${Fragment.encode(String100.sqliteType.opt, row.string100)}, + "string255" = ${Fragment.encode(String255.sqliteType.opt, row.string255)}, + "decimal5_2" = ${Fragment.encode(Decimal5_2.sqliteType.opt, row.decimal52)}, + "decimal10_2" = ${Fragment.encode(Decimal10_2.sqliteType.opt, row.decimal102)}, + "decimal18_4" = ${Fragment.encode(Decimal18_4.sqliteType.opt, row.decimal184)}, + "decimal5_0" = ${Fragment.encode(Int5.sqliteType.opt, row.decimal50)}, + "decimal10_0" = ${Fragment.encode(Int10.sqliteType.opt, row.decimal100)}, + "decimal18_0" = ${Fragment.encode(Int18.sqliteType.opt, row.decimal180)} + where "id" = ${Fragment.encode(PrecisionTypesNullId.sqliteType, id)}""".update().run(using c) > 0 + } + + override def upsert(unsaved: PrecisionTypesNullRow)(using c: Connection): PrecisionTypesNullRow = { + sql"""INSERT INTO "precision_types_null"("id", "string10", "string20", "string50", "string100", "string255", "decimal5_2", "decimal10_2", "decimal18_4", "decimal5_0", "decimal10_0", "decimal18_0") + VALUES (${Fragment.encode(PrecisionTypesNullId.sqliteType, unsaved.id)}, ${Fragment.encode(String10.sqliteType.opt, unsaved.string10)}, ${Fragment.encode(String20.sqliteType.opt, unsaved.string20)}, ${Fragment.encode(String50.sqliteType.opt, unsaved.string50)}, ${Fragment.encode(String100.sqliteType.opt, unsaved.string100)}, ${Fragment.encode(String255.sqliteType.opt, unsaved.string255)}, ${Fragment.encode(Decimal5_2.sqliteType.opt, unsaved.decimal52)}, ${Fragment.encode(Decimal10_2.sqliteType.opt, unsaved.decimal102)}, ${Fragment.encode(Decimal18_4.sqliteType.opt, unsaved.decimal184)}, ${Fragment.encode(Int5.sqliteType.opt, unsaved.decimal50)}, ${Fragment.encode(Int10.sqliteType.opt, unsaved.decimal100)}, ${Fragment.encode(Int18.sqliteType.opt, unsaved.decimal180)}) + ON CONFLICT ("id") + DO UPDATE SET + "string10" = EXCLUDED."string10", + "string20" = EXCLUDED."string20", + "string50" = EXCLUDED."string50", + "string100" = EXCLUDED."string100", + "string255" = EXCLUDED."string255", + "decimal5_2" = EXCLUDED."decimal5_2", + "decimal10_2" = EXCLUDED."decimal10_2", + "decimal18_4" = EXCLUDED."decimal18_4", + "decimal5_0" = EXCLUDED."decimal5_0", + "decimal10_0" = EXCLUDED."decimal10_0", + "decimal18_0" = EXCLUDED."decimal18_0" + RETURNING "id", "string10", "string20", "string50", "string100", "string255", "decimal5_2", "decimal10_2", "decimal18_4", "decimal5_0", "decimal10_0", "decimal18_0"""" + .updateReturning(PrecisionTypesNullRow.rowCodec.exactlyOne()) + .run(using c) + } + + override def upsertBatch(unsaved: Iterator[PrecisionTypesNullRow])(using c: Connection): List[PrecisionTypesNullRow] = { + sql"""INSERT INTO "precision_types_null"("id", "string10", "string20", "string50", "string100", "string255", "decimal5_2", "decimal10_2", "decimal18_4", "decimal5_0", "decimal10_0", "decimal18_0") + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + ON CONFLICT ("id") + DO UPDATE SET + "string10" = EXCLUDED."string10", + "string20" = EXCLUDED."string20", + "string50" = EXCLUDED."string50", + "string100" = EXCLUDED."string100", + "string255" = EXCLUDED."string255", + "decimal5_2" = EXCLUDED."decimal5_2", + "decimal10_2" = EXCLUDED."decimal10_2", + "decimal18_4" = EXCLUDED."decimal18_4", + "decimal5_0" = EXCLUDED."decimal5_0", + "decimal10_0" = EXCLUDED."decimal10_0", + "decimal18_0" = EXCLUDED."decimal18_0" + RETURNING "id", "string10", "string20", "string50", "string100", "string255", "decimal5_2", "decimal10_2", "decimal18_4", "decimal5_0", "decimal10_0", "decimal18_0"""" + .updateReturningEach(PrecisionTypesNullRow.rowCodec, unsaved) + .run(using c) + } +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/precision_types_null/PrecisionTypesNullRepoMock.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/precision_types_null/PrecisionTypesNullRepoMock.scala new file mode 100644 index 0000000000..789de46c03 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/precision_types_null/PrecisionTypesNullRepoMock.scala @@ -0,0 +1,73 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precision_types_null + +import dev.typr.dslsc.DeleteBuilder +import dev.typr.dslsc.DeleteBuilderMock +import dev.typr.dslsc.DeleteParams +import dev.typr.dslsc.SelectBuilder +import dev.typr.dslsc.SelectBuilderMock +import dev.typr.dslsc.SelectParams +import dev.typr.dslsc.UpdateBuilder +import dev.typr.dslsc.UpdateBuilderMock +import dev.typr.dslsc.UpdateParams +import dev.typr.foundationssc.Connection +import dev.typr.foundationssc.ConnectionRead +import java.lang.RuntimeException + +case class PrecisionTypesNullRepoMock(map: scala.collection.mutable.Map[PrecisionTypesNullId, PrecisionTypesNullRow] = scala.collection.mutable.Map.empty[PrecisionTypesNullId, PrecisionTypesNullRow]) extends PrecisionTypesNullRepo { + override def delete: DeleteBuilder[PrecisionTypesNullFields, PrecisionTypesNullRow] = DeleteBuilderMock(PrecisionTypesNullFields.structure, () => map.values.toList, DeleteParams.empty(), row => row.id, id => map.remove(id): @scala.annotation.nowarn) + + override def deleteById(id: PrecisionTypesNullId)(using c: Connection): Boolean = map.remove(id).isDefined + + override def deleteByIds(ids: List[PrecisionTypesNullId])(using c: Connection): Int = { + var count = 0 + ids.foreach { id => if (map.remove(id).isDefined) { + count = count + 1 + } } + return count + } + + override def insert(unsaved: PrecisionTypesNullRow)(using c: Connection): PrecisionTypesNullRow = { + if (map.contains(unsaved.id)) { + throw new RuntimeException(s"id ${unsaved.id} already exists") + } + map.put(unsaved.id, unsaved): @scala.annotation.nowarn + return unsaved + } + + override def select: SelectBuilder[PrecisionTypesNullFields, PrecisionTypesNullRow] = SelectBuilderMock(PrecisionTypesNullFields.structure, () => map.values.toList, SelectParams.empty()) + + override def selectAll(using c: ConnectionRead): List[PrecisionTypesNullRow] = map.values.toList + + override def selectById(id: PrecisionTypesNullId)(using c: ConnectionRead): Option[PrecisionTypesNullRow] = map.get(id) + + override def selectByIds(ids: List[PrecisionTypesNullId])(using c: ConnectionRead): List[PrecisionTypesNullRow] = ids.flatMap(map.get(_)).toList + + override def selectByIdsTracked(ids: List[PrecisionTypesNullId])(using c: ConnectionRead): Map[PrecisionTypesNullId, PrecisionTypesNullRow] = selectByIds(ids)(using c).map(x => (((row: PrecisionTypesNullRow) => row.id).apply(x), x)).toMap + + override def update: UpdateBuilder[PrecisionTypesNullFields, PrecisionTypesNullRow] = UpdateBuilderMock(PrecisionTypesNullFields.structure, () => map.values.toList, UpdateParams.empty(), row => row) + + override def update(row: PrecisionTypesNullRow)(using c: Connection): Boolean = { + val shouldUpdate = map.get(row.id).filter(oldRow => (oldRow != row)).isDefined + if (shouldUpdate) { + map.put(row.id, row): @scala.annotation.nowarn + } + return shouldUpdate + } + + override def upsert(unsaved: PrecisionTypesNullRow)(using c: Connection): PrecisionTypesNullRow = { + map.put(unsaved.id, unsaved): @scala.annotation.nowarn + return unsaved + } + + override def upsertBatch(unsaved: Iterator[PrecisionTypesNullRow])(using c: Connection): List[PrecisionTypesNullRow] = { + unsaved.map { row => + map.put(row.id, row): @scala.annotation.nowarn + row + }.toList + } +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/precision_types_null/PrecisionTypesNullRow.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/precision_types_null/PrecisionTypesNullRow.scala new file mode 100644 index 0000000000..ab5bbb4add --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/precision_types_null/PrecisionTypesNullRow.scala @@ -0,0 +1,68 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.precision_types_null + +import com.fasterxml.jackson.annotation.JsonProperty +import dev.typr.dslsc.RowCodecs +import dev.typr.foundations.Tuple.Tuple12 +import dev.typr.foundationssc.RowCodec +import testdb.precisetypes.Decimal10_2 +import testdb.precisetypes.Decimal18_4 +import testdb.precisetypes.Decimal5_2 +import testdb.precisetypes.Int10 +import testdb.precisetypes.Int18 +import testdb.precisetypes.Int5 +import testdb.precisetypes.String10 +import testdb.precisetypes.String100 +import testdb.precisetypes.String20 +import testdb.precisetypes.String255 +import testdb.precisetypes.String50 + +/** Table: precision_types_null + * Primary key: id + */ +case class PrecisionTypesNullRow( + id: PrecisionTypesNullId, + string10: Option[String10], + string20: Option[String20], + string50: Option[String50], + string100: Option[String100], + string255: Option[String255], + @JsonProperty("decimal5_2") decimal52: Option[Decimal5_2], + @JsonProperty("decimal10_2") decimal102: Option[Decimal10_2], + @JsonProperty("decimal18_4") decimal184: Option[Decimal18_4], + @JsonProperty("decimal5_0") decimal50: Option[Int5], + @JsonProperty("decimal10_0") decimal100: Option[Int10], + @JsonProperty("decimal18_0") decimal180: Option[Int18] +) extends Tuple12[PrecisionTypesNullId, Option[String10], Option[String20], Option[String50], Option[String100], Option[String255], Option[Decimal5_2], Option[Decimal10_2], Option[Decimal18_4], Option[Int5], Option[Int10], Option[Int18]] { + override def `_1`: PrecisionTypesNullId = id + + override def `_2`: Option[String10] = string10 + + override def `_3`: Option[String20] = string20 + + override def `_4`: Option[String50] = string50 + + override def `_5`: Option[String100] = string100 + + override def `_6`: Option[String255] = string255 + + override def `_7`: Option[Decimal5_2] = decimal52 + + override def `_8`: Option[Decimal10_2] = decimal102 + + override def `_9`: Option[Decimal18_4] = decimal184 + + override def `_10`: Option[Int5] = decimal50 + + override def `_11`: Option[Int10] = decimal100 + + override def `_12`: Option[Int18] = decimal180 +} + +object PrecisionTypesNullRow { + val rowCodec: RowCodec[PrecisionTypesNullRow] = RowCodecs.of(PrecisionTypesNullId.sqliteType, String10.sqliteType.opt, String20.sqliteType.opt, String50.sqliteType.opt, String100.sqliteType.opt, String255.sqliteType.opt, Decimal5_2.sqliteType.opt, Decimal10_2.sqliteType.opt, Decimal18_4.sqliteType.opt, Int5.sqliteType.opt, Int10.sqliteType.opt, Int18.sqliteType.opt)(PrecisionTypesNullRow.apply)(row => Array[Any](row.id, row.string10, row.string20, row.string50, row.string100, row.string255, row.decimal52, row.decimal102, row.decimal184, row.decimal50, row.decimal100, row.decimal180)) +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/product_details_with_sales/ProductDetailsWithSalesSqlRepo.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/product_details_with_sales/ProductDetailsWithSalesSqlRepo.scala new file mode 100644 index 0000000000..1659e5cd78 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/product_details_with_sales/ProductDetailsWithSalesSqlRepo.scala @@ -0,0 +1,12 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.product_details_with_sales + +import dev.typr.foundationssc.ConnectionRead + +trait ProductDetailsWithSalesSqlRepo { + def apply(minPrice: Option[BigDecimal])(using c: ConnectionRead): List[ProductDetailsWithSalesSqlRow] +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/product_details_with_sales/ProductDetailsWithSalesSqlRepoImpl.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/product_details_with_sales/ProductDetailsWithSalesSqlRepoImpl.scala new file mode 100644 index 0000000000..da5d3ba3a6 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/product_details_with_sales/ProductDetailsWithSalesSqlRepoImpl.scala @@ -0,0 +1,31 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.product_details_with_sales + +import dev.typr.foundationssc.ConnectionRead +import dev.typr.foundationssc.Fragment +import dev.typr.foundationssc.SqliteTypes +import dev.typr.foundationssc.Fragment.sql + +class ProductDetailsWithSalesSqlRepoImpl extends ProductDetailsWithSalesSqlRepo { + override def apply(minPrice: Option[BigDecimal])(using c: ConnectionRead): List[ProductDetailsWithSalesSqlRow] = { + sql"""-- Product details enriched with cumulative sales numbers. + -- Tests: subquery in SELECT, joining on FK, ordering by computed column. + + SELECT + p.product_id, + p.sku, + p.name AS product_name, + p.price, + COALESCE(SUM(oi.quantity), 0) AS total_units_sold, + COALESCE(SUM(oi.quantity * oi.unit_price), 0) AS total_revenue + FROM products p + LEFT JOIN order_items oi ON p.product_id = oi.product_id + WHERE (${Fragment.encode(SqliteTypes.numeric.opt, minPrice)} IS NULL OR p.price >= ${Fragment.encode(SqliteTypes.numeric.opt, minPrice)}) + GROUP BY p.product_id, p.sku, p.name, p.price + ORDER BY total_revenue DESC, p.product_id""".query(ProductDetailsWithSalesSqlRow.rowCodec.all()).run(using c) + } +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/product_details_with_sales/ProductDetailsWithSalesSqlRow.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/product_details_with_sales/ProductDetailsWithSalesSqlRow.scala new file mode 100644 index 0000000000..7d46ed8199 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/product_details_with_sales/ProductDetailsWithSalesSqlRow.scala @@ -0,0 +1,45 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.product_details_with_sales + +import com.fasterxml.jackson.annotation.JsonProperty +import dev.typr.dslsc.RowCodecs +import dev.typr.foundations.Tuple.Tuple6 +import dev.typr.foundationssc.RowCodec +import dev.typr.foundationssc.SqliteTypes +import testdb.products.ProductsId + +/** SQL file: product_details_with_sales.sql */ +case class ProductDetailsWithSalesSqlRow( + /** Points to [[testdb.products.ProductsRow.productId]] */ + @JsonProperty("product_id") productId: ProductsId, + /** Points to [[testdb.products.ProductsRow.sku]] */ + sku: String, + /** Points to [[testdb.products.ProductsRow.name]] */ + @JsonProperty("product_name") productName: String, + /** Points to [[testdb.products.ProductsRow.price]] */ + price: BigDecimal, + /** Points to [[testdb.order_items.OrderItemsRow.quantity]] */ + @JsonProperty("total_units_sold") totalUnitsSold: Option[Long], + /** Points to [[testdb.order_items.OrderItemsRow.unitPrice]] */ + @JsonProperty("total_revenue") totalRevenue: Option[BigDecimal] +) extends Tuple6[ProductsId, String, String, BigDecimal, Option[Long], Option[BigDecimal]] { + override def `_1`: ProductsId = productId + + override def `_2`: String = sku + + override def `_3`: String = productName + + override def `_4`: BigDecimal = price + + override def `_5`: Option[Long] = totalUnitsSold + + override def `_6`: Option[BigDecimal] = totalRevenue +} + +object ProductDetailsWithSalesSqlRow { + val rowCodec: RowCodec[ProductDetailsWithSalesSqlRow] = RowCodecs.of(ProductsId.sqliteType, SqliteTypes.varchar, SqliteTypes.text, SqliteTypes.numeric, SqliteTypes.bigint.opt, SqliteTypes.numeric.opt)(ProductDetailsWithSalesSqlRow.apply)(row => Array[Any](row.productId, row.sku, row.productName, row.price, row.totalUnitsSold, row.totalRevenue)) +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/products/ProductsFields.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/products/ProductsFields.scala new file mode 100644 index 0000000000..c4336bc2f0 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/products/ProductsFields.scala @@ -0,0 +1,101 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.products + +import dev.typr.dsl.FieldsBase +import dev.typr.dsl.Path +import dev.typr.dsl.SqlExpr.FieldLike +import dev.typr.dslsc.RelationStructure +import dev.typr.dslsc.SqlExpr +import dev.typr.dslsc.SqlExpr.Field +import dev.typr.dslsc.SqlExpr.IdField +import dev.typr.dslsc.SqlExpr.OptField +import dev.typr.dslsc.TupleExpr5 +import dev.typr.foundations.RowCodec +import dev.typr.foundations.data.Json +import dev.typr.foundationssc.SqliteTypes + +class ProductsFields(val `_path`: java.util.List[Path]) extends TupleExpr5[ProductsId, String, String, BigDecimal, Json] with RelationStructure[ProductsFields, ProductsRow] with FieldsBase[ProductsRow] { + def productId: IdField[ProductsId, ProductsRow] = { + new IdField[ProductsId, ProductsRow]( + _path, + "product_id", + _.productId, + None, + None, + (row, value) => row.copy(productId = value), + ProductsId.sqliteType.underlying + ) + } + + def sku: Field[String, ProductsRow] = { + new Field[String, ProductsRow]( + _path, + "sku", + _.sku, + None, + None, + (row, value) => row.copy(sku = value), + SqliteTypes.varchar.underlying + ) + } + + def name: Field[String, ProductsRow] = { + new Field[String, ProductsRow]( + _path, + "name", + _.name, + None, + None, + (row, value) => row.copy(name = value), + SqliteTypes.text.underlying + ) + } + + def price: Field[BigDecimal, ProductsRow] = { + new Field[BigDecimal, ProductsRow]( + _path, + "price", + _.price, + None, + None, + (row, value) => row.copy(price = value), + SqliteTypes.numeric.underlying + ) + } + + def metadata: OptField[Json, ProductsRow] = { + new OptField[Json, ProductsRow]( + _path, + "metadata", + _.metadata, + None, + None, + (row, value) => row.copy(metadata = value), + SqliteTypes.json.underlying + ) + } + + override def columns: java.util.List[FieldLike[?, ProductsRow]] = java.util.List.of(this.productId.underlying, this.sku.underlying, this.name.underlying, this.price.underlying, this.metadata.underlying) + + override def rowCodec: RowCodec[ProductsRow] = ProductsRow.rowCodec.underlying + + override def withPaths(`_path`: java.util.List[Path]): RelationStructure[ProductsFields, ProductsRow] = new ProductsFields(`_path`) + + override def `_1`: SqlExpr[ProductsId] = productId + + override def `_2`: SqlExpr[String] = sku + + override def `_3`: SqlExpr[String] = name + + override def `_4`: SqlExpr[BigDecimal] = price + + override def `_5`: SqlExpr[Json] = metadata +} + +object ProductsFields { + val structure: ProductsFields = new ProductsFields(java.util.Collections.emptyList()) +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/products/ProductsId.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/products/ProductsId.scala new file mode 100644 index 0000000000..a2febd5ac2 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/products/ProductsId.scala @@ -0,0 +1,20 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.products + +import com.fasterxml.jackson.annotation.JsonValue +import dev.typr.dslsc.Bijection +import dev.typr.foundationssc.SqliteType +import dev.typr.foundationssc.SqliteTypes + +/** Type for the primary key of table `products` */ +case class ProductsId(@JsonValue value: Long) extends scala.AnyVal + +object ProductsId { + given bijection: Bijection[ProductsId, Long] = Bijection.of[ProductsId, Long](_.value, ProductsId.apply) + + given sqliteType: SqliteType[ProductsId] = SqliteTypes.integer.to(Bijection.of(ProductsId.apply, _.value)) +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/products/ProductsRepo.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/products/ProductsRepo.scala new file mode 100644 index 0000000000..40544b1fe7 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/products/ProductsRepo.scala @@ -0,0 +1,42 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.products + +import dev.typr.dslsc.DeleteBuilder +import dev.typr.dslsc.SelectBuilder +import dev.typr.dslsc.UpdateBuilder +import dev.typr.foundationssc.Connection +import dev.typr.foundationssc.ConnectionRead + +trait ProductsRepo { + def delete: DeleteBuilder[ProductsFields, ProductsRow] + + def deleteById(productId: ProductsId)(using c: Connection): Boolean + + def deleteByIds(productIds: List[ProductsId])(using c: Connection): Int + + def insert(unsaved: ProductsRow)(using c: Connection): ProductsRow + + def select: SelectBuilder[ProductsFields, ProductsRow] + + def selectAll(using c: ConnectionRead): List[ProductsRow] + + def selectById(productId: ProductsId)(using c: ConnectionRead): Option[ProductsRow] + + def selectByIds(productIds: List[ProductsId])(using c: ConnectionRead): List[ProductsRow] + + def selectByIdsTracked(productIds: List[ProductsId])(using c: ConnectionRead): Map[ProductsId, ProductsRow] + + def selectByUniqueSku(sku: String)(using c: ConnectionRead): Option[ProductsRow] + + def update: UpdateBuilder[ProductsFields, ProductsRow] + + def update(row: ProductsRow)(using c: Connection): Boolean + + def upsert(unsaved: ProductsRow)(using c: Connection): ProductsRow + + def upsertBatch(unsaved: Iterator[ProductsRow])(using c: Connection): List[ProductsRow] +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/products/ProductsRepoImpl.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/products/ProductsRepoImpl.scala new file mode 100644 index 0000000000..b5b9a29539 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/products/ProductsRepoImpl.scala @@ -0,0 +1,110 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.products + +import dev.typr.dslsc.DeleteBuilder +import dev.typr.dslsc.Dialect +import dev.typr.dslsc.SelectBuilder +import dev.typr.dslsc.UpdateBuilder +import dev.typr.foundationssc.Connection +import dev.typr.foundationssc.ConnectionRead +import dev.typr.foundationssc.Fragment +import dev.typr.foundationssc.SqliteTypes +import scala.collection.mutable.ListBuffer +import dev.typr.foundationssc.Fragment.sql + +class ProductsRepoImpl extends ProductsRepo { + override def delete: DeleteBuilder[ProductsFields, ProductsRow] = DeleteBuilder.of(""""products"""", ProductsFields.structure, Dialect.SQLITE) + + override def deleteById(productId: ProductsId)(using c: Connection): Boolean = sql"""delete from "products" where "product_id" = ${Fragment.encode(ProductsId.sqliteType, productId)}""".update().run(using c) > 0 + + override def deleteByIds(productIds: List[ProductsId])(using c: Connection): Int = { + val fragments: ListBuffer[Fragment] = ListBuffer() + productIds.foreach { id => fragments.addOne(Fragment.encode(ProductsId.sqliteType, id)): @scala.annotation.nowarn } + return Fragment.concat(Fragment.of("""delete from "products" where "product_id" in ("""), Fragment.comma(fragments), Fragment.of(")")).update().run(using c) + } + + override def insert(unsaved: ProductsRow)(using c: Connection): ProductsRow = { + sql"""insert into "products"("product_id", "sku", "name", "price", "metadata") + values (${Fragment.encode(ProductsId.sqliteType, unsaved.productId)}, ${Fragment.encode(SqliteTypes.varchar, unsaved.sku)}, ${Fragment.encode(SqliteTypes.text, unsaved.name)}, ${Fragment.encode(SqliteTypes.numeric, unsaved.price)}, ${Fragment.encode(SqliteTypes.json.opt, unsaved.metadata)}) + RETURNING "product_id", "sku", "name", "price", "metadata" + """ + .updateReturning(ProductsRow.rowCodec.exactlyOne()).run(using c) + } + + override def select: SelectBuilder[ProductsFields, ProductsRow] = SelectBuilder.of(""""products"""", ProductsFields.structure, ProductsRow.rowCodec, Dialect.SQLITE) + + override def selectAll(using c: ConnectionRead): List[ProductsRow] = { + sql"""select "product_id", "sku", "name", "price", "metadata" + from "products" + """.query(ProductsRow.rowCodec.all()).run(using c) + } + + override def selectById(productId: ProductsId)(using c: ConnectionRead): Option[ProductsRow] = { + sql"""select "product_id", "sku", "name", "price", "metadata" + from "products" + where "product_id" = ${Fragment.encode(ProductsId.sqliteType, productId)}""".query(ProductsRow.rowCodec.first()).run(using c) + } + + override def selectByIds(productIds: List[ProductsId])(using c: ConnectionRead): List[ProductsRow] = { + val fragments: ListBuffer[Fragment] = ListBuffer() + productIds.foreach { id => fragments.addOne(Fragment.encode(ProductsId.sqliteType, id)): @scala.annotation.nowarn } + return Fragment.concat(Fragment.of("""select "product_id", "sku", "name", "price", "metadata" from "products" where "product_id" in ("""), Fragment.comma(fragments), Fragment.of(")")).query(ProductsRow.rowCodec.all()).run(using c) + } + + override def selectByIdsTracked(productIds: List[ProductsId])(using c: ConnectionRead): Map[ProductsId, ProductsRow] = { + val ret: scala.collection.mutable.Map[ProductsId, ProductsRow] = scala.collection.mutable.Map.empty[ProductsId, ProductsRow] + selectByIds(productIds)(using c).foreach(row => ret.put(row.productId, row): @scala.annotation.nowarn) + return ret.toMap + } + + override def selectByUniqueSku(sku: String)(using c: ConnectionRead): Option[ProductsRow] = { + sql"""select "product_id", "sku", "name", "price", "metadata" + from "products" + where "sku" = ${Fragment.encode(SqliteTypes.varchar, sku)} + """.query(ProductsRow.rowCodec.first()).run(using c) + } + + override def update: UpdateBuilder[ProductsFields, ProductsRow] = UpdateBuilder.of(""""products"""", ProductsFields.structure, ProductsRow.rowCodec, Dialect.SQLITE) + + override def update(row: ProductsRow)(using c: Connection): Boolean = { + val productId: ProductsId = row.productId + return sql"""update "products" + set "sku" = ${Fragment.encode(SqliteTypes.varchar, row.sku)}, + "name" = ${Fragment.encode(SqliteTypes.text, row.name)}, + "price" = ${Fragment.encode(SqliteTypes.numeric, row.price)}, + "metadata" = ${Fragment.encode(SqliteTypes.json.opt, row.metadata)} + where "product_id" = ${Fragment.encode(ProductsId.sqliteType, productId)}""".update().run(using c) > 0 + } + + override def upsert(unsaved: ProductsRow)(using c: Connection): ProductsRow = { + sql"""INSERT INTO "products"("product_id", "sku", "name", "price", "metadata") + VALUES (${Fragment.encode(ProductsId.sqliteType, unsaved.productId)}, ${Fragment.encode(SqliteTypes.varchar, unsaved.sku)}, ${Fragment.encode(SqliteTypes.text, unsaved.name)}, ${Fragment.encode(SqliteTypes.numeric, unsaved.price)}, ${Fragment.encode(SqliteTypes.json.opt, unsaved.metadata)}) + ON CONFLICT ("product_id") + DO UPDATE SET + "sku" = EXCLUDED."sku", + "name" = EXCLUDED."name", + "price" = EXCLUDED."price", + "metadata" = EXCLUDED."metadata" + RETURNING "product_id", "sku", "name", "price", "metadata"""" + .updateReturning(ProductsRow.rowCodec.exactlyOne()) + .run(using c) + } + + override def upsertBatch(unsaved: Iterator[ProductsRow])(using c: Connection): List[ProductsRow] = { + sql"""INSERT INTO "products"("product_id", "sku", "name", "price", "metadata") + VALUES (?, ?, ?, ?, ?) + ON CONFLICT ("product_id") + DO UPDATE SET + "sku" = EXCLUDED."sku", + "name" = EXCLUDED."name", + "price" = EXCLUDED."price", + "metadata" = EXCLUDED."metadata" + RETURNING "product_id", "sku", "name", "price", "metadata"""" + .updateReturningEach(ProductsRow.rowCodec, unsaved) + .run(using c) + } +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/products/ProductsRepoMock.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/products/ProductsRepoMock.scala new file mode 100644 index 0000000000..72194e513e --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/products/ProductsRepoMock.scala @@ -0,0 +1,75 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.products + +import dev.typr.dslsc.DeleteBuilder +import dev.typr.dslsc.DeleteBuilderMock +import dev.typr.dslsc.DeleteParams +import dev.typr.dslsc.SelectBuilder +import dev.typr.dslsc.SelectBuilderMock +import dev.typr.dslsc.SelectParams +import dev.typr.dslsc.UpdateBuilder +import dev.typr.dslsc.UpdateBuilderMock +import dev.typr.dslsc.UpdateParams +import dev.typr.foundationssc.Connection +import dev.typr.foundationssc.ConnectionRead +import java.lang.RuntimeException + +case class ProductsRepoMock(map: scala.collection.mutable.Map[ProductsId, ProductsRow] = scala.collection.mutable.Map.empty[ProductsId, ProductsRow]) extends ProductsRepo { + override def delete: DeleteBuilder[ProductsFields, ProductsRow] = DeleteBuilderMock(ProductsFields.structure, () => map.values.toList, DeleteParams.empty(), row => row.productId, id => map.remove(id): @scala.annotation.nowarn) + + override def deleteById(productId: ProductsId)(using c: Connection): Boolean = map.remove(productId).isDefined + + override def deleteByIds(productIds: List[ProductsId])(using c: Connection): Int = { + var count = 0 + productIds.foreach { id => if (map.remove(id).isDefined) { + count = count + 1 + } } + return count + } + + override def insert(unsaved: ProductsRow)(using c: Connection): ProductsRow = { + if (map.contains(unsaved.productId)) { + throw new RuntimeException(s"id ${unsaved.productId} already exists") + } + map.put(unsaved.productId, unsaved): @scala.annotation.nowarn + return unsaved + } + + override def select: SelectBuilder[ProductsFields, ProductsRow] = SelectBuilderMock(ProductsFields.structure, () => map.values.toList, SelectParams.empty()) + + override def selectAll(using c: ConnectionRead): List[ProductsRow] = map.values.toList + + override def selectById(productId: ProductsId)(using c: ConnectionRead): Option[ProductsRow] = map.get(productId) + + override def selectByIds(productIds: List[ProductsId])(using c: ConnectionRead): List[ProductsRow] = productIds.flatMap(map.get(_)).toList + + override def selectByIdsTracked(productIds: List[ProductsId])(using c: ConnectionRead): Map[ProductsId, ProductsRow] = selectByIds(productIds)(using c).map(x => (((row: ProductsRow) => row.productId).apply(x), x)).toMap + + override def selectByUniqueSku(sku: String)(using c: ConnectionRead): Option[ProductsRow] = map.values.toList.find(v => (sku == v.sku)) + + override def update: UpdateBuilder[ProductsFields, ProductsRow] = UpdateBuilderMock(ProductsFields.structure, () => map.values.toList, UpdateParams.empty(), row => row) + + override def update(row: ProductsRow)(using c: Connection): Boolean = { + val shouldUpdate = map.get(row.productId).filter(oldRow => (oldRow != row)).isDefined + if (shouldUpdate) { + map.put(row.productId, row): @scala.annotation.nowarn + } + return shouldUpdate + } + + override def upsert(unsaved: ProductsRow)(using c: Connection): ProductsRow = { + map.put(unsaved.productId, unsaved): @scala.annotation.nowarn + return unsaved + } + + override def upsertBatch(unsaved: Iterator[ProductsRow])(using c: Connection): List[ProductsRow] = { + unsaved.map { row => + map.put(row.productId, row): @scala.annotation.nowarn + row + }.toList + } +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/products/ProductsRow.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/products/ProductsRow.scala new file mode 100644 index 0000000000..0684071ce9 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/products/ProductsRow.scala @@ -0,0 +1,40 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.products + +import com.fasterxml.jackson.annotation.JsonProperty +import dev.typr.dslsc.RowCodecs +import dev.typr.foundations.Tuple.Tuple5 +import dev.typr.foundations.data.Json +import dev.typr.foundationssc.RowCodec +import dev.typr.foundationssc.SqliteTypes + +/** Table: products + * Primary key: product_id + */ +case class ProductsRow( + @JsonProperty("product_id") productId: ProductsId, + sku: String, + name: String, + price: BigDecimal, + metadata: Option[Json] +) extends Tuple5[ProductsId, String, String, BigDecimal, Option[Json]] { + def id: ProductsId = productId + + override def `_1`: ProductsId = productId + + override def `_2`: String = sku + + override def `_3`: String = name + + override def `_4`: BigDecimal = price + + override def `_5`: Option[Json] = metadata +} + +object ProductsRow { + val rowCodec: RowCodec[ProductsRow] = RowCodecs.of(ProductsId.sqliteType, SqliteTypes.varchar, SqliteTypes.text, SqliteTypes.numeric, SqliteTypes.json.opt)(ProductsRow.apply)(row => Array[Any](row.productId, row.sku, row.name, row.price, row.metadata)) +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/userdefined/Email.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/userdefined/Email.scala new file mode 100644 index 0000000000..12449b9cf7 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/userdefined/Email.scala @@ -0,0 +1,22 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.userdefined + +import com.fasterxml.jackson.annotation.JsonValue +import dev.typr.dslsc.Bijection +import dev.typr.foundationssc.SqliteType +import dev.typr.foundationssc.SqliteTypes + +/** Shared type `Email` + * Generated from TypeDefinitions matching + */ +case class Email(@JsonValue value: String) extends scala.AnyVal + +object Email { + given bijection: Bijection[Email, String] = Bijection.of[Email, String](_.value, Email.apply) + + given sqliteType: SqliteType[Email] = SqliteTypes.varchar.to(Bijection.of(Email.apply, _.value)) +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/users/UsersFields.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/users/UsersFields.scala new file mode 100644 index 0000000000..ff29a8cef0 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/users/UsersFields.scala @@ -0,0 +1,72 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.users + +import dev.typr.dsl.FieldsBase +import dev.typr.dsl.Path +import dev.typr.dsl.SqlExpr.FieldLike +import dev.typr.dslsc.RelationStructure +import dev.typr.dslsc.SqlExpr +import dev.typr.dslsc.SqlExpr.Field +import dev.typr.dslsc.SqlExpr.IdField +import dev.typr.dslsc.TupleExpr3 +import dev.typr.foundations.RowCodec +import dev.typr.foundationssc.SqliteTypes +import testdb.userdefined.Email + +class UsersFields(val `_path`: java.util.List[Path]) extends TupleExpr3[UsersId, String, /* user-picked */ Email] with RelationStructure[UsersFields, UsersRow] with FieldsBase[UsersRow] { + def userId: IdField[UsersId, UsersRow] = { + new IdField[UsersId, UsersRow]( + _path, + "user_id", + _.userId, + None, + None, + (row, value) => row.copy(userId = value), + UsersId.sqliteType.underlying + ) + } + + def username: Field[String, UsersRow] = { + new Field[String, UsersRow]( + _path, + "username", + _.username, + None, + None, + (row, value) => row.copy(username = value), + SqliteTypes.varchar.underlying + ) + } + + def email: Field[/* user-picked */ Email, UsersRow] = { + new Field[/* user-picked */ Email, UsersRow]( + _path, + "email", + _.email, + None, + None, + (row, value) => row.copy(email = value), + Email.sqliteType.underlying + ) + } + + override def columns: java.util.List[FieldLike[?, UsersRow]] = java.util.List.of(this.userId.underlying, this.username.underlying, this.email.underlying) + + override def rowCodec: RowCodec[UsersRow] = UsersRow.rowCodec.underlying + + override def withPaths(`_path`: java.util.List[Path]): RelationStructure[UsersFields, UsersRow] = new UsersFields(`_path`) + + override def `_1`: SqlExpr[UsersId] = userId + + override def `_2`: SqlExpr[String] = username + + override def `_3`: SqlExpr[/* user-picked */ Email] = email +} + +object UsersFields { + val structure: UsersFields = new UsersFields(java.util.Collections.emptyList()) +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/users/UsersId.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/users/UsersId.scala new file mode 100644 index 0000000000..0d7beaa210 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/users/UsersId.scala @@ -0,0 +1,20 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.users + +import com.fasterxml.jackson.annotation.JsonValue +import dev.typr.dslsc.Bijection +import dev.typr.foundationssc.SqliteType +import dev.typr.foundationssc.SqliteTypes + +/** Type for the primary key of table `users` */ +case class UsersId(@JsonValue value: Long) extends scala.AnyVal + +object UsersId { + given bijection: Bijection[UsersId, Long] = Bijection.of[UsersId, Long](_.value, UsersId.apply) + + given sqliteType: SqliteType[UsersId] = SqliteTypes.integer.to(Bijection.of(UsersId.apply, _.value)) +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/users/UsersRepo.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/users/UsersRepo.scala new file mode 100644 index 0000000000..35f911dc00 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/users/UsersRepo.scala @@ -0,0 +1,45 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.users + +import dev.typr.dslsc.DeleteBuilder +import dev.typr.dslsc.SelectBuilder +import dev.typr.dslsc.UpdateBuilder +import dev.typr.foundationssc.Connection +import dev.typr.foundationssc.ConnectionRead +import testdb.userdefined.Email + +trait UsersRepo { + def delete: DeleteBuilder[UsersFields, UsersRow] + + def deleteById(userId: UsersId)(using c: Connection): Boolean + + def deleteByIds(userIds: List[UsersId])(using c: Connection): Int + + def insert(unsaved: UsersRow)(using c: Connection): UsersRow + + def select: SelectBuilder[UsersFields, UsersRow] + + def selectAll(using c: ConnectionRead): List[UsersRow] + + def selectById(userId: UsersId)(using c: ConnectionRead): Option[UsersRow] + + def selectByIds(userIds: List[UsersId])(using c: ConnectionRead): List[UsersRow] + + def selectByIdsTracked(userIds: List[UsersId])(using c: ConnectionRead): Map[UsersId, UsersRow] + + def selectByUniqueEmail(email: /* user-picked */ Email)(using c: ConnectionRead): Option[UsersRow] + + def selectByUniqueUsername(username: String)(using c: ConnectionRead): Option[UsersRow] + + def update: UpdateBuilder[UsersFields, UsersRow] + + def update(row: UsersRow)(using c: Connection): Boolean + + def upsert(unsaved: UsersRow)(using c: Connection): UsersRow + + def upsertBatch(unsaved: Iterator[UsersRow])(using c: Connection): List[UsersRow] +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/users/UsersRepoImpl.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/users/UsersRepoImpl.scala new file mode 100644 index 0000000000..4435b14a28 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/users/UsersRepoImpl.scala @@ -0,0 +1,112 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.users + +import dev.typr.dslsc.DeleteBuilder +import dev.typr.dslsc.Dialect +import dev.typr.dslsc.SelectBuilder +import dev.typr.dslsc.UpdateBuilder +import dev.typr.foundationssc.Connection +import dev.typr.foundationssc.ConnectionRead +import dev.typr.foundationssc.Fragment +import dev.typr.foundationssc.SqliteTypes +import scala.collection.mutable.ListBuffer +import testdb.userdefined.Email +import dev.typr.foundationssc.Fragment.sql + +class UsersRepoImpl extends UsersRepo { + override def delete: DeleteBuilder[UsersFields, UsersRow] = DeleteBuilder.of(""""users"""", UsersFields.structure, Dialect.SQLITE) + + override def deleteById(userId: UsersId)(using c: Connection): Boolean = sql"""delete from "users" where "user_id" = ${Fragment.encode(UsersId.sqliteType, userId)}""".update().run(using c) > 0 + + override def deleteByIds(userIds: List[UsersId])(using c: Connection): Int = { + val fragments: ListBuffer[Fragment] = ListBuffer() + userIds.foreach { id => fragments.addOne(Fragment.encode(UsersId.sqliteType, id)): @scala.annotation.nowarn } + return Fragment.concat(Fragment.of("""delete from "users" where "user_id" in ("""), Fragment.comma(fragments), Fragment.of(")")).update().run(using c) + } + + override def insert(unsaved: UsersRow)(using c: Connection): UsersRow = { + sql"""insert into "users"("user_id", "username", "email") + values (${Fragment.encode(UsersId.sqliteType, unsaved.userId)}, ${Fragment.encode(SqliteTypes.varchar, unsaved.username)}, ${Fragment.encode(Email.sqliteType, unsaved.email)}) + RETURNING "user_id", "username", "email" + """ + .updateReturning(UsersRow.rowCodec.exactlyOne()).run(using c) + } + + override def select: SelectBuilder[UsersFields, UsersRow] = SelectBuilder.of(""""users"""", UsersFields.structure, UsersRow.rowCodec, Dialect.SQLITE) + + override def selectAll(using c: ConnectionRead): List[UsersRow] = { + sql"""select "user_id", "username", "email" + from "users" + """.query(UsersRow.rowCodec.all()).run(using c) + } + + override def selectById(userId: UsersId)(using c: ConnectionRead): Option[UsersRow] = { + sql"""select "user_id", "username", "email" + from "users" + where "user_id" = ${Fragment.encode(UsersId.sqliteType, userId)}""".query(UsersRow.rowCodec.first()).run(using c) + } + + override def selectByIds(userIds: List[UsersId])(using c: ConnectionRead): List[UsersRow] = { + val fragments: ListBuffer[Fragment] = ListBuffer() + userIds.foreach { id => fragments.addOne(Fragment.encode(UsersId.sqliteType, id)): @scala.annotation.nowarn } + return Fragment.concat(Fragment.of("""select "user_id", "username", "email" from "users" where "user_id" in ("""), Fragment.comma(fragments), Fragment.of(")")).query(UsersRow.rowCodec.all()).run(using c) + } + + override def selectByIdsTracked(userIds: List[UsersId])(using c: ConnectionRead): Map[UsersId, UsersRow] = { + val ret: scala.collection.mutable.Map[UsersId, UsersRow] = scala.collection.mutable.Map.empty[UsersId, UsersRow] + selectByIds(userIds)(using c).foreach(row => ret.put(row.userId, row): @scala.annotation.nowarn) + return ret.toMap + } + + override def selectByUniqueEmail(email: /* user-picked */ Email)(using c: ConnectionRead): Option[UsersRow] = { + sql"""select "user_id", "username", "email" + from "users" + where "email" = ${Fragment.encode(Email.sqliteType, email)} + """.query(UsersRow.rowCodec.first()).run(using c) + } + + override def selectByUniqueUsername(username: String)(using c: ConnectionRead): Option[UsersRow] = { + sql"""select "user_id", "username", "email" + from "users" + where "username" = ${Fragment.encode(SqliteTypes.varchar, username)} + """.query(UsersRow.rowCodec.first()).run(using c) + } + + override def update: UpdateBuilder[UsersFields, UsersRow] = UpdateBuilder.of(""""users"""", UsersFields.structure, UsersRow.rowCodec, Dialect.SQLITE) + + override def update(row: UsersRow)(using c: Connection): Boolean = { + val userId: UsersId = row.userId + return sql"""update "users" + set "username" = ${Fragment.encode(SqliteTypes.varchar, row.username)}, + "email" = ${Fragment.encode(Email.sqliteType, row.email)} + where "user_id" = ${Fragment.encode(UsersId.sqliteType, userId)}""".update().run(using c) > 0 + } + + override def upsert(unsaved: UsersRow)(using c: Connection): UsersRow = { + sql"""INSERT INTO "users"("user_id", "username", "email") + VALUES (${Fragment.encode(UsersId.sqliteType, unsaved.userId)}, ${Fragment.encode(SqliteTypes.varchar, unsaved.username)}, ${Fragment.encode(Email.sqliteType, unsaved.email)}) + ON CONFLICT ("user_id") + DO UPDATE SET + "username" = EXCLUDED."username", + "email" = EXCLUDED."email" + RETURNING "user_id", "username", "email"""" + .updateReturning(UsersRow.rowCodec.exactlyOne()) + .run(using c) + } + + override def upsertBatch(unsaved: Iterator[UsersRow])(using c: Connection): List[UsersRow] = { + sql"""INSERT INTO "users"("user_id", "username", "email") + VALUES (?, ?, ?) + ON CONFLICT ("user_id") + DO UPDATE SET + "username" = EXCLUDED."username", + "email" = EXCLUDED."email" + RETURNING "user_id", "username", "email"""" + .updateReturningEach(UsersRow.rowCodec, unsaved) + .run(using c) + } +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/users/UsersRepoMock.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/users/UsersRepoMock.scala new file mode 100644 index 0000000000..6163da637a --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/users/UsersRepoMock.scala @@ -0,0 +1,78 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.users + +import dev.typr.dslsc.DeleteBuilder +import dev.typr.dslsc.DeleteBuilderMock +import dev.typr.dslsc.DeleteParams +import dev.typr.dslsc.SelectBuilder +import dev.typr.dslsc.SelectBuilderMock +import dev.typr.dslsc.SelectParams +import dev.typr.dslsc.UpdateBuilder +import dev.typr.dslsc.UpdateBuilderMock +import dev.typr.dslsc.UpdateParams +import dev.typr.foundationssc.Connection +import dev.typr.foundationssc.ConnectionRead +import java.lang.RuntimeException +import testdb.userdefined.Email + +case class UsersRepoMock(map: scala.collection.mutable.Map[UsersId, UsersRow] = scala.collection.mutable.Map.empty[UsersId, UsersRow]) extends UsersRepo { + override def delete: DeleteBuilder[UsersFields, UsersRow] = DeleteBuilderMock(UsersFields.structure, () => map.values.toList, DeleteParams.empty(), row => row.userId, id => map.remove(id): @scala.annotation.nowarn) + + override def deleteById(userId: UsersId)(using c: Connection): Boolean = map.remove(userId).isDefined + + override def deleteByIds(userIds: List[UsersId])(using c: Connection): Int = { + var count = 0 + userIds.foreach { id => if (map.remove(id).isDefined) { + count = count + 1 + } } + return count + } + + override def insert(unsaved: UsersRow)(using c: Connection): UsersRow = { + if (map.contains(unsaved.userId)) { + throw new RuntimeException(s"id ${unsaved.userId} already exists") + } + map.put(unsaved.userId, unsaved): @scala.annotation.nowarn + return unsaved + } + + override def select: SelectBuilder[UsersFields, UsersRow] = SelectBuilderMock(UsersFields.structure, () => map.values.toList, SelectParams.empty()) + + override def selectAll(using c: ConnectionRead): List[UsersRow] = map.values.toList + + override def selectById(userId: UsersId)(using c: ConnectionRead): Option[UsersRow] = map.get(userId) + + override def selectByIds(userIds: List[UsersId])(using c: ConnectionRead): List[UsersRow] = userIds.flatMap(map.get(_)).toList + + override def selectByIdsTracked(userIds: List[UsersId])(using c: ConnectionRead): Map[UsersId, UsersRow] = selectByIds(userIds)(using c).map(x => (((row: UsersRow) => row.userId).apply(x), x)).toMap + + override def selectByUniqueEmail(email: /* user-picked */ Email)(using c: ConnectionRead): Option[UsersRow] = map.values.toList.find(v => (email == v.email)) + + override def selectByUniqueUsername(username: String)(using c: ConnectionRead): Option[UsersRow] = map.values.toList.find(v => (username == v.username)) + + override def update: UpdateBuilder[UsersFields, UsersRow] = UpdateBuilderMock(UsersFields.structure, () => map.values.toList, UpdateParams.empty(), row => row) + + override def update(row: UsersRow)(using c: Connection): Boolean = { + val shouldUpdate = map.get(row.userId).filter(oldRow => (oldRow != row)).isDefined + if (shouldUpdate) { + map.put(row.userId, row): @scala.annotation.nowarn + } + return shouldUpdate + } + + override def upsert(unsaved: UsersRow)(using c: Connection): UsersRow = { + map.put(unsaved.userId, unsaved): @scala.annotation.nowarn + return unsaved + } + + override def upsertBatch(unsaved: Iterator[UsersRow])(using c: Connection): List[UsersRow] = { + unsaved.map { row => + map.put(row.userId, row): @scala.annotation.nowarn + row + }.toList + } +} \ No newline at end of file diff --git a/testers/sqlite/scala/generated-and-checked-in/testdb/users/UsersRow.scala b/testers/sqlite/scala/generated-and-checked-in/testdb/users/UsersRow.scala new file mode 100644 index 0000000000..f657d64ec9 --- /dev/null +++ b/testers/sqlite/scala/generated-and-checked-in/testdb/users/UsersRow.scala @@ -0,0 +1,34 @@ +/** + * File has been automatically generated by `typo`. + * + * IF YOU CHANGE THIS FILE YOUR CHANGES WILL BE OVERWRITTEN. + */ +package testdb.users + +import com.fasterxml.jackson.annotation.JsonProperty +import dev.typr.dslsc.RowCodecs +import dev.typr.foundations.Tuple.Tuple3 +import dev.typr.foundationssc.RowCodec +import dev.typr.foundationssc.SqliteTypes +import testdb.userdefined.Email + +/** Table: users + * Primary key: user_id + */ +case class UsersRow( + @JsonProperty("user_id") userId: UsersId, + username: String, + email: /* user-picked */ Email +) extends Tuple3[UsersId, String, /* user-picked */ Email] { + def id: UsersId = userId + + override def `_1`: UsersId = userId + + override def `_2`: String = username + + override def `_3`: /* user-picked */ Email = email +} + +object UsersRow { + val rowCodec: RowCodec[UsersRow] = RowCodecs.of(UsersId.sqliteType, SqliteTypes.varchar, Email.sqliteType)(UsersRow.apply)(row => Array[Any](row.userId, row.username, row.email)) +} \ No newline at end of file diff --git a/testers/sqlite/scala/src/scala/testdb/AllTypesTest.scala b/testers/sqlite/scala/src/scala/testdb/AllTypesTest.scala new file mode 100644 index 0000000000..7bca7795f3 --- /dev/null +++ b/testers/sqlite/scala/src/scala/testdb/AllTypesTest.scala @@ -0,0 +1,186 @@ +package testdb + +import dev.typr.foundations.data.Json +import org.junit.Assert.* +import org.junit.Test +import testdb.all_scalar_types.* + +import java.time.{LocalDate, LocalDateTime, LocalTime} +import java.util.UUID + +/** Round-trip every SQLite scalar type through generated codecs. */ +class AllTypesTest { + private val repo = new AllScalarTypesRepoImpl() + + private def createSampleRow(id: Long): AllScalarTypesRow = + AllScalarTypesRow( + id = AllScalarTypesId(id), + colTinyint = Some(42.toByte), + colSmallint = Some(1000.toShort), + colInt = Some(100000), + colInteger = Some(10000000000L), + colBigint = Some(9223372036854775000L), + colBoolean = Some(true), + colReal = Some(3.14159), + colDouble = Some(2.718281828), + colFloat = Some(1.5f), + colDecimal = Some(BigDecimal("12345.67")), + colNumeric = Some(BigDecimal("999.999")), + colText = Some("text content"), + colVarchar = Some("varchar_value"), + colChar = Some("char5"), + colClob = Some("clob content"), + colBlob = Some(Array[Byte](1, 2, 3, 4, 5)), + colBinary = Some(Array[Byte](0x0a, 0x0b, 0x0c)), + colDate = Some(LocalDate.of(2025, 1, 15)), + colTime = Some(LocalTime.of(14, 30, 45)), + colDatetime = Some(LocalDateTime.of(2025, 1, 15, 14, 30, 45)), + colTimestamp = Some(LocalDateTime.of(2025, 6, 1, 9, 0, 0)), + colUuid = Some(UUID.fromString("550e8400-e29b-41d4-a716-446655440000")), + colJson = Some(Json("{\"key\": \"value\"}")), + colNotNull = "required_value" + ) + + @Test def testInsertAndSelectAllTypes(): Unit = withConnection { + val row = createSampleRow(1001L) + val inserted = repo.insert(row) + assertEquals(row.id, inserted.id) + assertEquals(row.colTinyint, inserted.colTinyint) + assertEquals(row.colSmallint, inserted.colSmallint) + assertEquals(row.colInt, inserted.colInt) + assertEquals(row.colInteger, inserted.colInteger) + assertEquals(row.colBoolean, inserted.colBoolean) + assertEquals(row.colVarchar, inserted.colVarchar) + assertEquals(row.colUuid, inserted.colUuid) + assertEquals(row.colNotNull, inserted.colNotNull) + assertTrue(repo.selectById(inserted.id).isDefined) + } + + @Test def testUpdateAllTypes(): Unit = withConnection { + val row = createSampleRow(1002L) + val inserted = repo.insert(row) + val updated = inserted.copy( + colVarchar = Some("updated"), + colDecimal = Some(BigDecimal("999.99")), + colBoolean = Some(false) + ) + assertTrue(repo.update(updated)) + val found = repo.selectById(inserted.id).get + assertEquals(Some("updated"), found.colVarchar) + assertEquals(Some(false), found.colBoolean) + } + + @Test def testDeleteAllTypes(): Unit = withConnection { + val inserted = repo.insert(createSampleRow(1003L)) + assertTrue(repo.deleteById(inserted.id)) + assertFalse(repo.selectById(inserted.id).isDefined) + } + + @Test def testInsertWithNulls(): Unit = withConnection { + val row = AllScalarTypesRow( + AllScalarTypesId(1004L), + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + None, + "required_only" + ) + val inserted = repo.insert(row) + assertEquals("required_only", inserted.colNotNull) + assertTrue(inserted.colTinyint.isEmpty) + assertTrue(inserted.colUuid.isEmpty) + assertTrue(inserted.colJson.isEmpty) + } + + @Test def testIntegerTypes(): Unit = withConnection { + val inserted = repo.insert(createSampleRow(1010L)) + assertEquals(Some(42.toByte), inserted.colTinyint) + assertEquals(Some(1000.toShort), inserted.colSmallint) + assertEquals(Some(100000), inserted.colInt) + assertEquals(Some(10000000000L), inserted.colInteger) + assertEquals(Some(9223372036854775000L), inserted.colBigint) + } + + @Test def testBooleanType(): Unit = withConnection { + val inserted = repo.insert(createSampleRow(1011L)) + assertEquals(Some(true), inserted.colBoolean) + repo.update(inserted.copy(colBoolean = Some(false))) + assertEquals(Some(false), repo.selectById(inserted.id).get.colBoolean) + } + + @Test def testFloatingPointTypes(): Unit = withConnection { + val inserted = repo.insert(createSampleRow(1012L)) + assertEquals(Some(3.14159), inserted.colReal) + assertEquals(Some(2.718281828), inserted.colDouble) + assertEquals(Some(1.5f), inserted.colFloat) + } + + @Test def testDecimalAndNumericTypes(): Unit = withConnection { + val inserted = repo.insert(createSampleRow(1013L)) + assertEquals(0, BigDecimal("12345.67").compare(inserted.colDecimal.get)) + assertEquals(0, BigDecimal("999.999").compare(inserted.colNumeric.get)) + } + + @Test def testTextTypes(): Unit = withConnection { + val inserted = repo.insert(createSampleRow(1014L)) + assertEquals(Some("text content"), inserted.colText) + assertEquals(Some("varchar_value"), inserted.colVarchar) + assertEquals(Some("char5"), inserted.colChar) + assertEquals(Some("clob content"), inserted.colClob) + } + + @Test def testBlobAndBinaryTypes(): Unit = withConnection { + val blob = Array[Byte](0, 1, 2, -1, -2) + val bin = Array[Byte](-54, -2, -70, -66) + val inserted = repo.insert(createSampleRow(1015L).copy(colBlob = Some(blob), colBinary = Some(bin))) + assertArrayEquals(blob, inserted.colBlob.get) + assertArrayEquals(bin, inserted.colBinary.get) + } + + @Test def testDateTimeTypes(): Unit = withConnection { + val inserted = repo.insert(createSampleRow(1016L)) + assertEquals(Some(LocalDate.of(2025, 1, 15)), inserted.colDate) + assertEquals(Some(LocalTime.of(14, 30, 45)), inserted.colTime) + assertEquals(Some(LocalDateTime.of(2025, 1, 15, 14, 30, 45)), inserted.colDatetime) + assertEquals(Some(LocalDateTime.of(2025, 6, 1, 9, 0, 0)), inserted.colTimestamp) + } + + @Test def testUuidType(): Unit = withConnection { + val uuid = UUID.randomUUID() + val inserted = repo.insert(createSampleRow(1017L).copy(colUuid = Some(uuid))) + assertEquals(Some(uuid), inserted.colUuid) + } + + @Test def testJsonType(): Unit = withConnection { + val json = Json("{\"name\":\"test\"}") + val inserted = repo.insert(createSampleRow(1018L).copy(colJson = Some(json))) + assertTrue(inserted.colJson.get.value.contains("name")) + } + + @Test def testSelectAllReturnsInsertedRow(): Unit = withConnection { + val row = createSampleRow(1019L) + repo.insert(row) + val all = repo.selectAll + assertTrue(all.size >= 2) + assertTrue(all.exists(_.id.value == 1019L)) + } +} diff --git a/testers/sqlite/scala/src/scala/testdb/BasicCrudTest.scala b/testers/sqlite/scala/src/scala/testdb/BasicCrudTest.scala new file mode 100644 index 0000000000..592807da51 --- /dev/null +++ b/testers/sqlite/scala/src/scala/testdb/BasicCrudTest.scala @@ -0,0 +1,37 @@ +package testdb + +import org.junit.Assert.* +import org.junit.Test +import testdb.customers.* +import testdb.customtypes.Defaulted +import testdb.products.* + +class BasicCrudTest { + private val customers = new CustomersRepoImpl + private val products = new ProductsRepoImpl + + @Test def selectAllCustomersFromSeedData(): Unit = withConnection { + val rows = customers.selectAll + assertEquals(2, rows.size) + } + + @Test def findCustomerById(): Unit = withConnection { + val row = customers.selectById(new CustomersId(1L)) + assertTrue(row.isDefined) + assertEquals("John Doe", row.get.name) + } + + @Test def deleteCustomerById(): Unit = withConnection { + val inserted = customers.insert( + CustomersRowUnsaved(CustomersId(999L), "Disposable", None, Defaulted.UseDefault()) + ) + assertTrue(customers.deleteById(inserted.customerId)) + } + + @Test def productsHaveExpectedPrices(): Unit = withConnection { + val ps = products.selectAll + assertEquals(2, ps.size) + val skus = ps.iterator.toList.map(_.sku).sorted + assertEquals(List("PROD-001", "PROD-002"), skus) + } +} diff --git a/testers/sqlite/scala/src/scala/testdb/CompositeKeyTest.scala b/testers/sqlite/scala/src/scala/testdb/CompositeKeyTest.scala new file mode 100644 index 0000000000..1b20d4cf73 --- /dev/null +++ b/testers/sqlite/scala/src/scala/testdb/CompositeKeyTest.scala @@ -0,0 +1,101 @@ +package testdb + +import org.junit.Assert.* +import org.junit.Test +import testdb.departments.* +import testdb.employees.* + +import java.time.LocalDate + +class CompositeKeyTest { + private val departments = new DepartmentsRepoImpl() + private val employees = new EmployeesRepoImpl() + + @Test def departmentsInsertAndSelect(): Unit = withConnection { + val d = DepartmentsRow("ENG", "EU-NORTH", "Engineering EU", Some(BigDecimal("750000"))) + val inserted = departments.insert(d) + assertEquals("Engineering EU", inserted.deptName) + assertEquals(0, BigDecimal("750000").compare(inserted.budget.get)) + } + + @Test def departmentsSelectBySeedId(): Unit = withConnection { + val found = departments.selectById(DepartmentsId("IT", "US-WEST")) + assertTrue(found.isDefined) + assertEquals("Information Technology", found.get.deptName) + } + + @Test def departmentsCompositeIdFromRow(): Unit = withConnection { + val inserted = departments.insert(DepartmentsRow("SALES", "APAC", "Sales APAC", Some(BigDecimal("500000")))) + val id = inserted.compositeId + assertEquals("SALES", id.deptCode) + assertEquals(inserted, departments.selectById(id).get) + } + + @Test def departmentsUpdate(): Unit = withConnection { + val inserted = departments.insert(DepartmentsRow("FINANCE", "US-CENTRAL", "Finance", Some(BigDecimal("800000")))) + val updated = inserted.copy(budget = Some(BigDecimal("900000"))) + assertTrue(departments.update(updated)) + assertEquals(0, BigDecimal("900000").compare(departments.selectById(inserted.compositeId).get.budget.get)) + } + + @Test def departmentsDelete(): Unit = withConnection { + val inserted = departments.insert(DepartmentsRow("TEMP", "TEMP-REGION", "Temporary", None)) + assertTrue(departments.deleteById(inserted.compositeId)) + assertTrue(departments.selectById(inserted.compositeId).isEmpty) + } + + @Test def departmentsMultipleSameCode(): Unit = withConnection { + departments.insert(DepartmentsRow("ENG2", "US", "Eng US", None)) + departments.insert(DepartmentsRow("ENG2", "EU", "Eng EU", None)) + departments.insert(DepartmentsRow("ENG2", "APAC", "Eng APAC", None)) + assertTrue(departments.selectById(DepartmentsId("ENG2", "US")).isDefined) + assertTrue(departments.selectById(DepartmentsId("ENG2", "EU")).isDefined) + assertTrue(departments.selectById(DepartmentsId("ENG2", "APAC")).isDefined) + } + + @Test def employeesInsert(): Unit = withConnection { + val emp = EmployeesRow(2001L, "A", "IT", "US-WEST", "Alice", Some(BigDecimal("95000")), LocalDate.of(2025, 1, 15)) + val inserted = employees.insert(emp) + assertEquals(2001L, inserted.empNumber) + assertEquals("Alice", inserted.empName) + } + + @Test def employeesSelectBySeedId(): Unit = withConnection { + val found = employees.selectById(EmployeesId(1001L, "A")) + assertTrue(found.isDefined) + assertEquals("Alice Johnson", found.get.empName) + } + + @Test def employeesCompositeIdFromRow(): Unit = withConnection { + val inserted = employees.insert(EmployeesRow(3001L, "C", "HR", "US-EAST", "Carol", None, LocalDate.of(2025, 3, 1))) + assertEquals(3001L, inserted.compositeId.empNumber) + assertEquals("C", inserted.compositeId.empSuffix) + } + + @Test def employeesUpdate(): Unit = withConnection { + val inserted = employees.insert(EmployeesRow(4001L, "D", "IT", "US-WEST", "David", Some(BigDecimal("120000")), LocalDate.of(2025, 4, 1))) + employees.update(inserted.copy(salary = Some(BigDecimal("130000")))) + assertEquals(0, BigDecimal("130000").compare(employees.selectById(inserted.compositeId).get.salary.get)) + } + + @Test def employeesDelete(): Unit = withConnection { + val inserted = employees.insert(EmployeesRow(5001L, "X", "IT", "US-WEST", "Disposable", None, LocalDate.of(2025, 5, 1))) + assertTrue(employees.deleteById(inserted.compositeId)) + } + + @Test def employeesMultipleSameNumber(): Unit = withConnection { + employees.insert(EmployeesRow(9999L, "A", "IT", "US-WEST", "Emp A", None, LocalDate.of(2025, 1, 1))) + employees.insert(EmployeesRow(9999L, "B", "IT", "US-WEST", "Emp B", None, LocalDate.of(2025, 1, 1))) + employees.insert(EmployeesRow(9999L, "C", "IT", "US-WEST", "Emp C", None, LocalDate.of(2025, 1, 1))) + assertTrue(employees.selectById(EmployeesId(9999L, "A")).isDefined) + assertTrue(employees.selectById(EmployeesId(9999L, "B")).isDefined) + assertTrue(employees.selectById(EmployeesId(9999L, "C")).isDefined) + } + + @Test def employeeDepartmentForeignKey(): Unit = withConnection { + departments.insert(DepartmentsRow("FK_TEST", "FK_REGION", "FK Dept", Some(BigDecimal("500000")))) + val emp = employees.insert(EmployeesRow(6001L, "F", "FK_TEST", "FK_REGION", "FK Emp", Some(BigDecimal("60000")), LocalDate.of(2025, 6, 1))) + assertEquals("FK_TEST", emp.deptCode) + assertTrue(departments.selectById(DepartmentsId(emp.deptCode, emp.deptRegion)).isDefined) + } +} diff --git a/testers/sqlite/scala/src/scala/testdb/DSLTest.scala b/testers/sqlite/scala/src/scala/testdb/DSLTest.scala new file mode 100644 index 0000000000..b292abc2bf --- /dev/null +++ b/testers/sqlite/scala/src/scala/testdb/DSLTest.scala @@ -0,0 +1,102 @@ +package testdb + +import dev.typr.foundations.Bijection +import org.junit.Assert.* +import org.junit.Test +import testdb.customers.* + +import java.time.LocalDateTime + +class DSLTest { + private val repo = new CustomersRepoImpl() + private def row(id: Long, name: String) = + CustomersRow(CustomersId(id), name, None, LocalDateTime.of(2025, 1, 1, 0, 0)) + + @Test def selectWithWhere(): Unit = withConnection { + repo.insert(row(5001L, "DSL Test User")) + val results = repo.select.where(_.name.isEqual("DSL Test User")).toList + assertEquals(1, results.size) + } + + @Test def selectWithOrderByAsc(): Unit = withConnection { + repo.insert(row(5002L, "Zebra")) + repo.insert(row(5003L, "Alpha")) + repo.insert(row(5004L, "Mike")) + val r = repo.select + .where(_.customerId.greaterThan(CustomersId(5001L))) + .orderBy(_.name.asc) + .toList + assertEquals("Alpha", r.head.name) + assertEquals("Zebra", r.last.name) + } + + @Test def selectWithOrderByDesc(): Unit = withConnection { + repo.insert(row(5005L, "DescA")) + repo.insert(row(5006L, "DescB")) + repo.insert(row(5007L, "DescC")) + val r = repo.select + .where(_.name.like("Desc%", Bijection.asString())) + .orderBy(_.name.desc) + .toList + assertEquals("DescC", r.head.name) + } + + @Test def selectWithLimit(): Unit = withConnection { + (0 until 10).foreach(i => repo.insert(row(5100L + i, s"Limit$i"))) + val r = repo.select.where(_.name.like("Limit%", Bijection.asString())).limit(3).toList + assertEquals(3, r.size) + } + + @Test def selectWithOffset(): Unit = withConnection { + repo.insert(row(5200L, "OffsetA")) + repo.insert(row(5201L, "OffsetB")) + repo.insert(row(5202L, "OffsetC")) + repo.insert(row(5203L, "OffsetD")) + val r = repo.select + .where(_.name.like("Offset%", Bijection.asString())) + .orderBy(_.name.asc) + .offset(2) + .limit(10) + .toList + assertEquals(List("OffsetC", "OffsetD"), r.map(_.name)) + } + + @Test def selectWithCount(): Unit = withConnection { + repo.insert(row(5300L, "CountA")) + repo.insert(row(5301L, "CountB")) + repo.insert(row(5302L, "CountC")) + val count = repo.select.where(_.name.like("Count%", Bijection.asString())).count + assertEquals(3L, count) + } + + @Test def selectWithLike(): Unit = withConnection { + repo.insert(row(5400L, "LikeTest_ABC")) + repo.insert(row(5401L, "LikeTest_XYZ")) + repo.insert(row(5402L, "Other")) + val r = repo.select.where(_.name.like("LikeTest%", Bijection.asString())).toList + assertEquals(2, r.size) + } + + @Test def selectWithIn(): Unit = withConnection { + repo.insert(row(5500L, "In1")) + repo.insert(row(5501L, "In2")) + repo.insert(row(5502L, "In3")) + val r = repo.select.where(_.customerId.in(CustomersId(5500L), CustomersId(5502L))).toList + assertEquals(2, r.size) + } + + @Test def updateBuilder(): Unit = withConnection { + repo.insert(row(5600L, "UpdateMe")) + val n = repo.update.where(_.customerId.isEqual(CustomersId(5600L))).setValue(_.name, "Updated").execute + assertEquals(1, n) + assertEquals("Updated", repo.selectById(CustomersId(5600L)).get.name) + } + + @Test def deleteBuilder(): Unit = withConnection { + repo.insert(row(5700L, "DeleteA")) + repo.insert(row(5701L, "DeleteB")) + repo.insert(row(5702L, "DeleteC")) + val n = repo.delete.where(_.name.like("Delete%", Bijection.asString())).execute + assertEquals(3, n) + } +} diff --git a/testers/sqlite/scala/src/scala/testdb/DatabaseFeaturesTest.scala b/testers/sqlite/scala/src/scala/testdb/DatabaseFeaturesTest.scala new file mode 100644 index 0000000000..38fa70bc6e --- /dev/null +++ b/testers/sqlite/scala/src/scala/testdb/DatabaseFeaturesTest.scala @@ -0,0 +1,108 @@ +package testdb + +import dev.typr.foundations.data.Json +import org.junit.Assert.* +import org.junit.Test +import testdb.customer_orders.CustomerOrdersViewRepoImpl +import testdb.customers.* +import testdb.customtypes.Defaulted +import testdb.order_details.OrderDetailsViewRepoImpl +import testdb.orders.* +import testdb.products.* +import testdb.userdefined.Email + +import java.time.{LocalDate, LocalDateTime} +import java.util.UUID + +class DatabaseFeaturesTest { + private val customers = new CustomersRepoImpl() + private val products = new ProductsRepoImpl() + private val orders = new OrdersRepoImpl() + private val customerOrdersRepo = new CustomerOrdersViewRepoImpl() + private val orderDetailsRepo = new OrderDetailsViewRepoImpl() + + @Test def insertReturningPopulatesGeneratedColumns(): Unit = withConnection { + val unsaved = CustomersRowUnsaved(CustomersId(10001L), "Returning Test") + val inserted = customers.insert(unsaved) + assertEquals(10001L, inserted.customerId.value) + assertNotNull(inserted.createdAt) + } + + @Test def insertWithProvidedDefault(): Unit = withConnection { + val explicit = LocalDateTime.of(2020, 5, 1, 12, 0) + val unsaved = CustomersRowUnsaved( + CustomersId(10002L), + "Explicit", + Some(Email("u@x.com")), + Defaulted.Provided(explicit) + ) + assertEquals(explicit, customers.insert(unsaved).createdAt) + } + + @Test def upsertInsertsNew(): Unit = withConnection { + val row = CustomersRow(CustomersId(20001L), "Upsert Insert", None, LocalDateTime.of(2025, 1, 1, 0, 0)) + assertEquals("Upsert Insert", customers.upsert(row).name) + } + + @Test def upsertUpdatesOnConflict(): Unit = withConnection { + val row = CustomersRow(CustomersId(20002L), "Original", Some(Email("a@x.com")), LocalDateTime.of(2025, 1, 1, 0, 0)) + customers.insert(row) + val updated = row.copy(name = "Updated via Upsert", email = Some(Email("b@x.com"))) + val result = customers.upsert(updated) + assertEquals("Updated via Upsert", result.name) + assertEquals("Updated via Upsert", customers.selectById(CustomersId(20002L)).get.name) + } + + @Test def uuidJsonRoundTrip(): Unit = withConnection { + val uuid = UUID.randomUUID() + val product = ProductsRow( + ProductsId(30001L), + s"SKU-UUID-$uuid", + "UUID Product", + BigDecimal("1.00"), + Some(Json(s"""{"uuid":"$uuid"}""")) + ) + val inserted = products.insert(product) + assertTrue(inserted.metadata.get.value.contains(uuid.toString)) + } + + @Test def customerOrdersView(): Unit = withConnection { + val rows = customerOrdersRepo.selectAll + assertEquals(2, rows.size) + assertTrue(rows.exists(_.customerName.contains("John Doe"))) + assertTrue(rows.exists(_.customerName.contains("Jane Smith"))) + } + + @Test def orderDetailsView(): Unit = withConnection { + val rows = orderDetailsRepo.selectAll + assertEquals(3, rows.size) + rows.foreach { r => + val s = r.lineTotal.get + assertTrue(BigDecimal(s) > BigDecimal(0)) + } + } + + @Test def selectByIdsReturnsRequested(): Unit = withConnection { + val found = customers.selectByIds(List(CustomersId(1L), CustomersId(2L))) + assertEquals(2, found.size) + } + + @Test def insertWithExplicitId(): Unit = withConnection { + val row = CustomersRow(CustomersId(50001L), "Explicit ID", None, LocalDateTime.of(2025, 1, 1, 0, 0)) + val inserted = customers.insert(row) + assertEquals(50001L, inserted.customerId.value) + } + + @Test def orderInsertWithForeignKeyValue(): Unit = withConnection { + val ord = orders.insert( + OrdersRow( + OrdersId(70001L), + CustomersId(1L), + LocalDate.of(2025, 7, 1), + Some(BigDecimal("250.00")), + "pending" + ) + ) + assertEquals(70001L, ord.orderId.value) + } +} diff --git a/testers/sqlite/scala/src/scala/testdb/ForeignKeyTest.scala b/testers/sqlite/scala/src/scala/testdb/ForeignKeyTest.scala new file mode 100644 index 0000000000..0f4654619f --- /dev/null +++ b/testers/sqlite/scala/src/scala/testdb/ForeignKeyTest.scala @@ -0,0 +1,74 @@ +package testdb + +import org.junit.Assert.* +import org.junit.Test +import testdb.customers.* +import testdb.order_items.* +import testdb.orders.* +import testdb.products.* +import testdb.userdefined.Email + +import java.time.{LocalDate, LocalDateTime} + +class ForeignKeyTest { + private val customers = new CustomersRepoImpl() + private val products = new ProductsRepoImpl() + private val orders = new OrdersRepoImpl() + private val orderItems = new OrderItemsRepoImpl() + + @Test def customerInsert(): Unit = withConnection { + val inserted = customers.insert( + CustomersRow(CustomersId(100L), "John", Some(Email("john@x.com")), LocalDateTime.of(2025, 1, 1, 0, 0)) + ) + assertEquals("John", inserted.name) + } + + @Test def productInsert(): Unit = withConnection { + val inserted = products.insert(ProductsRow(ProductsId(100L), "PROD-100", "Widget", BigDecimal("29.99"), None)) + assertEquals("PROD-100", inserted.sku) + } + + @Test def orderWithCustomerFK(): Unit = withConnection { + val cust = customers.insert( + CustomersRow(CustomersId(101L), "Jane", Some(Email("jane@x.com")), LocalDateTime.of(2025, 1, 2, 0, 0)) + ) + val ord = orders.insert( + OrdersRow(OrdersId(101L), cust.customerId, LocalDate.of(2025, 1, 15), Some(BigDecimal("99.99")), "pending") + ) + assertEquals(cust.customerId, ord.customerId) + } + + @Test def orderItemWithCompositePK(): Unit = withConnection { + customers.insert(CustomersRow(CustomersId(102L), "x", None, LocalDateTime.of(2025, 1, 1, 0, 0))) + val prod = products.insert(ProductsRow(ProductsId(102L), "PROD-102", "W", BigDecimal("49.99"), None)) + val ord = orders.insert( + OrdersRow(OrdersId(102L), CustomersId(102L), LocalDate.of(2025, 1, 16), Some(BigDecimal("149.97")), "pending") + ) + val item = orderItems.insert(OrderItemsRow(ord.orderId, prod.productId, 3L, BigDecimal("49.99"))) + assertEquals(3L, item.quantity) + } + + @Test def foreignKeyEnforcedOnInsert(): Unit = { + var threw = false + try { + withConnection { + orders.insert(OrdersRow(OrdersId(9999L), CustomersId(99999L), LocalDate.of(2025, 1, 1), None, "pending")) + } + } catch { + case e: Exception => + val msg = Option(e.getMessage).getOrElse("") + threw = msg.contains("FOREIGN KEY") || msg.toLowerCase.contains("foreign key") + } + assertTrue("Expected FK violation", threw) + } + + @Test def typeSafeIds(): Unit = withConnection { + val cid = CustomersId(200L); val pid = ProductsId(200L); val oid = OrdersId(200L) + customers.insert(CustomersRow(cid, "TS", None, LocalDateTime.of(2025, 1, 1, 0, 0))) + products.insert(ProductsRow(pid, "SKU-200", "TS Prod", BigDecimal("1.00"), None)) + orders.insert(OrdersRow(oid, cid, LocalDate.of(2025, 1, 1), None, "pending")) + assertTrue(customers.selectById(cid).isDefined) + assertTrue(products.selectById(pid).isDefined) + assertTrue(orders.selectById(oid).isDefined) + } +} diff --git a/testers/sqlite/scala/src/scala/testdb/MockRepoTest.scala b/testers/sqlite/scala/src/scala/testdb/MockRepoTest.scala new file mode 100644 index 0000000000..d624bbf519 --- /dev/null +++ b/testers/sqlite/scala/src/scala/testdb/MockRepoTest.scala @@ -0,0 +1,100 @@ +package testdb + +import dev.typr.foundations.Bijection +import org.junit.Assert.* +import org.junit.Test +import testdb.customers.* +import testdb.departments.* +import testdb.userdefined.Email + +import java.time.LocalDateTime + +class MockRepoTest { + private def mkMock(): CustomersRepoMock = + CustomersRepoMock(toRow = unsaved => unsaved.toRow(LocalDateTime.of(2025, 1, 1, 0, 0))) + + @Test def testMockInsertAndSelect(): Unit = { + val mock = mkMock() + val row = CustomersRow(CustomersId(1L), "Mock User", Some(Email("mock@test.com")), LocalDateTime.of(2025, 1, 1, 0, 0)) + val inserted = mock.insert(row)(using null) + assertEquals("Mock User", inserted.name) + val found = mock.selectById(CustomersId(1L))(using null) + assertTrue(found.isDefined) + assertEquals("Mock User", found.get.name) + } + + @Test def testMockUpdate(): Unit = { + val mock = mkMock() + val row = CustomersRow(CustomersId(2L), "Original", None, LocalDateTime.of(2025, 1, 1, 0, 0)) + mock.insert(row)(using null) + mock.update(row.copy(name = "Updated"))(using null) + assertEquals("Updated", mock.selectById(CustomersId(2L))(using null).get.name) + } + + @Test def testMockDelete(): Unit = { + val mock = mkMock() + mock.insert(CustomersRow(CustomersId(3L), "Del", None, LocalDateTime.of(2025, 1, 1, 0, 0)))(using null) + assertTrue(mock.selectById(CustomersId(3L))(using null).isDefined) + mock.deleteById(CustomersId(3L))(using null) + assertFalse(mock.selectById(CustomersId(3L))(using null).isDefined) + } + + @Test def testMockSelectAll(): Unit = { + val mock = mkMock() + mock.insert(CustomersRow(CustomersId(10L), "U1", None, LocalDateTime.of(2025, 1, 1, 0, 0)))(using null) + mock.insert(CustomersRow(CustomersId(11L), "U2", None, LocalDateTime.of(2025, 1, 1, 0, 0)))(using null) + mock.insert(CustomersRow(CustomersId(12L), "U3", None, LocalDateTime.of(2025, 1, 1, 0, 0)))(using null) + assertEquals(3, mock.selectAll(using null).size) + } + + @Test def testMockDSLLimit(): Unit = { + val mock = mkMock() + (0 until 10).foreach { i => + mock.insert(CustomersRow(CustomersId(300L + i), s"Limit$i", None, LocalDateTime.of(2025, 1, 1, 0, 0)))(using null) + } + val results = mock.select.where(c => c.name.like("Limit%", Bijection.asString())).limit(5).toList(using null) + assertEquals(5, results.size) + } + + @Test def testMockWithCompositeKey(): Unit = { + val mock = DepartmentsRepoMock() + mock.insert(DepartmentsRow("MOCK_IT", "MOCK_US", "Mock IT US", Some(BigDecimal("500000"))))(using null) + val found = mock.selectById(DepartmentsId("MOCK_IT", "MOCK_US"))(using null) + assertTrue(found.isDefined) + assertEquals("Mock IT US", found.get.deptName) + } + + @Test def testMockDSLQuery(): Unit = { + val mock = mkMock() + mock.insert(CustomersRow(CustomersId(100L), "Alice", None, LocalDateTime.of(2025, 1, 1, 0, 0)))(using null) + mock.insert(CustomersRow(CustomersId(101L), "Bob", None, LocalDateTime.of(2025, 1, 1, 0, 0)))(using null) + mock.insert(CustomersRow(CustomersId(102L), "Charlie", None, LocalDateTime.of(2025, 1, 1, 0, 0)))(using null) + + val results = mock.select + .where(c => c.customerId.greaterThan(CustomersId(100L))) + .orderBy(c => c.name.asc) + .toList(using null) + + assertEquals(2, results.size) + assertEquals("Bob", results.head.name) + assertEquals("Charlie", results(1).name) + } + + @Test def testMockDSLCount(): Unit = { + val mock = mkMock() + mock.insert(CustomersRow(CustomersId(200L), "Count1", None, LocalDateTime.of(2025, 1, 1, 0, 0)))(using null) + mock.insert(CustomersRow(CustomersId(201L), "Count2", None, LocalDateTime.of(2025, 1, 1, 0, 0)))(using null) + mock.insert(CustomersRow(CustomersId(202L), "Other", None, LocalDateTime.of(2025, 1, 1, 0, 0)))(using null) + + val count = mock.select.where(c => c.name.like("Count%", Bijection.asString())).count(using null) + assertEquals(2, count) + } + + @Test def testMockIsolation(): Unit = { + val mock1 = mkMock() + val mock2 = mkMock() + mock1.insert(CustomersRow(CustomersId(400L), "Mock1", None, LocalDateTime.of(2025, 1, 1, 0, 0)))(using null) + assertTrue(mock1.selectById(CustomersId(400L))(using null).isDefined) + assertFalse(mock2.selectById(CustomersId(400L))(using null).isDefined) + } +} diff --git a/testers/sqlite/scala/src/scala/testdb/SqlScriptTest.scala b/testers/sqlite/scala/src/scala/testdb/SqlScriptTest.scala new file mode 100644 index 0000000000..e91a7704fd --- /dev/null +++ b/testers/sqlite/scala/src/scala/testdb/SqlScriptTest.scala @@ -0,0 +1,104 @@ +package testdb + +import dev.typr.foundationssc.{Connection, ConnectionRead} +import org.junit.Assert.* +import org.junit.Test +import testdb.all_scalar_types_search.AllScalarTypesSearchSqlRepoImpl +import testdb.customer_search.CustomerSearchSqlRepoImpl +import testdb.delete_old_orders.DeleteOldOrdersSqlRepoImpl +import testdb.order_summary_by_customer.OrderSummaryByCustomerSqlRepoImpl +import testdb.product_details_with_sales.ProductDetailsWithSalesSqlRepoImpl + +import java.time.{LocalDate, LocalDateTime} + +class SqlScriptTest { + private val customerSearch = new CustomerSearchSqlRepoImpl() + private val orderSummary = new OrderSummaryByCustomerSqlRepoImpl() + private val productDetails = new ProductDetailsWithSalesSqlRepoImpl() + private val scalarSearch = new AllScalarTypesSearchSqlRepoImpl() + private val deleteOld = new DeleteOldOrdersSqlRepoImpl() + + @Test def customerSearchAll(): Unit = withConnection { + val rows = customerSearch(None, None, None, 100L)(using summon[ConnectionRead]) + assertEquals(2, rows.size) + } + + @Test def customerSearchByName(): Unit = withConnection { + val rows = customerSearch(Some("John%"), None, None, 100L)(using summon[ConnectionRead]) + assertEquals(1, rows.size) + assertEquals("John Doe", rows.head.name) + } + + @Test def customerSearchByEmail(): Unit = withConnection { + val rows = customerSearch(None, Some("%jane%"), None, 100L)(using summon[ConnectionRead]) + assertEquals(1, rows.size) + } + + @Test def customerSearchLimit(): Unit = withConnection { + val rows = customerSearch(None, None, None, 1L)(using summon[ConnectionRead]) + assertEquals(1, rows.size) + } + + @Test def customerSearchByCreatedAfter(): Unit = withConnection { + val rows = customerSearch(None, None, Some(LocalDateTime.of(2099, 1, 1, 0, 0)), 100L)(using summon[ConnectionRead]) + assertEquals(0, rows.size) + } + + @Test def orderSummaryInRange(): Unit = withConnection { + val rows = orderSummary(LocalDate.of(2025, 1, 1), LocalDate.of(2025, 12, 31))(using summon[ConnectionRead]) + assertEquals(2, rows.size) + val total = rows.flatMap(_.totalRevenue).sum + assertEquals(0, BigDecimal("109.97").compare(total)) + } + + @Test def orderSummaryEmptyRange(): Unit = withConnection { + val rows = orderSummary(LocalDate.of(2099, 1, 1), LocalDate.of(2099, 12, 31))(using summon[ConnectionRead]) + assertEquals(0, rows.size) + } + + @Test def productDetailsAll(): Unit = withConnection { + val rows = productDetails(None)(using summon[ConnectionRead]) + assertEquals(2, rows.size) + } + + @Test def productDetailsMinPrice(): Unit = withConnection { + val rows = productDetails(Some(BigDecimal("40.00")))(using summon[ConnectionRead]) + assertEquals(1, rows.size) + assertEquals("Widget B", rows.head.productName) + } + + @Test def allScalarSearchAll(): Unit = withConnection { + val rows = scalarSearch(None, None, None)(using summon[ConnectionRead]) + assertEquals(1, rows.size) + } + + @Test def allScalarSearchMinId(): Unit = withConnection { + val rows = scalarSearch(Some(100L), None, None)(using summon[ConnectionRead]) + assertEquals(0, rows.size) + } + + @Test def allScalarSearchByText(): Unit = withConnection { + val rows = scalarSearch(None, Some("hel%"), None)(using summon[ConnectionRead]) + assertEquals(1, rows.size) + } + + @Test def deleteOldOrders(): Unit = withConnection { + val ordersRepo = new testdb.orders.OrdersRepoImpl() + ordersRepo.insert( + testdb.orders.OrdersRow( + testdb.orders.OrdersId(9001L), + testdb.customers.CustomersId(1L), + LocalDate.of(2020, 1, 1), + Some(BigDecimal("10.00")), + "completed" + ) + ) + val deleted = deleteOld(LocalDate.of(2025, 1, 1)) + assertEquals(1, deleted) + } + + @Test def deleteOldOrdersNoneMatch(): Unit = withConnection { + val deleted = deleteOld(LocalDate.of(1900, 1, 1)) + assertEquals(0, deleted) + } +} diff --git a/testers/sqlite/scala/src/scala/testdb/TestInsertTest.scala b/testers/sqlite/scala/src/scala/testdb/TestInsertTest.scala new file mode 100644 index 0000000000..0376a8ed3f --- /dev/null +++ b/testers/sqlite/scala/src/scala/testdb/TestInsertTest.scala @@ -0,0 +1,73 @@ +package testdb + +import org.junit.Assert.* +import org.junit.Test + +import scala.util.Random + +/** Generated TestInsert helpers actually persist random rows via the connection (the Scala variant differs from Java's pure-construction API). Verifies the SqliteAdapter arm in ComputedTestInserts + * produces values that round-trip. + */ +class TestInsertTest { + private val testInsert = TestInsert(Random(1169258584)) + + @Test def customersInsert(): Unit = withConnection { + val row = testInsert.Customers() + assertNotNull(row.customerId) + assertNotNull(row.name) + } + + @Test def customersWithCustomization(): Unit = withConnection { + val row = testInsert.Customers(name = "Custom Name") + assertEquals("Custom Name", row.name) + } + + @Test def departmentsInsert(): Unit = withConnection { + val row = testInsert.Departments() + assertNotNull(row.deptCode) + assertNotNull(row.deptRegion) + } + + @Test def productsInsert(): Unit = withConnection { + val row = testInsert.Products() + assertNotNull(row.productId) + assertNotNull(row.sku) + } + + @Test def allScalarTypesInsert(): Unit = withConnection { + val row = testInsert.AllScalarTypes() + assertNotNull(row.id) + assertNotNull(row.colNotNull) + } + + @Test def employeesWithDepartmentFK(): Unit = withConnection { + val dept = testInsert.Departments() + val emp = testInsert.Employees(DepartmentsId = dept.compositeId) + assertEquals(dept.deptCode, emp.deptCode) + assertEquals(dept.deptRegion, emp.deptRegion) + } + + @Test def ordersWithCustomerFK(): Unit = withConnection { + val cust = testInsert.Customers() + val ord = testInsert.Orders(customerId = cust.customerId) + assertEquals(cust.customerId, ord.customerId) + } + + @Test def multipleInserts(): Unit = withConnection { + val r1 = testInsert.Customers() + val r2 = testInsert.Customers() + val r3 = testInsert.Customers() + assertNotEquals(r1.customerId, r2.customerId) + assertNotEquals(r2.customerId, r3.customerId) + } + + @Test def seededRandomReproducible(): Unit = { + val name1 = withConnection { + TestInsert(Random(123)).Customers().name + } + val name2 = withConnection { + TestInsert(Random(123)).Customers().name + } + assertEquals(name1, name2) + } +} diff --git a/testers/sqlite/scala/src/scala/testdb/TupleInTest.scala b/testers/sqlite/scala/src/scala/testdb/TupleInTest.scala new file mode 100644 index 0000000000..4816dd6aae --- /dev/null +++ b/testers/sqlite/scala/src/scala/testdb/TupleInTest.scala @@ -0,0 +1,50 @@ +package testdb + +import org.junit.Assert.* +import org.junit.Test +import testdb.departments.* + +class TupleInTest { + private val repo = new DepartmentsRepoImpl() + + @Test def compositeIdInWithMultipleIds(): Unit = withConnection { + val d1 = repo.insert(DepartmentsRow("TI_A", "US", "A US", None)) + repo.insert(DepartmentsRow("TI_A", "EU", "A EU", None)) + val d3 = repo.insert(DepartmentsRow("TI_B", "US", "B US", None)) + repo.insert(DepartmentsRow("TI_B", "EU", "B EU", None)) + + val result = repo.select.where(d => d.compositeIdIn(List(d1.compositeId, d3.compositeId))).toList + assertEquals(2, result.size) + val ids = result.map(_.compositeId).toSet + assertEquals(Set(d1.compositeId, d3.compositeId), ids) + } + + @Test def compositeIdInWithSingleId(): Unit = withConnection { + val d1 = repo.insert(DepartmentsRow("TI_S", "APAC", "S APAC", None)) + repo.insert(DepartmentsRow("TI_S", "EMEA", "S EMEA", None)) + val result = repo.select.where(d => d.compositeIdIn(List(d1.compositeId))).toList + assertEquals(1, result.size) + assertEquals(d1, result.head) + } + + @Test def compositeIdInWithEmptyList(): Unit = withConnection { + val result = repo.select.where(d => d.compositeIdIn(Nil)).toList + assertTrue(result.isEmpty) + } + + @Test def compositeIdInWithNonExistent(): Unit = withConnection { + val result = repo.select.where(d => d.compositeIdIn(List(DepartmentsId("NOPE", "NEVER"), DepartmentsId("ALSO", "MISSING")))).toList + assertTrue(result.isEmpty) + } + + @Test def compositeIdInCombinedWithOther(): Unit = withConnection { + val d1 = repo.insert(DepartmentsRow("TI_C", "US", "Combined US", Some(BigDecimal("100000")))) + val d2 = repo.insert(DepartmentsRow("TI_C", "EU", "Combined EU", Some(BigDecimal("50000")))) + val result = repo.select + .where(d => d.compositeIdIn(List(d1.compositeId, d2.compositeId))) + .where(d => d.budget.greaterThan(BigDecimal("75000"))) + .toList + assertEquals(1, result.size) + assertEquals(d1, result.head) + } +} diff --git a/testers/sqlite/scala/src/scala/testdb/withConnection.scala b/testers/sqlite/scala/src/scala/testdb/withConnection.scala new file mode 100644 index 0000000000..b51d59cccd --- /dev/null +++ b/testers/sqlite/scala/src/scala/testdb/withConnection.scala @@ -0,0 +1,61 @@ +package testdb + +import dev.typr.foundationssc.* +import dev.typr.foundationssc.connect.{ConnectionSettings, SqliteConfig} + +import java.nio.file.{Files, Path} +import java.util.concurrent.atomic.AtomicBoolean + +object withConnection { + private lazy val schemaSQL: String = Files.readString(Path.of("sql-init/sqlite/00-schema.sql")) + private val config = SqliteConfig.inMemory().foreignKeys(true).build() + private val base = Transactor.create(config, ConnectionSettings.EMPTY) + private val transactor = base.rollbackOnly() + private val initialised = new AtomicBoolean(false) + + /** Split a multi-statement SQL string on `;` outside of `'...'` literals, stripping `-- ...` line comments. */ + private def splitStatements(sql: String): List[String] = { + val out = List.newBuilder[String] + val cur = new StringBuilder + var inString = false + var i = 0 + while (i < sql.length) { + val c = sql.charAt(i) + if (!inString && c == '-' && i + 1 < sql.length && sql.charAt(i + 1) == '-') { + while (i < sql.length && sql.charAt(i) != '\n') i += 1 + } else if (c == '\'') { + cur.append(c) + inString = !inString + i += 1 + } else if (c == ';' && !inString) { + out += cur.toString + cur.clear() + i += 1 + } else { + cur.append(c) + i += 1 + } + } + out += cur.toString + out.result() + } + + private def ensureInitialised(): Unit = + if (initialised.compareAndSet(false, true)) { + base.transact { + (conn: Connection) ?=> + val stmt = summon[Connection].unwrap().createStatement() + try + splitStatements(schemaSQL).foreach { s => + val t = s.trim + if (t.nonEmpty) stmt.execute(t) + } + finally stmt.close() + } + } + + def apply[T](f: Connection ?=> T): T = { + ensureInitialised() + transactor.transact(f) + } +} diff --git a/typr-codegen/generated-and-checked-in-jsonschema/config/generated/SqliteBoundary.scala b/typr-codegen/generated-and-checked-in-jsonschema/config/generated/SqliteBoundary.scala new file mode 100644 index 0000000000..d89ec77a70 --- /dev/null +++ b/typr-codegen/generated-and-checked-in-jsonschema/config/generated/SqliteBoundary.scala @@ -0,0 +1,23 @@ +package typr.config.generated + +import io.circe.Decoder +import io.circe.Encoder + +case class SqliteBoundary( + /** Path to SQLite file or :memory: for in-memory */ + path: String, + /** Path to schema SQL file to execute on startup */ + schema_sql: Option[String], + selectors: Option[BoundarySelectors], + /** Path to SQL scripts directory */ + sql_scripts: Option[String], + `type`: Option[String], + /** Boundary-level type definitions */ + types: Option[Map[String, FieldType]] +) + +object SqliteBoundary { + implicit val decoder: Decoder[SqliteBoundary] = io.circe.generic.semiauto.deriveDecoder[typr.config.generated.SqliteBoundary] + + implicit val encoder: Encoder[SqliteBoundary] = io.circe.generic.semiauto.deriveEncoder[typr.config.generated.SqliteBoundary] +} diff --git a/typr-codegen/src/scala/typr/DbType.scala b/typr-codegen/src/scala/typr/DbType.scala index 6a624fe953..b9b12bf258 100644 --- a/typr-codegen/src/scala/typr/DbType.scala +++ b/typr-codegen/src/scala/typr/DbType.scala @@ -1,6 +1,6 @@ package typr -import typr.internal.codegen.{Db2Adapter, DbAdapter, DuckDbAdapter, MariaDbAdapter, OracleAdapter, PostgresAdapter, SqlServerAdapter} +import typr.internal.codegen.{Db2Adapter, DbAdapter, DuckDbAdapter, MariaDbAdapter, OracleAdapter, PostgresAdapter, SqlServerAdapter, SqliteAdapter} import java.sql.Connection @@ -38,6 +38,10 @@ object DbType { def adapter(needsTimestampCasts: Boolean): DbAdapter = Db2Adapter } + case object SQLite extends DbType { + def adapter(needsTimestampCasts: Boolean): DbAdapter = SqliteAdapter + } + def detect(connection: Connection): DbType = { val metadata = connection.getMetaData val productName = metadata.getDatabaseProductName.toLowerCase @@ -50,6 +54,7 @@ object DbType { case name if name.contains("microsoft sql server") => SqlServer case name if name.contains("sql server") => SqlServer case name if name.contains("db2") => DB2 + case name if name.contains("sqlite") => SQLite case other => sys.error(s"Unsupported database: $other") } } @@ -66,6 +71,7 @@ object DbType { case name if name.contains("sqlserver") => SqlServer case name if name.contains("db2") => DB2 case name if name.contains("ibm data server") => DB2 + case name if name.contains("sqlite") => SQLite case other => sys.error(s"Unknown database driver: $other") } } diff --git a/typr-codegen/src/scala/typr/MetaDb.scala b/typr-codegen/src/scala/typr/MetaDb.scala index b477c204a6..6cdbb43d84 100644 --- a/typr-codegen/src/scala/typr/MetaDb.scala +++ b/typr-codegen/src/scala/typr/MetaDb.scala @@ -6,6 +6,7 @@ import typr.internal.external.ExternalTools import typr.internal.mariadb.{MariaMetaDb, MariaTypeMapperDb} import typr.internal.oracle.{OracleMetaDb, OracleTypeMapperDb} import typr.internal.pg.{PgMetaDb, PgTypeMapperDb} +import typr.internal.sqlite.{SqliteMetaDb, SqliteTypeMapperDb} import typr.internal.sqlserver.{SqlServerMetaDb, SqlServerTypeMapperDb} import typr.internal.{Lazy, TypeMapperDb} @@ -44,6 +45,7 @@ case class MetaDb( case DbType.Oracle => OracleTypeMapperDb(oracleObjectTypes, oracleCollectionTypes) case DbType.SqlServer => SqlServerTypeMapperDb(domains) case DbType.DB2 => Db2TypeMapperDb() + case DbType.SQLite => SqliteTypeMapperDb() } } @@ -140,6 +142,7 @@ object MetaDb { case DbType.Oracle => OracleMetaDb.fromDb(logger, ds, viewSelector, schemaMode) case DbType.SqlServer => SqlServerMetaDb.fromDb(logger, ds, viewSelector, schemaMode) case DbType.DB2 => Db2MetaDb.fromDb(logger, ds, viewSelector, schemaMode) + case DbType.SQLite => SqliteMetaDb.fromDb(logger, ds, viewSelector, schemaMode) } /** Load metadata from PostgreSQL-specific input (for backwards compatibility) */ diff --git a/typr-codegen/src/scala/typr/TypoDataSource.scala b/typr-codegen/src/scala/typr/TypoDataSource.scala index eddfa307fc..0d42593f39 100644 --- a/typr-codegen/src/scala/typr/TypoDataSource.scala +++ b/typr-codegen/src/scala/typr/TypoDataSource.scala @@ -8,6 +8,7 @@ import dev.typr.foundations.connect.OracleConfig import dev.typr.foundations.connect.PgConfig import dev.typr.foundations.connect.SqlServerConfig import dev.typr.foundations.connect.SqlServerEncrypt +import dev.typr.foundations.connect.SqliteConfig import dev.typr.foundations.hikari.HikariDataSourceFactory import java.sql.Connection @@ -73,6 +74,25 @@ object TypoDataSource { TypoDataSource(pooled.unwrap(), DbType.DB2) } + /** Create an in-memory SQLite TypoDataSource (xerial driver, ISO-8601 dates). */ + def hikariSqliteInMemory(): TypoDataSource = { + val config = SqliteConfig.inMemory().build() + val pooled = HikariDataSourceFactory.create(config) + TypoDataSource(pooled.unwrap(), DbType.SQLite) + } + + /** Create a file-backed SQLite TypoDataSource. */ + def hikariSqliteFile(path: String): TypoDataSource = { + val config = SqliteConfig.builder(path).build() + val pooled = HikariDataSourceFactory.create(config) + TypoDataSource(pooled.unwrap(), DbType.SQLite) + } + + /** Create a SQLite TypoDataSource from a path (":memory:" for in-memory, otherwise file-backed). */ + def hikariSqlite(path: String): TypoDataSource = + if (path == ":memory:") hikariSqliteInMemory() + else hikariSqliteFile(path) + /** Create a TypoDataSource with auto-detection of database type */ def hikari(ds: DataSource): TypoDataSource = { val conn = ds.getConnection @@ -85,6 +105,7 @@ object TypoDataSource { case DatabaseKind.ORACLE => DbType.Oracle case DatabaseKind.SQLSERVER => DbType.SqlServer case DatabaseKind.DB2 => DbType.DB2 + case DatabaseKind.SQLITE => DbType.SQLite } TypoDataSource(ds, dbType) } finally conn.close() diff --git a/typr-codegen/src/scala/typr/db.scala b/typr-codegen/src/scala/typr/db.scala index b242cb1fbd..69adc09b97 100644 --- a/typr-codegen/src/scala/typr/db.scala +++ b/typr-codegen/src/scala/typr/db.scala @@ -402,8 +402,48 @@ object db { case class DistinctType(name: RelationName, sourceType: Type) extends DB2Type } + sealed trait SqliteType extends Type + object SqliteType { + // INTEGER affinity + case object Integer extends SqliteType // generic INTEGER, Long + case object BigInt extends SqliteType + case object Int extends SqliteType // 32-bit alias + case object SmallInt extends SqliteType + case object TinyInt extends SqliteType + case object Boolean extends SqliteType // stored as 0/1 INTEGER + + // REAL affinity + case object Real extends SqliteType + case object Double extends SqliteType + case object Float extends SqliteType + + // NUMERIC affinity + case class Decimal(precision: Option[Int], scale: Option[Int]) extends SqliteType + + // TEXT affinity + case object Text extends SqliteType + case class VarChar(length: Option[Int]) extends SqliteType + case class Char(length: Option[Int]) extends SqliteType + case object Clob extends SqliteType + + // BLOB affinity + case object Blob extends SqliteType + case object Binary extends SqliteType + case object VarBinary extends SqliteType + + // Date/time (ISO-8601 text by default in xerial / SqliteTypes) + case object Date extends SqliteType + case object Time extends SqliteType + case object Timestamp extends SqliteType + case object Instant extends SqliteType + + // Convenience types + case object Uuid extends SqliteType + case object Json extends SqliteType + } + // Shared/unknown type - extends PgType, MariaType, and OracleType for pattern matching - case class Unknown(sqlType: String) extends PgType with MariaType with DuckDbType with OracleType with SqlServerType with DB2Type + case class Unknown(sqlType: String) extends PgType with MariaType with DuckDbType with OracleType with SqlServerType with DB2Type with SqliteType case class Domain(name: RelationName, tpe: Type, originalType: String, isNotNull: Nullability, hasDefault: Boolean, constraintDefinition: Option[String]) case class StringEnum(name: RelationName, values: NonEmptyList[String]) diff --git a/typr-codegen/src/scala/typr/internal/ComputedTestInserts.scala b/typr-codegen/src/scala/typr/internal/ComputedTestInserts.scala index 9347e984b2..ef076dda7a 100644 --- a/typr-codegen/src/scala/typr/internal/ComputedTestInserts.scala +++ b/typr-codegen/src/scala/typr/internal/ComputedTestInserts.scala @@ -153,6 +153,9 @@ object ComputedTestInserts { case db.DB2Type.VarChar(Some(maxLength)) => maxLength // DuckDB case db.DuckDbType.VarChar(Some(maxLength)) => maxLength + // SQLite + case db.SqliteType.VarChar(Some(maxLength)) => maxLength + case db.SqliteType.Char(Some(maxLength)) => maxLength } .getOrElse(20) .min(20) diff --git a/typr-codegen/src/scala/typr/internal/InstanceRequirements.scala b/typr-codegen/src/scala/typr/internal/InstanceRequirements.scala index aa05e5d902..2e96eac7d5 100644 --- a/typr-codegen/src/scala/typr/internal/InstanceRequirements.scala +++ b/typr-codegen/src/scala/typr/internal/InstanceRequirements.scala @@ -76,6 +76,8 @@ object InstanceRequirements { Some(DbType.SqlServer) else if (lower.contains("db2")) Some(DbType.DB2) + else if (lower.contains("sqlite")) + Some(DbType.SQLite) else None } @@ -88,5 +90,6 @@ object InstanceRequirements { case DbType.Oracle => "oracleType" case DbType.SqlServer => "sqlServerType" case DbType.DB2 => "db2Type" + case DbType.SQLite => "sqliteType" } } diff --git a/typr-codegen/src/scala/typr/internal/TypeCompatibilityChecker.scala b/typr-codegen/src/scala/typr/internal/TypeCompatibilityChecker.scala index fc3f40ad92..e4658f47d5 100644 --- a/typr-codegen/src/scala/typr/internal/TypeCompatibilityChecker.scala +++ b/typr-codegen/src/scala/typr/internal/TypeCompatibilityChecker.scala @@ -95,6 +95,8 @@ object TypeCompatibilityChecker { CompatibilityClass("String") case db.DB2Type.VarChar(_) | db.DB2Type.Char(_) | db.DB2Type.Clob | db.DB2Type.Long | db.DB2Type.Graphic(_) | db.DB2Type.VarGraphic(_) | db.DB2Type.DbClob | db.DB2Type.LongVarGraphic => CompatibilityClass("String") + case db.SqliteType.Text | db.SqliteType.VarChar(_) | db.SqliteType.Char(_) | db.SqliteType.Clob => + CompatibilityClass("String") // Boolean types case db.PgType.Boolean => CompatibilityClass("Boolean") @@ -103,6 +105,7 @@ object TypeCompatibilityChecker { case db.OracleType.Boolean => CompatibilityClass("Boolean") case db.SqlServerType.Bit => CompatibilityClass("Boolean") case db.DB2Type.Boolean => CompatibilityClass("Boolean") + case db.SqliteType.Boolean => CompatibilityClass("Boolean") // 32-bit integer types case db.PgType.Int4 => CompatibilityClass("Int") @@ -110,6 +113,7 @@ object TypeCompatibilityChecker { case db.DuckDbType.Integer => CompatibilityClass("Int") case db.SqlServerType.Int => CompatibilityClass("Int") case db.DB2Type.Integer => CompatibilityClass("Int") + case db.SqliteType.Int => CompatibilityClass("Int") // 64-bit integer types case db.PgType.Int8 => CompatibilityClass("Long") @@ -117,6 +121,7 @@ object TypeCompatibilityChecker { case db.DuckDbType.BigInt => CompatibilityClass("Long") case db.SqlServerType.BigInt => CompatibilityClass("Long") case db.DB2Type.BigInt => CompatibilityClass("Long") + case db.SqliteType.Integer | db.SqliteType.BigInt => CompatibilityClass("Long") case db.OracleType.Number(Some(p), Some(0)) if p > 9 && p <= 18 => CompatibilityClass("Long") // 16-bit integer types @@ -125,6 +130,8 @@ object TypeCompatibilityChecker { case db.DuckDbType.SmallInt => CompatibilityClass("Short") case db.SqlServerType.SmallInt => CompatibilityClass("Short") case db.DB2Type.SmallInt => CompatibilityClass("Short") + case db.SqliteType.SmallInt => CompatibilityClass("Short") + case db.SqliteType.TinyInt => CompatibilityClass("Byte") // Single-precision float case db.PgType.Float4 => CompatibilityClass("Float") @@ -132,6 +139,7 @@ object TypeCompatibilityChecker { case db.DuckDbType.Float => CompatibilityClass("Float") case db.SqlServerType.Real => CompatibilityClass("Float") case db.DB2Type.Real => CompatibilityClass("Float") + case db.SqliteType.Float => CompatibilityClass("Float") case db.OracleType.BinaryFloat => CompatibilityClass("Float") // Double-precision float @@ -140,6 +148,8 @@ object TypeCompatibilityChecker { case db.DuckDbType.Double => CompatibilityClass("Double") case db.SqlServerType.Float => CompatibilityClass("Double") case db.DB2Type.Double => CompatibilityClass("Double") + case db.SqliteType.Real => CompatibilityClass("Double") + case db.SqliteType.Double => CompatibilityClass("Double") case db.OracleType.BinaryDouble => CompatibilityClass("Double") // Decimal/Numeric types -> BigDecimal @@ -150,6 +160,7 @@ object TypeCompatibilityChecker { case db.OracleType.Float(_) => CompatibilityClass("BigDecimal") case db.SqlServerType.Decimal(_, _) | db.SqlServerType.Numeric(_, _) | db.SqlServerType.Money | db.SqlServerType.SmallMoney => CompatibilityClass("BigDecimal") case db.DB2Type.Decimal(_, _) | db.DB2Type.DecFloat(_) => CompatibilityClass("BigDecimal") + case db.SqliteType.Decimal(_, _) => CompatibilityClass("BigDecimal") // Date types case db.PgType.Date => CompatibilityClass("LocalDate") @@ -158,6 +169,7 @@ object TypeCompatibilityChecker { case db.OracleType.Date => CompatibilityClass("LocalDate") case db.SqlServerType.Date => CompatibilityClass("LocalDate") case db.DB2Type.Date => CompatibilityClass("LocalDate") + case db.SqliteType.Date => CompatibilityClass("LocalDate") // Time types case db.PgType.Time => CompatibilityClass("LocalTime") @@ -165,6 +177,7 @@ object TypeCompatibilityChecker { case db.DuckDbType.Time => CompatibilityClass("LocalTime") case db.SqlServerType.Time(_) => CompatibilityClass("LocalTime") case db.DB2Type.Time => CompatibilityClass("LocalTime") + case db.SqliteType.Time => CompatibilityClass("LocalTime") // Timestamp with timezone case db.PgType.TimestampTz => CompatibilityClass("Instant") @@ -180,11 +193,14 @@ object TypeCompatibilityChecker { case db.OracleType.TimestampWithLocalTimeZone(_) => CompatibilityClass("Instant") case db.SqlServerType.DateTime | db.SqlServerType.DateTime2(_) | db.SqlServerType.SmallDateTime => CompatibilityClass("LocalDateTime") case db.DB2Type.Timestamp(_) => CompatibilityClass("LocalDateTime") + case db.SqliteType.Timestamp => CompatibilityClass("LocalDateTime") + case db.SqliteType.Instant => CompatibilityClass("Instant") // UUID case db.PgType.UUID => CompatibilityClass("UUID") case db.DuckDbType.UUID => CompatibilityClass("UUID") case db.SqlServerType.UniqueIdentifier => CompatibilityClass("UUID") + case db.SqliteType.Uuid => CompatibilityClass("UUID") // Binary types case db.PgType.Bytea => CompatibilityClass("ByteArray") @@ -193,6 +209,7 @@ object TypeCompatibilityChecker { case db.OracleType.Blob | db.OracleType.Raw(_) | db.OracleType.LongRaw => CompatibilityClass("ByteArray") case db.SqlServerType.Binary(_) | db.SqlServerType.VarBinary(_) | db.SqlServerType.Image => CompatibilityClass("ByteArray") case db.DB2Type.Blob | db.DB2Type.Binary(_) | db.DB2Type.VarBinary(_) => CompatibilityClass("ByteArray") + case db.SqliteType.Blob | db.SqliteType.Binary | db.SqliteType.VarBinary => CompatibilityClass("ByteArray") // JSON types case db.PgType.Json | db.PgType.Jsonb => CompatibilityClass("Json") @@ -200,6 +217,7 @@ object TypeCompatibilityChecker { case db.DuckDbType.Json => CompatibilityClass("Json") case db.OracleType.Json => CompatibilityClass("Json") case db.SqlServerType.Json => CompatibilityClass("Json") + case db.SqliteType.Json => CompatibilityClass("Json") // Array types - compatible if element types are compatible case db.PgType.Array(inner) => CompatibilityClass(s"Array[${compatibilityClass(inner).description}]") diff --git a/typr-codegen/src/scala/typr/internal/TypeMapperJvmNew.scala b/typr-codegen/src/scala/typr/internal/TypeMapperJvmNew.scala index bdd00aa1e1..7b5d8a8064 100644 --- a/typr-codegen/src/scala/typr/internal/TypeMapperJvmNew.scala +++ b/typr-codegen/src/scala/typr/internal/TypeMapperJvmNew.scala @@ -103,6 +103,12 @@ case class TypeMapperJvmNew( Some(jvm.Type.Qualified(naming.preciseBinaryNName(n))) case db.DB2Type.VarBinary(Some(n)) => Some(jvm.Type.Qualified(naming.preciseBinaryNName(n))) + case db.SqliteType.VarChar(Some(n)) => + Some(jvm.Type.Qualified(naming.preciseStringNName(n))) + case db.SqliteType.Char(Some(n)) => + Some(jvm.Type.Qualified(naming.precisePaddedStringNName(n))) + case db.SqliteType.Decimal(Some(precision), Some(scale)) => + Some(jvm.Type.Qualified(naming.preciseDecimalNName(precision, scale))) case _ => None } @@ -397,6 +403,33 @@ case class TypeMapperJvmNew( case db.DB2Type.DistinctType(name, _) => jvm.Type.Qualified(naming.domainName(name)) case db.Unknown(_) => TypesJava.runtime.Unknown } + case x: db.SqliteType => + x match { + case db.SqliteType.Integer => lang.Long + case db.SqliteType.BigInt => lang.Long + case db.SqliteType.Int => lang.Int + case db.SqliteType.SmallInt => lang.Short + case db.SqliteType.TinyInt => lang.Byte + case db.SqliteType.Boolean => lang.Boolean + case db.SqliteType.Real => lang.Double + case db.SqliteType.Double => lang.Double + case db.SqliteType.Float => lang.Float + case db.SqliteType.Decimal(_, _) => lang.BigDecimal + case db.SqliteType.Text => lang.String + case db.SqliteType.VarChar(_) => lang.String + case db.SqliteType.Char(_) => lang.String + case db.SqliteType.Clob => lang.String + case db.SqliteType.Blob => lang.ByteArrayType + case db.SqliteType.Binary => lang.ByteArrayType + case db.SqliteType.VarBinary => lang.ByteArrayType + case db.SqliteType.Date => TypesJava.LocalDate + case db.SqliteType.Time => TypesJava.LocalTime + case db.SqliteType.Timestamp => TypesJava.LocalDateTime + case db.SqliteType.Instant => TypesJava.Instant + case db.SqliteType.Uuid => TypesJava.UUID + case db.SqliteType.Json => TypesJava.runtime.Json + case db.Unknown(_) => TypesJava.runtime.Unknown + } } } } diff --git a/typr-codegen/src/scala/typr/internal/TypeMatcher.scala b/typr-codegen/src/scala/typr/internal/TypeMatcher.scala index b4fec7cb7c..b17cd50fbd 100644 --- a/typr-codegen/src/scala/typr/internal/TypeMatcher.scala +++ b/typr-codegen/src/scala/typr/internal/TypeMatcher.scala @@ -341,6 +341,31 @@ object TypeMatcher { case db.DB2Type.RowId => "rowid" case db.DB2Type.DistinctType(name, _) => name.value + // SQLite types + case db.SqliteType.Integer => "integer" + case db.SqliteType.BigInt => "bigint" + case db.SqliteType.Int => "int" + case db.SqliteType.SmallInt => "smallint" + case db.SqliteType.TinyInt => "tinyint" + case db.SqliteType.Boolean => "boolean" + case db.SqliteType.Real => "real" + case db.SqliteType.Double => "double" + case db.SqliteType.Float => "float" + case db.SqliteType.Decimal(_, _) => "decimal" + case db.SqliteType.Text => "text" + case db.SqliteType.VarChar(_) => "varchar" + case db.SqliteType.Char(_) => "char" + case db.SqliteType.Clob => "clob" + case db.SqliteType.Blob => "blob" + case db.SqliteType.Binary => "binary" + case db.SqliteType.VarBinary => "varbinary" + case db.SqliteType.Date => "date" + case db.SqliteType.Time => "time" + case db.SqliteType.Timestamp => "timestamp" + case db.SqliteType.Instant => "timestamp" + case db.SqliteType.Uuid => "uuid" + case db.SqliteType.Json => "json" + // Unknown case db.Unknown(sqlType) => sqlType } diff --git a/typr-codegen/src/scala/typr/internal/codegen/DbLibFoundations.scala b/typr-codegen/src/scala/typr/internal/codegen/DbLibFoundations.scala index 7bd786e2d9..8c129e5881 100644 --- a/typr-codegen/src/scala/typr/internal/codegen/DbLibFoundations.scala +++ b/typr-codegen/src/scala/typr/internal/codegen/DbLibFoundations.scala @@ -479,7 +479,7 @@ class DbLibFoundations( ) } - case DbType.SqlServer | DbType.DB2 => + case DbType.SqlServer | DbType.DB2 | DbType.SQLite => // SQL Server and DB2 don't support arrays, use same approach as MariaDB with IN clause id match { case x: IdComputed.Unary => @@ -740,7 +740,7 @@ class DbLibFoundations( ) } - case DbType.SqlServer | DbType.DB2 => + case DbType.SqlServer | DbType.DB2 | DbType.SQLite => // SQL Server and DB2 don't support arrays, use same approach as MariaDB with IN clause id match { case x: IdComputed.Unary => diff --git a/typr-codegen/src/scala/typr/internal/codegen/SqliteAdapter.scala b/typr-codegen/src/scala/typr/internal/codegen/SqliteAdapter.scala new file mode 100644 index 0000000000..1c11a09ab7 --- /dev/null +++ b/typr-codegen/src/scala/typr/internal/codegen/SqliteAdapter.scala @@ -0,0 +1,235 @@ +package typr +package internal +package codegen + +import typr.jvm.Code + +object SqliteAdapter extends DbAdapter { + val dbType: DbType = DbType.SQLite + + // ═══════════════════════════════════════════════════════════════════════════ + // LAYER 1: SQL Syntax + // ═══════════════════════════════════════════════════════════════════════════ + + def quoteIdent(name: String): String = s""""$name"""" + + def typeCast(value: Code, typeName: String): Code = + if (typeName.isEmpty) value else code"CAST($value AS $typeName)" + + def columnReadCast(col: ComputedColumn): Code = Code.Empty + def columnWriteCast(col: ComputedColumn): Code = Code.Empty + def writeCastTypeName(col: ComputedColumn): Option[String] = None + def writeCast(dbType: db.Type, udtName: Option[String]): Option[SqlCastValue] = None + def readCast(dbType: db.Type): Option[SqlCastValue] = None + + // ═══════════════════════════════════════════════════════════════════════════ + // LAYER 2: Runtime Type System + // ═══════════════════════════════════════════════════════════════════════════ + + override val KotlinTypes: jvm.Type.Qualified = jvm.Type.Qualified("dev.typr.foundationskt.SqliteTypes") + override val ScalaTypes: jvm.Type.Qualified = jvm.Type.Qualified("dev.typr.foundationssc.SqliteTypes") + val Types: jvm.Type.Qualified = jvm.Type.Qualified("dev.typr.foundations.SqliteTypes") + val TypeClass: jvm.Type.Qualified = jvm.Type.Qualified("dev.typr.foundations.SqliteType") + val TextClass: jvm.Type.Qualified = jvm.Type.Qualified("dev.typr.foundations.SqliteText") + val typeFieldName: jvm.Ident = jvm.Ident("sqliteType") + val textFieldName: jvm.Ident = jvm.Ident("sqliteText") + def dialectRef(lang: Lang): Code = code"${lang.dsl.Dialect}.SQLITE" + + override def numericTypeName: String = "numeric" + + def lookupType(typoType: TypoType, naming: Naming, typeSupport: TypeSupport): Code = + typoType match { + case TypoType.Standard(_, dbType) => + lookupByDbType(dbType, typeSupport) + + case TypoType.Nullable(_, inner) => + nullableType(lookupType(inner, naming, typeSupport)) + + case TypoType.Generated(_, _, qualifiedType) => + code"$qualifiedType.$typeFieldName" + + case TypoType.StringN(_, _, _, qualifiedType) => code"$qualifiedType.$typeFieldName" + case TypoType.NonEmptyString(_, _, qualifiedType) => code"$qualifiedType.$typeFieldName" + case TypoType.NonEmptyStringN(_, _, _, qualifiedType) => code"$qualifiedType.$typeFieldName" + case TypoType.BinaryN(_, _, _, qualifiedType) => code"$qualifiedType.$typeFieldName" + case TypoType.DecimalN(_, _, _, _, qualifiedType) => code"$qualifiedType.$typeFieldName" + case TypoType.LocalDateTimeN(_, _, _, qualifiedType) => code"$qualifiedType.$typeFieldName" + case TypoType.InstantN(_, _, _, qualifiedType) => code"$qualifiedType.$typeFieldName" + case TypoType.LocalTimeN(_, _, _, qualifiedType) => code"$qualifiedType.$typeFieldName" + case TypoType.OffsetDateTimeN(_, _, _, qualifiedType) => code"$qualifiedType.$typeFieldName" + + case TypoType.UserDefined(_, _, userType) => + userType match { + case Left(qualifiedType) => code"$qualifiedType.$typeFieldName" + case Right(primitive) => lookupPrimitive(primitive, typeSupport) + } + + case TypoType.Array(_, _) => + sys.error("SqliteAdapter.lookupType: SQLite does not support array types") + + case TypoType.Aligned(_, sourceType, _, _) => + lookupType(sourceType, naming, typeSupport) + } + + def lookupPrimitive(primitive: analysis.WellKnownPrimitive, typeSupport: TypeSupport): Code = { + def primitiveType(name: String): Code = { + val nameIdent = jvm.Ident(name) + typeSupport match { + case TypeSupportScala => code"$ScalaTypes.$nameIdent" + case TypeSupportKotlin => code"$KotlinTypes.$nameIdent" + case TypeSupportJava | _ => code"$Types.$nameIdent" + } + } + + primitive match { + case analysis.WellKnownPrimitive.String => primitiveType("text") + case analysis.WellKnownPrimitive.Boolean => primitiveType("boolean_") + case analysis.WellKnownPrimitive.Byte => primitiveType("tinyint") + case analysis.WellKnownPrimitive.Short => primitiveType("smallint") + case analysis.WellKnownPrimitive.Int => primitiveType("int_") + case analysis.WellKnownPrimitive.Long => primitiveType("integer") + case analysis.WellKnownPrimitive.Float => primitiveType("float_") + case analysis.WellKnownPrimitive.Double => primitiveType("real") + case analysis.WellKnownPrimitive.BigDecimal => primitiveType("numeric") + case analysis.WellKnownPrimitive.LocalDate => primitiveType("date") + case analysis.WellKnownPrimitive.LocalTime => primitiveType("time") + case analysis.WellKnownPrimitive.LocalDateTime => primitiveType("datetime") + case analysis.WellKnownPrimitive.Instant => primitiveType("instant") + case analysis.WellKnownPrimitive.UUID => primitiveType("uuid") + } + } + + def textType: db.Type = db.SqliteType.Text + + def lookupTypeByDbType(dbType: db.Type, Types: jvm.Type.Qualified, naming: Naming, typeSupport: TypeSupport): Code = + lookupByDbType(dbType, typeSupport) + + private def lookupByDbType(dbType: db.Type, typeSupport: TypeSupport): Code = { + def primitiveType(name: String): Code = { + val nameIdent = jvm.Ident(name) + typeSupport match { + case TypeSupportScala => code"$ScalaTypes.$nameIdent" + case TypeSupportKotlin => code"$KotlinTypes.$nameIdent" + case TypeSupportJava | _ => code"$Types.$nameIdent" + } + } + + dbType match { + case dbType: db.SqliteType => + dbType match { + // INTEGER affinity + case db.SqliteType.Integer => primitiveType("integer") + case db.SqliteType.BigInt => primitiveType("bigint") + case db.SqliteType.Int => primitiveType("int_") + case db.SqliteType.SmallInt => primitiveType("smallint") + case db.SqliteType.TinyInt => primitiveType("tinyint") + case db.SqliteType.Boolean => primitiveType("boolean_") + + // REAL affinity + case db.SqliteType.Real => primitiveType("real") + case db.SqliteType.Double => primitiveType("double_") + case db.SqliteType.Float => primitiveType("float_") + + // NUMERIC affinity + case db.SqliteType.Decimal(_, _) => primitiveType("numeric") + + // TEXT affinity + case db.SqliteType.Text => primitiveType("text") + case db.SqliteType.VarChar(_) => primitiveType("varchar") + case db.SqliteType.Char(_) => primitiveType("char_") + case db.SqliteType.Clob => primitiveType("clob") + + // BLOB affinity + case db.SqliteType.Blob => primitiveType("blob") + case db.SqliteType.Binary => primitiveType("binary") + case db.SqliteType.VarBinary => primitiveType("varbinary") + + // Date/time + case db.SqliteType.Date => primitiveType("date") + case db.SqliteType.Time => primitiveType("time") + case db.SqliteType.Timestamp => primitiveType("timestamp") + case db.SqliteType.Instant => primitiveType("instant") + + // Convenience + case db.SqliteType.Uuid => primitiveType("uuid") + case db.SqliteType.Json => primitiveType("json") + + case db.Unknown(_) => primitiveType("unknown") + } + case _ => + sys.error("SqliteAdapter.lookupByDbType: Cannot lookup type from another database") + } + } + + // ═══════════════════════════════════════════════════════════════════════════ + // LAYER 3: Capabilities + // ═══════════════════════════════════════════════════════════════════════════ + + val supportsArrays: Boolean = false // SQLite has no native array type + val supportsReturning: Boolean = true // since SQLite 3.35 (2021) + val supportsCopyStreaming: Boolean = false + val supportsDefaultInCopy: Boolean = false + + def returningStrategy(cols: NonEmptyList[ComputedColumn], rowType: jvm.Type, maybeId: Option[IdComputed]): ReturningStrategy = + ReturningStrategy.SqlReturning(rowType) + + def upsertStrategy(rowType: jvm.Type): UpsertStrategy = + UpsertStrategy.Returning(rowType) + + // ═══════════════════════════════════════════════════════════════════════════ + // LAYER 4: SQL Templates + // ═══════════════════════════════════════════════════════════════════════════ + + def upsertSql( + tableName: Code, + columns: Code, + idColumns: Code, + values: Code, + conflictUpdate: Code, + returning: Option[Code] + ): Code = + returning match { + case Some(cols) => + code"""|INSERT INTO $tableName($columns) + |VALUES ($values) + |ON CONFLICT ($idColumns) + |$conflictUpdate + |RETURNING $cols""".stripMargin + case None => + code"""|INSERT INTO $tableName($columns) + |VALUES ($values) + |ON CONFLICT ($idColumns) + |$conflictUpdate""".stripMargin + } + + def conflictUpdateClause(cols: List[ComputedColumn], quotedColName: ComputedColumn => Code): Code = + code"""|DO UPDATE SET + | ${cols.map(c => code"${quotedColName(c)} = EXCLUDED.${quotedColName(c)}").mkCode(",\n")}""".stripMargin + + def conflictNoOpClause(firstPkCol: ComputedColumn, quotedColName: ComputedColumn => Code): Code = + code"DO UPDATE SET ${quotedColName(firstPkCol)} = EXCLUDED.${quotedColName(firstPkCol)}" + + override def mergeOnClause(idCols: NonEmptyList[ComputedColumn], quotedColName: ComputedColumn => Code): Code = + idCols.map(quotedColName).mkCode(", ") + + def streamingInsertSql(tableName: Code, columns: Code): Code = + code"/* SQLite has no COPY; use batched inserts in a transaction */" + + def createTempTableLike(tempName: String, sourceTable: Code): Code = + code"CREATE TEMPORARY TABLE $tempName AS SELECT * FROM $sourceTable WHERE 0" + + def returningClause(columns: Code): Code = + code"RETURNING $columns" + + // ═══════════════════════════════════════════════════════════════════════════ + // LAYER 5: Schema DDL + // ═══════════════════════════════════════════════════════════════════════════ + + // SQLite has no schemas (the "main"/"temp"/attached database namespaces are not what other DBs call schemas). + // Provide no-ops so the generic pipeline doesn't choke. + def dropSchemaDdl(schemaName: String, cascade: Boolean): String = + "-- SQLite has no schemas; nothing to drop" + + def createSchemaDdl(schemaName: String): String = + "-- SQLite has no schemas; nothing to create" +} diff --git a/typr-codegen/src/scala/typr/internal/generate.scala b/typr-codegen/src/scala/typr/internal/generate.scala index 575540a15d..9ad9daaa9d 100644 --- a/typr-codegen/src/scala/typr/internal/generate.scala +++ b/typr-codegen/src/scala/typr/internal/generate.scala @@ -60,6 +60,7 @@ object generate { case DbType.Oracle => "oracle" case DbType.SqlServer => "sqlserver" case DbType.DB2 => "db2" + case DbType.SQLite => "sqlite" } val scanResult = TypeMatcher.scanTables( @@ -272,6 +273,9 @@ object generate { case db.DB2Type.Timestamp(Some(fsp)) if fsp > 0 => Some(PreciseConstraint.LocalDateTimeN(fsp, dbCol.tpe)) case db.DB2Type.Binary(Some(n)) => Some(PreciseConstraint.BinaryN(n, dbCol.tpe)) case db.DB2Type.VarBinary(Some(n)) => Some(PreciseConstraint.BinaryN(n, dbCol.tpe)) + case db.SqliteType.VarChar(Some(n)) => Some(PreciseConstraint.StringN(n, dbCol.tpe)) + case db.SqliteType.Char(Some(n)) => Some(PreciseConstraint.PaddedStringN(n, dbCol.tpe)) + case db.SqliteType.Decimal(Some(p), Some(s)) => Some(PreciseConstraint.DecimalN(p, s, dbCol.tpe)) case _ => None } }.toSet diff --git a/typr-codegen/src/scala/typr/internal/sqlfiles/SqlFileReader.scala b/typr-codegen/src/scala/typr/internal/sqlfiles/SqlFileReader.scala index bc2d9eafa6..9fbf1d59bb 100644 --- a/typr-codegen/src/scala/typr/internal/sqlfiles/SqlFileReader.scala +++ b/typr-codegen/src/scala/typr/internal/sqlfiles/SqlFileReader.scala @@ -8,6 +8,7 @@ import typr.internal.duckdb.DuckDbSqlFileMetadata import typr.internal.oracle.OracleSqlFileMetadata import typr.internal.sqlserver.SqlServerSqlFileMetadata import typr.internal.db2.Db2SqlFileMetadata +import typr.internal.sqlite.SqliteSqlFileMetadata import java.nio.file.Path import scala.concurrent.{ExecutionContext, Future} @@ -28,6 +29,8 @@ object SqlFileReader { SqlServerSqlFileMetadata(logger, scriptsPath, ds, externalTools) case DbType.DB2 => Db2SqlFileMetadata(logger, scriptsPath, ds, externalTools) + case DbType.SQLite => + SqliteSqlFileMetadata(logger, scriptsPath, ds, externalTools) } } } diff --git a/typr-codegen/src/scala/typr/internal/sqlite/SqliteJdbcMetadata.scala b/typr-codegen/src/scala/typr/internal/sqlite/SqliteJdbcMetadata.scala new file mode 100644 index 0000000000..2161aea8c4 --- /dev/null +++ b/typr-codegen/src/scala/typr/internal/sqlite/SqliteJdbcMetadata.scala @@ -0,0 +1,79 @@ +package typr +package internal +package sqlite + +import typr.internal.analysis.* + +import java.sql.{Connection, PreparedStatement, ResultSetMetaData} + +/** SQLite-specific JDBC metadata extraction for views and queries. + * + * The xerial JDBC driver returns much of the column metadata we need via the standard {@link java.sql.ResultSetMetaData} contract — including `getColumnTypeName`, `isNullable`, `getColumnLabel` — so + * this mirrors the DuckDB shape. + */ +case class SqliteJdbcMetadata(columns: MaybeReturnsRows[NonEmptyList[MetadataColumn]]) + +object SqliteJdbcMetadata { + + def from(sql: String)(implicit c: Connection): Either[String, SqliteJdbcMetadata] = { + val ps = c.prepareStatement(sql) + try from(ps) + finally ps.close() + } + + def from(ps: PreparedStatement): Either[String, SqliteJdbcMetadata] = { + def nonEmpty(str: String): Option[String] = if (str == null || str.isEmpty) None else Some(str) + + Option(ps.getMetaData) match { + case None => + Right(SqliteJdbcMetadata(MaybeReturnsRows.Update)) + + case Some(metadata: ResultSetMetaData) => + val cols = 0 + .until(metadata.getColumnCount) + .map(_ + 1) + .map { n => + val baseTableName = nonEmpty(metadata.getTableName(n)) + val baseSchemaName = nonEmpty(metadata.getSchemaName(n)) + val baseColumnName = nonEmpty(metadata.getColumnName(n)) + + val columnLabel = metadata.getColumnLabel(n) + + MetadataColumn( + baseColumnName = baseColumnName.map(db.ColName.apply), + baseRelationName = baseTableName.map(name => db.RelationName(baseSchemaName, name)), + catalogName = nonEmpty(metadata.getCatalogName(n)), + columnClassName = metadata.getColumnClassName(n), + columnDisplaySize = metadata.getColumnDisplaySize(n), + parsedColumnName = ParsedName.of(columnLabel), + columnName = db.ColName(columnLabel), + columnType = JdbcType.fromInt(metadata.getColumnType(n)), + columnTypeName = metadata.getColumnTypeName(n), + format = 0, + isAutoIncrement = metadata.isAutoIncrement(n), + isCaseSensitive = metadata.isCaseSensitive(n), + isCurrency = metadata.isCurrency(n), + isDefinitelyWritable = metadata.isDefinitelyWritable(n), + isNullable = ColumnNullable.fromInt(metadata.isNullable(n)).getOrElse { + sys.error(s"Couldn't understand metadata.isNullable($n) = ${metadata.isNullable(n)}") + }, + isReadOnly = metadata.isReadOnly(n), + isSearchable = metadata.isSearchable(n), + isSigned = metadata.isSigned(n), + isWritable = metadata.isWritable(n), + precision = metadata.getPrecision(n), + scale = metadata.getScale(n), + schemaName = baseSchemaName, + tableName = baseTableName + ) + } + + NonEmptyList.fromList(cols.toList) match { + case Some(cols) => + Right(SqliteJdbcMetadata(MaybeReturnsRows.Query(cols))) + case None => + Left(s"found no columns for query") + } + } + } +} diff --git a/typr-codegen/src/scala/typr/internal/sqlite/SqliteMetaDb.scala b/typr-codegen/src/scala/typr/internal/sqlite/SqliteMetaDb.scala new file mode 100644 index 0000000000..963e7b4cb6 --- /dev/null +++ b/typr-codegen/src/scala/typr/internal/sqlite/SqliteMetaDb.scala @@ -0,0 +1,364 @@ +package typr +package internal +package sqlite + +import anorm.Column +import anorm.RowParser +import anorm.SqlStringInterpolation +import anorm.Success +import typr.internal.analysis.* + +import java.sql.Connection +import scala.concurrent.{ExecutionContext, Future} + +/** SQLite metadata extraction. + * + * SQLite has a single namespace per database (no schemas in the SQL-standard sense — the `main`, `temp`, and attached database names aren't user-defined schemas). We surface every relation under + * `RelationName(None, name)`. + * + * The metadata comes from: + * - `sqlite_master` (or `sqlite_schema`) for tables, views, and their DDL + * - `pragma_table_info(name)` for column info (type, notnull, dflt_value, pk-ordinal) + * - `pragma_foreign_key_list(name)` for foreign keys + * - `pragma_index_list(name)` + `pragma_index_info(idx)` for unique indexes + * + * SQLite has no native ENUM types or DOMAINs, so those are always empty. + */ +object SqliteMetaDb { + + case class SqliteMaster( + objectType: String, // "table" | "view" + name: String, + sql: Option[String] + ) + + object SqliteMaster { + def rowParser(idx: Int): RowParser[SqliteMaster] = RowParser[SqliteMaster] { row => + Success( + SqliteMaster( + objectType = row(idx + 0)(Column.columnToString), + name = row(idx + 1)(Column.columnToString), + sql = row(idx + 2)(Column.columnToOption(Column.columnToString)) + ) + ) + } + } + + /** One row from `PRAGMA table_info(name)`. */ + case class SqliteColumn( + tableName: String, + cid: Int, + columnName: String, + declaredType: String, + notNull: Boolean, + defaultValue: Option[String], + pkOrdinal: Int // 0 = not PK; >0 = position in composite PK + ) + + /** One row from `PRAGMA foreign_key_list(name)`. */ + case class SqliteForeignKey( + tableName: String, + id: Int, // groups multi-column FKs together + seq: Int, // ordinal within the FK + refTable: String, + fromColumn: String, + toColumn: Option[String] // null when the FK targets the PK without explicit column listing + ) + + /** Unique-index column from `pragma_index_list` + `pragma_index_info`. + * + * `origin` distinguishes: + * - "pk" — the primary-key index (we already have PK info from PRAGMA table_info) + * - "u" — UNIQUE constraint + * - "c" — explicit CREATE UNIQUE INDEX + */ + case class SqliteUniqueIndex( + tableName: String, + indexName: String, + origin: String, + seqno: Int, + columnName: String + ) + + case class AnalyzedView( + row: SqliteMaster, + decomposedSql: DecomposedSql, + jdbcMetadata: SqliteJdbcMetadata + ) + + case class Input( + tables: List[SqliteMaster], + columns: List[SqliteColumn], + foreignKeys: List[SqliteForeignKey], + uniqueIndexes: List[SqliteUniqueIndex], + analyzedViews: Map[db.RelationName, AnalyzedView] + ) + + object Input { + def fromDb(logger: TypoLogger, ds: TypoDataSource, viewSelector: Selector)(implicit ec: ExecutionContext): Future[Input] = { + for { + master <- logger.timed("fetching sqlite_master")(ds.run(implicit c => fetchMaster(c))) + tableNames = master.filter(m => m.objectType == "table" || m.objectType == "view").map(_.name) + columns <- logger.timed("fetching columns")(ds.run(implicit c => fetchColumns(c, tableNames))) + foreignKeys <- logger.timed("fetching foreign keys")(ds.run(implicit c => fetchForeignKeys(c, tableNames))) + uniqueIndexes <- logger.timed("fetching unique indexes")(ds.run(implicit c => fetchUniqueIndexes(c, tableNames))) + analyzedViews <- logger.timed("analysing views")(analyzeViews(ds, master, viewSelector)) + } yield Input( + tables = master.filter(_.objectType == "table"), + columns = columns, + foreignKeys = foreignKeys, + uniqueIndexes = uniqueIndexes, + analyzedViews = analyzedViews + ) + } + + private def analyzeViews(ds: TypoDataSource, master: List[SqliteMaster], viewSelector: Selector)(implicit ec: ExecutionContext): Future[Map[db.RelationName, AnalyzedView]] = { + ds.run { implicit c => + master + .filter(_.objectType == "view") + .flatMap { row => + val name = db.RelationName(None, row.name) + if (row.sql.isDefined && viewSelector.include(name)) { + val sqlContent = row.sql.get + val decomposed = DecomposedSql.parse(sqlContent) + val jdbcMetadata = SqliteJdbcMetadata.from(s"SELECT * FROM ${quoteIdent(row.name)}") match { + case Right(meta) => meta + case Left(_) => SqliteJdbcMetadata(MaybeReturnsRows.Update) + } + Some(name -> AnalyzedView(row, decomposed, jdbcMetadata)) + } else None + } + .toMap + } + } + + private def quoteIdent(name: String): String = s""""${name.replace("\"", "\"\"")}"""" + + private def fetchMaster(implicit conn: Connection): List[SqliteMaster] = + SQL"""SELECT type, name, sql + FROM sqlite_master + WHERE type IN ('table', 'view') + AND name NOT LIKE 'sqlite_%' + ORDER BY type, name""" + .as(SqliteMaster.rowParser(1).*) + + private def fetchColumns(conn: Connection, tableNames: List[String]): List[SqliteColumn] = + tableNames.flatMap { t => + val sql = s"""SELECT cid, name, type, "notnull", dflt_value, pk + FROM pragma_table_info(${quoteLiteral(t)}) + ORDER BY cid""" + val rows = executeAll(conn, sql) { rs => + SqliteColumn( + tableName = t, + cid = rs.getInt("cid"), + columnName = rs.getString("name"), + declaredType = Option(rs.getString("type")).getOrElse(""), + notNull = rs.getInt("notnull") != 0, + defaultValue = Option(rs.getString("dflt_value")), + pkOrdinal = rs.getInt("pk") + ) + } + rows + } + + private def fetchForeignKeys(conn: Connection, tableNames: List[String]): List[SqliteForeignKey] = + tableNames.flatMap { t => + val sql = s"""SELECT id, seq, "table", "from", "to" + FROM pragma_foreign_key_list(${quoteLiteral(t)}) + ORDER BY id, seq""" + executeAll(conn, sql) { rs => + SqliteForeignKey( + tableName = t, + id = rs.getInt("id"), + seq = rs.getInt("seq"), + refTable = rs.getString("table"), + fromColumn = rs.getString("from"), + toColumn = Option(rs.getString("to")) + ) + } + } + + private def fetchUniqueIndexes(conn: Connection, tableNames: List[String]): List[SqliteUniqueIndex] = { + case class IdxInfo(name: String, origin: String) + + tableNames.flatMap { t => + val listSql = s"""SELECT name, origin + FROM pragma_index_list(${quoteLiteral(t)}) + WHERE "unique" = 1 + ORDER BY seq""" + val idxRows = executeAll(conn, listSql) { rs => + IdxInfo(rs.getString("name"), rs.getString("origin")) + } + + idxRows.flatMap { idx => + val infoSql = s"""SELECT seqno, name + FROM pragma_index_info(${quoteLiteral(idx.name)}) + ORDER BY seqno""" + executeAll(conn, infoSql) { rs => + SqliteUniqueIndex( + tableName = t, + indexName = idx.name, + origin = idx.origin, + seqno = rs.getInt("seqno"), + columnName = rs.getString("name") + ) + } + } + } + } + + private def executeAll[T](conn: Connection, sql: String)(read: java.sql.ResultSet => T): List[T] = { + val stmt = conn.createStatement() + try { + val rs = stmt.executeQuery(sql) + try { + val out = List.newBuilder[T] + while (rs.next()) out += read(rs) + out.result() + } finally rs.close() + } finally stmt.close() + } + + private def quoteLiteral(s: String): String = "'" + s.replace("'", "''") + "'" + } + + def fromDb(logger: TypoLogger, ds: TypoDataSource, viewSelector: Selector, schemaMode: SchemaMode)(implicit ec: ExecutionContext): Future[MetaDb] = { + // SQLite has no schemas; schemaMode is ignored. + val _ = schemaMode + Input.fromDb(logger, ds, viewSelector).map(fromInput) + } + + def fromInput(input: Input): MetaDb = { + val typeMapper = SqliteTypeMapperDb() + + val columnsByTable: Map[db.RelationName, List[SqliteColumn]] = + input.columns.groupBy(c => db.RelationName(None, c.tableName)) + + val primaryKeys: Map[db.RelationName, db.PrimaryKey] = + input.columns + .filter(_.pkOrdinal > 0) + .groupBy(c => db.RelationName(None, c.tableName)) + .flatMap { case (rel, cols) => + NonEmptyList + .fromList(cols.sortBy(_.pkOrdinal).map(c => db.ColName(c.columnName))) + .map(nel => rel -> db.PrimaryKey(nel, db.RelationName(None, rel.name + "_pkey"))) + } + + val uniqueKeys: Map[db.RelationName, List[db.UniqueKey]] = + input.uniqueIndexes + .filter(u => u.origin == "u" || u.origin == "c") // skip "pk" — covered above + .groupBy(u => (db.RelationName(None, u.tableName), u.indexName)) + .toList + .flatMap { case ((rel, idxName), cols) => + NonEmptyList + .fromList(cols.sortBy(_.seqno).map(c => db.ColName(c.columnName))) + .map(nel => rel -> db.UniqueKey(nel, db.RelationName(None, idxName))) + } + .groupBy(_._1) + .map { case (k, v) => k -> v.map(_._2) } + + val foreignKeys: Map[db.RelationName, List[db.ForeignKey]] = + input.foreignKeys + .groupBy(fk => (db.RelationName(None, fk.tableName), fk.id)) + .toList + .flatMap { case ((rel, fkId), rows) => + val refTable = db.RelationName(None, rows.head.refTable) + val sorted = rows.sortBy(_.seq) + val fromCols = NonEmptyList.fromList(sorted.map(r => db.ColName(r.fromColumn))) + val toCols = NonEmptyList.fromList( + sorted + .flatMap(r => + r.toColumn.orElse { + // Implicit FK to PK — pick the PK columns from primaryKeys, in order + primaryKeys.get(refTable).map(pk => pk.colNames.toList(r.seq).value) + } + ) + .map(db.ColName.apply) + ) + for { + fc <- fromCols + tc <- toCols + } yield rel -> db.ForeignKey(fc, refTable, tc, db.RelationName(None, s"${rel.name}_fk_$fkId")) + } + .groupBy(_._1) + .map { case (k, v) => k -> v.map(_._2) } + + def colToDbCol(c: SqliteColumn): db.Col = { + val parsedName = ParsedName.of(c.columnName) + val nullability = + if (c.pkOrdinal > 0) Nullability.NoNulls + else if (c.notNull) Nullability.NoNulls + else Nullability.Nullable + + val parsedType = typeMapper.parseType(c.declaredType, characterMaximumLength = None) { () => () } + + db.Col( + parsedName = parsedName, + tpe = parsedType, + udtName = Some(c.declaredType), + nullability = nullability, + columnDefault = c.defaultValue, + maybeGenerated = None, + comment = None, + constraints = Nil, + jsonDescription = DebugJson(Map("declaredType" -> c.declaredType)) + ) + } + + val tables: Map[db.RelationName, Lazy[db.Relation]] = + input.tables.flatMap { tbl => + val rel = db.RelationName(None, tbl.name) + NonEmptyList.fromList(columnsByTable.getOrElse(rel, Nil).sortBy(_.cid)).map { cols => + val lazyT: Lazy[db.Relation] = Lazy { + db.Table( + name = rel, + comment = None, + cols = cols.map(colToDbCol), + primaryKey = primaryKeys.get(rel), + uniqueKeys = uniqueKeys.getOrElse(rel, Nil), + foreignKeys = foreignKeys.getOrElse(rel, Nil) + ) + } + rel -> lazyT + } + }.toMap + + val views: Map[db.RelationName, Lazy[db.Relation]] = + input.analyzedViews.flatMap { case (rel, analyzed) => + NonEmptyList.fromList(columnsByTable.getOrElse(rel, Nil).sortBy(_.cid)).map { cols => + val lazyV: Lazy[db.Relation] = Lazy { + val deps: Map[db.ColName, List[(db.RelationName, db.ColName)]] = + analyzed.jdbcMetadata.columns match { + case MaybeReturnsRows.Query(metadataCols) => + metadataCols.toList.flatMap { col => + col.baseRelationName.zip(col.baseColumnName).map(t => col.name -> List(t)) + }.toMap + case MaybeReturnsRows.Update => Map.empty + } + + val viewCols: NonEmptyList[(db.Col, ParsedName)] = cols.map { c => + val parsed = ParsedName.of(c.columnName) + (colToDbCol(c), parsed) + } + + db.View( + name = rel, + comment = None, + decomposedSql = analyzed.decomposedSql, + cols = viewCols, + deps = deps, + isMaterialized = false + ) + } + rel -> lazyV + } + } + + MetaDb( + dbType = DbType.SQLite, + relations = tables ++ views, + enums = Nil, + domains = Nil + ) + } +} diff --git a/typr-codegen/src/scala/typr/internal/sqlite/SqliteSqlFileMetadata.scala b/typr-codegen/src/scala/typr/internal/sqlite/SqliteSqlFileMetadata.scala new file mode 100644 index 0000000000..317dab761f --- /dev/null +++ b/typr-codegen/src/scala/typr/internal/sqlite/SqliteSqlFileMetadata.scala @@ -0,0 +1,377 @@ +package typr +package internal +package sqlite + +import _root_.typr.internal.analysis.* +import _root_.typr.internal.external.ExternalTools +import _root_.typr.internal.sqlfiles.SqlFile +import _root_.typr.internal.sqlglot.* + +import java.nio.file.{Files, Path} +import java.sql.Connection +import scala.concurrent.{ExecutionContext, Future} + +/** SQLite-specific SQL file metadata extraction via sqlglot. Mirrors DuckDbSqlFileMetadata. */ +object SqliteSqlFileMetadata { + + private case class TableColumnInfo( + tableName: String, + columnName: String, + dataType: String, + isNullable: Boolean, + isPrimaryKey: Boolean + ) + + def apply( + logger: TypoLogger, + scriptsPath: Path, + ds: TypoDataSource, + externalTools: ExternalTools + )(implicit ec: ExecutionContext): Future[List[SqlFile]] = { + val schemaFuture = ds.run { implicit c => + logger.info("Reading table schema from SQLite for sqlglot analysis") + readTableSchema(c) + } + + schemaFuture.flatMap { schema => + val sqlFilePaths = findSqlFilesUnder(scriptsPath) + if (sqlFilePaths.isEmpty) { + Future.successful(Nil) + } else { + val parsedFiles = sqlFilePaths.map { path => + val content = Files.readString(path) + val decomposed = DecomposedSql.parse(content) + (path, decomposed) + } + + val sqlglotResults = runSqlglotAnalysis(logger, externalTools, schema, parsedFiles) + + Future.successful(parsedFiles.flatMap { case (path, decomposed) => + buildSqlFile(logger, path, scriptsPath, decomposed, sqlglotResults.get(path.toString), schema) + }) + } + } + } + + /** Read SQLite schema by walking sqlite_master + PRAGMA table_info. */ + private def readTableSchema(implicit conn: Connection): Map[String, Map[String, SqlglotColumnSchema]] = { + val tableNames: List[String] = { + val stmt = conn.createStatement() + try { + val rs = stmt.executeQuery( + """SELECT name FROM sqlite_master + WHERE type IN ('table', 'view') AND name NOT LIKE 'sqlite_%' + ORDER BY name""" + ) + try { + val out = List.newBuilder[String] + while (rs.next()) out += rs.getString(1) + out.result() + } finally rs.close() + } finally stmt.close() + } + + tableNames.map { tableName => + val pragmaSql = s"""SELECT name, type, "notnull", pk + FROM pragma_table_info('${tableName.replace("'", "''")}')""" + val cols: List[TableColumnInfo] = { + val stmt = conn.createStatement() + try { + val rs = stmt.executeQuery(pragmaSql) + try { + val out = List.newBuilder[TableColumnInfo] + while (rs.next()) { + out += TableColumnInfo( + tableName = tableName, + columnName = rs.getString("name"), + dataType = Option(rs.getString("type")).getOrElse(""), + isNullable = rs.getInt("notnull") == 0, + isPrimaryKey = rs.getInt("pk") > 0 + ) + } + out.result() + } finally rs.close() + } finally stmt.close() + } + + val columnMap = cols.map { c => + c.columnName -> SqlglotColumnSchema( + `type` = if (c.dataType.isEmpty) "TEXT" else c.dataType.toUpperCase, + nullable = c.isNullable && !c.isPrimaryKey, + primaryKey = c.isPrimaryKey + ) + }.toMap + + tableName -> columnMap + }.toMap + } + + private def runSqlglotAnalysis( + logger: TypoLogger, + externalTools: ExternalTools, + schema: Map[String, Map[String, SqlglotColumnSchema]], + parsedFiles: List[(Path, DecomposedSql)] + ): Map[String, SqlglotFileResult] = { + val config = SqlglotAnalyzer.configFromExternalTools(externalTools) + + val fileInputs = parsedFiles.map { case (path, decomposed) => + SqlglotFileInput(path.toString, renderForSqlglot(decomposed)) + } + + val input = SqlglotAnalysisInput( + dialect = "sqlite", + schema = schema, + files = fileInputs + ) + + SqlglotAnalyzer.analyze(config, input, Some(logger)) match { + case SqlglotAnalyzer.AnalyzerResult.Success(output) => + output.results.map(r => r.path -> r).toMap + case SqlglotAnalyzer.AnalyzerResult.PythonError(code, stderr) => + logger.warn(s"sqlglot analysis failed with exit code $code: $stderr") + Map.empty + case SqlglotAnalyzer.AnalyzerResult.JsonParseError(_, error) => + logger.warn(s"sqlglot analysis returned invalid JSON: $error") + Map.empty + case SqlglotAnalyzer.AnalyzerResult.ProcessError(msg) => + logger.warn(s"sqlglot analysis process error: $msg") + Map.empty + } + } + + private def renderForSqlglot(decomposed: DecomposedSql): String = { + var unnamedIdx = 0 + decomposed.frags.map { + case DecomposedSql.SqlText(text) => text + case DecomposedSql.NotNamedParam => + val name = s":param$unnamedIdx" + unnamedIdx += 1 + name + case DecomposedSql.NamedParam(parsedName) => + s":${parsedName.name.value}" + }.mkString + } + + private def buildSqlFile( + logger: TypoLogger, + path: Path, + scriptsPath: Path, + decomposed: DecomposedSql, + sqlglotResult: Option[SqlglotFileResult], + schema: Map[String, Map[String, SqlglotColumnSchema]] + ): Option[SqlFile] = { + sqlglotResult match { + case None => + logger.warn(s"No sqlglot result for $path, skipping") + None + + case Some(result) if !result.success => + logger.warn(s"sqlglot failed to parse $path: ${result.error.getOrElse("unknown error")}, skipping") + None + + case Some(result) => + result.queryType.map(_.toUpperCase) match { + case Some("SELECT") | Some("WITH") => + buildSelectSqlFile(logger, path, scriptsPath, decomposed, result, schema) + + case Some("UPDATE") | Some("INSERT") | Some("DELETE") => + if (result.columns.nonEmpty) { + buildSelectSqlFile(logger, path, scriptsPath, decomposed, result, schema) + } else { + buildParams(logger, path, decomposed, result, schema).map { params => + val jdbcMetadata = JdbcMetadata(params, MaybeReturnsRows.Update) + SqlFile(RelPath.relativeTo(scriptsPath, path), decomposed, jdbcMetadata, None) + } + } + + case Some(other) => + logger.warn(s"Unknown query type '$other' for $path, skipping") + None + + case None => + if ( + result.columns.isEmpty && decomposed.frags.forall { + case DecomposedSql.SqlText(t) => t.trim.isEmpty + case _ => false + } + ) { + logger.info(s"Skipping $path because it's empty") + } else { + logger.warn(s"Could not determine query type for $path, skipping") + } + None + } + } + } + + private def buildSelectSqlFile( + logger: TypoLogger, + path: Path, + scriptsPath: Path, + decomposed: DecomposedSql, + result: SqlglotFileResult, + schema: Map[String, Map[String, SqlglotColumnSchema]] + ): Option[SqlFile] = { + if (result.columns.isEmpty) { + logger.warn(s"sqlglot found no columns for $path, skipping") + return None + } + + val missingTypes = result.columns.filter(col => col.sourceType.orElse(col.inferredType).isEmpty) + if (missingTypes.nonEmpty) { + val missing = missingTypes.map(c => s"${c.name}").mkString(", ") + logger.warn(s"Columns without type information in $path: $missing, skipping") + return None + } + + val cols = result.columns.map { col => + val parsedName = ParsedName.of(col.alias.getOrElse(col.name)) + val effectiveType = + if (col.isExpression) col.inferredType.orElse(col.sourceType).get + else col.sourceType.orElse(col.inferredType).get + + val isNullable = + if (col.nullableFromJoin) ColumnNullable.Nullable + else if (col.nullableInSchema) ColumnNullable.Nullable + else ColumnNullable.NoNulls + + MetadataColumn( + baseColumnName = col.sourceColumn.map(db.ColName.apply), + baseRelationName = col.sourceTable.map(t => db.RelationName(None, t)), + catalogName = None, + columnClassName = "", + columnDisplaySize = 0, + parsedColumnName = parsedName, + columnName = db.ColName(col.name), + columnType = JdbcType.VarChar, + columnTypeName = effectiveType, + format = 0, + isAutoIncrement = false, + isCaseSensitive = true, + isCurrency = false, + isDefinitelyWritable = false, + isNullable = isNullable, + isReadOnly = true, + isSearchable = true, + isSigned = true, + isWritable = false, + precision = 0, + scale = 0, + schemaName = None, + tableName = col.sourceTable, + isExpression = col.isExpression + ) + } + + NonEmptyList.fromList(cols) match { + case None => + logger.warn(s"No columns found for $path, skipping") + None + case Some(nel) => + buildParams(logger, path, decomposed, result, schema).map { params => + val jdbcMetadata = JdbcMetadata(params, MaybeReturnsRows.Query(nel)) + val nullableIndices = SqlglotAnalyzer.extractNullableIndices(result) + SqlFile(RelPath.relativeTo(scriptsPath, path), decomposed, jdbcMetadata, nullableIndices) + } + } + } + + private def buildParams( + logger: TypoLogger, + path: Path, + decomposed: DecomposedSql, + result: SqlglotFileResult, + schema: Map[String, Map[String, SqlglotColumnSchema]] + ): Option[List[MetadataParameterColumn]] = { + val paramsByName: Map[String, List[SqlglotParameterInfo]] = result.parameters.groupBy(_.name) + + val paramsWithTypes = decomposed.params.zipWithIndex.map { case (param, idx) => + val (paramName, userOverriddenType) = param match { + case DecomposedSql.NotNamedParam => (s"param$idx", None) + case DecomposedSql.NamedParam(parsedName) => (parsedName.name.value, parsedName.overriddenType) + } + + val matchingParams = paramsByName.getOrElse(paramName, Nil) + val sqlglotParam = + matchingParams + .find(p => p.sourceTable.isDefined && p.sourceColumn.isDefined) + .orElse(matchingParams.find(_.inferredType.isDefined)) + .orElse(matchingParams.headOption) + + val schemaType: Option[String] = for { + p <- sqlglotParam + sourceTable <- p.sourceTable + sourceColumn <- p.sourceColumn + tableSchema <- schema + .find { case (tableName, _) => + tableName.endsWith(s".$sourceTable") || tableName == sourceTable + } + .map(_._2) + columnSchema <- tableSchema.get(sourceColumn) + } yield columnSchema.`type` + + val fallbackFromUserType: Option[String] = userOverriddenType.flatMap { + case OverriddenType.Primitive(p) => Some(sqliteTypeNameFor(p)) + case OverriddenType.Qualified(_) => None + } + + val effectiveType = schemaType.orElse(sqlglotParam.flatMap(_.inferredType)).orElse(fallbackFromUserType) + val hasNullableHint = matchingParams.exists(_.nullableHint) + + (paramName, effectiveType, hasNullableHint) + } + + val missingTypes = paramsWithTypes.filter(_._2.isEmpty).map(_._1) + if (missingTypes.nonEmpty) { + logger.warn(s"Parameters without type information in $path: ${missingTypes.mkString(", ")}, skipping") + return None + } + + Some(paramsWithTypes.map { case (_, effectiveTypeOpt, hasNullableHint) => + val typeName = effectiveTypeOpt.get + MetadataParameterColumn( + isNullable = if (hasNullableHint) ParameterNullable.Nullable else ParameterNullable.NullableUnknown, + isSigned = true, + parameterMode = ParameterMode.ModeIn, + parameterType = JdbcType.VarChar, + parameterTypeName = typeName, + precision = 0, + scale = 0 + ) + }) + } + + def findSqlFilesUnder(scriptsPath: Path): List[Path] = { + if (!Files.exists(scriptsPath)) Nil + else { + val found = List.newBuilder[Path] + Files.walkFileTree( + scriptsPath, + new java.nio.file.SimpleFileVisitor[Path] { + override def visitFile(file: Path, attrs: java.nio.file.attribute.BasicFileAttributes): java.nio.file.FileVisitResult = { + if (file.toString.endsWith(".sql")) found += file + java.nio.file.FileVisitResult.CONTINUE + } + } + ) + found.result() + } + } + + private def sqliteTypeNameFor(p: WellKnownPrimitive): String = p match { + case WellKnownPrimitive.String => "TEXT" + case WellKnownPrimitive.Boolean => "BOOLEAN" + case WellKnownPrimitive.Byte => "TINYINT" + case WellKnownPrimitive.Short => "SMALLINT" + case WellKnownPrimitive.Int => "INT" + case WellKnownPrimitive.Long => "INTEGER" + case WellKnownPrimitive.Float => "FLOAT" + case WellKnownPrimitive.Double => "REAL" + case WellKnownPrimitive.BigDecimal => "NUMERIC" + case WellKnownPrimitive.LocalDate => "DATE" + case WellKnownPrimitive.LocalTime => "TIME" + case WellKnownPrimitive.LocalDateTime => "DATETIME" + case WellKnownPrimitive.Instant => "TIMESTAMP" + case WellKnownPrimitive.UUID => "UUID" + } +} diff --git a/typr-codegen/src/scala/typr/internal/sqlite/SqliteTypeMapperDb.scala b/typr-codegen/src/scala/typr/internal/sqlite/SqliteTypeMapperDb.scala new file mode 100644 index 0000000000..9edcbdf010 --- /dev/null +++ b/typr-codegen/src/scala/typr/internal/sqlite/SqliteTypeMapperDb.scala @@ -0,0 +1,118 @@ +package typr +package internal +package sqlite + +import scala.util.Try + +/** Map a SQLite declared type name to a db.SqliteType. + * + * SQLite's "type affinity" rules let columns be declared with almost any text and assign a storage class by substring matching ([SQLite docs §3.1]). We pick a single canonical SqliteType per + * declared name, treating the foundations SqliteTypes catalogue as the source of truth for what each name means in practice. + * + * Unknown declared names fall back to `Text` (TEXT affinity) — the same behaviour SQLite uses for an empty or unrecognised type declaration. + */ +case class SqliteTypeMapperDb() extends TypeMapperDb { + + private def toIntOption(s: String): Option[Int] = Try(s.toInt).toOption + + override def dbTypeFrom(typeName: String, characterMaximumLength: Option[Int])(logWarning: () => Unit): db.Type = + parseType(typeName, characterMaximumLength)(logWarning) + + /** Parse a declared SQLite type string into db.SqliteType. */ + def parseType(typeStr: String, characterMaximumLength: Option[Int])(logWarning: () => Unit): db.Type = { + val raw = typeStr.trim + if (raw.isEmpty) return db.SqliteType.Text + + val upper = raw.toUpperCase + val base = upper.takeWhile(c => c != '(' && !c.isWhitespace) + + // Parameterised types + if (upper.startsWith("DECIMAL(") || upper.startsWith("NUMERIC(") || upper.startsWith("NUMBER(")) { + val inner = upper.dropWhile(_ != '(').drop(1).takeWhile(_ != ')') + val parts = inner.split(",").map(_.trim) + val precision = parts.headOption.flatMap(toIntOption) + val scale = parts.lift(1).flatMap(toIntOption) + return db.SqliteType.Decimal(precision, scale) + } + if (upper.startsWith("VARCHAR(") || upper.startsWith("VARYING CHARACTER(") || upper.startsWith("NVARCHAR(")) { + val inner = upper.dropWhile(_ != '(').drop(1).takeWhile(_ != ')') + return db.SqliteType.VarChar(toIntOption(inner.trim)) + } + if (upper.startsWith("CHAR(") || upper.startsWith("CHARACTER(") || upper.startsWith("NCHAR(") || upper.startsWith("NATIVE CHARACTER(")) { + val inner = upper.dropWhile(_ != '(').drop(1).takeWhile(_ != ')') + return db.SqliteType.Char(toIntOption(inner.trim)) + } + + // Affinity by substring (SQLite §3.1 — order matters): + // 1. "INT" -> INTEGER affinity + // 2. "CHAR" / "CLOB" / "TEXT" -> TEXT + // 3. "BLOB" / "" (no decl) -> BLOB + // 4. "REAL" / "FLOA" / "DOUB" -> REAL + // 5. otherwise -> NUMERIC + // + // We refine that by keeping a more specific Java type where the foundations SqliteTypes + // catalogue exposes one (smallint, tinyint, etc.). + base match { + // INTEGER affinity — specific + case "INTEGER" => db.SqliteType.Integer + case "INT" => db.SqliteType.Int + case "INT2" | "INT4" => db.SqliteType.Int + case "INT8" | "BIGINT" => db.SqliteType.BigInt + case "SMALLINT" => db.SqliteType.SmallInt + case "TINYINT" => db.SqliteType.TinyInt + case "MEDIUMINT" => db.SqliteType.Int + case "UNSIGNED" => db.SqliteType.BigInt // "UNSIGNED BIG INT" + case "BOOLEAN" | "BOOL" => db.SqliteType.Boolean + + // REAL affinity + case "REAL" => db.SqliteType.Real + case "DOUBLE" => db.SqliteType.Double + case "FLOAT" | "FLOAT4" => db.SqliteType.Float + case "FLOAT8" => db.SqliteType.Double + + // NUMERIC affinity + case "NUMERIC" | "DECIMAL" | "NUMBER" => db.SqliteType.Decimal(None, None) + + // TEXT affinity — specific + case "TEXT" => db.SqliteType.Text + case "VARCHAR" | "NVARCHAR" => db.SqliteType.VarChar(characterMaximumLength) + case "CHAR" | "CHARACTER" | "NCHAR" => db.SqliteType.Char(characterMaximumLength) + case "CLOB" => db.SqliteType.Clob + + // BLOB affinity + case "BLOB" => db.SqliteType.Blob + case "BINARY" => db.SqliteType.Binary + case "VARBINARY" => db.SqliteType.VarBinary + + // Date/time (TEXT-affinity, but we track them as date/time) + case "DATE" => db.SqliteType.Date + case "TIME" => db.SqliteType.Time + case "DATETIME" => db.SqliteType.Timestamp + case "TIMESTAMP" => db.SqliteType.Timestamp + + // Convenience + case "UUID" => db.SqliteType.Uuid + case "JSON" => db.SqliteType.Json + + case _ => + // Fall back to SQLite's affinity rules on substrings, since SQLite itself accepts + // arbitrary declarations like "VARYING CHARACTER" or "DOUBLE PRECISION". + if (upper.contains("INT")) + db.SqliteType.Integer + else if (upper.contains("CHAR") || upper.contains("CLOB") || upper.contains("TEXT")) + db.SqliteType.Text + else if (upper.contains("BLOB") || upper.isEmpty) + db.SqliteType.Blob + else if (upper.contains("REAL") || upper.contains("FLOA") || upper.contains("DOUB")) + db.SqliteType.Real + else if (upper.contains("DEC") || upper.contains("NUM")) + db.SqliteType.Decimal(None, None) + else if (upper.contains("DATE") || upper.contains("TIME")) + db.SqliteType.Timestamp + else { + logWarning() + db.SqliteType.Text + } + } + } +} diff --git a/typr-config.schema.json b/typr-config.schema.json index 1abb20f69c..426988d934 100644 --- a/typr-config.schema.json +++ b/typr-config.schema.json @@ -405,7 +405,7 @@ "properties": { "type": { "type": "string", - "enum": ["postgresql", "mariadb", "mysql", "sqlserver", "oracle", "duckdb", "db2", "openapi", "jsonschema", "avro", "grpc"] + "enum": ["postgresql", "mariadb", "mysql", "sqlserver", "oracle", "duckdb", "db2", "sqlite", "openapi", "jsonschema", "avro", "grpc"] } }, "allOf": [ @@ -425,6 +425,14 @@ "$ref": "#/$defs/duckdbBoundary" } }, + { + "if": { + "properties": { "type": { "const": "sqlite" } } + }, + "then": { + "$ref": "#/$defs/sqliteBoundary" + } + }, { "if": { "properties": { "type": { "const": "openapi" } } @@ -557,6 +565,36 @@ } } }, + "sqliteBoundary": { + "type": "object", + "required": ["path"], + "properties": { + "type": { "type": "string" }, + "path": { + "type": "string", + "description": "Path to SQLite file or :memory: for in-memory" + }, + "schema_sql": { + "type": "string", + "description": "Path to schema SQL file to execute on startup" + }, + "sql_scripts": { + "type": "string", + "description": "Path to SQL scripts directory" + }, + "selectors": { + "$ref": "#/$defs/boundarySelectors", + "description": "Boundary-level selectors for tables, schemas, etc." + }, + "types": { + "type": "object", + "description": "Boundary-level type definitions", + "additionalProperties": { + "$ref": "#/$defs/fieldType" + } + } + } + }, "openapiBoundary": { "type": "object", "description": "OpenAPI boundary for REST API types", diff --git a/typr-dsl-kotlin/src/kotlin/dev/typr/dslkt/DeleteBuilder.kt b/typr-dsl-kotlin/src/kotlin/dev/typr/dslkt/DeleteBuilder.kt index e9621fefd8..d23acdec41 100644 --- a/typr-dsl-kotlin/src/kotlin/dev/typr/dslkt/DeleteBuilder.kt +++ b/typr-dsl-kotlin/src/kotlin/dev/typr/dslkt/DeleteBuilder.kt @@ -18,8 +18,8 @@ class DeleteBuilder internal constructor( * Add a WHERE clause to the delete. * Consecutive calls will be combined with AND. */ - fun where(predicate: (Fields) -> SqlExpr): DeleteBuilder { - return DeleteBuilder(javaBuilder.where { fields -> predicate(fields).underlying }) + fun where(predicate: SqlExprExtensions.(Fields) -> SqlExpr): DeleteBuilder { + return DeleteBuilder(javaBuilder.where { fields -> SqlExprExtensionsInstance.predicate(fields).underlying }) } /** diff --git a/typr-dsl-kotlin/src/kotlin/dev/typr/dslkt/UpdateBuilder.kt b/typr-dsl-kotlin/src/kotlin/dev/typr/dslkt/UpdateBuilder.kt index d0f669cf19..c6221877f9 100644 --- a/typr-dsl-kotlin/src/kotlin/dev/typr/dslkt/UpdateBuilder.kt +++ b/typr-dsl-kotlin/src/kotlin/dev/typr/dslkt/UpdateBuilder.kt @@ -57,8 +57,8 @@ class UpdateBuilder internal constructor( * Add a WHERE clause to the update. * Consecutive calls will be combined with AND. */ - fun where(predicate: (Fields) -> SqlExpr): UpdateBuilder { - return UpdateBuilder(javaBuilder.where { fields -> predicate(fields).underlying }) + fun where(predicate: SqlExprExtensions.(Fields) -> SqlExpr): UpdateBuilder { + return UpdateBuilder(javaBuilder.where { fields -> SqlExprExtensionsInstance.predicate(fields).underlying }) } /** diff --git a/typr-dsl-scala/src/scala/dev/typr/dslsc/package.scala b/typr-dsl-scala/src/scala/dev/typr/dslsc/package.scala index 5311b53fab..7bb7ac33ae 100644 --- a/typr-dsl-scala/src/scala/dev/typr/dslsc/package.scala +++ b/typr-dsl-scala/src/scala/dev/typr/dslsc/package.scala @@ -113,5 +113,6 @@ package object dslsc { val ORACLE: dev.typr.dsl.Dialect = dev.typr.dsl.Dialect.ORACLE val SQLSERVER: dev.typr.dsl.Dialect = dev.typr.dsl.Dialect.SQLSERVER val DB2: dev.typr.dsl.Dialect = dev.typr.dsl.Dialect.DB2 + val SQLITE: dev.typr.dsl.Dialect = dev.typr.dsl.Dialect.SQLITE } } diff --git a/typr-dsl/src/java/dev/typr/dsl/Dialect.java b/typr-dsl/src/java/dev/typr/dsl/Dialect.java index 1d4cf9fa45..6f4a4b9946 100644 --- a/typr-dsl/src/java/dev/typr/dsl/Dialect.java +++ b/typr-dsl/src/java/dev/typr/dsl/Dialect.java @@ -782,6 +782,89 @@ public boolean supportsTupleIn() { // SQL Server uses default column-by-column for tuples }; + /** + * SQLite dialect — uses double quotes for identifiers, CAST() for casts, and the {@code IS} / + * {@code IS NOT} operators for null-safe comparisons. SQLite has no schemas and only one + * namespace per database. + */ + Dialect SQLITE = + new Dialect() { + @Override + public DbType bigint() { + return dev.typr.foundations.SqliteTypes.bigint; + } + + @Override + public String quoteIdent(String name) { + return "\"" + name + "\""; + } + + @Override + public String escapeIdent(String name) { + return name.replace("\"", "\"\""); + } + + @Override + public Fragment typeCast(Fragment value, String typeName) { + if (typeName == null || typeName.isEmpty()) { + return value; + } + return Fragment.of("CAST(").append(value).append(Fragment.of(" AS " + typeName + ")")); + } + + @Override + public String columnRef(String alias, String quotedColumn) { + return alias + "." + quotedColumn; + } + + @Override + public Fragment nullSafeEquals(Fragment left, Fragment right) { + // SQLite: a IS b — the IS operator does null-safe comparison. + return Fragment.of("(") + .append(left) + .append(Fragment.of(" IS ")) + .append(right) + .append(Fragment.of(")")); + } + + @Override + public Fragment nullSafeNotEquals(Fragment left, Fragment right) { + return Fragment.of("(") + .append(left) + .append(Fragment.of(" IS NOT ")) + .append(right) + .append(Fragment.of(")")); + } + + @Override + public boolean supportsTupleIn() { + // Native (a,b) IN ((1,2)) is supported since SQLite 3.7.11 (2012). + return true; + } + + @Override + public Fragment appendPaginationClauses( + Fragment subquery, + String alias, + boolean queryIsAlreadyOrdered, + java.util.Optional limit, + java.util.Optional offset, + java.util.List> fields) { + + // SQLite requires LIMIT before OFFSET: `LIMIT n OFFSET m`. The default base order + // (OFFSET then LIMIT, inherited from the postgres-ish dialect) is a syntax error. + if (limit.isPresent()) { + subquery = subquery.append(Fragment.of(" " + limitClause(limit.get()))); + } + if (offset.isPresent()) { + subquery = subquery.append(Fragment.of(" " + offsetClause(offset.get()))); + } + return subquery; + } + + // SQLite uses default column-by-column for tuples (no native tuple IS). + }; + /** * DB2 dialect - uses double quotes for identifiers, CAST() for casts, and FETCH FIRST for limits. */ diff --git a/typr-scripts/src/scala/scripts/GeneratedShowcase.scala b/typr-scripts/src/scala/scripts/GeneratedShowcase.scala index 1c0b858138..721f288804 100644 --- a/typr-scripts/src/scala/scripts/GeneratedShowcase.scala +++ b/typr-scripts/src/scala/scripts/GeneratedShowcase.scala @@ -37,7 +37,8 @@ object GeneratedShowcase { DbType.DuckDB, DbType.Oracle, DbType.SqlServer, - DbType.DB2 + DbType.DB2, + DbType.SQLite ) dbTypes.foreach { dbType => @@ -48,6 +49,7 @@ object GeneratedShowcase { case DbType.Oracle => "oracle" case DbType.SqlServer => "sqlserver" case DbType.DB2 => "db2" + case DbType.SQLite => "sqlite" } try { @@ -63,58 +65,9 @@ object GeneratedShowcase { } } - formatJavaFiles(logger) - logger.warn("Showcase code generation complete!") } - /** Format Java files with google-java-format via coursier */ - def formatJavaFiles(logger: ryddig.Logger): Unit = { - import coursier.cache.FileCache - import coursier.util.{Artifact, Task} - import scala.concurrent.{Await, ExecutionContext} - import scala.concurrent.duration.Duration - - try { - logger.warn("Formatting Java files with google-java-format...") - val javaFiles = java.nio.file.Files - .walk(buildDir.resolve("site/showcase-generated")) - .filter(p => p.toString.endsWith(".java")) - .toArray - .map(_.toString) - .toSeq - - if (javaFiles.nonEmpty) { - val version = "1.25.2" - val ec: ExecutionContext = ExecutionContext.global - val fileCache = FileCache[Task]() - val artifact = Artifact(s"https://github.com/google/google-java-format/releases/download/v$version/google-java-format-$version-all-deps.jar") - val jar = Await.result(fileCache.file(artifact).run.value(ec), Duration.Inf) match { - case Left(err) => throw new Exception(s"Failed to fetch google-java-format: $err") - case Right(file) => file.toPath - } - - val jvmFlags = List( - "--add-exports=jdk.compiler/com.sun.tools.javac.api=ALL-UNNAMED", - "--add-exports=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED", - "--add-exports=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED", - "--add-exports=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED", - "--add-exports=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED", - "--add-exports=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED" - ) - val cmd = Seq("java") ++ jvmFlags ++ Seq("-jar", jar.toString, "--replace") ++ javaFiles - import scala.sys.process._ - val result = cmd.! - if (result == 0) { - logger.warn(s" Formatted ${javaFiles.size} Java files") - } - } - } catch { - case e: Exception => - logger.error(s"Failed to format Java files: ${e.getMessage}") - } - } - /** Build a MetaDb directly from ShowcaseSchema definitions. No database connection required. */ def buildMetaDb(dbType: DbType): MetaDb = { val allRelations = ShowcaseSchema.relations(dbType) diff --git a/typr-scripts/src/scala/scripts/showcase/ShowcaseSchema.scala b/typr-scripts/src/scala/scripts/showcase/ShowcaseSchema.scala index 9eb4937c7a..7f183a31e7 100644 --- a/typr-scripts/src/scala/scripts/showcase/ShowcaseSchema.scala +++ b/typr-scripts/src/scala/scripts/showcase/ShowcaseSchema.scala @@ -695,6 +695,11 @@ object ShowcaseSchema { col("resume", db.DB2Type.Clob, notNull = false), col("photo", db.DB2Type.Blob, notNull = false) ) + case DbType.SQLite => + // SQLite has no native arrays/structs/maps/json/binary columns beyond BLOB, + // and no domain/distinct-type system. Showcase keeps the SQLite employee + // to just the base columns. + Nil } Table( @@ -833,6 +838,13 @@ object ShowcaseSchema { col("thumbnail", db.DB2Type.Blob, notNull = false), col("xml_data", db.DB2Type.Xml, notNull = false) ) + case DbType.SQLite => + List( + col("description_long", db.SqliteType.Text, notNull = false), + col("thumbnail", db.SqliteType.Blob, notNull = false), + col("attributes", db.SqliteType.Json, notNull = false), + col("product_uid", db.SqliteType.Uuid, notNull = false) + ) } Table( @@ -915,6 +927,13 @@ object ShowcaseSchema { col("avatar", db.DB2Type.Blob, notNull = false), col("notes", db.DB2Type.Clob, notNull = false) ) + case DbType.SQLite => + List( + col("preferences", db.SqliteType.Json, notNull = false), + col("avatar", db.SqliteType.Blob, notNull = false), + col("customer_uid", db.SqliteType.Uuid, notNull = false), + col("notes", db.SqliteType.Text, notNull = false) + ) } Table( @@ -980,6 +999,10 @@ object ShowcaseSchema { List( col("notes", db.DB2Type.Clob, notNull = false) ) + case DbType.SQLite => + List( + col("notes", db.SqliteType.Text, notNull = false) + ) } Table( @@ -1076,6 +1099,13 @@ object ShowcaseSchema { col("receipt_data", db.DB2Type.Blob, notNull = false), col("xml_invoice", db.DB2Type.Xml, notNull = false) ) + case DbType.SQLite => + List( + col("order_uid", db.SqliteType.Uuid, notNull = false), + col("metadata", db.SqliteType.Json, notNull = false), + col("notes_extended", db.SqliteType.Text, notNull = false), + col("receipt_data", db.SqliteType.Blob, notNull = false) + ) } Table( @@ -1217,6 +1247,13 @@ object ShowcaseSchema { col("attachments", db.DB2Type.Blob, notNull = false), col("xml_plan", db.DB2Type.Xml, notNull = false) ) + case DbType.SQLite => + List( + col("project_uid", db.SqliteType.Uuid, notNull = false), + col("metadata", db.SqliteType.Json, notNull = false), + col("description_long", db.SqliteType.Text, notNull = false), + col("attachments", db.SqliteType.Blob, notNull = false) + ) } Table( @@ -1442,6 +1479,7 @@ object ShowcaseSchema { case DbType.Oracle => db.OracleType.Varchar2(maxLength) case DbType.SqlServer => db.SqlServerType.NVarChar(maxLength) case DbType.DB2 => db.DB2Type.VarChar(maxLength) + case DbType.SQLite => db.SqliteType.VarChar(maxLength) } private def intType(dbType: DbType): db.Type = dbType match { @@ -1451,6 +1489,7 @@ object ShowcaseSchema { case DbType.Oracle => db.OracleType.Number(Some(10), Some(0)) case DbType.SqlServer => db.SqlServerType.Int case DbType.DB2 => db.DB2Type.Integer + case DbType.SQLite => db.SqliteType.Int } private def boolType(dbType: DbType): db.Type = dbType match { @@ -1460,6 +1499,7 @@ object ShowcaseSchema { case DbType.Oracle => db.OracleType.Number(Some(1), Some(0)) case DbType.SqlServer => db.SqlServerType.Bit case DbType.DB2 => db.DB2Type.Boolean + case DbType.SQLite => db.SqliteType.Boolean } private def decimalType(dbType: DbType, precision: Int, scale: Int): db.Type = dbType match { @@ -1469,6 +1509,7 @@ object ShowcaseSchema { case DbType.Oracle => db.OracleType.Number(Some(precision), Some(scale)) case DbType.SqlServer => db.SqlServerType.Decimal(Some(precision), Some(scale)) case DbType.DB2 => db.DB2Type.Decimal(Some(precision), Some(scale)) + case DbType.SQLite => db.SqliteType.Decimal(Some(precision), Some(scale)) } private def dateType(dbType: DbType): db.Type = dbType match { @@ -1478,6 +1519,7 @@ object ShowcaseSchema { case DbType.Oracle => db.OracleType.Date case DbType.SqlServer => db.SqlServerType.Date case DbType.DB2 => db.DB2Type.Date + case DbType.SQLite => db.SqliteType.Date } private def timestampType(dbType: DbType): db.Type = dbType match { @@ -1487,6 +1529,7 @@ object ShowcaseSchema { case DbType.Oracle => db.OracleType.Timestamp(None) case DbType.SqlServer => db.SqlServerType.DateTime2(None) case DbType.DB2 => db.DB2Type.Timestamp(None) + case DbType.SQLite => db.SqliteType.Timestamp } private def bigintType(dbType: DbType): db.Type = dbType match { @@ -1496,6 +1539,7 @@ object ShowcaseSchema { case DbType.Oracle => db.OracleType.Number(Some(19), Some(0)) case DbType.SqlServer => db.SqlServerType.BigInt case DbType.DB2 => db.DB2Type.BigInt + case DbType.SQLite => db.SqliteType.BigInt } // ═══════════════════════════════════════════════════════════════════════════ diff --git a/typr.yaml b/typr.yaml index bc9758d4ca..d0e69fae38 100644 --- a/typr.yaml +++ b/typr.yaml @@ -207,6 +207,19 @@ boundaries: db: column: email type: duckdb + sqlite: + schema_sql: sql-init/sqlite/00-schema.sql + selectors: + precision_types: + - precision_types + - precision_types_null + sql_scripts: sql-scripts/sqlite + path: ':memory:' + types: + Email: + db: + column: email + type: sqlite db2: username: db2inst1 password: password @@ -694,6 +707,42 @@ outputs: package: com.example.grpc path: testers/grpc/java/generated-and-checked-in sources: grpc-services + sqlite-java: + path: testers/sqlite/java/generated-and-checked-in + package: testdb + json: jackson + sources: sqlite + language: java + db_lib: foundations + matchers: + mock_repos: all + primary_key_types: all + test_inserts: all + sqlite-kotlin: + path: testers/sqlite/kotlin/generated-and-checked-in + package: testdb + json: jackson + sources: sqlite + language: kotlin + db_lib: foundations + matchers: + mock_repos: all + primary_key_types: all + test_inserts: all + sqlite-scala: + path: testers/sqlite/scala/generated-and-checked-in + package: testdb + json: jackson + sources: sqlite + language: scala + db_lib: foundations + scala: + dialect: scala3 + dsl: scala + matchers: + mock_repos: all + primary_key_types: all + test_inserts: all types: Customer: fields: diff --git a/typr/src/scala/typr/bridge/TypeSuggester.scala b/typr/src/scala/typr/bridge/TypeSuggester.scala index 0da5d614e2..33b33a1560 100644 --- a/typr/src/scala/typr/bridge/TypeSuggester.scala +++ b/typr/src/scala/typr/bridge/TypeSuggester.scala @@ -175,6 +175,22 @@ object TypeSuggester { case typr.db.DuckDbType.UUID => "uuid" + // SQLite types + case _: typr.db.SqliteType.VarChar | _: typr.db.SqliteType.Char | typr.db.SqliteType.Text | typr.db.SqliteType.Clob => + "text" + case typr.db.SqliteType.Integer | typr.db.SqliteType.BigInt | typr.db.SqliteType.Int | typr.db.SqliteType.SmallInt | typr.db.SqliteType.TinyInt => + "integer" + case typr.db.SqliteType.Real | typr.db.SqliteType.Double | typr.db.SqliteType.Float | _: typr.db.SqliteType.Decimal => + "numeric" + case typr.db.SqliteType.Boolean => + "boolean" + case typr.db.SqliteType.Date | typr.db.SqliteType.Time | typr.db.SqliteType.Timestamp | typr.db.SqliteType.Instant => + "temporal" + case typr.db.SqliteType.Uuid => + "uuid" + case typr.db.SqliteType.Json => + "json" + // Default: use type name as its own class case other => getTypeName(other) diff --git a/typr/src/scala/typr/cli/app/ConnectionTest.scala b/typr/src/scala/typr/cli/app/ConnectionTest.scala index 89fb7f0b8e..ba0785d8f8 100644 --- a/typr/src/scala/typr/cli/app/ConnectionTest.scala +++ b/typr/src/scala/typr/cli/app/ConnectionTest.scala @@ -4,7 +4,7 @@ import com.zaxxer.hikari.HikariDataSource import io.circe.Json import typr.TypoDataSource import typr.cli.config.{ConfigParser, ParsedSource} -import typr.config.generated.{DatabaseBoundary, DuckdbBoundary} +import typr.config.generated.{DatabaseBoundary, DuckdbBoundary, SqliteBoundary} /** Synchronous "does this source actually connect / parse?" probe. Returns `Left(message)` on failure, `Right(message)` with a short success line on success (e.g. database product / version). * Designed to be invoked from a daemon thread; never throws. @@ -13,9 +13,10 @@ object ConnectionTest { def run(sourceJson: Json): Either[String, String] = ConfigParser.parseSource(sourceJson) match { - case Right(ParsedSource.Database(db)) => tryDatabase(db) - case Right(ParsedSource.DuckDb(duck)) => tryDuckDb(duck) - case Right(other) => + case Right(ParsedSource.Database(db)) => tryDatabase(db) + case Right(ParsedSource.DuckDb(duck)) => tryDuckDb(duck) + case Right(ParsedSource.Sqlite(sqlite)) => trySqlite(sqlite) + case Right(other) => Left(s"${other.sourceType} sources don't support connection testing — try the browser screen to validate the spec/schema.") case Left(err) => Left(err) } @@ -55,6 +56,12 @@ object ConnectionTest { finally close(d) } + private def trySqlite(sqlite: SqliteBoundary): Either[String, String] = { + val d = TypoDataSource.hikariSqlite(sqlite.path) + try probe(d, "sqlite") + finally close(d) + } + private def probe(ds: TypoDataSource, fallbackLabel: String): Either[String, String] = try { val conn = ds.ds.getConnection @@ -80,7 +87,7 @@ object ConnectionTest { /** Whether the test button should be offered for a given source — only db/duckdb sources today. */ def isTestable(json: Json): Boolean = ConfigParser.parseSource(json).toOption.exists { - case _: ParsedSource.Database | _: ParsedSource.DuckDb => true - case _ => false + case _: ParsedSource.Database | _: ParsedSource.DuckDb | _: ParsedSource.Sqlite => true + case _ => false } } diff --git a/typr/src/scala/typr/cli/app/LoadedSource.scala b/typr/src/scala/typr/cli/app/LoadedSource.scala index cb888d89cf..d63e7efd61 100644 --- a/typr/src/scala/typr/cli/app/LoadedSource.scala +++ b/typr/src/scala/typr/cli/app/LoadedSource.scala @@ -34,7 +34,7 @@ object LoadedSource { def load(name: String, json: Json, buildDir: Path): Either[String, LoadedSource] = { given ExecutionContext = ExecutionContext.global ConfigParser.parseSource(json).flatMap { - case _: ParsedSource.Database | _: ParsedSource.DuckDb => + case _: ParsedSource.Database | _: ParsedSource.DuckDb | _: ParsedSource.Sqlite => // MetaDbFetch.fetch can throw (Hikari connect, Python install, await). Wrap once. try Right(Db(MetaDbFetch.fetch(name, json, TypoLogger.Noop))) catch case e: Throwable => Left(Option(e.getMessage).getOrElse(e.toString)) diff --git a/typr/src/scala/typr/cli/app/MetaDbFetch.scala b/typr/src/scala/typr/cli/app/MetaDbFetch.scala index f5e2b759ef..a51a7f2c5b 100644 --- a/typr/src/scala/typr/cli/app/MetaDbFetch.scala +++ b/typr/src/scala/typr/cli/app/MetaDbFetch.scala @@ -3,7 +3,7 @@ package typr.cli.app import com.zaxxer.hikari.HikariDataSource import io.circe.Json import typr.cli.config.{ConfigParser, ConfigToOptions, ParsedSource} -import typr.config.generated.{DatabaseBoundary, DuckdbBoundary} +import typr.config.generated.{DatabaseBoundary, DuckdbBoundary, SqliteBoundary} import typr.TypoDataSource import typr.internal.external.{ExternalTools, ExternalToolsConfig} import typr.{MetaDb, TypoLogger} @@ -22,9 +22,10 @@ object MetaDbFetch { .fold( err => throw new Exception(s"parse source config: $err"), { - case ParsedSource.Database(db) => fetchDatabase(name, db, logger) - case ParsedSource.DuckDb(duck) => fetchDuckDb(name, duck, logger) - case _ => throw new Exception("not a database / duckdb source") + case ParsedSource.Database(db) => fetchDatabase(name, db, logger) + case ParsedSource.DuckDb(duck) => fetchDuckDb(name, duck, logger) + case ParsedSource.Sqlite(sqlite) => fetchSqlite(name, sqlite, logger) + case _ => throw new Exception("not a database / duckdb / sqlite source") } ) @@ -75,6 +76,35 @@ object MetaDbFetch { } finally close(ds) } + private def fetchSqlite(name: String, sqliteConfig: SqliteBoundary, logger: TypoLogger)(implicit + ec: ExecutionContext + ): MetaDb = { + val sourceConfig = ConfigToOptions + .convertSqliteSource(name, sqliteConfig) + .fold( + err => throw new Exception(s"convert source config: $err"), + identity + ) + val ds = TypoDataSource.hikariSqlite(sqliteConfig.path) + try { + sqliteConfig.schema_sql.foreach { sqlPath => + val conn = ds.ds.getConnection + try { + val stmt = conn.createStatement() + val sql = java.nio.file.Files.readString(java.nio.file.Paths.get(sqlPath)) + // Run statements one at a time — xerial driver doesn't multi-execute. + sql.split(";").map(_.trim).filter(_.nonEmpty).foreach(stmt.execute) + stmt.close() + } finally conn.close() + } + val externalTools = ExternalTools.init(logger, ExternalToolsConfig.default) + Await.result( + MetaDb.fromDb(logger, ds, sourceConfig.selector, sourceConfig.schemaMode, externalTools), + Duration.Inf + ) + } finally close(ds) + } + private def buildDataSource(dbConfig: DatabaseBoundary): TypoDataSource = { val dbType = dbConfig.`type`.getOrElse("").toLowerCase val host = dbConfig.host.getOrElse("") diff --git a/typr/src/scala/typr/cli/app/screens/MainMenu.scala b/typr/src/scala/typr/cli/app/screens/MainMenu.scala index a9671002f0..4730ca9fc8 100644 --- a/typr/src/scala/typr/cli/app/screens/MainMenu.scala +++ b/typr/src/scala/typr/cli/app/screens/MainMenu.scala @@ -32,7 +32,7 @@ object MainMenu { ) private val items: List[Item] = List( - Item(Action.Sources, "◈", "Sources", "Database Connections", "Postgres, MariaDB, Oracle, SQL Server, DuckDB", "where typr reads schemas from"), + Item(Action.Sources, "◈", "Sources", "Database Connections", "Postgres, MariaDB, Oracle, SQL Server, DuckDB, SQLite", "where typr reads schemas from"), Item(Action.Schemas, "◇", "Schema Browser", "Explore Database", "Tables, columns, types, and relationships", "see what's there before you generate"), Item(Action.Outputs, "▣", "Outputs", "Code Targets", "Scala, Java, or Kotlin code generation", "languages, libraries, output paths"), Item( diff --git a/typr/src/scala/typr/cli/app/screens/SchemaPicker.scala b/typr/src/scala/typr/cli/app/screens/SchemaPicker.scala index 73e5143094..e7200f0110 100644 --- a/typr/src/scala/typr/cli/app/screens/SchemaPicker.scala +++ b/typr/src/scala/typr/cli/app/screens/SchemaPicker.scala @@ -48,11 +48,11 @@ object SchemaPicker { val routed: List[(String, Json, Routing)] = sources.map { case (name, json) => val r = ConfigParser.parseSource(json) match { - case Right(_: ParsedSource.Database | _: ParsedSource.DuckDb) => Routing.DbBrowser - case Right(_: ParsedSource.OpenApi | _: ParsedSource.JsonSchema) => Routing.SpecBrowser - case Right(_: ParsedSource.Avro) => Routing.AvroBrowser - case Right(_: ParsedSource.Grpc) => Routing.ProtoBrowser - case Left(_) => Routing.Unsupported + case Right(_: ParsedSource.Database | _: ParsedSource.DuckDb | _: ParsedSource.Sqlite) => Routing.DbBrowser + case Right(_: ParsedSource.OpenApi | _: ParsedSource.JsonSchema) => Routing.SpecBrowser + case Right(_: ParsedSource.Avro) => Routing.AvroBrowser + case Right(_: ParsedSource.Grpc) => Routing.ProtoBrowser + case Left(_) => Routing.Unsupported } (name, json, r) } @@ -217,8 +217,8 @@ object SchemaPicker { private def connectionLabel(json: Json): String = { val c = json.hcursor kindOf(json) match { - case "duckdb" => c.get[String]("path").getOrElse(":memory:") - case _ => + case "duckdb" | "sqlite" => c.get[String]("path").getOrElse(":memory:") + case _ => val host = c.get[String]("host").getOrElse("") val port = c.get[Long]("port").map(_.toString).getOrElse("") val db = c.get[String]("database").getOrElse("") diff --git a/typr/src/scala/typr/cli/app/screens/SourceForm.scala b/typr/src/scala/typr/cli/app/screens/SourceForm.scala index 0ce9c03806..729779e40f 100644 --- a/typr/src/scala/typr/cli/app/screens/SourceForm.scala +++ b/typr/src/scala/typr/cli/app/screens/SourceForm.scala @@ -16,6 +16,7 @@ object SourceForm { /** Which fields are surfaced for which kind. Order is render order. */ val fieldsByKind: Map[String, List[Field]] = Map( "duckdb" -> List(Field("path", "path")), + "sqlite" -> List(Field("path", "path")), "openapi" -> List(Field("spec", "spec path")), "jsonschema" -> List(Field("spec", "spec path")), "oracle" -> List( diff --git a/typr/src/scala/typr/cli/app/screens/SourceList.scala b/typr/src/scala/typr/cli/app/screens/SourceList.scala index 7f5007fcc2..7c302760a5 100644 --- a/typr/src/scala/typr/cli/app/screens/SourceList.scala +++ b/typr/src/scala/typr/cli/app/screens/SourceList.scala @@ -207,6 +207,7 @@ object SourceList { private def sourceIcon(json: Json): String = sourceKind(json) match { case "duckdb" => "◆" + case "sqlite" => "◆" case "openapi" => "✦" case "jdbc" => "◈" case _ => "◇" @@ -215,7 +216,7 @@ object SourceList { private def sourceDetails(json: Json): String = { val c = json.hcursor sourceKind(json) match { - case "duckdb" => + case "duckdb" | "sqlite" => c.get[String]("path").getOrElse(":memory:") case "openapi" => c.get[String]("spec") diff --git a/typr/src/scala/typr/cli/commands/Generate.scala b/typr/src/scala/typr/cli/commands/Generate.scala index 7c88ba92cb..7056fa8040 100644 --- a/typr/src/scala/typr/cli/commands/Generate.scala +++ b/typr/src/scala/typr/cli/commands/Generate.scala @@ -9,6 +9,7 @@ import typr.cli.config.* import typr.config.generated.AvroBoundary import typr.config.generated.DatabaseBoundary import typr.config.generated.DuckdbBoundary +import typr.config.generated.SqliteBoundary import typr.config.generated.GrpcBoundary import typr.config.generated.OpenapiBoundary import typr.db @@ -361,6 +362,14 @@ object Generate { case Left(error) => onBoundaryStep(boundaryName, s"Failed: $error") } + case ParsedBoundary.Sqlite(sqliteConfig) => + fetchSqliteBoundary(boundaryName, sqliteConfig, buildDir, typoLogger, externalTools, step => onBoundaryStep(boundaryName, step)) match { + case Right(fetched) => + fetchedBoundaries.put(boundaryName, fetched) + onBoundaryStep(boundaryName, "Done") + case Left(error) => + onBoundaryStep(boundaryName, s"Failed: $error") + } case ParsedBoundary.OpenApi(_) => onBoundaryStep(boundaryName, "Done") case ParsedBoundary.JsonSchema(_) => @@ -509,6 +518,11 @@ object Generate { case Right(files) => totalFiles += files case Left(error) => throw new Exception(error) } + case ParsedBoundary.Sqlite(sqliteConfig) => + generateSqliteForOutput(outputName, boundaryName, sqliteConfig, effectiveOutputConfig, buildDir, typoLogger, externalTools, tracker, skipSqlScripts = isMultiSource) match { + case Right(files) => totalFiles += files + case Left(error) => throw new Exception(error) + } case ParsedBoundary.OpenApi(openapiConfig) => generateOpenApiForOutput(outputName, boundaryName, openapiConfig, outputConfig, buildDir, isMultiSource, tracker) match { case Right(files) => totalFiles += files @@ -704,6 +718,121 @@ object Generate { } yield written } + private def generateSqliteForOutput( + outputName: String, + boundaryName: String, + sqliteConfig: SqliteBoundary, + outputConfig: ConfigToOptions.OutputConfig, + buildDir: Path, + typoLogger: TypoLogger, + externalTools: ExternalTools, + tracker: ProgressTracker, + skipSqlScripts: Boolean + ): Either[String, Int] = { + for { + boundaryConfig <- ConfigToOptions.convertSqliteBoundary(boundaryName, sqliteConfig) + dataSource = TypoDataSource.hikariSqlite(sqliteConfig.path) + + _ = boundaryConfig.schemaSqlPath.foreach { schemaPath => + tracker.update(outputName, OutputStatus.Processing(boundaryName, "Loading schema...")) + val fullPath = buildDir.resolve(schemaPath) + Await.result( + dataSource.run { conn => + val schemaSql = Files.readString(fullPath) + val stmt = conn.createStatement() + executeBatch(stmt, schemaSql) + stmt.close() + }, + Duration.Inf + ) + } + + _ = tracker.update(outputName, OutputStatus.Processing(boundaryName, "Fetching metadata...")) + + metadb = Await.result( + MetaDb.fromDb(typoLogger, dataSource, boundaryConfig.selector, boundaryConfig.schemaMode, externalTools), + Duration.Inf + ) + + _ = if (!skipSqlScripts) tracker.update(outputName, OutputStatus.Processing(boundaryName, "Reading SQL scripts...")) + + sqlScripts = + if (skipSqlScripts) Nil + else + boundaryConfig.sqlScriptsPath match { + case Some(path) => + val scriptsPath = buildDir.resolve(path) + Await.result(SqlFileReader(typoLogger, scriptsPath, dataSource, externalTools), Duration.Inf) + case None => Nil + } + + stats = BoundaryStats( + tables = metadb.relations.values.count(_.forceGet.isInstanceOf[db.Table]), + views = metadb.relations.values.count(_.forceGet.isInstanceOf[db.View]), + enums = metadb.enums.size, + domains = metadb.domains.size, + sqlScripts = sqlScripts.size + ) + _ = tracker.setBoundaryStats(outputName, boundaryName, stats) + + _ = tracker.update(outputName, OutputStatus.Processing(boundaryName, s"Generating (${stats.summary})...")) + + mergedOptions = mergeBoundaryIntoOptions(outputConfig.options, boundaryConfig) + targetSources = buildDir.resolve(outputConfig.path) + + newFiles = generate + .orThrow( + mergedOptions, + metadb, + ProjectGraph("", targetSources, None, boundaryConfig.selector, sqlScripts, Nil), + Map.empty + ) + .head + + _ = tracker.update(outputName, OutputStatus.Processing(boundaryName, "Writing files...")) + + syncResults = newFiles.overwriteFolder(softWrite = FileSync.SoftWrite.Yes(Set.empty)) + + written = syncResults.count { case (_, s) => s == FileSync.Synced.New || s == FileSync.Synced.Changed } + unchanged = syncResults.count { case (_, s) => s == FileSync.Synced.Unchanged } + deleted = syncResults.count { case (_, s) => s == FileSync.Synced.Deleted } + + _ = tracker.addFileStats(outputName, written, unchanged, deleted) + + _ = dataSource.ds.asInstanceOf[com.zaxxer.hikari.HikariDataSource].close() + } yield written + } + + /** SQLite's JDBC driver cannot execute multi-statement strings via a single execute() call. Split on `;` boundaries and run each non-empty statement. We keep this simple — strip line comments and + * split on `;` outside of single-quoted strings. + */ + private def executeBatch(stmt: java.sql.Statement, sql: String): Unit = { + val builder = new StringBuilder + var inString = false + var i = 0 + while (i < sql.length) { + val c = sql.charAt(i) + // Strip line comments `-- ...` when outside a string literal + if (!inString && c == '-' && i + 1 < sql.length && sql.charAt(i + 1) == '-') { + while (i < sql.length && sql.charAt(i) != '\n') i += 1 + } else if (c == '\'') { + builder.append(c) + inString = !inString + i += 1 + } else if (c == ';' && !inString) { + val piece = builder.toString.trim + if (piece.nonEmpty) stmt.execute(piece) + builder.clear() + i += 1 + } else { + builder.append(c) + i += 1 + } + } + val tail = builder.toString.trim + if (tail.nonEmpty) stmt.execute(tail) + } + private def mergeBoundaryIntoOptions(outputOptions: Options, boundaryConfig: ConfigToOptions.BoundaryConfig): Options = { outputOptions.copy( schemaMode = boundaryConfig.schemaMode, @@ -1108,6 +1237,58 @@ object Generate { } yield FetchedBoundary(boundaryName, metadb, dataSource, boundaryConfig, stats, Map.empty, sqlScripts) } + def fetchSqliteBoundary( + boundaryName: String, + sqliteConfig: SqliteBoundary, + buildDir: Path, + typoLogger: TypoLogger, + externalTools: ExternalTools, + onStep: String => Unit + ): Either[String, FetchedBoundary] = { + for { + boundaryConfig <- ConfigToOptions.convertSqliteBoundary(boundaryName, sqliteConfig) + dataSource = TypoDataSource.hikariSqlite(sqliteConfig.path) + + _ = boundaryConfig.schemaSqlPath.foreach { schemaPath => + onStep("Loading schema...") + val fullPath = buildDir.resolve(schemaPath) + Await.result( + dataSource.run { conn => + val schemaSql = Files.readString(fullPath) + val stmt = conn.createStatement() + executeBatch(stmt, schemaSql) + stmt.close() + }, + Duration.Inf + ) + } + + _ = onStep("Fetching metadata...") + + metadb = Await.result( + MetaDb.fromDb(typoLogger, dataSource, boundaryConfig.selector, boundaryConfig.schemaMode, externalTools), + Duration.Inf + ) + + _ = onStep("Reading SQL scripts...") + + sqlScripts = boundaryConfig.sqlScriptsPath match { + case Some(path) => + val scriptsPath = buildDir.resolve(path) + Await.result(SqlFileReader(typoLogger, scriptsPath, dataSource, externalTools), Duration.Inf) + case None => Nil + } + + stats = BoundaryStats( + tables = metadb.relations.values.count(_.forceGet.isInstanceOf[db.Table]), + views = metadb.relations.values.count(_.forceGet.isInstanceOf[db.View]), + enums = metadb.enums.size, + domains = metadb.domains.size, + sqlScripts = sqlScripts.size + ) + } yield FetchedBoundary(boundaryName, metadb, dataSource, boundaryConfig, stats, Map.empty, sqlScripts) + } + def generateWithCachedBoundary( outputName: String, outputConfig: ConfigToOptions.OutputConfig, @@ -1183,6 +1364,16 @@ object Generate { ): Either[String, FetchedBoundary] = fetchDuckDbBoundary(sourceName, duckConfig, buildDir, typoLogger, externalTools, onStep) + def fetchSqliteSource( + sourceName: String, + sqliteConfig: SqliteBoundary, + buildDir: Path, + typoLogger: TypoLogger, + externalTools: ExternalTools, + onStep: String => Unit + ): Either[String, FetchedBoundary] = + fetchSqliteBoundary(sourceName, sqliteConfig, buildDir, typoLogger, externalTools, onStep) + def generateWithCachedSource( outputName: String, outputConfig: ConfigToOptions.OutputConfig, diff --git a/typr/src/scala/typr/cli/config/ConfigParser.scala b/typr/src/scala/typr/cli/config/ConfigParser.scala index 0e4c90c6d8..55f8ffcd83 100644 --- a/typr/src/scala/typr/cli/config/ConfigParser.scala +++ b/typr/src/scala/typr/cli/config/ConfigParser.scala @@ -5,6 +5,7 @@ import io.circe.yaml.v12.parser import typr.config.generated.AvroBoundary import typr.config.generated.DatabaseBoundary import typr.config.generated.DuckdbBoundary +import typr.config.generated.SqliteBoundary import typr.config.generated.GrpcBoundary import typr.config.generated.JsonschemaBoundary import typr.config.generated.OpenapiBoundary @@ -24,6 +25,8 @@ object ConfigParser { json.as[DatabaseBoundary].map(ParsedSource.Database.apply).left.map(e => s"Failed to parse database source: ${e.getMessage}") case Some("duckdb") => json.as[DuckdbBoundary].map(ParsedSource.DuckDb.apply).left.map(e => s"Failed to parse DuckDB source: ${e.getMessage}") + case Some("sqlite") => + json.as[SqliteBoundary].map(ParsedSource.Sqlite.apply).left.map(e => s"Failed to parse SQLite source: ${e.getMessage}") case Some("openapi") => json.as[OpenapiBoundary].map(ParsedSource.OpenApi.apply).left.map(e => s"Failed to parse OpenAPI source: ${e.getMessage}") case Some("jsonschema") => @@ -44,6 +47,8 @@ object ConfigParser { json.as[DatabaseBoundary].map(ParsedBoundary.Database.apply).left.map(e => s"Failed to parse database boundary: ${e.getMessage}") case Some("duckdb") => json.as[DuckdbBoundary].map(ParsedBoundary.DuckDb.apply).left.map(e => s"Failed to parse DuckDB boundary: ${e.getMessage}") + case Some("sqlite") => + json.as[SqliteBoundary].map(ParsedBoundary.Sqlite.apply).left.map(e => s"Failed to parse SQLite boundary: ${e.getMessage}") case Some("openapi") => json.as[OpenapiBoundary].map(ParsedBoundary.OpenApi.apply).left.map(e => s"Failed to parse OpenAPI boundary: ${e.getMessage}") case Some("jsonschema") => @@ -69,6 +74,9 @@ object ParsedBoundary { case class DuckDb(config: DuckdbBoundary) extends ParsedBoundary { def boundaryType: String = "duckdb" } + case class Sqlite(config: SqliteBoundary) extends ParsedBoundary { + def boundaryType: String = "sqlite" + } case class OpenApi(config: OpenapiBoundary) extends ParsedBoundary { def boundaryType: String = "openapi" } @@ -94,6 +102,9 @@ object ParsedSource { case class DuckDb(config: DuckdbBoundary) extends ParsedSource { def sourceType: String = "duckdb" } + case class Sqlite(config: SqliteBoundary) extends ParsedSource { + def sourceType: String = "sqlite" + } case class OpenApi(config: OpenapiBoundary) extends ParsedSource { def sourceType: String = "openapi" } diff --git a/typr/src/scala/typr/cli/config/ConfigToOptions.scala b/typr/src/scala/typr/cli/config/ConfigToOptions.scala index 32843e29bd..454781c54b 100644 --- a/typr/src/scala/typr/cli/config/ConfigToOptions.scala +++ b/typr/src/scala/typr/cli/config/ConfigToOptions.scala @@ -80,6 +80,28 @@ object ConfigToOptions { ) } + def convertSqliteBoundary(name: String, sqliteConfig: SqliteBoundary): Either[String, BoundaryConfig] = { + val selector = buildSelectorFromBoundary(sqliteConfig.selectors, None) + val typeDefinitions = buildTypeDefinitions(sqliteConfig.types) + val openEnumsSelector = PatternMatcher.fromFeatureMatcherDefaultNone(sqliteConfig.selectors.flatMap(_.open_enums)) + val precisionTypesSelector = PatternMatcher.fromFeatureMatcherDefaultNone(sqliteConfig.selectors.flatMap(_.precision_types)) + + Right( + BoundaryConfig( + name = name, + boundaryType = "sqlite", + schemaMode = SchemaMode.SingleSchema("main"), + selector = selector, + sqlScriptsPath = sqliteConfig.sql_scripts, + schemaSqlPath = sqliteConfig.schema_sql, + typeDefinitions = typeDefinitions, + typeOverride = TypeOverride.Empty, + openEnumsSelector = openEnumsSelector, + precisionTypesSelector = precisionTypesSelector + ) + ) + } + def convertAvroBoundary( name: String, config: AvroBoundary, @@ -542,4 +564,7 @@ object ConfigToOptions { def convertDuckDbSource(name: String, duckConfig: DuckdbBoundary): Either[String, BoundaryConfig] = convertDuckDbBoundary(name, duckConfig) + + def convertSqliteSource(name: String, sqliteConfig: SqliteBoundary): Either[String, BoundaryConfig] = + convertSqliteBoundary(name, sqliteConfig) }