@zio.dev/zio-blocks 0.0.33 → 0.0.55
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/adr/2026-07-18-data-migration.md +123 -0
- package/guides/async-getting-started.md +687 -0
- package/guides/compile-time-resource-safety-with-scope.md +21 -16
- package/guides/getting-started-with-mux.md +1395 -0
- package/guides/query-dsl-extending.md +161 -102
- package/guides/query-dsl-fluent-builder.md +217 -157
- package/guides/query-dsl-reified-optics.md +12 -10
- package/guides/query-dsl-sql.md +640 -165
- package/guides/sql-checked-interpolation.md +173 -0
- package/guides/sql-transactions.md +286 -0
- package/guides/telemetry-guide.md +1130 -0
- package/guides/zio-schema-migration.md +29 -22
- package/index.md +248 -389
- package/package.json +1 -1
- package/plans/config-follow-up-prs.md +188 -0
- package/plans/config-pr-assessment-roadmap.md +310 -0
- package/reference/MuxDataFlow.jsx +250 -0
- package/reference/async.md +1499 -0
- package/reference/chunk.md +3533 -308
- package/reference/codegen/case-class.md +436 -0
- package/reference/codegen/emitter-config.md +383 -0
- package/reference/codegen/examples.md +664 -0
- package/reference/codegen/field.md +316 -0
- package/reference/codegen/index.md +317 -0
- package/reference/codegen/scala-emitter.md +392 -0
- package/reference/codegen/scala-file.md +276 -0
- package/reference/codegen/sealed-trait.md +408 -0
- package/reference/codegen/type-definition.md +340 -0
- package/reference/codegen/type-ref.md +201 -0
- package/reference/combinators.md +347 -117
- package/reference/config/config-decoder.md +460 -0
- package/reference/config/config-source.md +489 -0
- package/reference/config/errors.md +278 -0
- package/reference/config/flags.md +369 -0
- package/reference/config/formats.md +314 -0
- package/reference/config/index.md +304 -0
- package/reference/config/rollout.md +336 -0
- package/reference/context.md +9 -52
- package/reference/data-migration.md +269 -0
- package/reference/datastar/attributes.md +302 -0
- package/reference/datastar/events.md +234 -0
- package/reference/datastar/index.md +256 -0
- package/reference/datastar/signals.md +230 -0
- package/reference/datastar/sse.md +295 -0
- package/reference/datastar.md +346 -0
- package/reference/docs.md +1461 -345
- package/reference/endpoint/auth-type.md +146 -0
- package/reference/endpoint/bulk-creation.md +96 -0
- package/reference/endpoint/endpoint.md +297 -0
- package/reference/endpoint/http-codec.md +249 -0
- package/reference/endpoint/index.md +745 -0
- package/reference/endpoint/path-codec.md +225 -0
- package/reference/endpoint/route-pattern.md +194 -0
- package/reference/endpoint/route-tree.md +111 -0
- package/reference/endpoint/segment-codec.md +199 -0
- package/reference/html.md +1424 -0
- package/reference/htmx/attribute-values.md +359 -0
- package/reference/htmx/hx-encoding.md +111 -0
- package/reference/htmx/hx-params.md +204 -0
- package/reference/htmx/hx-swap.md +276 -0
- package/reference/htmx/hx-sync.md +251 -0
- package/reference/htmx/hx-target.md +314 -0
- package/reference/htmx/hx-trigger.md +457 -0
- package/reference/htmx/hx-url-update.md +239 -0
- package/reference/htmx/index.md +807 -0
- package/reference/htmx/response-headers.md +240 -0
- package/reference/http-model/headers.md +735 -0
- package/reference/http-model/index.md +49 -0
- package/reference/http-model/model.md +1517 -0
- package/reference/http-model/schema-codecs.md +522 -0
- package/reference/http-model/schema.md +750 -0
- package/reference/http-model/server-sent-event.md +341 -0
- package/reference/jwt.md +195 -0
- package/reference/maybe.md +943 -0
- package/reference/media-type.md +2 -2
- package/reference/mux.md +254 -0
- package/reference/mux.mdx +828 -0
- package/reference/openapi.md +1351 -0
- package/reference/projection.md +654 -0
- package/reference/resource-management/defer-handle.md +1 -1
- package/reference/resource-management/resource.md +31 -98
- package/reference/resource-management/scope.md +28 -220
- package/reference/resource-management/wire.md +5 -55
- package/reference/ringbuffer/MpmcDiagram.jsx +717 -0
- package/reference/ringbuffer/MpscDiagram.jsx +618 -0
- package/reference/ringbuffer/SpmcDiagram.jsx +680 -0
- package/reference/ringbuffer/SpscDiagram.jsx +677 -0
- package/reference/ringbuffer/advanced.mdx +109 -0
- package/reference/ringbuffer/index.mdx +145 -0
- package/reference/ringbuffer/mpmc.mdx +185 -0
- package/reference/ringbuffer/mpsc.mdx +164 -0
- package/reference/ringbuffer/spmc.mdx +108 -0
- package/reference/ringbuffer/spsc.mdx +416 -0
- package/reference/{allows.md → schema/allows.md} +4 -100
- package/reference/{binding-resolver.md → schema/binding-resolver.md} +1 -1
- package/reference/{binding.md → schema/binding.md} +3 -4
- package/reference/schema/built-in-codecs/avro.md +451 -0
- package/reference/schema/built-in-codecs/bson.md +510 -0
- package/reference/schema/built-in-codecs/csv.md +564 -0
- package/reference/schema/built-in-codecs/index.md +77 -0
- package/reference/schema/built-in-codecs/json/index.md +295 -0
- package/reference/schema/built-in-codecs/json/json-config.md +217 -0
- package/reference/{json-patch.md → schema/built-in-codecs/json/json-patch.md} +5 -5
- package/reference/{json-schema.md → schema/built-in-codecs/json/json-schema.md} +14 -47
- package/reference/schema/built-in-codecs/json/json-selection.md +322 -0
- package/reference/{json.md → schema/built-in-codecs/json/json.md} +32 -64
- package/reference/schema/built-in-codecs/messagepack.md +508 -0
- package/reference/schema/built-in-codecs/thrift.md +433 -0
- package/reference/schema/built-in-codecs/toon.md +1078 -0
- package/reference/{xml.md → schema/built-in-codecs/xml.md} +13 -9
- package/reference/schema/built-in-codecs/yaml.md +552 -0
- package/reference/{codec.md → schema/codec.md} +11 -11
- package/reference/{dynamic-optic.md → schema/dynamic-optic.md} +196 -5
- package/reference/{dynamic-schema.md → schema/dynamic-schema.md} +8 -8
- package/reference/schema/format.md +92 -0
- package/reference/schema/index.md +52 -0
- package/reference/schema/migration.md +297 -0
- package/reference/{modifier.md → schema/modifier.md} +58 -7
- package/reference/{optics.md → schema/optics.md} +2 -2
- package/reference/{patch.md → schema/patch.md} +1 -1
- package/{path-interpolator.md → reference/schema/path-interpolator.md} +167 -72
- package/reference/schema/reflect-transformer.md +140 -0
- package/reference/{schema-evolution → schema/schema-evolution}/as.md +8 -8
- package/reference/{schema-evolution → schema/schema-evolution}/index.md +2 -2
- package/reference/{schema-evolution → schema/schema-evolution}/into.md +8 -8
- package/reference/{schema-expr.md → schema/schema-expr.md} +110 -175
- package/reference/schema/schema-search.md +263 -0
- package/reference/{schema.md → schema/schema.md} +22 -2
- package/reference/{structural-types.md → schema/structural-types.md} +1 -1
- package/reference/{type-class-derivation.md → schema/type-class-derivation.md} +63 -1
- package/reference/smithy.md +1032 -0
- package/reference/sql/db-codec-deriver.md +71 -0
- package/reference/sql/db-codec.md +687 -0
- package/reference/sql/db-con.md +271 -0
- package/reference/sql/db-connection.md +153 -0
- package/reference/sql/db-param-writer.md +77 -0
- package/reference/sql/db-param.md +66 -0
- package/reference/sql/db-result-reader.md +148 -0
- package/reference/sql/db-tx.md +114 -0
- package/reference/sql/db-value.md +41 -0
- package/reference/sql/ddl.md +85 -0
- package/reference/sql/frag.md +288 -0
- package/reference/sql/index.md +341 -0
- package/reference/sql/repo.md +600 -0
- package/reference/sql/sql-dialect.md +73 -0
- package/reference/sql/sql-logger.md +62 -0
- package/reference/sql/sql-name-mapper.md +70 -0
- package/reference/sql/table-metadata.md +134 -0
- package/reference/sql/table.md +448 -0
- package/reference/sql/transactor-zio.md +399 -0
- package/reference/sql/transactor.md +363 -0
- package/reference/sql-zio.md +112 -0
- package/reference/streams/core/index.md +32 -0
- package/reference/streams/core/pipeline.md +854 -0
- package/reference/streams/core/sink.md +1404 -0
- package/reference/streams/core/stream.md +3236 -0
- package/reference/streams/execution-and-compatibility/async-execution.md +822 -0
- package/reference/streams/execution-and-compatibility/index.md +35 -0
- package/reference/streams/execution-and-compatibility/platform-differences.md +297 -0
- package/reference/streams/execution-and-compatibility/scala-2-compatibility.md +88 -0
- package/reference/streams/execution-and-compatibility/zero-boxing.md +393 -0
- package/reference/streams/index.md +726 -0
- package/reference/streams/primitives/index.md +30 -0
- package/reference/streams/primitives/reader.md +1992 -0
- package/reference/streams/primitives/writer.md +1201 -0
- package/reference/telemetry/common/any-value.md +90 -0
- package/reference/telemetry/common/attribute-key.md +87 -0
- package/reference/telemetry/common/attributes.md +118 -0
- package/reference/telemetry/common/index.md +39 -0
- package/reference/telemetry/common/instrumentation-scope.md +24 -0
- package/reference/telemetry/common/resource.md +34 -0
- package/reference/telemetry/index.md +311 -0
- package/reference/telemetry/logging/index.md +197 -0
- package/reference/telemetry/logging/log-enrichment.md +72 -0
- package/reference/telemetry/logging/log-formatter.md +100 -0
- package/reference/telemetry/logging/log-record-processor.md +56 -0
- package/reference/telemetry/logging/log-record.md +44 -0
- package/reference/telemetry/logging/log-writer.md +64 -0
- package/reference/telemetry/logging/logger-provider.md +142 -0
- package/reference/telemetry/logging/logger.md +83 -0
- package/reference/telemetry/logging/severity.md +62 -0
- package/reference/telemetry/metrics/index.md +150 -0
- package/reference/telemetry/metrics/instruments.md +183 -0
- package/reference/telemetry/metrics/labeled-instruments.md +74 -0
- package/reference/telemetry/metrics/meter-provider.md +76 -0
- package/reference/telemetry/metrics/meter.md +98 -0
- package/reference/telemetry/metrics/metric-data.md +57 -0
- package/reference/telemetry/otel/custom-exporter.md +216 -0
- package/reference/telemetry/otel/index.md +212 -0
- package/reference/telemetry/tracing/index.md +155 -0
- package/reference/telemetry/tracing/sampler.md +89 -0
- package/reference/telemetry/tracing/span-builder.md +57 -0
- package/reference/telemetry/tracing/span-context.md +39 -0
- package/reference/telemetry/tracing/span-data.md +32 -0
- package/reference/telemetry/tracing/span-kind.md +55 -0
- package/reference/telemetry/tracing/span-processor.md +53 -0
- package/reference/telemetry/tracing/span-status.md +47 -0
- package/reference/telemetry/tracing/span.md +117 -0
- package/reference/telemetry/tracing/tracer-provider.md +91 -0
- package/reference/telemetry/tracing/tracer.md +52 -0
- package/reference/typeid.md +5 -83
- package/sidebars.js +376 -43
- package/undocumented-report.md +528 -270
- package/reference/formats.md +0 -694
- package/reference/http-model.md +0 -1716
- package/reference/streams.md +0 -989
- package/ringbuffer.md +0 -249
- /package/reference/{json-differ.md → schema/built-in-codecs/json/json-differ.md} +0 -0
- /package/reference/{dynamic-value.md → schema/dynamic-value.md} +0 -0
- /package/reference/{lazy.md → schema/lazy.md} +0 -0
- /package/reference/{reflect.md → schema/reflect.md} +0 -0
- /package/reference/{registers.md → schema/registers.md} +0 -0
- /package/reference/{schema-error.md → schema/schema-error.md} +0 -0
- /package/reference/{syntax.md → schema/syntax.md} +0 -0
- /package/reference/{validation.md → schema/validation.md} +0 -0
|
@@ -57,12 +57,12 @@ In this guide, we solve both problems: bridge extensions eliminate `.toExpr`, an
|
|
|
57
57
|
This guide builds on [Part 1: Expressions](./query-dsl-reified-optics.md), [Part 2: SQL Generation](./query-dsl-sql.md), and [Part 3: Extending the Expression Language](./query-dsl-extending.md).
|
|
58
58
|
|
|
59
59
|
```scala
|
|
60
|
-
libraryDependencies += "dev.zio" %% "zio-blocks-schema" % "0.0.
|
|
60
|
+
libraryDependencies += "dev.zio" %% "zio-blocks-schema" % "0.0.55"
|
|
61
61
|
```
|
|
62
62
|
|
|
63
63
|
## Domain Setup
|
|
64
64
|
|
|
65
|
-
We carry forward the product catalog domain and the Part 3 independent `Expr` ADT. The key additions in Part 4 are bridge extension methods, schema-driven table names, and statement builder types.
|
|
65
|
+
We carry forward the product catalog domain and the Part 3 independent `Expr` ADT. The key additions in Part 4 are bridge extension methods, schema-driven table names, and statement builder types. As in Part 3, the public expression layer stays typed: built-in logic remains `SchemaExpr`, and the SQL builder only drops to the dynamic AST inside interpreter helpers.
|
|
66
66
|
|
|
67
67
|
```scala
|
|
68
68
|
import zio.blocks.schema._
|
|
@@ -135,6 +135,7 @@ object OrderItem extends CompanionOptics[OrderItem] {
|
|
|
135
135
|
sealed trait Expr[S, A]
|
|
136
136
|
|
|
137
137
|
object Expr {
|
|
138
|
+
final case class Builtin[S, A](schemaExpr: SchemaExpr[S, A]) extends Expr[S, A]
|
|
138
139
|
final case class Column[S, A](optic: Optic[S, A]) extends Expr[S, A]
|
|
139
140
|
final case class Lit[S, A](value: A, schema: Schema[A]) extends Expr[S, A]
|
|
140
141
|
|
|
@@ -155,38 +156,7 @@ object Expr {
|
|
|
155
156
|
def col[S, A](optic: Optic[S, A]): Expr[S, A] = Column(optic)
|
|
156
157
|
def lit[S, A](value: A)(implicit schema: Schema[A]): Expr[S, A] = Lit(value, schema)
|
|
157
158
|
|
|
158
|
-
def fromSchemaExpr[S, A](se: SchemaExpr[S, A]): Expr[S, A] =
|
|
159
|
-
val result = se match {
|
|
160
|
-
case SchemaExpr.Optic(optic) => Column(optic)
|
|
161
|
-
case l: SchemaExpr.Literal[_, _] => Lit(l.value, l.schema)
|
|
162
|
-
case SchemaExpr.Relational(l, r, op) =>
|
|
163
|
-
val relOp = op match {
|
|
164
|
-
case SchemaExpr.RelationalOperator.Equal => RelOp.Equal
|
|
165
|
-
case SchemaExpr.RelationalOperator.NotEqual => RelOp.NotEqual
|
|
166
|
-
case SchemaExpr.RelationalOperator.LessThan => RelOp.LessThan
|
|
167
|
-
case SchemaExpr.RelationalOperator.LessThanOrEqual => RelOp.LessThanOrEqual
|
|
168
|
-
case SchemaExpr.RelationalOperator.GreaterThan => RelOp.GreaterThan
|
|
169
|
-
case SchemaExpr.RelationalOperator.GreaterThanOrEqual => RelOp.GreaterThanOrEqual
|
|
170
|
-
}
|
|
171
|
-
Relational(fromSchemaExpr(l), fromSchemaExpr(r), relOp)
|
|
172
|
-
case SchemaExpr.Logical(l, r, op) => op match {
|
|
173
|
-
case SchemaExpr.LogicalOperator.And => And(fromSchemaExpr(l), fromSchemaExpr(r))
|
|
174
|
-
case SchemaExpr.LogicalOperator.Or => Or(fromSchemaExpr(l), fromSchemaExpr(r))
|
|
175
|
-
}
|
|
176
|
-
case SchemaExpr.Not(inner) => Not(fromSchemaExpr(inner))
|
|
177
|
-
case SchemaExpr.Arithmetic(l, r, op, _) =>
|
|
178
|
-
val arithOp = op match {
|
|
179
|
-
case SchemaExpr.ArithmeticOperator.Add => ArithOp.Add
|
|
180
|
-
case SchemaExpr.ArithmeticOperator.Subtract => ArithOp.Subtract
|
|
181
|
-
case SchemaExpr.ArithmeticOperator.Multiply => ArithOp.Multiply
|
|
182
|
-
}
|
|
183
|
-
Arithmetic(fromSchemaExpr(l), fromSchemaExpr(r), arithOp)
|
|
184
|
-
case SchemaExpr.StringConcat(l, r) => StringConcat(fromSchemaExpr(l), fromSchemaExpr(r))
|
|
185
|
-
case SchemaExpr.StringRegexMatch(regex, string) => StringRegexMatch(fromSchemaExpr(regex), fromSchemaExpr(string))
|
|
186
|
-
case SchemaExpr.StringLength(string) => StringLength(fromSchemaExpr(string))
|
|
187
|
-
}
|
|
188
|
-
result.asInstanceOf[Expr[S, A]]
|
|
189
|
-
}
|
|
159
|
+
def fromSchemaExpr[S, A](se: SchemaExpr[S, A]): Expr[S, A] = Builtin(se)
|
|
190
160
|
}
|
|
191
161
|
|
|
192
162
|
sealed trait RelOp
|
|
@@ -211,6 +181,9 @@ object ArithOp {
|
|
|
211
181
|
def columnName(optic: zio.blocks.schema.Optic[_, _]): String =
|
|
212
182
|
optic.toDynamic.nodes.collect { case f: DynamicOptic.Node.Field => f.name }.mkString("_")
|
|
213
183
|
|
|
184
|
+
def columnName(path: DynamicOptic): String =
|
|
185
|
+
path.nodes.collect { case f: DynamicOptic.Node.Field => f.name }.mkString("_")
|
|
186
|
+
|
|
214
187
|
def sqlLiteral[A](value: A, schema: Schema[A]): String = {
|
|
215
188
|
val dv = schema.toDynamicValue(value)
|
|
216
189
|
dv match {
|
|
@@ -223,6 +196,22 @@ def sqlLiteral[A](value: A, schema: Schema[A]): String = {
|
|
|
223
196
|
}
|
|
224
197
|
}
|
|
225
198
|
|
|
199
|
+
def sqlLiteralDV(dv: DynamicValue): String = dv match {
|
|
200
|
+
case DynamicValue.Primitive(pv) =>
|
|
201
|
+
pv match {
|
|
202
|
+
case PrimitiveValue.String(s) => s"'${s.replace("'", "''")}'"
|
|
203
|
+
case PrimitiveValue.Boolean(b) => if (b) "TRUE" else "FALSE"
|
|
204
|
+
case PrimitiveValue.Int(n) => n.toString
|
|
205
|
+
case PrimitiveValue.Long(n) => n.toString
|
|
206
|
+
case PrimitiveValue.Double(n) => n.toString
|
|
207
|
+
case PrimitiveValue.Float(n) => n.toString
|
|
208
|
+
case PrimitiveValue.Short(n) => n.toString
|
|
209
|
+
case PrimitiveValue.Byte(n) => n.toString
|
|
210
|
+
case other => other.toString
|
|
211
|
+
}
|
|
212
|
+
case other => other.toString
|
|
213
|
+
}
|
|
214
|
+
|
|
226
215
|
// --- Optic extension methods ---
|
|
227
216
|
|
|
228
217
|
implicit final class OpticExprOps[S, A](private val optic: Optic[S, A]) {
|
|
@@ -255,8 +244,9 @@ implicit final class SchemaExprBooleanBridge[S](private val self: SchemaExpr[S,
|
|
|
255
244
|
// --- Single unified SQL interpreter ---
|
|
256
245
|
|
|
257
246
|
def exprToSql[S, A](expr: Expr[S, A]): String = expr match {
|
|
258
|
-
case Expr.
|
|
259
|
-
case Expr.
|
|
247
|
+
case Expr.Builtin(schemaExpr) => schemaExprToSql(schemaExpr)
|
|
248
|
+
case Expr.Column(optic) => columnName(optic)
|
|
249
|
+
case Expr.Lit(value, schema) => sqlLiteral(value, schema)
|
|
260
250
|
case Expr.Relational(left, right, op) =>
|
|
261
251
|
val sqlOp = op match {
|
|
262
252
|
case RelOp.Equal => "="
|
|
@@ -287,6 +277,46 @@ def exprToSql[S, A](expr: Expr[S, A]): String = expr match {
|
|
|
287
277
|
case Expr.IsNull(e) => s"${exprToSql(e)} IS NULL"
|
|
288
278
|
case Expr.Like(e, pattern) => s"${exprToSql(e)} LIKE '${pattern.replace("'", "''")}'"
|
|
289
279
|
}
|
|
280
|
+
|
|
281
|
+
def schemaExprToSql[S, A](expr: SchemaExpr[S, A]): String =
|
|
282
|
+
toSqlDynamic(expr.dynamic)
|
|
283
|
+
|
|
284
|
+
def toSqlDynamic(expr: DynamicSchemaExpr): String = expr match {
|
|
285
|
+
case DynamicSchemaExpr.Select(path) => columnName(path)
|
|
286
|
+
case DynamicSchemaExpr.Literal(value, _) => sqlLiteralDV(value)
|
|
287
|
+
case DynamicSchemaExpr.Relational(left, right, op) =>
|
|
288
|
+
val sqlOp = op match {
|
|
289
|
+
case DynamicSchemaExpr.RelationalOperator.Equal => "="
|
|
290
|
+
case DynamicSchemaExpr.RelationalOperator.NotEqual => "<>"
|
|
291
|
+
case DynamicSchemaExpr.RelationalOperator.LessThan => "<"
|
|
292
|
+
case DynamicSchemaExpr.RelationalOperator.LessThanOrEqual => "<="
|
|
293
|
+
case DynamicSchemaExpr.RelationalOperator.GreaterThan => ">"
|
|
294
|
+
case DynamicSchemaExpr.RelationalOperator.GreaterThanOrEqual => ">="
|
|
295
|
+
}
|
|
296
|
+
s"(${toSqlDynamic(left)} $sqlOp ${toSqlDynamic(right)})"
|
|
297
|
+
case DynamicSchemaExpr.Logical(left, right, op) =>
|
|
298
|
+
val sqlOp = op match {
|
|
299
|
+
case DynamicSchemaExpr.LogicalOperator.And => "AND"
|
|
300
|
+
case DynamicSchemaExpr.LogicalOperator.Or => "OR"
|
|
301
|
+
}
|
|
302
|
+
s"(${toSqlDynamic(left)} $sqlOp ${toSqlDynamic(right)})"
|
|
303
|
+
case DynamicSchemaExpr.Not(inner) =>
|
|
304
|
+
s"NOT (${toSqlDynamic(inner)})"
|
|
305
|
+
case DynamicSchemaExpr.Arithmetic(left, right, op, _) =>
|
|
306
|
+
val sqlOp = op match {
|
|
307
|
+
case DynamicSchemaExpr.ArithmeticOperator.Add => "+"
|
|
308
|
+
case DynamicSchemaExpr.ArithmeticOperator.Subtract => "-"
|
|
309
|
+
case DynamicSchemaExpr.ArithmeticOperator.Multiply => "*"
|
|
310
|
+
case _ => "?"
|
|
311
|
+
}
|
|
312
|
+
s"(${toSqlDynamic(left)} $sqlOp ${toSqlDynamic(right)})"
|
|
313
|
+
case DynamicSchemaExpr.StringConcat(left, right) =>
|
|
314
|
+
s"CONCAT(${toSqlDynamic(left)}, ${toSqlDynamic(right)})"
|
|
315
|
+
case DynamicSchemaExpr.StringRegexMatch(regex, string) =>
|
|
316
|
+
s"(${toSqlDynamic(string)} LIKE ${toSqlDynamic(regex)})"
|
|
317
|
+
case DynamicSchemaExpr.StringLength(string) =>
|
|
318
|
+
s"LENGTH(${toSqlDynamic(string)})"
|
|
319
|
+
}
|
|
290
320
|
```
|
|
291
321
|
|
|
292
322
|
## Seamless Condition Composition
|
|
@@ -380,7 +410,7 @@ exprToSql(condition)
|
|
|
380
410
|
// res0: String = "((((price BETWEEN 10.0 AND 500.0) AND (category = 'Electronics')) AND (rating >= 4)) AND name LIKE 'L%')"
|
|
381
411
|
```
|
|
382
412
|
|
|
383
|
-
The first
|
|
413
|
+
The first `&&` already involves `between`, so the bridge activates as soon as an `Expr` enters the chain. From that point on, the whole condition is represented as `Expr`.
|
|
384
414
|
|
|
385
415
|
## Schema-Driven Table Names
|
|
386
416
|
|
|
@@ -496,51 +526,51 @@ val basicSelect = select(Product.table)
|
|
|
496
526
|
// table = Table("products"),
|
|
497
527
|
// columnList = List("name", "price"),
|
|
498
528
|
// whereExpr = Some(
|
|
499
|
-
//
|
|
500
|
-
//
|
|
501
|
-
//
|
|
502
|
-
//
|
|
503
|
-
//
|
|
504
|
-
//
|
|
505
|
-
//
|
|
506
|
-
//
|
|
507
|
-
//
|
|
508
|
-
//
|
|
509
|
-
//
|
|
510
|
-
//
|
|
511
|
-
//
|
|
512
|
-
//
|
|
513
|
-
//
|
|
514
|
-
//
|
|
515
|
-
//
|
|
529
|
+
// Builtin(
|
|
530
|
+
// SchemaExpr(
|
|
531
|
+
// dynamic = Relational(
|
|
532
|
+
// left = Select(DynamicOptic(ArraySeq(Field("inStock")))),
|
|
533
|
+
// right = Literal(
|
|
534
|
+
// value = Primitive(Boolean(true)),
|
|
535
|
+
// schema = Schema(
|
|
536
|
+
// Primitive(
|
|
537
|
+
// primitiveType = Boolean(None),
|
|
538
|
+
// typeId = Boolean,
|
|
539
|
+
// primitiveBinding = Primitive(),
|
|
540
|
+
// doc = Doc(blocks = IndexedSeq(), metadata = Map()),
|
|
541
|
+
// modifiers = List(),
|
|
542
|
+
// storedDefaultValue = None,
|
|
543
|
+
// storedExamples = List()
|
|
544
|
+
// )
|
|
545
|
+
// )
|
|
546
|
+
// ),
|
|
547
|
+
// operator = Equal
|
|
548
|
+
// ),
|
|
549
|
+
// inputSchema = Schema(
|
|
550
|
+
// Record(
|
|
551
|
+
// fields = Vector(
|
|
552
|
+
// Term(
|
|
553
|
+
// name = "name",
|
|
554
|
+
// value = Primitive(
|
|
555
|
+
// primitiveType = String(None),
|
|
556
|
+
// typeId = String,
|
|
557
|
+
// primitiveBinding = Primitive(),
|
|
516
558
|
// doc = Doc(blocks = IndexedSeq(), metadata = Map()),
|
|
517
|
-
// modifiers = List()
|
|
559
|
+
// modifiers = List(),
|
|
560
|
+
// storedDefaultValue = None,
|
|
561
|
+
// storedExamples = List()
|
|
518
562
|
// ),
|
|
519
|
-
//
|
|
520
|
-
//
|
|
521
|
-
//
|
|
522
|
-
//
|
|
523
|
-
//
|
|
524
|
-
//
|
|
525
|
-
//
|
|
526
|
-
//
|
|
527
|
-
//
|
|
528
|
-
// storedExamples = List()
|
|
529
|
-
// ),
|
|
563
|
+
// doc = Doc(blocks = IndexedSeq(), metadata = Map()),
|
|
564
|
+
// modifiers = List()
|
|
565
|
+
// ),
|
|
566
|
+
// Term(
|
|
567
|
+
// name = "price",
|
|
568
|
+
// value = Primitive(
|
|
569
|
+
// primitiveType = Double(None),
|
|
570
|
+
// typeId = Double,
|
|
571
|
+
// primitiveBinding = Primitive(),
|
|
530
572
|
// doc = Doc(blocks = IndexedSeq(), metadata = Map()),
|
|
531
|
-
// modifiers = List()
|
|
532
|
-
// ),
|
|
533
|
-
// Term(
|
|
534
|
-
// name = "category",
|
|
535
|
-
// value = Primitive(
|
|
536
|
-
// primitiveType = String(None),
|
|
537
|
-
// typeId = String,
|
|
538
|
-
// primitiveBinding = Primitive(),
|
|
539
|
-
// doc = Doc(blocks = IndexedSeq(), metadata = Map()),
|
|
540
|
-
// modifiers = List(),
|
|
541
|
-
// storedDefaultValue = None,
|
|
542
|
-
// storedExamples = List()
|
|
543
|
-
// ),
|
|
573
|
+
// modifiers = List(),
|
|
544
574
|
// ...
|
|
545
575
|
|
|
546
576
|
renderSelect(basicSelect)
|
|
@@ -723,48 +753,48 @@ val multiUpdate =
|
|
|
723
753
|
// Assignment(column = "inStock", value = "FALSE")
|
|
724
754
|
// ),
|
|
725
755
|
// whereExpr = Some(
|
|
726
|
-
//
|
|
727
|
-
//
|
|
728
|
-
//
|
|
729
|
-
//
|
|
730
|
-
//
|
|
731
|
-
//
|
|
732
|
-
//
|
|
733
|
-
//
|
|
734
|
-
//
|
|
735
|
-
//
|
|
736
|
-
//
|
|
737
|
-
//
|
|
738
|
-
//
|
|
739
|
-
//
|
|
740
|
-
//
|
|
741
|
-
//
|
|
742
|
-
//
|
|
743
|
-
//
|
|
744
|
-
//
|
|
745
|
-
//
|
|
746
|
-
//
|
|
747
|
-
//
|
|
748
|
-
//
|
|
749
|
-
//
|
|
750
|
-
//
|
|
751
|
-
//
|
|
752
|
-
//
|
|
753
|
-
//
|
|
754
|
-
//
|
|
755
|
-
// storedExamples = List()
|
|
756
|
-
// ),
|
|
756
|
+
// Builtin(
|
|
757
|
+
// SchemaExpr(
|
|
758
|
+
// dynamic = Relational(
|
|
759
|
+
// left = Select(DynamicOptic(ArraySeq(Field("category")))),
|
|
760
|
+
// right = Literal(
|
|
761
|
+
// value = Primitive(String("Clearance")),
|
|
762
|
+
// schema = Schema(
|
|
763
|
+
// Primitive(
|
|
764
|
+
// primitiveType = String(None),
|
|
765
|
+
// typeId = String,
|
|
766
|
+
// primitiveBinding = Primitive(),
|
|
767
|
+
// doc = Doc(blocks = IndexedSeq(), metadata = Map()),
|
|
768
|
+
// modifiers = List(),
|
|
769
|
+
// storedDefaultValue = None,
|
|
770
|
+
// storedExamples = List()
|
|
771
|
+
// )
|
|
772
|
+
// )
|
|
773
|
+
// ),
|
|
774
|
+
// operator = Equal
|
|
775
|
+
// ),
|
|
776
|
+
// inputSchema = Schema(
|
|
777
|
+
// Record(
|
|
778
|
+
// fields = Vector(
|
|
779
|
+
// Term(
|
|
780
|
+
// name = "name",
|
|
781
|
+
// value = Primitive(
|
|
782
|
+
// primitiveType = String(None),
|
|
783
|
+
// typeId = String,
|
|
784
|
+
// primitiveBinding = Primitive(),
|
|
757
785
|
// doc = Doc(blocks = IndexedSeq(), metadata = Map()),
|
|
758
|
-
// modifiers = List()
|
|
786
|
+
// modifiers = List(),
|
|
787
|
+
// storedDefaultValue = None,
|
|
788
|
+
// storedExamples = List()
|
|
759
789
|
// ),
|
|
760
|
-
//
|
|
761
|
-
//
|
|
762
|
-
//
|
|
763
|
-
//
|
|
764
|
-
//
|
|
765
|
-
//
|
|
766
|
-
//
|
|
767
|
-
//
|
|
790
|
+
// doc = Doc(blocks = IndexedSeq(), metadata = Map()),
|
|
791
|
+
// modifiers = List()
|
|
792
|
+
// ),
|
|
793
|
+
// Term(
|
|
794
|
+
// name = "price",
|
|
795
|
+
// value = Primitive(
|
|
796
|
+
// primitiveType = Double(None),
|
|
797
|
+
// typeId = Double,
|
|
768
798
|
// ...
|
|
769
799
|
|
|
770
800
|
renderUpdate(multiUpdate)
|
|
@@ -901,7 +931,7 @@ For batch inserts, create one `InsertStmt` per row and render each separately. T
|
|
|
901
931
|
|
|
902
932
|
## Putting It Together
|
|
903
933
|
|
|
904
|
-
Here is a complete example combining schema-driven table names, bridge extensions, all four statement builders, and the renderers. The `Expr` ADT, extension methods, SQL rendering, and builder types are defined in `Common.scala` and `package.scala` — the usage code stays focused on building queries:
|
|
934
|
+
Here is a complete example combining schema-driven table names, bridge extensions, all four statement builders, and the renderers. The `Expr` ADT, extension methods, SQL rendering, and builder types are defined in `Common.scala` and `package.scala` — the usage code stays focused on building queries with typed optics and `SchemaExpr`, not on manipulating `Dynamic*` nodes directly:
|
|
905
935
|
|
|
906
936
|
```scala
|
|
907
937
|
import zio.blocks.schema._
|
|
@@ -972,6 +1002,7 @@ object OrderItem extends CompanionOptics[OrderItem] {
|
|
|
972
1002
|
sealed trait Expr[S, A]
|
|
973
1003
|
|
|
974
1004
|
object Expr {
|
|
1005
|
+
final case class Builtin[S, A](schemaExpr: SchemaExpr[S, A]) extends Expr[S, A]
|
|
975
1006
|
final case class Column[S, A](optic: Optic[S, A]) extends Expr[S, A]
|
|
976
1007
|
final case class Lit[S, A](value: A, schema: Schema[A]) extends Expr[S, A]
|
|
977
1008
|
|
|
@@ -992,38 +1023,7 @@ object Expr {
|
|
|
992
1023
|
def col[S, A](optic: Optic[S, A]): Expr[S, A] = Column(optic)
|
|
993
1024
|
def lit[S, A](value: A)(implicit schema: Schema[A]): Expr[S, A] = Lit(value, schema)
|
|
994
1025
|
|
|
995
|
-
def fromSchemaExpr[S, A](se: SchemaExpr[S, A]): Expr[S, A] =
|
|
996
|
-
val result = se match {
|
|
997
|
-
case SchemaExpr.Optic(optic) => Column(optic)
|
|
998
|
-
case l: SchemaExpr.Literal[_, _] => Lit(l.value, l.schema)
|
|
999
|
-
case SchemaExpr.Relational(l, r, op) =>
|
|
1000
|
-
val relOp = op match {
|
|
1001
|
-
case SchemaExpr.RelationalOperator.Equal => RelOp.Equal
|
|
1002
|
-
case SchemaExpr.RelationalOperator.NotEqual => RelOp.NotEqual
|
|
1003
|
-
case SchemaExpr.RelationalOperator.LessThan => RelOp.LessThan
|
|
1004
|
-
case SchemaExpr.RelationalOperator.LessThanOrEqual => RelOp.LessThanOrEqual
|
|
1005
|
-
case SchemaExpr.RelationalOperator.GreaterThan => RelOp.GreaterThan
|
|
1006
|
-
case SchemaExpr.RelationalOperator.GreaterThanOrEqual => RelOp.GreaterThanOrEqual
|
|
1007
|
-
}
|
|
1008
|
-
Relational(fromSchemaExpr(l), fromSchemaExpr(r), relOp)
|
|
1009
|
-
case SchemaExpr.Logical(l, r, op) => op match {
|
|
1010
|
-
case SchemaExpr.LogicalOperator.And => And(fromSchemaExpr(l), fromSchemaExpr(r))
|
|
1011
|
-
case SchemaExpr.LogicalOperator.Or => Or(fromSchemaExpr(l), fromSchemaExpr(r))
|
|
1012
|
-
}
|
|
1013
|
-
case SchemaExpr.Not(inner) => Not(fromSchemaExpr(inner))
|
|
1014
|
-
case SchemaExpr.Arithmetic(l, r, op, _) =>
|
|
1015
|
-
val arithOp = op match {
|
|
1016
|
-
case SchemaExpr.ArithmeticOperator.Add => ArithOp.Add
|
|
1017
|
-
case SchemaExpr.ArithmeticOperator.Subtract => ArithOp.Subtract
|
|
1018
|
-
case SchemaExpr.ArithmeticOperator.Multiply => ArithOp.Multiply
|
|
1019
|
-
}
|
|
1020
|
-
Arithmetic(fromSchemaExpr(l), fromSchemaExpr(r), arithOp)
|
|
1021
|
-
case SchemaExpr.StringConcat(l, r) => StringConcat(fromSchemaExpr(l), fromSchemaExpr(r))
|
|
1022
|
-
case SchemaExpr.StringRegexMatch(regex, string) => StringRegexMatch(fromSchemaExpr(regex), fromSchemaExpr(string))
|
|
1023
|
-
case SchemaExpr.StringLength(string) => StringLength(fromSchemaExpr(string))
|
|
1024
|
-
}
|
|
1025
|
-
result.asInstanceOf[Expr[S, A]]
|
|
1026
|
-
}
|
|
1026
|
+
def fromSchemaExpr[S, A](se: SchemaExpr[S, A]): Expr[S, A] = Builtin(se)
|
|
1027
1027
|
}
|
|
1028
1028
|
|
|
1029
1029
|
sealed trait RelOp
|
|
@@ -1075,6 +1075,9 @@ implicit final class SchemaExprBooleanBridge[S](private val self: SchemaExpr[S,
|
|
|
1075
1075
|
def columnName(optic: zio.blocks.schema.Optic[_, _]): String =
|
|
1076
1076
|
optic.toDynamic.nodes.collect { case f: DynamicOptic.Node.Field => f.name }.mkString("_")
|
|
1077
1077
|
|
|
1078
|
+
def columnName(path: DynamicOptic): String =
|
|
1079
|
+
path.nodes.collect { case f: DynamicOptic.Node.Field => f.name }.mkString("_")
|
|
1080
|
+
|
|
1078
1081
|
def sqlLiteral[A](value: A, schema: Schema[A]): String = {
|
|
1079
1082
|
val dv = schema.toDynamicValue(value)
|
|
1080
1083
|
dv match {
|
|
@@ -1087,9 +1090,26 @@ def sqlLiteral[A](value: A, schema: Schema[A]): String = {
|
|
|
1087
1090
|
}
|
|
1088
1091
|
}
|
|
1089
1092
|
|
|
1093
|
+
def sqlLiteralDV(dv: DynamicValue): String = dv match {
|
|
1094
|
+
case DynamicValue.Primitive(pv) =>
|
|
1095
|
+
pv match {
|
|
1096
|
+
case PrimitiveValue.String(s) => s"'${s.replace("'", "''")}'"
|
|
1097
|
+
case PrimitiveValue.Boolean(b) => if (b) "TRUE" else "FALSE"
|
|
1098
|
+
case PrimitiveValue.Int(n) => n.toString
|
|
1099
|
+
case PrimitiveValue.Long(n) => n.toString
|
|
1100
|
+
case PrimitiveValue.Double(n) => n.toString
|
|
1101
|
+
case PrimitiveValue.Float(n) => n.toString
|
|
1102
|
+
case PrimitiveValue.Short(n) => n.toString
|
|
1103
|
+
case PrimitiveValue.Byte(n) => n.toString
|
|
1104
|
+
case other => other.toString
|
|
1105
|
+
}
|
|
1106
|
+
case other => other.toString
|
|
1107
|
+
}
|
|
1108
|
+
|
|
1090
1109
|
def exprToSql[S, A](expr: Expr[S, A]): String = expr match {
|
|
1091
|
-
case Expr.
|
|
1092
|
-
case Expr.
|
|
1110
|
+
case Expr.Builtin(schemaExpr) => schemaExprToSql(schemaExpr)
|
|
1111
|
+
case Expr.Column(optic) => columnName(optic)
|
|
1112
|
+
case Expr.Lit(value, schema) => sqlLiteral(value, schema)
|
|
1093
1113
|
case Expr.Relational(left, right, op) =>
|
|
1094
1114
|
val sqlOp = op match {
|
|
1095
1115
|
case RelOp.Equal => "="
|
|
@@ -1121,6 +1141,46 @@ def exprToSql[S, A](expr: Expr[S, A]): String = expr match {
|
|
|
1121
1141
|
case Expr.Like(e, pattern) => s"${exprToSql(e)} LIKE '${pattern.replace("'", "''")}'"
|
|
1122
1142
|
}
|
|
1123
1143
|
|
|
1144
|
+
def schemaExprToSql[S, A](expr: SchemaExpr[S, A]): String =
|
|
1145
|
+
toSqlDynamic(expr.dynamic)
|
|
1146
|
+
|
|
1147
|
+
def toSqlDynamic(expr: DynamicSchemaExpr): String = expr match {
|
|
1148
|
+
case DynamicSchemaExpr.Select(path) => columnName(path)
|
|
1149
|
+
case DynamicSchemaExpr.Literal(value, _) => sqlLiteralDV(value)
|
|
1150
|
+
case DynamicSchemaExpr.Relational(left, right, op) =>
|
|
1151
|
+
val sqlOp = op match {
|
|
1152
|
+
case DynamicSchemaExpr.RelationalOperator.Equal => "="
|
|
1153
|
+
case DynamicSchemaExpr.RelationalOperator.NotEqual => "<>"
|
|
1154
|
+
case DynamicSchemaExpr.RelationalOperator.LessThan => "<"
|
|
1155
|
+
case DynamicSchemaExpr.RelationalOperator.LessThanOrEqual => "<="
|
|
1156
|
+
case DynamicSchemaExpr.RelationalOperator.GreaterThan => ">"
|
|
1157
|
+
case DynamicSchemaExpr.RelationalOperator.GreaterThanOrEqual => ">="
|
|
1158
|
+
}
|
|
1159
|
+
s"(${toSqlDynamic(left)} $sqlOp ${toSqlDynamic(right)})"
|
|
1160
|
+
case DynamicSchemaExpr.Logical(left, right, op) =>
|
|
1161
|
+
val sqlOp = op match {
|
|
1162
|
+
case DynamicSchemaExpr.LogicalOperator.And => "AND"
|
|
1163
|
+
case DynamicSchemaExpr.LogicalOperator.Or => "OR"
|
|
1164
|
+
}
|
|
1165
|
+
s"(${toSqlDynamic(left)} $sqlOp ${toSqlDynamic(right)})"
|
|
1166
|
+
case DynamicSchemaExpr.Not(inner) =>
|
|
1167
|
+
s"NOT (${toSqlDynamic(inner)})"
|
|
1168
|
+
case DynamicSchemaExpr.Arithmetic(left, right, op, _) =>
|
|
1169
|
+
val sqlOp = op match {
|
|
1170
|
+
case DynamicSchemaExpr.ArithmeticOperator.Add => "+"
|
|
1171
|
+
case DynamicSchemaExpr.ArithmeticOperator.Subtract => "-"
|
|
1172
|
+
case DynamicSchemaExpr.ArithmeticOperator.Multiply => "*"
|
|
1173
|
+
case _ => "?"
|
|
1174
|
+
}
|
|
1175
|
+
s"(${toSqlDynamic(left)} $sqlOp ${toSqlDynamic(right)})"
|
|
1176
|
+
case DynamicSchemaExpr.StringConcat(left, right) =>
|
|
1177
|
+
s"CONCAT(${toSqlDynamic(left)}, ${toSqlDynamic(right)})"
|
|
1178
|
+
case DynamicSchemaExpr.StringRegexMatch(regex, string) =>
|
|
1179
|
+
s"(${toSqlDynamic(string)} LIKE ${toSqlDynamic(regex)})"
|
|
1180
|
+
case DynamicSchemaExpr.StringLength(string) =>
|
|
1181
|
+
s"LENGTH(${toSqlDynamic(string)})"
|
|
1182
|
+
}
|
|
1183
|
+
|
|
1124
1184
|
// --- Statement builders ---
|
|
1125
1185
|
|
|
1126
1186
|
sealed trait SortOrder
|
|
@@ -1231,7 +1291,7 @@ val q = select(Product.table)
|
|
|
1231
1291
|
.where(
|
|
1232
1292
|
Product.category.in("Electronics", "Books") &&
|
|
1233
1293
|
Product.price.between(10.0, 500.0) &&
|
|
1234
|
-
(Product.rating >= 4)
|
|
1294
|
+
(Product.rating >= 4)
|
|
1235
1295
|
)
|
|
1236
1296
|
.orderBy(Product.price, SortOrder.Desc)
|
|
1237
1297
|
.limit(20)
|
|
@@ -1281,7 +1341,7 @@ println(renderSelect(orderQuery))
|
|
|
1281
1341
|
- **[Part 1: Expressions](./query-dsl-reified-optics.md)** — Building query expressions with reified optics
|
|
1282
1342
|
- **[Part 2: SQL Generation](./query-dsl-sql.md)** — Translating built-in expressions to SQL
|
|
1283
1343
|
- **[Part 3: Extending the Expression Language](./query-dsl-extending.md)** — Adding custom operators beyond SchemaExpr
|
|
1284
|
-
- **[SchemaExpr Reference](../reference/schema-expr.md)** — Full API coverage of expression types
|
|
1285
|
-
- **[Optics Reference](../reference/optics.md)** — Lens, Prism, Optional, and Traversal
|
|
1344
|
+
- **[SchemaExpr Reference](../reference/schema/schema-expr.md)** — Full API coverage of expression types
|
|
1345
|
+
- **[Optics Reference](../reference/schema/optics.md)** — Lens, Prism, Optional, and Traversal
|
|
1286
1346
|
|
|
1287
1347
|
The builder pattern shown here extends naturally to JOIN clauses (using lenses from multiple table types), subqueries (nesting `SelectStmt` in WHERE conditions), and parameterized queries (collecting `?` placeholders and parameter values during rendering). Each of these builds on the same foundation: optics for column names, `Expr` for conditions, and immutable builders for statement structure.
|
|
@@ -43,14 +43,14 @@ In this guide, we'll solve this by using ZIO Blocks' `SchemaExpr` and reified op
|
|
|
43
43
|
Add the ZIO Blocks Schema dependency:
|
|
44
44
|
|
|
45
45
|
```scala
|
|
46
|
-
libraryDependencies += "dev.zio" %% "zio-blocks-schema" % "0.0.
|
|
46
|
+
libraryDependencies += "dev.zio" %% "zio-blocks-schema" % "0.0.55"
|
|
47
47
|
```
|
|
48
48
|
|
|
49
49
|
```scala
|
|
50
50
|
import zio.blocks.schema._
|
|
51
51
|
```
|
|
52
52
|
|
|
53
|
-
This guide assumes familiarity with ZIO Blocks schemas and basic optics. See the [Schema](../reference/schema.md) and [Optics](../reference/optics.md) reference pages for background.
|
|
53
|
+
This guide assumes familiarity with ZIO Blocks schemas and basic optics. See the [Schema](../reference/schema/schema.md) and [Optics](../reference/schema/optics.md) reference pages for background.
|
|
54
54
|
|
|
55
55
|
## Defining Your Domain
|
|
56
56
|
|
|
@@ -233,9 +233,9 @@ val nameLength: SchemaExpr[Product, Int] =
|
|
|
233
233
|
|
|
234
234
|
```scala
|
|
235
235
|
startsWithL.eval(laptop)
|
|
236
|
-
// res12: Either[OpticCheck, Seq[Boolean]] = Right(
|
|
236
|
+
// res12: Either[OpticCheck, Seq[Boolean]] = Right(List(true))
|
|
237
237
|
startsWithL.eval(pen)
|
|
238
|
-
// res13: Either[OpticCheck, Seq[Boolean]] = Right(
|
|
238
|
+
// res13: Either[OpticCheck, Seq[Boolean]] = Right(List(false))
|
|
239
239
|
|
|
240
240
|
labeledName.eval(laptop)
|
|
241
241
|
// res14: Either[OpticCheck, Seq[String]] = Right(IndexedSeq("Laptop [SALE]"))
|
|
@@ -346,7 +346,9 @@ val hasExpensiveItem: SchemaExpr[Order, Boolean] =
|
|
|
346
346
|
|
|
347
347
|
```scala
|
|
348
348
|
hasExpensiveItem.eval(order)
|
|
349
|
-
// res21: Either[OpticCheck, Seq[Boolean]] = Right(
|
|
349
|
+
// res21: Either[OpticCheck, Seq[Boolean]] = Right(
|
|
350
|
+
// IndexedSeq(false, true, false)
|
|
351
|
+
// )
|
|
350
352
|
```
|
|
351
353
|
|
|
352
354
|
:::tip
|
|
@@ -486,9 +488,9 @@ catalog.foreach { p =>
|
|
|
486
488
|
- **[Part 2: SQL Generation](./query-dsl-sql.md)** -- Translating query expressions to SQL
|
|
487
489
|
- **[Part 3: Extending the Expression Language](./query-dsl-extending.md)** -- Adding custom operators (IN, BETWEEN, aggregates) beyond SchemaExpr
|
|
488
490
|
- **[Part 4: A Fluent SQL Builder](./query-dsl-fluent-builder.md)** -- Type-safe SELECT, UPDATE, INSERT, DELETE with seamless condition mixing
|
|
489
|
-
- **[Optics Reference](../reference/optics.md)** -- Full API coverage of Lens, Prism, Optional, and Traversal
|
|
490
|
-
- **[DynamicOptic Reference](../reference/dynamic-optic.md)** -- Runtime optic paths for programmatic query construction
|
|
491
|
-
- **[Schema Reference](../reference/schema.md)** -- Schema derivation and type-level metadata
|
|
492
|
-
- **[Path Interpolator](../path-interpolator.md)** -- String-based path construction with `p"..."` syntax
|
|
491
|
+
- **[Optics Reference](../reference/schema/optics.md)** -- Full API coverage of Lens, Prism, Optional, and Traversal
|
|
492
|
+
- **[DynamicOptic Reference](../reference/schema/dynamic-optic.md)** -- Runtime optic paths for programmatic query construction
|
|
493
|
+
- **[Schema Reference](../reference/schema/schema.md)** -- Schema derivation and type-level metadata
|
|
494
|
+
- **[Path Interpolator](../reference/schema/path-interpolator.md)** -- String-based path construction with `p"..."` syntax
|
|
493
495
|
|
|
494
|
-
|
|
496
|
+
`SchemaExpr` is a typed wrapper around a serializable `DynamicSchemaExpr` tree, making it straightforward to write interpreters that translate queries to SQL, MongoDB filters, Elasticsearch queries, or any other target language. Because each optic carries its `DynamicOptic` path (via `toDynamic`), you can extract field names and paths programmatically for these translations.
|