@@ -26,24 +26,33 @@ import scalaz.{@@, Tag}
2626import slick .jdbc .canton .ActionBasedSQLInterpolation .Implicits .actionBasedSQLInterpolationCanton
2727import slick .jdbc .canton .SQLActionBuilder
2828import slick .jdbc .{GetResult , PositionedResult , SetParameter }
29+ import slick .dbio .Effect
30+ import slick .sql .SqlStreamingAction
2931
3032trait AcsQueries extends AcsJdbcTypes {
3133
3234 /** @param tableName Must be SQL-safe, as it needs to be interpolated unsafely.
3335 * This is fine, as all calls to this method should use static string constants.
3436 */
35- protected def selectFromAcsTable (
37+ protected def selectFromAcsTable [ C , TCid <: ContractId [_], T ] (
3638 tableName : String ,
3739 storeId : AcsStoreId ,
3840 migrationId : Long ,
39- where : SQLActionBuilder ,
41+ companion : C ,
42+ where : SQLActionBuilder = sql " true " ,
4043 orderLimit : SQLActionBuilder = sql " " ,
41- ) =
44+ )(implicit companionClass : ContractCompanion [C , TCid , T ]) = {
45+ val packageQualifiedName = companionClass.packageQualifiedName(companion)
4246 (sql """
4347 select # ${SelectFromAcsTableResult .sqlColumnsCommaSeparated()}
4448 from # $tableName acs
45- where acs.store_id = $storeId and acs.migration_id = $migrationId and """ ++ where ++ sql """
49+ where acs.store_id = $storeId
50+ and acs.migration_id = $migrationId
51+ and acs.package_name = ${packageQualifiedName.packageName}
52+ and acs.template_id_qualified_name = ${packageQualifiedName.qualifiedName}
53+ and """ ++ where ++ sql """
4654 """ ++ orderLimit).toActionBuilder.as[AcsQueries .SelectFromAcsTableResult ]
55+ }
4756
4857 implicit val GetResultSelectFromAcsTable : GetResult [AcsQueries .SelectFromAcsTableResult ] =
4958 GetResult { prs =>
@@ -55,7 +64,7 @@ trait AcsQueries extends AcsJdbcTypes {
5564 << [Long ],
5665 << [ContractId [Any ]],
5766 << [String ],
58- << [QualifiedName ],
67+ << [PackageQualifiedName ],
5968 << [Json ],
6069 << [Array [Byte ]],
6170 << [Timestamp ],
@@ -65,18 +74,27 @@ trait AcsQueries extends AcsJdbcTypes {
6574 }
6675
6776 /** Similar to [[selectFromAcsTable ]], but also returns the contract state (i.e., the domain to which a contract is currently assigned) */
68- protected def selectFromAcsTableWithState (
77+ protected def selectFromAcsTableWithState [ C , TCid <: ContractId [_], T ] (
6978 tableName : String ,
7079 storeId : AcsStoreId ,
7180 migrationId : Long ,
72- where : SQLActionBuilder ,
81+ companion : C ,
82+ additionalWhere : SQLActionBuilder = sql " " ,
7383 orderLimit : SQLActionBuilder = sql " " ,
74- ) =
84+ )(implicit companionClass : ContractCompanion [C , TCid , T ]): SqlStreamingAction [Vector [
85+ SelectFromAcsTableWithStateResult
86+ ], SelectFromAcsTableWithStateResult , Effect .Read ] = {
87+ val packageQualifiedName = companionClass.packageQualifiedName(companion)
7588 (sql """
7689 select # ${SelectFromAcsTableWithStateResult .sqlColumnsCommaSeparated()}
7790 from # $tableName acs
78- where acs.store_id = $storeId and acs.migration_id = $migrationId and """ ++ where ++ sql """
91+ where acs.store_id = $storeId
92+ and acs.migration_id = $migrationId
93+ and acs.package_name = ${packageQualifiedName.packageName}
94+ and acs.template_id_qualified_name = ${packageQualifiedName.qualifiedName}
95+ """ ++ additionalWhere ++ sql """
7996 """ ++ orderLimit).toActionBuilder.as[AcsQueries .SelectFromAcsTableWithStateResult ]
97+ }
8098
8199 implicit val GetResultSelectFromContractStateResult
82100 : GetResult [AcsQueries .SelectFromContractStateResult ] =
@@ -104,13 +122,15 @@ trait AcsQueries extends AcsJdbcTypes {
104122 * This guarantees that the fetched contracts exist in the given offset,
105123 * whereas two separate queries (one to fetch the contract and one to fetch the offset) don't guarantee that.
106124 */
107- protected def selectFromAcsTableWithOffset (
125+ protected def selectFromAcsTableWithOffset [ C , TCid <: ContractId [_], T ] (
108126 tableName : String ,
109127 storeId : AcsStoreId ,
110128 migrationId : Long ,
129+ companion : C ,
111130 where : SQLActionBuilder ,
112131 orderLimit : SQLActionBuilder = sql " " ,
113- ) =
132+ )(implicit companionClass : ContractCompanion [C , TCid , T ]) = {
133+ val packageQualifiedName = companionClass.packageQualifiedName(companion)
114134 (sql """
115135 select
116136 acs.store_id,
@@ -120,6 +140,7 @@ trait AcsQueries extends AcsJdbcTypes {
120140 contract_id,
121141 template_id_package_id,
122142 template_id_qualified_name,
143+ package_name,
123144 create_arguments,
124145 created_event_blob,
125146 created_at,
@@ -130,10 +151,13 @@ trait AcsQueries extends AcsJdbcTypes {
130151 left join # $tableName acs
131152 on o.store_id = acs.store_id
132153 and o.migration_id = acs.migration_id
154+ and acs.package_name = ${packageQualifiedName.packageName}
155+ and acs.template_id_qualified_name = ${packageQualifiedName.qualifiedName}
133156 and """ ++ where ++ sql """
134157 where sd.id = $storeId and o.migration_id = $migrationId
135158 """ ++ orderLimit).toActionBuilder
136159 .as[AcsQueries .SelectFromAcsTableResultWithOffset ]
160+ }
137161
138162 implicit val GetResultSelectFromAcsTableResultWithOffset
139163 : GetResult [AcsQueries .SelectFromAcsTableResultWithOffset ] = { (pp : PositionedResult ) =>
@@ -161,13 +185,15 @@ trait AcsQueries extends AcsJdbcTypes {
161185
162186 /** Same as [[selectFromAcsTableWithOffset ]], but also includes the contract state.
163187 */
164- protected def selectFromAcsTableWithStateAndOffset (
188+ protected def selectFromAcsTableWithStateAndOffset [ C , TCid <: ContractId [_], T ] (
165189 tableName : String ,
166190 storeId : AcsStoreId ,
167191 migrationId : Long ,
192+ companion : C ,
168193 where : SQLActionBuilder = sql " true " ,
169194 orderLimit : SQLActionBuilder = sql " " ,
170- ) =
195+ )(implicit companionClass : ContractCompanion [C , TCid , T ]) = {
196+ val packageQualifiedName = companionClass.packageQualifiedName(companion)
171197 (sql """
172198 select
173199 acs.store_id,
@@ -177,6 +203,7 @@ trait AcsQueries extends AcsJdbcTypes {
177203 acs.contract_id,
178204 acs.template_id_package_id,
179205 acs.template_id_qualified_name,
206+ acs.package_name,
180207 acs.create_arguments,
181208 acs.created_event_blob,
182209 acs.created_at,
@@ -194,10 +221,13 @@ trait AcsQueries extends AcsJdbcTypes {
194221 left join # $tableName acs
195222 on o.store_id = acs.store_id
196223 and o.migration_id = acs.migration_id
224+ and acs.package_name = ${packageQualifiedName.packageName}
225+ and acs.template_id_qualified_name = ${packageQualifiedName.qualifiedName}
197226 and """ ++ where ++ sql """
198227 where sd.id = $storeId and o.migration_id = $migrationId
199228 """ ++ orderLimit).toActionBuilder
200229 .as[AcsQueries .SelectFromAcsTableResultWithStateAndOffset ]
230+ }
201231
202232 implicit val GetResultSelectFromAcsTableResultWithStateOffset
203233 : GetResult [AcsQueries .SelectFromAcsTableResultWithStateAndOffset ] = {
@@ -311,7 +341,7 @@ object AcsQueries {
311341 eventNumber : Long ,
312342 contractId : ContractId [Any ],
313343 templateIdPackageId : String ,
314- templateIdQualifiedName : QualifiedName ,
344+ packageQualifiedName : PackageQualifiedName ,
315345 createArguments : Json ,
316346 createdEventBlob : Array [Byte ],
317347 createdAt : Timestamp ,
@@ -321,12 +351,22 @@ object AcsQueries {
321351 companionClass : ContractCompanion [C , TCId , T ],
322352 decoder : TemplateJsonDecoder ,
323353 ): Contract [TCId , T ] = {
354+ // safety check: if the PackageQualifiedNames don't match,
355+ // it means that we would be returning a contract of a different template
356+ // note that the packageId not matching is expected due to upgrades, but the name will be stable
357+ val expectedPackageQualifiedName = companionClass.packageQualifiedName(companion)
358+ if (expectedPackageQualifiedName != packageQualifiedName) {
359+ throw new IllegalStateException (
360+ s " Contract $contractId has a different package qualified name than expected. Expected: $expectedPackageQualifiedName - Got: $packageQualifiedName"
361+ )
362+ }
363+
324364 companionClass
325365 .fromJson(companion)(
326366 new Identifier (
327367 templateIdPackageId,
328- templateIdQualifiedName .moduleName,
329- templateIdQualifiedName .entityName,
368+ packageQualifiedName.qualifiedName .moduleName,
369+ packageQualifiedName.qualifiedName .entityName,
330370 ),
331371 contractId.contractId,
332372 createArguments,
@@ -351,6 +391,7 @@ object AcsQueries {
351391 ${qualifier}contract_id,
352392 ${qualifier}template_id_package_id,
353393 ${qualifier}template_id_qualified_name,
394+ ${qualifier}package_name,
354395 ${qualifier}create_arguments,
355396 ${qualifier}created_event_blob,
356397 ${qualifier}created_at,
0 commit comments