-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
openapi: Extend the /v1/compile
API
#108
base: main
Are you sure you want to change the base?
Conversation
openapi/openapi.yaml
Outdated
type: array | ||
targetFormat: | ||
type: string | ||
enum: [json_ast, sql, ucast] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe we may need further per-targetFormat options?
For example "ucast" would have different valid inputs (PE fragment) depending on whether it's meant for conversion with ucast.as_sql
, or ucast-linq or ucast-prisma. Could be a "flavour", akin to database dialects? 🤔
Same for SQL, if we want to expand the set of builtins that we can translate, this could depend on the target dialect, too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, that's a good point. 🤔 I suppose we could switch this to be an object type or something that allows us to nest target-specific options.
I was interested in seeing if we could actually separate out the response types for different targets into different I don't want to overload the response to just generic arbitrary JSON |
One concern I've seen come up in discussions around the new Compile targets is about handling multiple output targets in a single request. The argument is that firing up the PE machinery for a single target vs several targets is roughly the same amount of work, so we might as well be able to handle N-many targets in our responses. I propose the following:
EDIT: A third option might be to provide a |
e42fdd5
to
0bf704a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for pushing this forward!
queries: | ||
type: array | ||
description: Array of UCAST JSON objects describing each query. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why an array? I think we're constructing a single condition, so if "queries" from PE are translated, they'll become and OR-of-AND condition object, a single one. So let's do
queries: | |
type: array | |
description: Array of UCAST JSON objects describing each query. | |
ucast: | |
type: object | |
description: UCAST JSON objects describing the conditions under which the query is true. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The array was a holdover from the original PE output format, which might contain results for several queries, as I understood it. I'll refactor this tomorrow.
queries: | ||
type: array | ||
description: Array of strings representing the SQL equivalent of each query. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
queries: | |
type: array | |
description: Array of strings representing the SQL equivalent of each query. | |
sql: | |
type: string | |
description: A string representing the SQL WHERE clauses for the conditions under which the query is true. |
If we have a response like
{
result: {
ucast: { ... }
}
}
for UCAST and
{
result: {
sql: { ... }
}
}
for SQL targets, the mixed response could be
{
result: {
ucast: { ... },
sql: "..."
}
}
OTOH if we want to support multiple SQL dialects in a single "mixed" request, then we might need to return something like
{
result: {
ucast+prisma: { ... },
ucast+linq: { ... },
sql+postgres: "...",
sql+mysql: "..."
}
}
For UCAST, it might not be necessary, because the encoding of the it is the same for different dialects -- only the set of builtins varies, but if your data policy is valid for LINQ, it's valid for Prisma, too, the same UCAST IR.
But for SQL, we'll have to differentiate...
ℹ️ After thinking on it a bit, I find the "third option" (explicit header variant for mixed/multi-target use case) is appealing because it locks down the different things the implementation might have to do, and it prevents the whole "if I'll push up the change to the spec shortly... |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for pushing this forward. I think the end is near ✨
openapi/openapi.yaml
Outdated
ucastAll: | ||
type: object | ||
properties: | ||
queries: | ||
type: array | ||
description: Array of UCAST JSON objects describing each query. | ||
ucastMinimal: | ||
type: object | ||
properties: | ||
queries: | ||
type: array | ||
description: Array of UCAST JSON objects describing each query. | ||
ucastPrisma: | ||
type: object | ||
properties: | ||
queries: | ||
type: array | ||
description: Array of UCAST JSON objects describing each query. | ||
ucastLINQ: | ||
type: object | ||
properties: | ||
queries: | ||
type: array | ||
description: Array of UCAST JSON objects describing each query. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So far, my understanding (and the way the code works right now) is a bit different: the UCAST format is always the same, so there's no difference in form depending on the dialects used.
The supported builtins are different, and this is what I thought we'd want to support when querying for multiple dialects: if you want UCAST for Prisma and LINQ, the set of supported builtins and features is the intersection of the builtins and features supported by each of them. But the outcome will be a single UCAST object.
For the SQL-target dialects, it's similar, but their out form can also be different, so we need to differentiate them.
Does that make sense? I think I'd expect an output for mixed targets like this:
{
result: {
sqlMSSQL: "...",
sqlPostgres: " ...", // if these two have been requested for target SQL
ucast: { ... } // one field only, for all the requested dialects.
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah! Interesting. I'd misunderstood-- my thought was that the policy would be run through PE potentially N-many times, allowing each compilation to use the "best" builtins/form for each target. But! That would be a hideously expensive approach (given that PE is expensive right now), so a more "constricted" shared target (essentially the lowest common denominator) makes sense. 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've refactored the spec to match the "single UCAST target" idea. Do we want to update the description to explain why, or is the "baseline" description enough, you think?
Signed-off-by: Philip Conrad <[email protected]>
Signed-off-by: Philip Conrad <[email protected]>
This commit adds a response type for the /v1/compile API, and begins extending it for supporting more output formats than just the JSON AST format. Signed-off-by: Philip Conrad <[email protected]>
This commit also includes a small change to include table mapping info for the SQL targets. Signed-off-by: Philip Conrad <[email protected]>
Signed-off-by: Philip Conrad <[email protected]>
Signed-off-by: Philip Conrad <[email protected]>
This commit makes the following changes: - A few of the new array types have `items` type constraints now. - Some descriptions have been added and updated. - Proposed initial target dialects include Prisma, LINQ, MySQL, and Postgres. Signed-off-by: Philip Conrad <[email protected]>
Signed-off-by: Philip Conrad <[email protected]>
Signed-off-by: Philip Conrad <[email protected]>
Signed-off-by: Philip Conrad <[email protected]>
Signed-off-by: Philip Conrad <[email protected]>
2a45ffb
to
8945cb7
Compare
Signed-off-by: Philip Conrad <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! I think the end is near 🥳
properties: | ||
query: | ||
type: object | ||
description: UCAST JSON object describing the conditions under which the query is true. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you think we need the extra {"ucast": {"query": ... }}
wrapping? I think I'd drop the inner wrap, i.e. only keep {"ucast": ... }
.
Same for the SQL target/dialect pairs... 🤔
description: The partially evaluated result of the query as SQL. | ||
additionalProperties: true | ||
properties: | ||
queries: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
queries: | |
query: |
But to be aligned with below, I think I'd rather drop "query"/"queries" altogether, except for where the legacy Compile API demands it (plain AST). So SQL would become
{ "result": "WHERE ticket.tenant = 3" }
etc
What changed?
This PR tracks a planned extension to the Enterprise OPA
/v1/compile
API, as part of our intended support for UCAST and data filtering experiments.Currently, my approach is to add a single additional string option under
"options"
➡️"targetFormat"
. Allowed values for the field include:json_ast
(the default),sql
, anducast
.Here's what an example
/v1/compile
input might look like:The response would then resemble: