Skip to content
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

Add Oracle support in the trigger service #9286

Merged
merged 2 commits into from
Mar 31, 2021
Merged

Add Oracle support in the trigger service #9286

merged 2 commits into from
Mar 31, 2021

Conversation

cocreature
Copy link
Contributor

This PR migrates the ddl & queries and adds tests for this. It does
not yet expose this to users. I’ll handle that in a separate PR.

changelog_begin
changelog_end

Pull Request Checklist

  • Read and understand the contribution guidelines
  • Include appropriate tests
  • Set a descriptive title and thorough description
  • Add a reference to the issue this PR will solve, if appropriate
  • Include changelog additions in one or more commit message bodies between the CHANGELOG_BEGIN and CHANGELOG_END tags
  • Normal production system change, include purpose of change in description

NOTE: CI is not automatically run on non-members pull-requests for security
reasons. The reviewer will have to comment with /AzurePipelines run to
trigger the build.

@@ -29,7 +31,7 @@ trait OracleAround {
// See https://docs.oracle.com/cd/B19306_01/server.102/b14200/sql_elements008.htm#i27570
// for name restrictions.
val u = "u" + Random.alphanumeric.take(29).mkString("")
createNewUser(u)
createNewUser(u.toUpperCase)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oracle is case insensitive so this seems like a less confusing option.

-- Copyright (c) 2020 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
-- SPDX-License-Identifier: Apache-2.0

-- Running trigger table.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could in theory use only one migration here since nobody has any historical data on oracle. However, keeping the two in sync seems easier to understand.

trigger_party nvarchar2(255) not null,
-- the identifier for the trigger in its dalf,
-- of the form "packageId:moduleName:triggerName"
full_trigger_name nvarchar2(1000) not null
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1000 is somewhat arbitrary. There is no length limit on module name and trigger name. Oracle really does not like unlimited length (there are options but they all suck). The JSON API and canton also use somewhat arbitrary limits here.

): ConnectionIO[Unit] =
{
val insert: Fragment = sql"""
insert /*+ ignore_row_on_dupkey_index ( dalfs ( package_id ) ) */
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes magic comments are how you do on conflict do nothing in oracle. This is fine.gif

@@ -11,7 +11,7 @@
<logger name="io.grpc.netty" level="WARN">
<appender-ref ref="stderr-appender"/>
</logger>
<logger name="com.daml.lf.engine.trigger" level="DEBUG">
<logger name="com.daml.lf.engine.trigger" level="INFO">
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

happy to revert this but I found it super hard to find the right places with debug logs turned on.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems fine to change

@cocreature cocreature force-pushed the trigger-oracle branch 5 times, most recently from 6768a11 to 7712d78 Compare March 30, 2021 15:35
This PR migrates the ddl & queries and adds tests for this. It does
not yet expose this to users. I’ll handle that in a separate PR.

changelog_begin
changelog_end
@@ -56,6 +57,7 @@ object JdbcConfig {
user <- requiredField(x)("user")
password <- requiredField(x)("password")
} yield JdbcConfig(
driver = "org.postgresql.Driver", // TODO make this configurable
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is what prevents this from being user-facing at the moment.

*> dropTriggerTable.update.run
*> dropDalfTable.update.run).void
}
private def dropTables: ConnectionIO[Unit] = flywayMigrations.clean()
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

flyway names things slightly differently depending on the driver and there really seems no point in reinventing what Flyway.clean does.

@cocreature cocreature requested review from aherrmann-da and S11001001 and removed request for aherrmann-da March 30, 2021 15:52
@cocreature cocreature marked this pull request as ready for review March 30, 2021 15:52
@cocreature cocreature requested a review from a user March 30, 2021 15:52
def apply(c: JdbcConfig, poolSize: PoolSize = Production)(implicit
ec: ExecutionContext
): DbTriggerDao = {
implicit val cs: ContextShift[IO] = IO.contextShift(ec)
val (ds, conn) = Connection.connect(c, poolSize)
new DbTriggerDao(ds, conn)
val driver = supportedJdbcDrivers.get(c.driver) match {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can use supportedJdbcDrivers.getOrElse here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

c3cbb7c thanks

@@ -11,7 +11,7 @@
<logger name="io.grpc.netty" level="WARN">
<appender-ref ref="stderr-appender"/>
</logger>
<logger name="com.daml.lf.engine.trigger" level="DEBUG">
<logger name="com.daml.lf.engine.trigger" level="INFO">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems fine to change

private lazy val jdbcConfig_ =
JdbcConfig("oracle.jdbc.OracleDriver", oracleJdbcUrl, oracleUser, oraclePwd)
// TODO For whatever reason we need a larger pool here, otherwise
// the connection deadlocks. I have no idea why :(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My guess would be that culprit=flyway, maybe more connections when running on Oracle.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah it’s definitely flyway. I just don’t really get why it would use more connections against Oracle than against PostgreSQL for the same number of migrations but 🤷 doesn’t seem that bad to change it.

changelog_begin
changelog_end
@cocreature cocreature merged commit f7b2f14 into main Mar 31, 2021
@cocreature cocreature deleted the trigger-oracle branch March 31, 2021 16:39
@S11001001 S11001001 added this to the Trigger Service milestone Apr 5, 2021
S11001001 added a commit that referenced this pull request Apr 5, 2021
mergify bot pushed a commit that referenced this pull request Apr 12, 2021
* comparison queries

* name the contract primary key constraint

* use ignore_row_on_dupkey_index instead of merge

- suggested by @cocreature in #9286 f7b2f14; thanks

* retrySqlStates for oracle

* enable all non-websocket tests

* name the template_id primary key constraint

* clean up concatFragment calls

* add Websocket tests for oracle

* move iouCreateCommand to be usable by oracle integration tests

* work around Scala 2.12 NPE in Source

* multiquery support for Oracle

* matchedQueries, therefore query-stream support for Oracle

* enable websocket tests

* test '& bar' and 5kb strings

- 5kb string fails on Oracle with
  ORA-01704: string literal too long

* refine the long data cases; gets too long at 4000 bytes as expected

- however, the predicate fails for unknown reason before then; possibly a missed
  escape character case

* handle long data with a fallback

- now the predicate fails in all cases instead of a SQL error, which is...better

* only interpolate true, false, null into JSON predicate conditions

- the problem was with JSON-formatted data; it must be SQL-typed instead

* adapt equal's large-data solution for comparison as well

- only works for numbers and strings, but that's all we need to compare

* move Implicits to Queries

* remove stray spaces in output

* test Oracle query expressions alongside Postgresql

* test that bools aren't compared like numbers and strings

* test @> conjunctions and special {}-query handling

* no changelog

CHANGELOG_BEGIN
CHANGELOG_END

* note on PASSING ... AS X

- suggested by @cocreature; thanks

* remove printlns; these functions don't really need scaffolding anymore

- suggested by @stefanobaghino-da; thanks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants