mirror of
https://github.com/digital-asset/daml.git
synced 2024-11-10 10:46:11 +03:00
better JsNull check for Oracle; test scenarios for nested cases (#15022)
* a couple comparison query scenarios with nested position * same JSON null test, but different - 'gt string' (scenario 0) fails without this change - 'gt int' (scenario 1) succeeds regardless of this change CHANGELOG_BEGIN - [JSON API with Oracle] Fix some nested queries that were returning no data. DisableContractPayloadIndexing must be set to true to take advantage of this fix. CHANGELOG_END
This commit is contained in:
parent
5a3cb468f8
commit
77672d2896
@ -987,7 +987,7 @@ private final class OracleQueries(
|
||||
private[http] override def containsAtContractPath(path: JsonPath, literal: JsValue) = {
|
||||
def ensureNotNull = {
|
||||
// we are only trying to reject None for an Optional record/variant/list
|
||||
val pred: Cord = ('$' -: pathSteps(path)) ++ "?(@ != null)"
|
||||
val pred: Cord = ('$' -: pathSteps(path)) ++ "?(!(@ == null))"
|
||||
sql"JSON_EXISTS($contractColumnName, ${oracleShortPathEscape(pred)})"
|
||||
}
|
||||
literal match {
|
||||
|
@ -327,6 +327,7 @@ alias(
|
||||
"//ledger-service/http-json-testing:{}".format(edition),
|
||||
"//ledger-service/db-backend",
|
||||
"//ledger-service/jwt",
|
||||
"//ledger-service/lf-value-json",
|
||||
"//ledger-service/utils",
|
||||
"//ledger/ledger-api-auth",
|
||||
"//ledger/ledger-api-common",
|
||||
|
@ -526,6 +526,80 @@ abstract class AbstractHttpServiceIntegrationTestTokenIndependent
|
||||
}): Future[Assertion]
|
||||
}
|
||||
}
|
||||
|
||||
"nested comparison filters" onlyIfLargeQueries_- {
|
||||
import shapeless.Coproduct, shapeless.syntax.singleton._
|
||||
val irrelevant = Ref.Identifier assertFromString "none:Discarded:Identifier"
|
||||
val (_, bazRecordVA) = VA.record(irrelevant, ShRecord(baz = VA.text))
|
||||
val (_, fooVA) =
|
||||
VA.variant(irrelevant, ShRecord(Bar = VA.int64, Baz = bazRecordVA, Qux = VA.unit))
|
||||
val fooVariant = Coproduct[fooVA.Inj]
|
||||
val (_, kbvarVA) = VA.record(
|
||||
irrelevant,
|
||||
ShRecord(
|
||||
name = VA.text,
|
||||
party = VAx.partyDomain,
|
||||
age = VA.int64,
|
||||
fooVariant = fooVA,
|
||||
bazRecord = bazRecordVA,
|
||||
),
|
||||
)
|
||||
|
||||
def withBazRecord(bazRecord: VA.text.Inj)(p: domain.Party): kbvarVA.Inj =
|
||||
ShRecord(
|
||||
name = "ABC DEF",
|
||||
party = p,
|
||||
age = 123L,
|
||||
fooVariant = fooVariant(Symbol("Bar") ->> 42L),
|
||||
bazRecord = ShRecord(baz = bazRecord),
|
||||
)
|
||||
|
||||
def withFooVariant(v: VA.int64.Inj)(p: domain.Party): kbvarVA.Inj =
|
||||
ShRecord(
|
||||
name = "ABC DEF",
|
||||
party = p,
|
||||
age = 123L,
|
||||
fooVariant = fooVariant(Symbol("Bar") ->> v),
|
||||
bazRecord = ShRecord(baz = "another baz value"),
|
||||
)
|
||||
|
||||
val kbvarId = TpId.Account.KeyedByVariantAndRecord
|
||||
import FilterDiscriminatorScenario.Scenario
|
||||
Seq(
|
||||
Scenario(
|
||||
"gt string",
|
||||
kbvarId,
|
||||
kbvarVA,
|
||||
Map("bazRecord" -> Map("baz" -> Map("%gt" -> "b")).toJson),
|
||||
)(
|
||||
withBazRecord("c"),
|
||||
withBazRecord("a"),
|
||||
),
|
||||
Scenario(
|
||||
"gt int",
|
||||
kbvarId,
|
||||
kbvarVA,
|
||||
Map("fooVariant" -> Map("tag" -> "Bar".toJson, "value" -> Map("%gt" -> 2).toJson).toJson),
|
||||
)(withFooVariant(3), withFooVariant(1)),
|
||||
).zipWithIndex.foreach { case (scenario, ix) =>
|
||||
import scenario._
|
||||
s"$label (scenario $ix)" in withHttpService { fixture =>
|
||||
for {
|
||||
(alice, headers) <- fixture.getUniquePartyAndAuthHeaders("Alice")
|
||||
contracts <- searchExpectOk(
|
||||
List(matches, doesNotMatch).map { payload =>
|
||||
domain.CreateCommand(ctId, argToApi(va)(payload(alice)), None)
|
||||
},
|
||||
JsObject(Map("templateIds" -> Seq(ctId).toJson, "query" -> query.toJson)),
|
||||
fixture,
|
||||
headers,
|
||||
)
|
||||
} yield contracts.map(_.payload) should contain theSameElementsAs Seq(
|
||||
LfValueCodec.apiValueToJsValue(va.inj(matches(alice)))
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"query with invalid JSON query should return error" in withHttpService { fixture =>
|
||||
|
@ -414,6 +414,7 @@ trait AbstractHttpServiceIntegrationTestFuns
|
||||
}
|
||||
object Account {
|
||||
val Account: TId = CtId.Template(None, "Account", "Account")
|
||||
val KeyedByVariantAndRecord: TId = CtId.Template(None, "Account", "KeyedByVariantAndRecord")
|
||||
}
|
||||
object User {
|
||||
val User: Id = domain.TemplateId(None, "User", "User")
|
||||
|
@ -0,0 +1,31 @@
|
||||
// Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package com.daml.http
|
||||
|
||||
import com.daml.lf.value.test.TypedValueGenerators.{ValueAddend => VA}
|
||||
import spray.json.JsValue
|
||||
|
||||
/** A query, a value that matches the query, and a value that doesn't match.
|
||||
*/
|
||||
class FilterDiscriminatorScenario[Inj](
|
||||
val label: String,
|
||||
val ctId: domain.ContractTypeId.OptionalPkg,
|
||||
val va: VA.Aux[Inj],
|
||||
val query: Map[String, JsValue],
|
||||
val matches: domain.Party => Inj,
|
||||
val doesNotMatch: domain.Party => Inj,
|
||||
)
|
||||
|
||||
object FilterDiscriminatorScenario {
|
||||
def Scenario(
|
||||
label: String,
|
||||
ctId: domain.ContractTypeId.OptionalPkg,
|
||||
va: VA,
|
||||
query: Map[String, JsValue],
|
||||
)(
|
||||
matches: domain.Party => va.Inj,
|
||||
doesNotMatch: domain.Party => va.Inj,
|
||||
): FilterDiscriminatorScenario[va.Inj] =
|
||||
new FilterDiscriminatorScenario(label, ctId, va, query, matches, doesNotMatch)
|
||||
}
|
@ -257,7 +257,7 @@ class ValuePredicateTest
|
||||
"{}",
|
||||
tuple3VA,
|
||||
sql"payload @> ${"""{"foo":{}}""".parseJson}::jsonb",
|
||||
sql"""JSON_EXISTS(payload, '$$."foo"?(@ != null)')""",
|
||||
sql"""JSON_EXISTS(payload, '$$."foo"?(!(@ == null))')""",
|
||||
),
|
||||
(
|
||||
"""{"%lte": 42}""",
|
||||
|
@ -5,7 +5,7 @@
|
||||
- Updating the package service succeeds with sufficient authorization: [AuthorizationTest.scala](ledger-service/http-json/src/it/scala/http/AuthorizationTest.scala#L85)
|
||||
- accept user tokens: [TestMiddleware.scala](triggers/service/auth/src/test/scala/com/daml/auth/middleware/oauth2/TestMiddleware.scala#L152)
|
||||
- badly-authorized create is rejected: [AuthorizationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthorizationSpec.scala#L60)
|
||||
- badly-authorized create is rejected: [AbstractHttpServiceIntegrationTest.scala](ledger-service/http-json/src/itlib/scala/http/AbstractHttpServiceIntegrationTest.scala#L1136)
|
||||
- badly-authorized create is rejected: [AbstractHttpServiceIntegrationTest.scala](ledger-service/http-json/src/itlib/scala/http/AbstractHttpServiceIntegrationTest.scala#L1210)
|
||||
- badly-authorized exercise is rejected: [AuthorizationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthorizationSpec.scala#L158)
|
||||
- badly-authorized exercise/create (create is unauthorized) is rejected: [AuthPropagationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthPropagationSpec.scala#L273)
|
||||
- badly-authorized exercise/create (exercise is unauthorized) is rejected: [AuthPropagationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthPropagationSpec.scala#L241)
|
||||
@ -18,7 +18,7 @@
|
||||
- create with no signatories is rejected: [AuthorizationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthorizationSpec.scala#L50)
|
||||
- create with non-signatory maintainers is rejected: [AuthorizationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthorizationSpec.scala#L72)
|
||||
- exercise with no controllers is rejected: [AuthorizationSpec.scala](daml-lf/engine/src/test/scala/com/digitalasset/daml/lf/engine/AuthorizationSpec.scala#L148)
|
||||
- fetch fails when readAs not authed, even if prior fetch succeeded: [AbstractHttpServiceIntegrationTest.scala](ledger-service/http-json/src/itlib/scala/http/AbstractHttpServiceIntegrationTest.scala#L1204)
|
||||
- fetch fails when readAs not authed, even if prior fetch succeeded: [AbstractHttpServiceIntegrationTest.scala](ledger-service/http-json/src/itlib/scala/http/AbstractHttpServiceIntegrationTest.scala#L1278)
|
||||
- forbid a non-authorized party to check the status of a trigger: [TriggerServiceTest.scala](triggers/service/src/test/scala/com/digitalasset/daml/lf/engine/trigger/TriggerServiceTest.scala#L680)
|
||||
- forbid a non-authorized party to list triggers: [TriggerServiceTest.scala](triggers/service/src/test/scala/com/digitalasset/daml/lf/engine/trigger/TriggerServiceTest.scala#L670)
|
||||
- forbid a non-authorized party to start a trigger: [TriggerServiceTest.scala](triggers/service/src/test/scala/com/digitalasset/daml/lf/engine/trigger/TriggerServiceTest.scala#L659)
|
||||
@ -26,7 +26,7 @@
|
||||
- forbid a non-authorized user to upload a DAR: [TriggerServiceTest.scala](triggers/service/src/test/scala/com/digitalasset/daml/lf/engine/trigger/TriggerServiceTest.scala#L712)
|
||||
- multiple websocket requests over the same WebSocket connection are NOT allowed: [AbstractWebsocketServiceIntegrationTest.scala](ledger-service/http-json/src/itlib/scala/http/AbstractWebsocketServiceIntegrationTest.scala#L130)
|
||||
- refresh a token after expiry on the server side: [TriggerServiceTest.scala](triggers/service/src/test/scala/com/digitalasset/daml/lf/engine/trigger/TriggerServiceTest.scala#L737)
|
||||
- reject requests with missing auth header: [AbstractHttpServiceIntegrationTest.scala](ledger-service/http-json/src/itlib/scala/http/AbstractHttpServiceIntegrationTest.scala#L573)
|
||||
- reject requests with missing auth header: [AbstractHttpServiceIntegrationTest.scala](ledger-service/http-json/src/itlib/scala/http/AbstractHttpServiceIntegrationTest.scala#L647)
|
||||
- request a fresh token after expiry on user request: [TriggerServiceTest.scala](triggers/service/src/test/scala/com/digitalasset/daml/lf/engine/trigger/TriggerServiceTest.scala#L722)
|
||||
- return the token from a cookie: [TestMiddleware.scala](triggers/service/auth/src/test/scala/com/daml/auth/middleware/oauth2/TestMiddleware.scala#L96)
|
||||
- return unauthorized on an expired token: [TestMiddleware.scala](triggers/service/auth/src/test/scala/com/daml/auth/middleware/oauth2/TestMiddleware.scala#L139)
|
||||
@ -208,7 +208,7 @@
|
||||
|
||||
## Performance:
|
||||
- Tail call optimization: Tail recursion does not blow the scala JVM stack.: [TailCallTest.scala](daml-lf/interpreter/src/test/scala/com/digitalasset/daml/lf/speedy/TailCallTest.scala#L16)
|
||||
- archiving a large number of contracts should succeed: [AbstractHttpServiceIntegrationTest.scala](ledger-service/http-json/src/itlib/scala/http/AbstractHttpServiceIntegrationTest.scala#L1410)
|
||||
- archiving a large number of contracts should succeed: [AbstractHttpServiceIntegrationTest.scala](ledger-service/http-json/src/itlib/scala/http/AbstractHttpServiceIntegrationTest.scala#L1484)
|
||||
- creating and listing 20K users should be possible: [HttpServiceIntegrationTestUserManagement.scala](ledger-service/http-json/src/it/scala/http/HttpServiceIntegrationTestUserManagement.scala#L558)
|
||||
|
||||
## Input Validation:
|
||||
|
Loading…
Reference in New Issue
Block a user