From f6ada54c267020c4cbb29906fc4f8ef7ba6cdfbf Mon Sep 17 00:00:00 2001 From: Flavian Alexandru Date: Tue, 16 Apr 2019 09:22:01 +0100 Subject: [PATCH 1/8] Adding safe guard around collection types null checking on parsing --- .../builder/primitives/Primitive.scala | 13 ++- .../builder/primitives/Primitives.scala | 2 +- .../PrimitiveColumnRecipesTest.scala | 90 +++++++++++++++++++ .../builder/primitives/PrimitivesTest.scala | 7 ++ .../phantom/tables/TestDatabase.scala | 1 + .../tables/bugs/PrimitiveColumnRecipes.scala | 52 +++++++++++ 6 files changed, 162 insertions(+), 3 deletions(-) create mode 100644 phantom-dsl/src/test/scala/com/outworkers/phantom/builder/primitives/PrimitiveColumnRecipesTest.scala create mode 100644 phantom-dsl/src/test/scala/com/outworkers/phantom/tables/bugs/PrimitiveColumnRecipes.scala diff --git a/phantom-dsl/src/main/scala/com/outworkers/phantom/builder/primitives/Primitive.scala b/phantom-dsl/src/main/scala/com/outworkers/phantom/builder/primitives/Primitive.scala index 660fbf304..08636ac50 100644 --- a/phantom-dsl/src/main/scala/com/outworkers/phantom/builder/primitives/Primitive.scala +++ b/phantom-dsl/src/main/scala/com/outworkers/phantom/builder/primitives/Primitive.scala @@ -76,7 +76,12 @@ abstract class Primitive[RR] { row: Row )(fn: Row => T): Try[T] = { if (Option(row).isEmpty || row.isNull(index)) { - Failure(new Exception(s"Column $index is null") with NoStackTrace) + + if (row.getColumnDefinitions.getType(index).isCollection) { + Try(fn(row)) + } else { + Failure(new Exception(s"Column $index is null") with NoStackTrace) + } } else { Try(fn(row)) } @@ -87,7 +92,11 @@ abstract class Primitive[RR] { row: Row )(fn: Row => T): Try[T] = { if (Option(row).isEmpty || row.isNull(column)) { - Failure(new Exception(s"Column $column is null") with NoStackTrace) + if (row.getColumnDefinitions.getType(column).isCollection) { + Try(fn(row)) + } else { + Failure(new Exception(s"Column $column is null") with NoStackTrace) + } } else { Try(fn(row)) } diff --git a/phantom-dsl/src/main/scala/com/outworkers/phantom/builder/primitives/Primitives.scala b/phantom-dsl/src/main/scala/com/outworkers/phantom/builder/primitives/Primitives.scala index 786e022bc..b118f1bec 100644 --- a/phantom-dsl/src/main/scala/com/outworkers/phantom/builder/primitives/Primitives.scala +++ b/phantom-dsl/src/main/scala/com/outworkers/phantom/builder/primitives/Primitives.scala @@ -151,7 +151,7 @@ object Primitives { val coll = cbf() coll.sizeHint(size) - for (i <- 0 until size) { + for (_ <- 0 until size) { val databb = CodecUtils.readValue(input, version) coll += ev.deserialize(databb, version) } diff --git a/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/primitives/PrimitiveColumnRecipesTest.scala b/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/primitives/PrimitiveColumnRecipesTest.scala new file mode 100644 index 000000000..a6906c01b --- /dev/null +++ b/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/primitives/PrimitiveColumnRecipesTest.scala @@ -0,0 +1,90 @@ +/* + * Copyright 2013 - 2019 Outworkers Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.outworkers.phantom.builder.primitives + + +import com.outworkers.phantom.PhantomSuite +import com.outworkers.phantom.dsl._ +import com.outworkers.phantom.tables.Recipe +import com.outworkers.phantom.tables.bugs.NpeRecipe +import com.outworkers.util.samplers._ + +class PrimitiveColumnRecipesTest extends PhantomSuite { + + override def beforeAll(): Unit = { + super.beforeAll() + database.recipes.createSchema() + database.collectionNpeTable.createSchema() + } + + it should "insert a new record in the recipes table and retrieve it" in { + val sample = gen[NpeRecipe] + + val chain = for { + _ <- database.collectionNpeTable.storeRecord(sample) + res <- database.collectionNpeTable.select.where(_.id eqs sample.id).one() + } yield res + + whenReady(chain) { res => + res shouldBe defined + res.value shouldEqual sample + } + } + + it should "update the author of a recipe" in { + val sample = gen[Recipe] + val newAuthor = Some(gen[ShortString].value) + + val chain = for { + _ <- database.recipes.storeRecord(sample) + res <- database.recipes.select.where(_.url eqs sample.url).one() + _ <- database.recipes + .update.where(_.url eqs sample.url) + .modify(_.description setTo newAuthor) + .future() + res2 <- database.recipes.select.where(_.url eqs sample.url).one() + } yield (res, res2) + + whenReady(chain) { case (res, res2) => + res shouldBe defined + res.value shouldEqual sample + res2 shouldBe defined + res2.value shouldEqual sample.copy(description = newAuthor) + } + } + + it should "retrieve an empty ingredients set" in { + val sample = gen[NpeRecipe] + + val chain = for { + _ <- database.collectionNpeTable.insert() + .value(_.id, sample.id) + .value(_.name, sample.name) + .value(_.title, sample.title) + .value(_.author, sample.author) + .value(_.description, sample.description) + .value(_.timestamp, sample.timestamp) + .future() + res <- database.collectionNpeTable.findRecipeById(sample.id) + } yield res + + whenReady(chain) { res => + res shouldBe defined + res.value.ingredients shouldBe empty + res.value.props shouldBe empty + } + } +} \ No newline at end of file diff --git a/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/primitives/PrimitivesTest.scala b/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/primitives/PrimitivesTest.scala index df7f9401c..84fcbd95f 100644 --- a/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/primitives/PrimitivesTest.scala +++ b/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/primitives/PrimitivesTest.scala @@ -165,6 +165,13 @@ class PrimitivesTest extends FlatSpec with Matchers with GeneratorDrivenProperty test.asCql(EnumTest.one) shouldEqual CQLQuery.escape("one") } + it should "read a bytebuffer with a single size element as an empty collection" in { + val ev = Primitive[List[String]] + val bb = ev.serialize(List.empty[String], ProtocolVersion.V4) + val decoded = ev.deserialize(bb, ProtocolVersion.V4) + decoded shouldEqual List.empty[String] + } + it should "derive a primitive for a custom wrapper type" in { val str = gen[String] diff --git a/phantom-dsl/src/test/scala/com/outworkers/phantom/tables/TestDatabase.scala b/phantom-dsl/src/test/scala/com/outworkers/phantom/tables/TestDatabase.scala index 6da0b009d..7b9cdedfb 100644 --- a/phantom-dsl/src/test/scala/com/outworkers/phantom/tables/TestDatabase.scala +++ b/phantom-dsl/src/test/scala/com/outworkers/phantom/tables/TestDatabase.scala @@ -47,6 +47,7 @@ class TestDatabase( object secondaryCounterTable extends SecondaryCounterTable with Connector object brokenCounterCounterTable extends BrokenCounterTableTest with Connector + object collectionNpeTable extends PrimitiveColumnRecipes with Connector object indexedCollectionsTable extends IndexedCollectionsTable with Connector object indexedEntriesTable extends IndexedEntriesTable with Connector object jsonTable extends JsonTable with Connector diff --git a/phantom-dsl/src/test/scala/com/outworkers/phantom/tables/bugs/PrimitiveColumnRecipes.scala b/phantom-dsl/src/test/scala/com/outworkers/phantom/tables/bugs/PrimitiveColumnRecipes.scala new file mode 100644 index 000000000..9ba0941a6 --- /dev/null +++ b/phantom-dsl/src/test/scala/com/outworkers/phantom/tables/bugs/PrimitiveColumnRecipes.scala @@ -0,0 +1,52 @@ + +/* + * Copyright 2013 - 2018 Outworkers Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.outworkers.phantom.tables.bugs + +import java.util.UUID + +import scala.concurrent.{Future => ScalaFuture} +import com.outworkers.phantom.dsl._ +import org.joda.time.DateTime + +case class NpeRecipe( + id: UUID, + name: String, + title: String, + author: String, + description: String, + ingredients: Set[String], + props: Map[String, String], + timestamp: DateTime +) + + +abstract class PrimitiveColumnRecipes extends Table[PrimitiveColumnRecipes, NpeRecipe] { + object id extends Col[UUID] with PartitionKey + object name extends Col[String] + object title extends Col[String] + object author extends Col[String] + object description extends Col[String] + object ingredients extends Col[Set[String]] + + object props extends Col[Map[String, String]] + + object timestamp extends Col[DateTime] + + def findRecipeById(id: UUID): ScalaFuture[Option[NpeRecipe]] = { + select.where(_.id eqs id).one() + } +} \ No newline at end of file From fec94dffa950d32f7dd3ecd698f6ee49dcdb3519 Mon Sep 17 00:00:00 2001 From: Flavian Alexandru Date: Tue, 16 Apr 2019 09:32:12 +0100 Subject: [PATCH 2/8] Nesting if check --- .../phantom/builder/primitives/Primitive.scala | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/phantom-dsl/src/main/scala/com/outworkers/phantom/builder/primitives/Primitive.scala b/phantom-dsl/src/main/scala/com/outworkers/phantom/builder/primitives/Primitive.scala index 08636ac50..e371a8a0d 100644 --- a/phantom-dsl/src/main/scala/com/outworkers/phantom/builder/primitives/Primitive.scala +++ b/phantom-dsl/src/main/scala/com/outworkers/phantom/builder/primitives/Primitive.scala @@ -75,8 +75,9 @@ abstract class Primitive[RR] { index: Int, row: Row )(fn: Row => T): Try[T] = { - if (Option(row).isEmpty || row.isNull(index)) { - + if (row == Primitive.nullValue) { + Failure(new Exception(s"Row for column $index is null") with NoStackTrace) + } else if (row.isNull(index)) { if (row.getColumnDefinitions.getType(index).isCollection) { Try(fn(row)) } else { @@ -91,7 +92,10 @@ abstract class Primitive[RR] { column: String, row: Row )(fn: Row => T): Try[T] = { - if (Option(row).isEmpty || row.isNull(column)) { + + if (row == Primitive.nullValue) { + Failure(new Exception(s"Row for column $column is null") with NoStackTrace) + } else if (row.isNull(column)) { if (row.getColumnDefinitions.getType(column).isCollection) { Try(fn(row)) } else { From 4f124740e0b469f022499561ddcb65ab0d29b936 Mon Sep 17 00:00:00 2001 From: Flavian Alexandru Date: Sun, 28 Apr 2019 15:45:20 +0100 Subject: [PATCH 3/8] Fixed Allow filtering support --- .../builder/ops/ImplicitMechanism.scala | 2 +- .../outworkers/phantom/keys/PrimaryKey.scala | 4 +- .../phantom/tables/TestDatabase.scala | 1 + .../tables/bugs/NonIndexQueryColumns.scala | 57 +++++++++++++++++++ 4 files changed, 62 insertions(+), 2 deletions(-) create mode 100644 phantom-dsl/src/test/scala/com/outworkers/phantom/tables/bugs/NonIndexQueryColumns.scala diff --git a/phantom-dsl/src/main/scala/com/outworkers/phantom/builder/ops/ImplicitMechanism.scala b/phantom-dsl/src/main/scala/com/outworkers/phantom/builder/ops/ImplicitMechanism.scala index c19d64fbc..8cd5ce57d 100644 --- a/phantom-dsl/src/main/scala/com/outworkers/phantom/builder/ops/ImplicitMechanism.scala +++ b/phantom-dsl/src/main/scala/com/outworkers/phantom/builder/ops/ImplicitMechanism.scala @@ -175,7 +175,7 @@ private[phantom] trait ImplicitMechanism extends ModifyMechanism { } implicit def partitionColumnQueries[RR : Primitive]( - col: AbstractColumn[RR] with PartitionKey + col: AbstractColumn[RR] //with PartitionKey ): PartitionQueryColumn[RR] = new PartitionQueryColumn[RR](col.name) /** diff --git a/phantom-dsl/src/main/scala/com/outworkers/phantom/keys/PrimaryKey.scala b/phantom-dsl/src/main/scala/com/outworkers/phantom/keys/PrimaryKey.scala index 86630fa93..a4faa3cc0 100644 --- a/phantom-dsl/src/main/scala/com/outworkers/phantom/keys/PrimaryKey.scala +++ b/phantom-dsl/src/main/scala/com/outworkers/phantom/keys/PrimaryKey.scala @@ -24,7 +24,9 @@ private[phantom] trait Unmodifiable private[phantom] trait Indexed object Indexed { - implicit def indexedToQueryColumn[T : Primitive](col: AbstractColumn[T] with Indexed): QueryColumn[T] = { + implicit def indexedToQueryColumn[T : Primitive]( + col: AbstractColumn[T] with Indexed + ): QueryColumn[T] = { new QueryColumn(col.name) } diff --git a/phantom-dsl/src/test/scala/com/outworkers/phantom/tables/TestDatabase.scala b/phantom-dsl/src/test/scala/com/outworkers/phantom/tables/TestDatabase.scala index 7b9cdedfb..ea5041be7 100644 --- a/phantom-dsl/src/test/scala/com/outworkers/phantom/tables/TestDatabase.scala +++ b/phantom-dsl/src/test/scala/com/outworkers/phantom/tables/TestDatabase.scala @@ -47,6 +47,7 @@ class TestDatabase( object secondaryCounterTable extends SecondaryCounterTable with Connector object brokenCounterCounterTable extends BrokenCounterTableTest with Connector + object tokensTable extends TokensTable with Connector object collectionNpeTable extends PrimitiveColumnRecipes with Connector object indexedCollectionsTable extends IndexedCollectionsTable with Connector object indexedEntriesTable extends IndexedEntriesTable with Connector diff --git a/phantom-dsl/src/test/scala/com/outworkers/phantom/tables/bugs/NonIndexQueryColumns.scala b/phantom-dsl/src/test/scala/com/outworkers/phantom/tables/bugs/NonIndexQueryColumns.scala new file mode 100644 index 000000000..ffbca8cec --- /dev/null +++ b/phantom-dsl/src/test/scala/com/outworkers/phantom/tables/bugs/NonIndexQueryColumns.scala @@ -0,0 +1,57 @@ +/* + * Copyright 2013 - 2019 Outworkers Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.outworkers.phantom.tables.bugs + +import com.outworkers.phantom.dsl._ + +import scala.concurrent.Future + +final case class Token(email: String, token: UUID, counter: Int) + +abstract class TokensTable extends Table[TokensTable, Token] { + object email extends StringColumn + object token extends UUIDColumn with PartitionKey { + override val name = "tokenuid" + } + object counter extends IntColumn + + def save(t: Token): Future[ResultSet] = { + insert + .value(_.email, t.email) + .value(_.token, t.token) + .value(_.counter, t.counter) + .future() + } + + def get(id: UUID): Future[Option[Token]] = { + select.where( _.token eqs id).one() + } + + def delete(id: UUID) : Future[ResultSet] = { + delete.where( _.token eqs id).future() + } + + def expired(counter: Int): Future[List[Token]] = { + + /* PHANTOM NOT IMPLEMENTED FEATURE: + * With "allow filtering" Cassandra allows to query + * non indexed column. Restrictions are on querying part of multi column + * partition key. You need Cassandra 3.10+ to be able to filter + * on partition key columns. + */ + select.where(_.counter gte counter).allowFiltering().fetch() + } +} \ No newline at end of file From ff151fe8301452cb388f584fff87fd6e237b6124 Mon Sep 17 00:00:00 2001 From: Flavian Alexandru Date: Fri, 31 May 2019 10:07:39 +0100 Subject: [PATCH 4/8] Adding prepared TTL binds --- .../phantom/connectors/Versions.scala | 1 + .../phantom/builder/query/UpdateQuery.scala | 49 +++++++++++++++---- .../outworkers/phantom/ops/QueryContext.scala | 5 +- .../builder/query/db/crud/InsertTest.scala | 23 +++++---- .../query/db/crud/ListOperatorsTest.scala | 2 +- .../query/db/crud/SelectJsonTest.scala | 4 +- .../builder/query/db/crud/SelectTest.scala | 19 +++++++ .../builder/query/db/crud/TruncateTest.scala | 12 ++--- .../specialized/ConditionalQueriesTest.scala | 32 ++++++------ .../query/db/specialized/InOperatorTest.scala | 6 +-- .../specialized/IndexedCollectionsTest.scala | 16 +++--- .../specialized/JodaDateTimeColumnTest.scala | 2 +- .../query/db/specialized/JsonColumnTest.scala | 16 +++--- .../db/specialized/OptionalIndexesTest.scala | 6 +-- .../db/specialized/SecondaryIndexTest.scala | 4 +- .../db/specialized/TupleColumnTest.scala | 24 ++++----- .../prepared/ExactlyOncePromiseTests.scala | 6 +-- .../query/prepared/JsonPreparedInserts.scala | 4 +- .../prepared/PreparedInsertQueryTest.scala | 16 +++--- .../prepared/PreparedUpdateQueryTest.scala | 23 +++++++++ .../tables/OptionalSecondaryIndexTable.scala | 2 +- .../tables/bugs/NonIndexQueryColumns.scala | 18 ++++--- 22 files changed, 184 insertions(+), 106 deletions(-) diff --git a/phantom-connectors/src/main/scala/com/outworkers/phantom/connectors/Versions.scala b/phantom-connectors/src/main/scala/com/outworkers/phantom/connectors/Versions.scala index 02751de5f..fa4de87ec 100644 --- a/phantom-connectors/src/main/scala/com/outworkers/phantom/connectors/Versions.scala +++ b/phantom-connectors/src/main/scala/com/outworkers/phantom/connectors/Versions.scala @@ -56,4 +56,5 @@ object DefaultVersions { val `3.6.0` = Version(3, 6, 0) val `3.7.0` = Version(3, 7, 0) val `3.8.0` = Version(3, 8, 0) + val `3.10.0` = Version(3, 10, 0) } \ No newline at end of file diff --git a/phantom-dsl/src/main/scala/com/outworkers/phantom/builder/query/UpdateQuery.scala b/phantom-dsl/src/main/scala/com/outworkers/phantom/builder/query/UpdateQuery.scala index 93d9c300e..1ec64eb50 100644 --- a/phantom-dsl/src/main/scala/com/outworkers/phantom/builder/query/UpdateQuery.scala +++ b/phantom-dsl/src/main/scala/com/outworkers/phantom/builder/query/UpdateQuery.scala @@ -39,7 +39,8 @@ case class UpdateQuery[ Order <: OrderBound, Status <: ConsistencyBound, Chain <: WhereBound, - PS <: HList + PS <: HList, + TTL <: HList ](table: Table, init: CQLQuery, tokens: List[TokenizerKey], @@ -65,7 +66,7 @@ case class UpdateQuery[ ](condition: Table => QueryCondition[HL])(implicit ev: Chain =:= Unchainned, prepend: Prepend.Aux[HL, PS, Out] - ): UpdateQuery[Table, Record, Limit, Order, Status, Chainned, Out] = { + ): UpdateQuery[Table, Record, Limit, Order, Status, Chainned, Out, TTL] = { copy( wherePart = wherePart append QueryBuilder.Update.where(condition(table).qb), tokens = tokens ::: condition(table).tokens @@ -85,7 +86,7 @@ case class UpdateQuery[ ](condition: Table => QueryCondition[HL])(implicit ev: Chain =:= Chainned, prepend: Prepend.Aux[HL, PS, Out] - ): UpdateQuery[Table, Record, Limit, Order, Status, Chainned, Out] = { + ): UpdateQuery[Table, Record, Limit, Order, Status, Chainned, Out, TTL] = { copy( wherePart = wherePart append QueryBuilder.Update.and(condition(table).qb), tokens = tokens ::: condition(table).tokens @@ -97,7 +98,7 @@ case class UpdateQuery[ Out <: HList ](clause: Table => UpdateClause.Condition[HL])( implicit prepend: Prepend.Aux[HL, HNil, Out] - ): AssignmentsQuery[Table, Record, Limit, Order, Status, Chain, PS, Out, HNil] = { + ): AssignmentsQuery[Table, Record, Limit, Order, Status, Chain, PS, Out, TTL] = { AssignmentsQuery( table = table, init = init, @@ -132,18 +133,48 @@ case class UpdateQuery[ ) } - def ttl(seconds: Long): UpdateQuery[Table, Record, Limit, Order, Status, Chain, PS] = { + def ttl(seconds: Long): UpdateQuery[Table, Record, Limit, Order, Status, Chain, PS, TTL] = { copy(setPart = setPart append QueryBuilder.ttl(seconds.toString)) } - def withOptions(opts: QueryOptions => QueryOptions): UpdateQuery[Table, Record, Limit, Order, Status, Chain, PS] = { + final def ttl( + mark: PrepareMark + ): UpdateQuery[Table, Record, Limit, Order, Status, Chain, PS, Int :: HNil] = { + copy(usingPart = usingPart append QueryBuilder.ttl(mark.qb.queryString)) + } + + def prepareAsync[ + P[_], + F[_], + RevWhere <: HList, + TTLAdded <: HList + ]()( + implicit session: Session, + executor: ExecutionContextExecutor, + keySpace: KeySpace, + ev: PS =:!= HNil, + rev: Reverse.Aux[PS, RevWhere], + prependTTL: Prepend.Aux[TTL, RevWhere, TTLAdded], + fMonad: FutureMonad[F], + adapter: GuavaAdapter[F], + interface: PromiseInterface[P, F] + ): F[PreparedBlock[TTLAdded]] = { + val flatten = new PreparedFlattener(qb) + + flatten.async map { ps => + new PreparedBlock[TTLAdded](ps, flatten.protocolVersion, options) + } + } + + + def withOptions(opts: QueryOptions => QueryOptions): UpdateQuery[Table, Record, Limit, Order, Status, Chain, PS, TTL] = { copy(options = opts(this.options)) } def consistencyLevel_=(level: ConsistencyLevel)( implicit ev: Status =:= Unspecified, session: Session - ): UpdateQuery[Table, Record, Limit, Order, Specified, Chain, PS] = { + ): UpdateQuery[Table, Record, Limit, Order, Specified, Chain, PS, TTL] = { if (session.protocolConsistency) { copy(options = options.consistencyLevel_=(level)) } else { @@ -412,10 +443,10 @@ sealed case class ConditionalQuery[ object UpdateQuery { - type Default[T <: CassandraTable[T, _], R] = UpdateQuery[T, R, Unlimited, Unordered, Unspecified, Unchainned, HNil] + type Default[T <: CassandraTable[T, _], R] = UpdateQuery[T, R, Unlimited, Unordered, Unspecified, Unchainned, HNil, HNil] def apply[T <: CassandraTable[T, _], R](table: T)(implicit keySpace: KeySpace): UpdateQuery.Default[T, R] = { - new UpdateQuery[T, R, Unlimited, Unordered, Unspecified, Unchainned, HNil]( + new UpdateQuery[T, R, Unlimited, Unordered, Unspecified, Unchainned, HNil, HNil]( table = table, init = QueryBuilder.Update.update( QueryBuilder.keyspace(keySpace.name, table.tableName).queryString diff --git a/phantom-dsl/src/main/scala/com/outworkers/phantom/ops/QueryContext.scala b/phantom-dsl/src/main/scala/com/outworkers/phantom/ops/QueryContext.scala index 4bffbed4c..94a0fa5f0 100644 --- a/phantom-dsl/src/main/scala/com/outworkers/phantom/ops/QueryContext.scala +++ b/phantom-dsl/src/main/scala/com/outworkers/phantom/ops/QueryContext.scala @@ -115,8 +115,9 @@ abstract class QueryContext[P[_], F[_], Timeout]( O <: OrderBound, S <: ConsistencyBound, Chain <: WhereBound, - PS <: HList - ](query: UpdateQuery[T, R, L, O, S, Chain, PS]): UpdateIncompleteQueryOps[P, F] = { + PS <: HList, + TTL <: HList + ](query: UpdateQuery[T, R, L, O, S, Chain, PS, TTL]): UpdateIncompleteQueryOps[P, F] = { new UpdateIncompleteQueryOps(query.executableQuery, query.setPart) } diff --git a/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/crud/InsertTest.scala b/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/crud/InsertTest.scala index d36f8e310..853634680 100644 --- a/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/crud/InsertTest.scala +++ b/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/crud/InsertTest.scala @@ -44,7 +44,7 @@ class InsertTest extends PhantomSuite { val row = gen[OldPrimitiveRecord].copy(timeuuid = UUIDs.timeBased()) val chain = for { - store <- database.oldPrimitives.store(row).future() + _ <- database.oldPrimitives.store(row).future() one <- database.oldPrimitives.select.where(_.pkey eqs row.pkey).one } yield one @@ -57,7 +57,7 @@ class InsertTest extends PhantomSuite { val row = gen[PrimitiveRecord] val chain = for { - store <- database.primitives.store(row).future() + _ <- database.primitives.store(row).future() one <- database.primitives.select.where(_.pkey eqs row.pkey).one } yield one @@ -68,11 +68,10 @@ class InsertTest extends PhantomSuite { if (session.v4orNewer) { "Insert" should "work fine for primitives cassandra 2.2 columns" in { - JodaTimeSampler val row = gen[PrimitiveCassandra22] val chain = for { - store <- database.primitivesCassandra22.store(row).future() + _ <- database.primitivesCassandra22.store(row).future() one <- database.primitivesCassandra22.select.where(_.pkey eqs row.pkey).one } yield one @@ -86,7 +85,7 @@ class InsertTest extends PhantomSuite { val row = gen[TestRow].copy(key = "test'", mapIntToInt = Map.empty[Int, Int]) val chain = for { - store <- database.testTable.store(row).future() + _ <- database.testTable.store(row).future() one <- database.testTable.select.where(_.key eqs row.key).one } yield one @@ -99,7 +98,7 @@ class InsertTest extends PhantomSuite { val row = gen[TestRow].copy(mapIntToInt = Map.empty) val chain = for { - store <- database.testTable.store(row).future() + _ <- database.testTable.store(row).future() one <- database.testTable.select.where(_.key eqs row.key).one } yield one @@ -112,7 +111,7 @@ class InsertTest extends PhantomSuite { val recipe = gen[Recipe] val chain = for { - store <- database.recipes.store(recipe).future() + _ <- database.recipes.store(recipe).future() one <- database.recipes.select.where(_.url eqs recipe.url).one } yield one @@ -131,7 +130,7 @@ class InsertTest extends PhantomSuite { val row = gen[MyTestRow].copy(stringlist = List.empty) val chain = for { - store <- database.listCollectionTable.store(row).future() + _ <- database.listCollectionTable.store(row).future() one <- database.listCollectionTable.select.where(_.key eqs row.key).one } yield one @@ -145,7 +144,7 @@ class InsertTest extends PhantomSuite { val row = gen[MyTestRow] val chain = for { - store <- database.listCollectionTable.store(row).future() + _ <- database.listCollectionTable.store(row).future() get <- database.listCollectionTable.select.where(_.key eqs row.key).one } yield get @@ -158,7 +157,7 @@ class InsertTest extends PhantomSuite { val sample = gen[Recipe] val chain = for { - store <- database.recipes.insert.json(compactJson(renderJValue(Extraction.decompose(sample)))).future() + _ <- database.recipes.insert.json(compactJson(renderJValue(Extraction.decompose(sample)))).future() get <- database.recipes.select.where(_.url eqs sample.url).one() } yield get @@ -176,7 +175,7 @@ class InsertTest extends PhantomSuite { val sample = gen[OptTypesRecord].copy(wrapped = None) val chain = for { - store <- database.optDerivedTable.store(sample).future() + _ <- database.optDerivedTable.store(sample).future() res <- database.optDerivedTable.select.where(_.pkey eqs sample.pkey).one() } yield res @@ -190,7 +189,7 @@ class InsertTest extends PhantomSuite { val sample = gen[OptTypesRecord] val chain = for { - store <- database.optDerivedTable.store(sample).future() + _ <- database.optDerivedTable.store(sample).future() res <- database.optDerivedTable.select.where(_.pkey eqs sample.pkey).one() } yield res diff --git a/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/crud/ListOperatorsTest.scala b/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/crud/ListOperatorsTest.scala index feee85028..4bb546dec 100644 --- a/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/crud/ListOperatorsTest.scala +++ b/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/crud/ListOperatorsTest.scala @@ -51,7 +51,7 @@ class ListOperatorsTest extends PhantomSuite { whenReady(operation) { items => items.value shouldEqual recipe.ingredients - items.value should have size recipe.ingredients.size + items.value should have size recipe.ingredients.size.toLong } } diff --git a/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/crud/SelectJsonTest.scala b/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/crud/SelectJsonTest.scala index 654d1f6f6..3d19bf50a 100644 --- a/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/crud/SelectJsonTest.scala +++ b/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/crud/SelectJsonTest.scala @@ -34,7 +34,7 @@ class SelectJsonTest extends PhantomSuite { val row = gen[PrimitiveRecord] val chain = for { - store <- database.primitives.store(row).future() + _ <- database.primitives.store(row).future() b <- database.primitives.select.json().where(_.pkey eqs row.pkey).one } yield b @@ -56,7 +56,7 @@ class SelectJsonTest extends PhantomSuite { val expected = row.take(Nat._8) val chain = for { - store <- database.primitives.store(row).future() + _ <- database.primitives.store(row).future() one <- database.primitives.select(_.pkey, _.long, _.boolean, _.bDecimal, _.double, _.float, _.inet, _.int) .json() .where(_.pkey eqs row.pkey).one() diff --git a/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/crud/SelectTest.scala b/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/crud/SelectTest.scala index 09d1f493d..d44d1f5d8 100644 --- a/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/crud/SelectTest.scala +++ b/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/crud/SelectTest.scala @@ -19,6 +19,7 @@ import com.outworkers.phantom.PhantomSuite import com.outworkers.phantom.builder.query.bugs.UserSchema import com.outworkers.phantom.dsl._ import com.outworkers.phantom.tables._ +import com.outworkers.phantom.tables.bugs.TokenRecord import com.outworkers.util.samplers._ class SelectTest extends PhantomSuite { @@ -27,6 +28,7 @@ class SelectTest extends PhantomSuite { super.beforeAll() val _ = database.primitives.createSchema() database.userSchema.createSchema() + database.tokensTable.createSchema() } "Selecting the whole row" should "work fine" in { @@ -70,4 +72,21 @@ class SelectTest extends PhantomSuite { res.value shouldEqual row.id } } + + it should "allowFiltering on partition key columns with Cassandra 3.10+" in { + if (cassandraVersion.value > Version.`3.10.0`) { + + val counter = gen[Int] + val rows = genList[TokenRecord]().map(_.copy(counter = counter)) + + val chain = for { + _ <- database.tokensTable.storeRecords(rows) + res <- database.tokensTable.expired(counter) + } yield res + + whenReady(chain) { res => + res should contain allElementsOf rows + } + } + } } diff --git a/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/crud/TruncateTest.scala b/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/crud/TruncateTest.scala index 948e119d1..728d27f32 100644 --- a/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/crud/TruncateTest.scala +++ b/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/crud/TruncateTest.scala @@ -31,10 +31,10 @@ class TruncateTest extends PhantomSuite { val articles = genList[Article]() val result = for { - truncateBefore <- database.articles.truncate.future() - store <- database.articles.storeRecords(articles) + _ <- database.articles.truncate.future() + _ <- database.articles.storeRecords(articles) records <- database.articles.select.fetch - truncate <- database.articles.truncate.future() + _ <- database.articles.truncate.future() records1 <- database.articles.select.fetch } yield (records, records1) @@ -52,10 +52,10 @@ class TruncateTest extends PhantomSuite { val articles = genList[Article]() val result = for { - truncateBefore <- database.articles.truncate.future() - i1 <- database.articles.storeRecords(articles) + _ <- database.articles.truncate.future() + _ <- database.articles.storeRecords(articles) records <- database.articles.select.fetch - truncate <- database.articles.truncate.consistencyLevel_=(ConsistencyLevel.ONE).future() + _ <- database.articles.truncate.consistencyLevel_=(ConsistencyLevel.ONE).future() records1 <- database.articles.select.fetch } yield (records, records1) diff --git a/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/specialized/ConditionalQueriesTest.scala b/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/specialized/ConditionalQueriesTest.scala index 0afe6408f..2971ef90c 100644 --- a/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/specialized/ConditionalQueriesTest.scala +++ b/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/specialized/ConditionalQueriesTest.scala @@ -33,9 +33,9 @@ class ConditionalQueriesTest extends PhantomSuite { val updated = genOpt[String] val chain = for { - insert <- database.recipes.store(recipe).future() + _ <- database.recipes.store(recipe).future() select1 <- database.recipes.select.where(_.url eqs recipe.url).one() - update <- database.recipes.update.where(_.url eqs recipe.url) + _ <- database.recipes.update.where(_.url eqs recipe.url) .modify(_.description setTo updated) .onlyIf(_.description is recipe.description).future() select2 <- database.recipes.select.where(_.url eqs recipe.url).one() @@ -62,9 +62,9 @@ class ConditionalQueriesTest extends PhantomSuite { val updated = genOpt[String] val chain = for { - insert <- database.recipes.store(recipe).future() + _ <- database.recipes.store(recipe).future() select1 <- database.recipes.select.where(_.url eqs recipe.url).one() - update <- database.recipes.update.where(_.url eqs recipe.url) + _ <- database.recipes.update.where(_.url eqs recipe.url) .modify(_.description setTo updated) .onlyIf(_.ingredients is recipe.ingredients).future() select2 <- database.recipes.select.where(_.url eqs recipe.url).one() @@ -91,9 +91,9 @@ class ConditionalQueriesTest extends PhantomSuite { val updated = genOpt[String] val chain = for { - insert <- database.recipes.store(recipe).future() + _ <- database.recipes.store(recipe).future() select1 <- database.recipes.select.where(_.url eqs recipe.url).one() - update <- database.recipes.update.where(_.url eqs recipe.url) + _ <- database.recipes.update.where(_.url eqs recipe.url) .modify(_.description setTo updated) .onlyIf(_.ingredients is invalidMatch).future() select2 <- database.recipes.select.where(_.url eqs recipe.url).one() @@ -120,9 +120,9 @@ class ConditionalQueriesTest extends PhantomSuite { val updated = genOpt[String] val chain = for { - insert <- database.recipes.store(recipe).future() + _ <- database.recipes.store(recipe).future() select1 <- database.recipes.select.where(_.url eqs recipe.url).one() - update <- database.recipes.update.where(_.url eqs recipe.url) + _ <- database.recipes.update.where(_.url eqs recipe.url) .modify(_.description setTo updated) .onlyIf(_.description is updated).future() select2 <- database.recipes.select.where(_.url eqs recipe.url).one() @@ -150,9 +150,9 @@ class ConditionalQueriesTest extends PhantomSuite { val updated = genOpt[String] val chain = for { - insert <- database.recipes.store(recipe).future() + _ <- database.recipes.store(recipe).future() select1 <- database.recipes.select.where(_.url eqs recipe.url).one() - update <- database.recipes.update.where(_.url eqs recipe.url) + _ <- database.recipes.update.where(_.url eqs recipe.url) .modify(_.description setTo updated) .onlyIf(_.description is recipe.description) .and(_.uid is recipe.uid).future() @@ -182,9 +182,9 @@ class ConditionalQueriesTest extends PhantomSuite { val updated = genOpt[String] val chain = for { - insert <- database.recipes.store(recipe).future() + _ <- database.recipes.store(recipe).future() select1 <- database.recipes.select.where(_.url eqs recipe.url).one() - update <- database.recipes.update.where(_.url eqs recipe.url) + _ <- database.recipes.update.where(_.url eqs recipe.url) .modify(_.description setTo updated) .onlyIf(_.description is recipe.description) .and(_.lastcheckedat is recipe.lastCheckedAt) @@ -213,9 +213,9 @@ class ConditionalQueriesTest extends PhantomSuite { val updated = genOpt[String] val chain = for { - insert <- database.recipes.store(recipe).future() + _ <- database.recipes.store(recipe).future() select1 <- database.recipes.select.where(_.url eqs recipe.url).one() - update <- database.recipes.update.where(_.url eqs recipe.url) + _ <- database.recipes.update.where(_.url eqs recipe.url) .modify(_.description setTo updated) .onlyIf(_.props is recipe.props) .and(_.ingredients is recipe.ingredients) @@ -244,9 +244,9 @@ class ConditionalQueriesTest extends PhantomSuite { val updated = genOpt[String] val chain = for { - insert <- database.recipes.store(recipe).future() + _ <- database.recipes.store(recipe).future() select1 <- database.recipes.select.where(_.url eqs recipe.url).one() - update <- database.recipes.update.where(_.url eqs recipe.url) + _ <- database.recipes.update.where(_.url eqs recipe.url) .modify(_.description setTo updated) .onlyIf(_.props is recipe.props) .and(_.uid is recipe.uid) diff --git a/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/specialized/InOperatorTest.scala b/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/specialized/InOperatorTest.scala index 7bffbdb2e..775db58d3 100644 --- a/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/specialized/InOperatorTest.scala +++ b/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/specialized/InOperatorTest.scala @@ -31,7 +31,7 @@ class InOperatorTest extends PhantomSuite { val recipe = gen[Recipe] val chain = for { - done <- database.recipes.store(recipe).future() + _ <- database.recipes.store(recipe).future() select <- database.recipes.select.where(_.url in List(recipe.url, gen[EmailAddress].value)).one() } yield select @@ -44,7 +44,7 @@ class InOperatorTest extends PhantomSuite { val recipe = gen[Recipe] val chain = for { - done <- database.recipes.store(recipe).future() + _ <- database.recipes.store(recipe).future() selectIn <- database.recipes.select.where(_.url in ?).prepareAsync() bindedIn <- selectIn.bind(ListValue(recipe.url, gen[ShortString].value)).one() } yield bindedIn @@ -58,7 +58,7 @@ class InOperatorTest extends PhantomSuite { val recipe = gen[Recipe] val chain = for { - done <- database.recipes.store(recipe).future() + _ <- database.recipes.store(recipe).future() select <- database.recipes.select.where(_.url in List(gen[EmailAddress].value)).one() } yield select diff --git a/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/specialized/IndexedCollectionsTest.scala b/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/specialized/IndexedCollectionsTest.scala index fd71d4c77..64a184794 100644 --- a/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/specialized/IndexedCollectionsTest.scala +++ b/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/specialized/IndexedCollectionsTest.scala @@ -38,7 +38,7 @@ class IndexedCollectionsTest extends PhantomSuite { val record = gen[TestRow] val chain = for { - store <- database.indexedCollectionsTable.store(record).future() + _ <- database.indexedCollectionsTable.store(record).future() one <- database.indexedCollectionsTable.select .where(_.setText contains record.setText.headOption.value) .fetch() @@ -64,7 +64,7 @@ class IndexedCollectionsTest extends PhantomSuite { .prepareAsync() val chain = for { - store <- database.indexedCollectionsTable.store(record).future() + _ <- database.indexedCollectionsTable.store(record).future() prep <- query list <- prep.bind(record.setText.headOption.value).fetch() } yield list @@ -86,7 +86,7 @@ class IndexedCollectionsTest extends PhantomSuite { val record = gen[TestRow] val chain = for { - store <- database.indexedCollectionsTable.store(record).future() + _ <- database.indexedCollectionsTable.store(record).future() one <- database.indexedCollectionsTable.select .where(_.mapTextToText contains record.mapTextToText.values.headOption.value) .fetch() @@ -112,7 +112,7 @@ class IndexedCollectionsTest extends PhantomSuite { .prepareAsync() val chain = for { - store <- database.indexedCollectionsTable.store(record).future() + _ <- database.indexedCollectionsTable.store(record).future() results <- query.flatMap(_.bind(record.mapTextToText.values.headOption.value).fetch()) } yield results @@ -130,7 +130,7 @@ class IndexedCollectionsTest extends PhantomSuite { val record = gen[TestRow] val chain = for { - store <- database.indexedCollectionsTable.store(record).future() + _ <- database.indexedCollectionsTable.store(record).future() get <- database.indexedCollectionsTable .select .where(_.mapIntToText containsKey record.mapIntToText.keys.headOption.value) @@ -153,7 +153,7 @@ class IndexedCollectionsTest extends PhantomSuite { val record = gen[TestRow] val chain = for { - store <- database.indexedCollectionsTable.store(record).future() + _ <- database.indexedCollectionsTable.store(record).future() get <- database.indexedCollectionsTable .select .where(_.mapIntToText containsKey ?) @@ -177,7 +177,7 @@ class IndexedCollectionsTest extends PhantomSuite { val record = gen[TestRow].copy(mapIntToInt = Map(5 -> 10, 10 -> 15, 20 -> 25)) val chain = for { - store <- database.indexedEntriesTable.store(record).future() + _ <- database.indexedEntriesTable.store(record).future() result <- database.indexedEntriesTable.select.where(_.mapIntToInt(20) eqs 25).fetch() } yield result @@ -199,7 +199,7 @@ class IndexedCollectionsTest extends PhantomSuite { val query = database.indexedEntriesTable.select.where(_.mapIntToInt(20) eqs ?).prepareAsync() val chain = for { - store <- database.indexedEntriesTable.store(record).future() + _ <- database.indexedEntriesTable.store(record).future() result <- query.flatMap(_.bind(25).fetch()) } yield result diff --git a/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/specialized/JodaDateTimeColumnTest.scala b/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/specialized/JodaDateTimeColumnTest.scala index 6a606e274..9813156ba 100644 --- a/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/specialized/JodaDateTimeColumnTest.scala +++ b/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/specialized/JodaDateTimeColumnTest.scala @@ -31,7 +31,7 @@ class JodaDateTimeColumnTest extends PhantomSuite { val row = gen[JodaRow] val chain = for { - store <- database.primitivesJoda.store(row).future() + _ <- database.primitivesJoda.store(row).future() select <- database.primitivesJoda.select.where(_.pkey eqs row.pkey).one() } yield select diff --git a/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/specialized/JsonColumnTest.scala b/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/specialized/JsonColumnTest.scala index 80be36fa1..f64eeda6f 100644 --- a/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/specialized/JsonColumnTest.scala +++ b/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/specialized/JsonColumnTest.scala @@ -31,7 +31,7 @@ class JsonColumnTest extends PhantomSuite { val sample = gen[JsonClass] val chain = for { - done <- database.jsonTable.store(sample).future() + _ <- database.jsonTable.store(sample).future() select <- database.jsonTable.select.where(_.id eqs sample.id).one } yield select @@ -45,9 +45,9 @@ class JsonColumnTest extends PhantomSuite { val sample2 = gen[JsonClass] val chain = for { - done <- database.jsonTable.store(sample).future() + _ <- database.jsonTable.store(sample).future() select <- database.jsonTable.select.where(_.id eqs sample.id).one - update <- database.jsonTable.update.where(_.id eqs sample.id).modify(_.json setTo sample2.json).future() + _ <- database.jsonTable.update.where(_.id eqs sample.id).modify(_.json setTo sample2.json).future() select2 <- database.jsonTable.select.where(_.id eqs sample.id).one() } yield (select, select2) @@ -62,7 +62,7 @@ class JsonColumnTest extends PhantomSuite { val updated = genOpt[JsonTest] val chain = for { - done <- database.jsonTable.store(sample).future() + _ <- database.jsonTable.store(sample).future() select <- database.jsonTable.select.where(_.id eqs sample.id).one _ <- database.jsonTable.update .where(_.id eqs sample.id) @@ -82,9 +82,9 @@ class JsonColumnTest extends PhantomSuite { val sample2 = gen[JsonClass] val chain = for { - done <- database.jsonTable.store(sample).future() + _ <- database.jsonTable.store(sample).future() select <- database.jsonTable.select.where(_.id eqs sample.id).one - update <- database.jsonTable.update.where(_.id eqs sample.id) + _ <- database.jsonTable.update.where(_.id eqs sample.id) .modify(_.jsonList setIdx (0, sample2.json) ).future() select2 <- database.jsonTable.select.where(_.id eqs sample.id).one() } yield (select, select2) @@ -100,9 +100,9 @@ class JsonColumnTest extends PhantomSuite { val sample2 = gen[JsonClass] val chain = for { - done <- database.jsonTable.store(sample).future() + _ <- database.jsonTable.store(sample).future() select <- database.jsonTable.select.where(_.id eqs sample.id).one - update <- database.jsonTable.update.where(_.id eqs sample.id).modify(_.jsonSet add sample2.json).future() + _ <- database.jsonTable.update.where(_.id eqs sample.id).modify(_.jsonSet add sample2.json).future() select2 <- database.jsonTable.select.where(_.id eqs sample.id).one() } yield (select, select2) diff --git a/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/specialized/OptionalIndexesTest.scala b/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/specialized/OptionalIndexesTest.scala index 87103698c..35a589544 100644 --- a/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/specialized/OptionalIndexesTest.scala +++ b/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/specialized/OptionalIndexesTest.scala @@ -32,7 +32,7 @@ class OptionalIndexesTest extends PhantomSuite { val sample = gen[OptionalSecondaryRecord].copy(secondary = Some(gen[Int])) val chain = for { - store <- database.optionalIndexesTable.store(sample).future() + _ <- database.optionalIndexesTable.store(sample).future() select <- database.optionalIndexesTable.findById(sample.id) select2 <- database.optionalIndexesTable.findByOptionalSecondary(sample.secondary.value) } yield (select, select2) @@ -50,9 +50,9 @@ class OptionalIndexesTest extends PhantomSuite { val sample = gen[OptionalSecondaryRecord].copy(secondary = Some(gen[Int])) val chain = for { - store <- database.optionalIndexesTable.store(sample).future() + _ <- database.optionalIndexesTable.store(sample).future() select <- database.optionalIndexesTable.findByOptionalSecondary(sample.secondary.value) - delete <- database.optionalIndexesTable.delete.where(_.secondary eqs sample.secondary.value).future() + _ <- database.optionalIndexesTable.delete.where(_.secondary eqs sample.secondary).future() select2 <- database.optionalIndexesTable.findByOptionalSecondary(sample.secondary.value) } yield (select, select2) diff --git a/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/specialized/SecondaryIndexTest.scala b/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/specialized/SecondaryIndexTest.scala index 23354d54d..38bffbb34 100644 --- a/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/specialized/SecondaryIndexTest.scala +++ b/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/specialized/SecondaryIndexTest.scala @@ -132,8 +132,8 @@ class SecondaryIndexTest extends PhantomSuite { val sample = gen[SecondaryIndexRecord] val chain = for { - create <- database.quotedSecondaryIndexTable.create.ifNotExists().future() - insert <- database.quotedSecondaryIndexTable.storeRecord(sample) + _ <- database.quotedSecondaryIndexTable.create.ifNotExists().future() + _ <- database.quotedSecondaryIndexTable.storeRecord(sample) query <- database.quotedSecondaryIndexTable.select.where(_.secondary eqs sample.secondary).one() } yield query diff --git a/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/specialized/TupleColumnTest.scala b/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/specialized/TupleColumnTest.scala index 0321e1504..77d636d5a 100644 --- a/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/specialized/TupleColumnTest.scala +++ b/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/specialized/TupleColumnTest.scala @@ -36,7 +36,7 @@ class TupleColumnTest extends PhantomSuite { val insert = database.tuple2Table.store(sample) val chain = for { - store <- insert.future() + _ <- insert.future() rec <- database.tuple2Table.findById(sample.id) } yield rec @@ -53,9 +53,9 @@ class TupleColumnTest extends PhantomSuite { val insert = database.tuple2Table.store(sample) val chain = for { - store <- insert.future() + _ <- insert.future() rec <- database.tuple2Table.findById(sample.id) - update <- database.tuple2Table.update.where(_.id eqs sample.id).modify(_.tp setTo sample2.tp).future() + _ <- database.tuple2Table.update.where(_.id eqs sample.id).modify(_.tp setTo sample2.tp).future() rec2 <- database.tuple2Table.findById(sample.id) } yield (rec, rec2) @@ -74,7 +74,7 @@ class TupleColumnTest extends PhantomSuite { val insert = database.nestedTupleTable.store(sample) val chain = for { - store <- insert.future() + _ <- insert.future() rec <- database.nestedTupleTable.findById(sample.id) } yield rec @@ -91,9 +91,9 @@ class TupleColumnTest extends PhantomSuite { val insert = database.nestedTupleTable.store(sample) val chain = for { - store <- insert.future() + _ <- insert.future() rec <- database.nestedTupleTable.findById(sample.id) - update <- database.nestedTupleTable.update + _ <- database.nestedTupleTable.update .where(_.id eqs sample.id) .modify(_.tp setTo sample2.tp) .future() @@ -116,7 +116,7 @@ class TupleColumnTest extends PhantomSuite { val insert = database.tupleCollectionsTable.store(sample) val chain = for { - store <- insert.future() + _ <- insert.future() rec <- database.tupleCollectionsTable.findById(sample.id) } yield rec @@ -133,9 +133,9 @@ class TupleColumnTest extends PhantomSuite { val appended = gen[Int] -> gen[String] val chain = for { - store <- database.tupleCollectionsTable.store(sample).future() + _ <- database.tupleCollectionsTable.store(sample).future() rec <- database.tupleCollectionsTable.findById(sample.id) - update <- database.tupleCollectionsTable.update + _ <- database.tupleCollectionsTable.update .where(_.id eqs sample.id) .modify(_.tuples append appended) .future() @@ -156,7 +156,7 @@ class TupleColumnTest extends PhantomSuite { val sample = gen[TuplePartitionRecord] val chain = for { - store <- database.tuplePartitionKeyTable.store(sample).future + _ <- database.tuplePartitionKeyTable.store(sample).future rec <- database.tuplePartitionKeyTable.select.where(_.id eqs sample.id).one() } yield rec @@ -171,9 +171,9 @@ class TupleColumnTest extends PhantomSuite { val newUuid = gen[UUID] val chain = for { - store <- database.tuplePartitionKeyTable.store(sample).future + _ <- database.tuplePartitionKeyTable.store(sample).future rec <- database.tuplePartitionKeyTable.select.where(_.id eqs sample.id).one() - updateRec <- database.tuplePartitionKeyTable.update + _ <- database.tuplePartitionKeyTable.update .where(_.id eqs sample.id) .modify(_.rec setTo newUuid) .future() diff --git a/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/prepared/ExactlyOncePromiseTests.scala b/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/prepared/ExactlyOncePromiseTests.scala index f4d8e4293..8c542df72 100644 --- a/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/prepared/ExactlyOncePromiseTests.scala +++ b/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/prepared/ExactlyOncePromiseTests.scala @@ -32,9 +32,9 @@ class ExactlyOncePromiseTests extends FlatSpec with Matchers with ScalaFutures { val promise = new ExactlyOncePromise(Future(atomic.incrementAndGet())) val chain = for { - one <- promise.future - two <- promise.future - three <- promise.future + _ <- promise.future + _ <- promise.future + _ <- promise.future four <- promise.future } yield four diff --git a/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/prepared/JsonPreparedInserts.scala b/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/prepared/JsonPreparedInserts.scala index 32a96d718..02f5105b2 100644 --- a/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/prepared/JsonPreparedInserts.scala +++ b/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/prepared/JsonPreparedInserts.scala @@ -31,7 +31,7 @@ class JsonPreparedInserts extends PhantomSuite { val sample = gen[NestedJsonRecord] val chain = for { - insert <- database.jsonPreparedTable.insertItem(sample) + _ <- database.jsonPreparedTable.insertItem(sample) one <- database.jsonPreparedTable.findById(sample.id) } yield one @@ -45,7 +45,7 @@ class JsonPreparedInserts extends PhantomSuite { val sample = gen[NestedJsonRecord] val chain = for { - insert <- database.jsonPreparedTable.storeRecord(sample) + _ <- database.jsonPreparedTable.storeRecord(sample) one <- database.jsonPreparedTable.findById(sample.id) } yield one diff --git a/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/prepared/PreparedInsertQueryTest.scala b/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/prepared/PreparedInsertQueryTest.scala index c9fdaf7c1..bf9cd50e6 100644 --- a/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/prepared/PreparedInsertQueryTest.scala +++ b/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/prepared/PreparedInsertQueryTest.scala @@ -73,7 +73,7 @@ class PreparedInsertQueryTest extends PhantomSuite { .p_value(_.props, ?) .p_value(_.uid, ?) .prepareAsync() - store <- query.bind(sample).future() + _ <- query.bind(sample).future() get <- database.recipes.select.where(_.url eqs sample.url).one() } yield get @@ -134,7 +134,7 @@ class PreparedInsertQueryTest extends PhantomSuite { .prepare() val chain = for { - store <- query.bind(sample).future() + _ <- query.bind(sample).future() get <- database.primitives.select.where(_.pkey eqs sample.pkey).one() } yield get @@ -160,7 +160,7 @@ class PreparedInsertQueryTest extends PhantomSuite { .prepare() val chain = for { - store <- query.bind(sample).future() + _ <- query.bind(sample).future() res <- selectQuery.bind(sample.pkey).one() } yield res @@ -199,7 +199,7 @@ class PreparedInsertQueryTest extends PhantomSuite { ) val chain = for { - store <- exec.future() + _ <- exec.future() res <- database.recipes.select.where(_.url eqs sample.url).one() } yield res @@ -225,7 +225,7 @@ class PreparedInsertQueryTest extends PhantomSuite { .prepare() val chain = for { - store <- query.bind(sample).future() + _ <- query.bind(sample).future() res <- database.derivedPrimitivesTable.select.where(_.id eqs sample.id).one() } yield res @@ -249,7 +249,7 @@ class PreparedInsertQueryTest extends PhantomSuite { .p_value(_.rec, ?) .p_value(_.complex, ?) .prepareAsync() - store <- query.bind(sample).future() + _ <- query.bind(sample).future() res <- database.derivedPrimitivesTable.select.where(_.id eqs sample.id).one() } yield res @@ -278,7 +278,7 @@ class PreparedInsertQueryTest extends PhantomSuite { .prepare() val chain = for { - store <- query.bind(sample).future() + _ <- query.bind(sample).future() res <- database.primitives.select.where(_.pkey eqs sample.pkey).one() } yield res @@ -306,7 +306,7 @@ class PreparedInsertQueryTest extends PhantomSuite { .p_value(_.bi, ?) .p_value(_.ascii, ?) .prepareAsync() - store <- query.bind(sample).future() + _ <- query.bind(sample).future() res <- database.primitives.select.where(_.pkey eqs sample.pkey).one() } yield res diff --git a/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/prepared/PreparedUpdateQueryTest.scala b/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/prepared/PreparedUpdateQueryTest.scala index 954b73ba8..94806c2c0 100644 --- a/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/prepared/PreparedUpdateQueryTest.scala +++ b/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/prepared/PreparedUpdateQueryTest.scala @@ -269,4 +269,27 @@ class PreparedUpdateQueryTest extends PhantomSuite { res.value.isDeleted shouldBe false } } + + it should "allow using TTL in prepared update statements without a modify clause" in { + val sample = gen[VerizonRecord].copy(isDeleted = true) + val sample2 = gen[VerizonRecord].copy(isDeleted = true) + val bindedTTL = 5 + + lazy val updateWithTTL = db.verizonSchema.update + .where(_.uid eqs ?) + .ttl(?) + .prepareAsync() + + val chain = for { + _ <- db.verizonSchema.storeRecord(sample) + _ <- db.verizonSchema.storeRecord(sample2) + _ <- updateWithTTL.flatMap(_.bind(bindedTTL, sample.uid).future()) + res <- db.verizonSchema.select.where(_.uid eqs sample.uid).one() + } yield res + + whenReady(chain) { res => + res shouldBe defined + res.value.isDeleted shouldBe false + } + } } diff --git a/phantom-dsl/src/test/scala/com/outworkers/phantom/tables/OptionalSecondaryIndexTable.scala b/phantom-dsl/src/test/scala/com/outworkers/phantom/tables/OptionalSecondaryIndexTable.scala index ed60f66eb..2b7f31121 100644 --- a/phantom-dsl/src/test/scala/com/outworkers/phantom/tables/OptionalSecondaryIndexTable.scala +++ b/phantom-dsl/src/test/scala/com/outworkers/phantom/tables/OptionalSecondaryIndexTable.scala @@ -38,6 +38,6 @@ abstract class OptionalSecondaryIndexTable extends Table[ } def findByOptionalSecondary(sec: Int): Future[Option[OptionalSecondaryRecord]] = { - select.where(_.secondary eqs sec).one() + select.where(_.secondary eqs Some(sec)).one() } } diff --git a/phantom-dsl/src/test/scala/com/outworkers/phantom/tables/bugs/NonIndexQueryColumns.scala b/phantom-dsl/src/test/scala/com/outworkers/phantom/tables/bugs/NonIndexQueryColumns.scala index ffbca8cec..5b1155da1 100644 --- a/phantom-dsl/src/test/scala/com/outworkers/phantom/tables/bugs/NonIndexQueryColumns.scala +++ b/phantom-dsl/src/test/scala/com/outworkers/phantom/tables/bugs/NonIndexQueryColumns.scala @@ -19,16 +19,20 @@ import com.outworkers.phantom.dsl._ import scala.concurrent.Future -final case class Token(email: String, token: UUID, counter: Int) +final case class TokenRecord( + email: String, + token: UUID, + counter: Int +) -abstract class TokensTable extends Table[TokensTable, Token] { +abstract class TokensTable extends Table[TokensTable, TokenRecord] { object email extends StringColumn object token extends UUIDColumn with PartitionKey { override val name = "tokenuid" } object counter extends IntColumn - def save(t: Token): Future[ResultSet] = { + def save(t: TokenRecord): Future[ResultSet] = { insert .value(_.email, t.email) .value(_.token, t.token) @@ -36,15 +40,15 @@ abstract class TokensTable extends Table[TokensTable, Token] { .future() } - def get(id: UUID): Future[Option[Token]] = { + def getById(id: UUID): Future[Option[TokenRecord]] = { select.where( _.token eqs id).one() } - def delete(id: UUID) : Future[ResultSet] = { - delete.where( _.token eqs id).future() + def deleteById(id: UUID) : Future[ResultSet] = { + this.delete.where( _.token eqs id).future() } - def expired(counter: Int): Future[List[Token]] = { + def expired(counter: Int): Future[List[TokenRecord]] = { /* PHANTOM NOT IMPLEMENTED FEATURE: * With "allow filtering" Cassandra allows to query From 8822369673159218e500abe0d0d0465f4fafcdad Mon Sep 17 00:00:00 2001 From: Flavian Alexandru Date: Fri, 31 May 2019 16:08:16 +0100 Subject: [PATCH 5/8] Reverting work --- .../phantom/builder/query/UpdateQuery.scala | 30 ------------------- .../prepared/PreparedUpdateQueryTest.scala | 25 +--------------- 2 files changed, 1 insertion(+), 54 deletions(-) diff --git a/phantom-dsl/src/main/scala/com/outworkers/phantom/builder/query/UpdateQuery.scala b/phantom-dsl/src/main/scala/com/outworkers/phantom/builder/query/UpdateQuery.scala index 1ec64eb50..404c5380e 100644 --- a/phantom-dsl/src/main/scala/com/outworkers/phantom/builder/query/UpdateQuery.scala +++ b/phantom-dsl/src/main/scala/com/outworkers/phantom/builder/query/UpdateQuery.scala @@ -137,36 +137,6 @@ case class UpdateQuery[ copy(setPart = setPart append QueryBuilder.ttl(seconds.toString)) } - final def ttl( - mark: PrepareMark - ): UpdateQuery[Table, Record, Limit, Order, Status, Chain, PS, Int :: HNil] = { - copy(usingPart = usingPart append QueryBuilder.ttl(mark.qb.queryString)) - } - - def prepareAsync[ - P[_], - F[_], - RevWhere <: HList, - TTLAdded <: HList - ]()( - implicit session: Session, - executor: ExecutionContextExecutor, - keySpace: KeySpace, - ev: PS =:!= HNil, - rev: Reverse.Aux[PS, RevWhere], - prependTTL: Prepend.Aux[TTL, RevWhere, TTLAdded], - fMonad: FutureMonad[F], - adapter: GuavaAdapter[F], - interface: PromiseInterface[P, F] - ): F[PreparedBlock[TTLAdded]] = { - val flatten = new PreparedFlattener(qb) - - flatten.async map { ps => - new PreparedBlock[TTLAdded](ps, flatten.protocolVersion, options) - } - } - - def withOptions(opts: QueryOptions => QueryOptions): UpdateQuery[Table, Record, Limit, Order, Status, Chain, PS, TTL] = { copy(options = opts(this.options)) } diff --git a/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/prepared/PreparedUpdateQueryTest.scala b/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/prepared/PreparedUpdateQueryTest.scala index 94806c2c0..4b0bb907a 100644 --- a/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/prepared/PreparedUpdateQueryTest.scala +++ b/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/prepared/PreparedUpdateQueryTest.scala @@ -182,7 +182,7 @@ class PreparedUpdateQueryTest extends PhantomSuite { res <- db.verizonSchema.select.where(_.uid eqs sample.uid).one() } yield (updated, res) - whenReady(chain) { case (updated, res) => + whenReady(chain) { case (_, res) => res shouldBe defined res.value.isDeleted shouldBe false } @@ -269,27 +269,4 @@ class PreparedUpdateQueryTest extends PhantomSuite { res.value.isDeleted shouldBe false } } - - it should "allow using TTL in prepared update statements without a modify clause" in { - val sample = gen[VerizonRecord].copy(isDeleted = true) - val sample2 = gen[VerizonRecord].copy(isDeleted = true) - val bindedTTL = 5 - - lazy val updateWithTTL = db.verizonSchema.update - .where(_.uid eqs ?) - .ttl(?) - .prepareAsync() - - val chain = for { - _ <- db.verizonSchema.storeRecord(sample) - _ <- db.verizonSchema.storeRecord(sample2) - _ <- updateWithTTL.flatMap(_.bind(bindedTTL, sample.uid).future()) - res <- db.verizonSchema.select.where(_.uid eqs sample.uid).one() - } yield res - - whenReady(chain) { res => - res shouldBe defined - res.value.isDeleted shouldBe false - } - } } From a85ed8ac15f46c56de1abc9592247c6c589078c3 Mon Sep 17 00:00:00 2001 From: Flavian Alexandru Date: Mon, 3 Jun 2019 01:22:09 +0300 Subject: [PATCH 6/8] Fixing up params --- .../phantom/builder/query/UpdateQuery.scala | 19 +++++++++---------- .../outworkers/phantom/ops/QueryContext.scala | 5 ++--- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/phantom-dsl/src/main/scala/com/outworkers/phantom/builder/query/UpdateQuery.scala b/phantom-dsl/src/main/scala/com/outworkers/phantom/builder/query/UpdateQuery.scala index 404c5380e..93d9c300e 100644 --- a/phantom-dsl/src/main/scala/com/outworkers/phantom/builder/query/UpdateQuery.scala +++ b/phantom-dsl/src/main/scala/com/outworkers/phantom/builder/query/UpdateQuery.scala @@ -39,8 +39,7 @@ case class UpdateQuery[ Order <: OrderBound, Status <: ConsistencyBound, Chain <: WhereBound, - PS <: HList, - TTL <: HList + PS <: HList ](table: Table, init: CQLQuery, tokens: List[TokenizerKey], @@ -66,7 +65,7 @@ case class UpdateQuery[ ](condition: Table => QueryCondition[HL])(implicit ev: Chain =:= Unchainned, prepend: Prepend.Aux[HL, PS, Out] - ): UpdateQuery[Table, Record, Limit, Order, Status, Chainned, Out, TTL] = { + ): UpdateQuery[Table, Record, Limit, Order, Status, Chainned, Out] = { copy( wherePart = wherePart append QueryBuilder.Update.where(condition(table).qb), tokens = tokens ::: condition(table).tokens @@ -86,7 +85,7 @@ case class UpdateQuery[ ](condition: Table => QueryCondition[HL])(implicit ev: Chain =:= Chainned, prepend: Prepend.Aux[HL, PS, Out] - ): UpdateQuery[Table, Record, Limit, Order, Status, Chainned, Out, TTL] = { + ): UpdateQuery[Table, Record, Limit, Order, Status, Chainned, Out] = { copy( wherePart = wherePart append QueryBuilder.Update.and(condition(table).qb), tokens = tokens ::: condition(table).tokens @@ -98,7 +97,7 @@ case class UpdateQuery[ Out <: HList ](clause: Table => UpdateClause.Condition[HL])( implicit prepend: Prepend.Aux[HL, HNil, Out] - ): AssignmentsQuery[Table, Record, Limit, Order, Status, Chain, PS, Out, TTL] = { + ): AssignmentsQuery[Table, Record, Limit, Order, Status, Chain, PS, Out, HNil] = { AssignmentsQuery( table = table, init = init, @@ -133,18 +132,18 @@ case class UpdateQuery[ ) } - def ttl(seconds: Long): UpdateQuery[Table, Record, Limit, Order, Status, Chain, PS, TTL] = { + def ttl(seconds: Long): UpdateQuery[Table, Record, Limit, Order, Status, Chain, PS] = { copy(setPart = setPart append QueryBuilder.ttl(seconds.toString)) } - def withOptions(opts: QueryOptions => QueryOptions): UpdateQuery[Table, Record, Limit, Order, Status, Chain, PS, TTL] = { + def withOptions(opts: QueryOptions => QueryOptions): UpdateQuery[Table, Record, Limit, Order, Status, Chain, PS] = { copy(options = opts(this.options)) } def consistencyLevel_=(level: ConsistencyLevel)( implicit ev: Status =:= Unspecified, session: Session - ): UpdateQuery[Table, Record, Limit, Order, Specified, Chain, PS, TTL] = { + ): UpdateQuery[Table, Record, Limit, Order, Specified, Chain, PS] = { if (session.protocolConsistency) { copy(options = options.consistencyLevel_=(level)) } else { @@ -413,10 +412,10 @@ sealed case class ConditionalQuery[ object UpdateQuery { - type Default[T <: CassandraTable[T, _], R] = UpdateQuery[T, R, Unlimited, Unordered, Unspecified, Unchainned, HNil, HNil] + type Default[T <: CassandraTable[T, _], R] = UpdateQuery[T, R, Unlimited, Unordered, Unspecified, Unchainned, HNil] def apply[T <: CassandraTable[T, _], R](table: T)(implicit keySpace: KeySpace): UpdateQuery.Default[T, R] = { - new UpdateQuery[T, R, Unlimited, Unordered, Unspecified, Unchainned, HNil, HNil]( + new UpdateQuery[T, R, Unlimited, Unordered, Unspecified, Unchainned, HNil]( table = table, init = QueryBuilder.Update.update( QueryBuilder.keyspace(keySpace.name, table.tableName).queryString diff --git a/phantom-dsl/src/main/scala/com/outworkers/phantom/ops/QueryContext.scala b/phantom-dsl/src/main/scala/com/outworkers/phantom/ops/QueryContext.scala index 94a0fa5f0..4bffbed4c 100644 --- a/phantom-dsl/src/main/scala/com/outworkers/phantom/ops/QueryContext.scala +++ b/phantom-dsl/src/main/scala/com/outworkers/phantom/ops/QueryContext.scala @@ -115,9 +115,8 @@ abstract class QueryContext[P[_], F[_], Timeout]( O <: OrderBound, S <: ConsistencyBound, Chain <: WhereBound, - PS <: HList, - TTL <: HList - ](query: UpdateQuery[T, R, L, O, S, Chain, PS, TTL]): UpdateIncompleteQueryOps[P, F] = { + PS <: HList + ](query: UpdateQuery[T, R, L, O, S, Chain, PS]): UpdateIncompleteQueryOps[P, F] = { new UpdateIncompleteQueryOps(query.executableQuery, query.setPart) } From eadda69f22518a6bf46a18bb85fc106c2dcfa9e8 Mon Sep 17 00:00:00 2001 From: Flavian Alexandru Date: Wed, 12 Jun 2019 12:27:37 +0100 Subject: [PATCH 7/8] Adding query column methods for allow filtering clauses --- .../phantom/builder/ops/ImplicitMechanism.scala | 6 +++++- .../query/db/specialized/OptionalIndexesTest.scala | 2 +- .../serializers/InsertQuerySerializationTest.scala | 2 ++ .../phantom/tables/OptionalSecondaryIndexTable.scala | 2 +- .../phantom/tables/TableHelperRuntimeTests.scala | 4 ++-- .../thrift/tests/binary/suites/ThriftMapColumnTest.scala | 8 ++++---- 6 files changed, 15 insertions(+), 9 deletions(-) diff --git a/phantom-dsl/src/main/scala/com/outworkers/phantom/builder/ops/ImplicitMechanism.scala b/phantom-dsl/src/main/scala/com/outworkers/phantom/builder/ops/ImplicitMechanism.scala index 8cd5ce57d..13e3d1560 100644 --- a/phantom-dsl/src/main/scala/com/outworkers/phantom/builder/ops/ImplicitMechanism.scala +++ b/phantom-dsl/src/main/scala/com/outworkers/phantom/builder/ops/ImplicitMechanism.scala @@ -174,8 +174,12 @@ private[phantom] trait ImplicitMechanism extends ModifyMechanism { new MapEntriesConditionals[K, V](cond) } + implicit def nonIndexedColumnQueries[RR : Primitive](col: AbstractColumn[RR])( + implicit ev: col.type <:!< Indexed + ): QueryColumn[RR] = new QueryColumn[RR](col.name) + implicit def partitionColumnQueries[RR : Primitive]( - col: AbstractColumn[RR] //with PartitionKey + col: AbstractColumn[RR] with PartitionKey ): PartitionQueryColumn[RR] = new PartitionQueryColumn[RR](col.name) /** diff --git a/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/specialized/OptionalIndexesTest.scala b/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/specialized/OptionalIndexesTest.scala index 35a589544..517352b15 100644 --- a/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/specialized/OptionalIndexesTest.scala +++ b/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/specialized/OptionalIndexesTest.scala @@ -52,7 +52,7 @@ class OptionalIndexesTest extends PhantomSuite { val chain = for { _ <- database.optionalIndexesTable.store(sample).future() select <- database.optionalIndexesTable.findByOptionalSecondary(sample.secondary.value) - _ <- database.optionalIndexesTable.delete.where(_.secondary eqs sample.secondary).future() + _ <- database.optionalIndexesTable.delete.where(_.secondary eqs sample.secondary.value).future() select2 <- database.optionalIndexesTable.findByOptionalSecondary(sample.secondary.value) } yield (select, select2) diff --git a/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/serializers/InsertQuerySerializationTest.scala b/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/serializers/InsertQuerySerializationTest.scala index 0e0b1460c..1e106513f 100644 --- a/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/serializers/InsertQuerySerializationTest.scala +++ b/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/serializers/InsertQuerySerializationTest.scala @@ -111,6 +111,8 @@ class InsertQuerySerializationTest extends QueryBuilderTest { val sample = gen[Recipe] val json = compactJson(renderJValue(Extraction.decompose(sample))) val query = TestDatabase.recipes.insert.json(json).queryString + + query shouldEqual query } "should append USING clause after lightweight part " in { diff --git a/phantom-dsl/src/test/scala/com/outworkers/phantom/tables/OptionalSecondaryIndexTable.scala b/phantom-dsl/src/test/scala/com/outworkers/phantom/tables/OptionalSecondaryIndexTable.scala index 2b7f31121..ed60f66eb 100644 --- a/phantom-dsl/src/test/scala/com/outworkers/phantom/tables/OptionalSecondaryIndexTable.scala +++ b/phantom-dsl/src/test/scala/com/outworkers/phantom/tables/OptionalSecondaryIndexTable.scala @@ -38,6 +38,6 @@ abstract class OptionalSecondaryIndexTable extends Table[ } def findByOptionalSecondary(sec: Int): Future[Option[OptionalSecondaryRecord]] = { - select.where(_.secondary eqs Some(sec)).one() + select.where(_.secondary eqs sec).one() } } diff --git a/phantom-dsl/src/test/scala/com/outworkers/phantom/tables/TableHelperRuntimeTests.scala b/phantom-dsl/src/test/scala/com/outworkers/phantom/tables/TableHelperRuntimeTests.scala index f367d87db..1b8268b3a 100644 --- a/phantom-dsl/src/test/scala/com/outworkers/phantom/tables/TableHelperRuntimeTests.scala +++ b/phantom-dsl/src/test/scala/com/outworkers/phantom/tables/TableHelperRuntimeTests.scala @@ -34,7 +34,7 @@ class TableHelperRuntimeTests extends PhantomSuite { val (id, _, _) = sample val chain = for { - store <- database.tableTypeTuple.store(sample).future() + _ <- database.tableTypeTuple.store(sample).future() find <- database.tableTypeTuple.findById(id) } yield find @@ -48,7 +48,7 @@ class TableHelperRuntimeTests extends PhantomSuite { val sample = gen[OAuth2Session] val chain = for { - store <- database.sessionsByUser.store(sample).future() + _ <- database.sessionsByUser.store(sample).future() find <- database.sessionsByUser.select.where(_.user_id eqs sample.user_id).one() } yield find diff --git a/phantom-thrift/src/test/scala/com/outworkers/phantom/thrift/tests/binary/suites/ThriftMapColumnTest.scala b/phantom-thrift/src/test/scala/com/outworkers/phantom/thrift/tests/binary/suites/ThriftMapColumnTest.scala index 01c692f67..400a46269 100644 --- a/phantom-thrift/src/test/scala/com/outworkers/phantom/thrift/tests/binary/suites/ThriftMapColumnTest.scala +++ b/phantom-thrift/src/test/scala/com/outworkers/phantom/thrift/tests/binary/suites/ThriftMapColumnTest.scala @@ -67,8 +67,8 @@ class ThriftMapColumnTest extends BinarySuite { val expected = sample.thriftMap ++ toAdd val operation = for { - insertDone <- thriftDb.thriftColumnTable.store(sample).future - update <- thriftDb.thriftColumnTable.update + _ <- thriftDb.thriftColumnTable.store(sample).future + _ <- thriftDb.thriftColumnTable.update .where(_.id eqs sample.id) .modify(_.thriftMap putAll toAdd).future() select <- thriftDb.thriftColumnTable @@ -91,8 +91,8 @@ class ThriftMapColumnTest extends BinarySuite { val expected = sample.thriftMap ++ toAdd val operation = for { - insertDone <- thriftDb.thriftColumnTable.store(sample).future() - update <- thriftDb.thriftColumnTable.update.where(_.id eqs sample.id).modify(_.thriftMap putAll toAdd).future() + _ <- thriftDb.thriftColumnTable.store(sample).future() + _ <- thriftDb.thriftColumnTable.update.where(_.id eqs sample.id).modify(_.thriftMap putAll toAdd).future() select <- thriftDb.thriftColumnTable.select(_.thriftMap).where(_.id eqs sample.id).one } yield select From 99cbf31c6d0eed0775053deabd9ff2e451c50917 Mon Sep 17 00:00:00 2001 From: Flavian Alexandru Date: Wed, 12 Jun 2019 13:55:07 +0100 Subject: [PATCH 8/8] Further cleanup work --- .../query/db/crud/MapOperationsTest.scala | 54 +++++++++---------- .../tables/bugs/NonIndexQueryColumns.scala | 12 +---- 2 files changed, 28 insertions(+), 38 deletions(-) diff --git a/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/crud/MapOperationsTest.scala b/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/crud/MapOperationsTest.scala index fb01499dd..b0820e4f3 100644 --- a/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/crud/MapOperationsTest.scala +++ b/phantom-dsl/src/test/scala/com/outworkers/phantom/builder/query/db/crud/MapOperationsTest.scala @@ -35,8 +35,8 @@ class MapOperationsTest extends PhantomSuite { val (key , value) = gen[(String, String)] val operation = for { - insertDone <- database.recipes.store(recipe).future() - update <- database.recipes.update.where(_.url eqs recipe.url).modify(_.props set (key, value)).future() + _ <- database.recipes.store(recipe).future() + _ <- database.recipes.update.where(_.url eqs recipe.url).modify(_.props set (key, value)).future() select <- database.recipes.select(_.props).where(_.url eqs recipe.url).one } yield select @@ -55,8 +55,8 @@ class MapOperationsTest extends PhantomSuite { val query = database.recipes.update.where(_.url eqs ?).modify(_.props set ?).prepareAsync() val operation = for { - insertDone <- database.recipes.store(recipe).future() - update <- query.flatMap(_.bind(key, value, recipe.url).future()) + _ <- database.recipes.store(recipe).future() + _ <- query.flatMap(_.bind(key, value, recipe.url).future()) select <- database.recipes.select(_.props).where(_.url eqs recipe.url).one } yield select @@ -73,8 +73,8 @@ class MapOperationsTest extends PhantomSuite { val item = gen[(String, String)] val operation = for { - insertDone <- database.recipes.store(recipe).future() - update <- database.recipes.update.where(_.url eqs recipe.url).modify(_.props put item).future() + _ <- database.recipes.store(recipe).future() + _ <- database.recipes.update.where(_.url eqs recipe.url).modify(_.props put item).future() select <- database.recipes.select(_.props).where(_.url eqs recipe.url).one } yield select @@ -89,8 +89,8 @@ class MapOperationsTest extends PhantomSuite { val mapItems = genMap[String, String](mapSize) val operation = for { - insertDone <- database.recipes.store(recipe).future() - update <- database.recipes.update.where(_.url eqs recipe.url).modify(_.props putAll mapItems).future() + _ <- database.recipes.store(recipe).future() + _ <- database.recipes.update.where(_.url eqs recipe.url).modify(_.props putAll mapItems).future() select <- database.recipes.select(_.props).where(_.url eqs recipe.url).one } yield select @@ -107,8 +107,8 @@ class MapOperationsTest extends PhantomSuite { val updateQuery = database.recipes.update.where(_.url eqs ?).modify(_.props putAll ?).prepareAsync() val operation = for { - insertDone <- database.recipes.store(recipe).future() - update <- updateQuery.flatMap(_.bind(mapItems, recipe.url).future()) + _ <- database.recipes.store(recipe).future() + _ <- updateQuery.flatMap(_.bind(mapItems, recipe.url).future()) select <- database.recipes.select(_.props).where(_.url eqs recipe.url).one } yield select @@ -124,8 +124,8 @@ class MapOperationsTest extends PhantomSuite { val postRemove = recipe.props - removals val operation = for { - insertDone <- database.recipes.store(recipe).future() - update <- database.recipes.update + _ <- database.recipes.store(recipe).future() + _ <- database.recipes.update .where(_.url eqs recipe.url) .modify(_.props - removals) .future() @@ -145,8 +145,8 @@ class MapOperationsTest extends PhantomSuite { } val operation = for { - insertDone <- database.recipes.store(recipe).future() - update <- database.recipes.update + _ <- database.recipes.store(recipe).future() + _ <- database.recipes.update .where(_.url eqs recipe.url) .modify(_.props - removals) .future() @@ -162,13 +162,11 @@ class MapOperationsTest extends PhantomSuite { val event = gen[SampleEvent] val chain = for { - store <- database.events.store(event).future() - get <- database.events.findById(event.id) - } yield get + _ <- database.events.store(event).future() + res <- database.events.findById(event.id) + } yield res - whenReady(chain) { - res => res.value shouldEqual event - } + whenReady(chain) { res => res.value shouldEqual event } } it should "allow storing maps that use Scala primitives who do not have a TypeCodec" in { @@ -182,9 +180,9 @@ class MapOperationsTest extends PhantomSuite { ) val chain = for { - store <- database.scalaPrimitivesTable.store(sample).future() - get <- database.scalaPrimitivesTable.findById(sample.id) - } yield get + _ <- database.scalaPrimitivesTable.store(sample).future() + res <- database.scalaPrimitivesTable.findById(sample.id) + } yield res whenReady(chain) { res => res.value shouldEqual sample @@ -206,14 +204,14 @@ class MapOperationsTest extends PhantomSuite { ) val chain = for { - store <- database.scalaPrimitivesTable.store(sample).future() - get <- database.scalaPrimitivesTable.findById(sample.id) - update <- database.scalaPrimitivesTable.update + _ <- database.scalaPrimitivesTable.store(sample).future() + res <- database.scalaPrimitivesTable.findById(sample.id) + _ <- database.scalaPrimitivesTable.update .where(_.id eqs sample.id) .modify(_.map(updateKey) setTo BigDecimal(updatedValue)) .future() - get2 <- database.scalaPrimitivesTable.findById(sample.id) - } yield (get, get2) + res2 <- database.scalaPrimitivesTable.findById(sample.id) + } yield (res, res2) whenReady(chain) { case (beforeUpdate, afterUpdate) => beforeUpdate.value shouldEqual sample diff --git a/phantom-dsl/src/test/scala/com/outworkers/phantom/tables/bugs/NonIndexQueryColumns.scala b/phantom-dsl/src/test/scala/com/outworkers/phantom/tables/bugs/NonIndexQueryColumns.scala index 5b1155da1..c8a22099d 100644 --- a/phantom-dsl/src/test/scala/com/outworkers/phantom/tables/bugs/NonIndexQueryColumns.scala +++ b/phantom-dsl/src/test/scala/com/outworkers/phantom/tables/bugs/NonIndexQueryColumns.scala @@ -32,20 +32,12 @@ abstract class TokensTable extends Table[TokensTable, TokenRecord] { } object counter extends IntColumn - def save(t: TokenRecord): Future[ResultSet] = { - insert - .value(_.email, t.email) - .value(_.token, t.token) - .value(_.counter, t.counter) - .future() - } - - def getById(id: UUID): Future[Option[TokenRecord]] = { + def findById(id: UUID): Future[Option[TokenRecord]] = { select.where( _.token eqs id).one() } def deleteById(id: UUID) : Future[ResultSet] = { - this.delete.where( _.token eqs id).future() + delete.where( _.token eqs id).future() } def expired(counter: Int): Future[List[TokenRecord]] = {