Skip to content

Commit

Permalink
Merge pull request #95 from newzly/release/multipart_conditionals
Browse files Browse the repository at this point in the history
PHANTOM-79: Added ability to chain multiple CAS clauses to a single quer...
  • Loading branch information
alexflav23 committed May 26, 2014
2 parents 0d9e18a + 46a9f86 commit ce36e91
Show file tree
Hide file tree
Showing 6 changed files with 570 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,18 @@ class InsertQuery[T <: CassandraTable[T, R], R](table: T, val qb: Insert) extend

final def value[RR](c: T => AbstractColumn[RR], value: RR): InsertQuery[T, R] = {
val col = c(table)
qb.value(col.name, col.toCType(value))
this
new InsertQuery[T, R](table, qb.value(col.name, col.toCType(value)))
}

final def valueOrNull[RR](c: T => AbstractColumn[RR], value: RR): InsertQuery[T, R] = {
val col = c(table)
qb.value(col.name, Try {
new InsertQuery[T, R](table, qb.value(col.name, Try {
col.toCType(value)
} getOrElse null.asInstanceOf[T])
this
} getOrElse null.asInstanceOf[T]))
}

final def ifNotExists[RR] = {
new InsertQuery[T, R](table, qb.ifNotExists())
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,17 @@ class AssignmentOptionQuery[T <: CassandraTable[T, R], R](table: T, val qb: Upda
class ConditionalUpdateQuery[T <: CassandraTable[T, R], R](table: T, val qb: Update.Conditions)
extends SharedQueryMethods[ConditionalUpdateQuery[T, R], Update.Conditions](qb) {

def where[RR](condition: T => QueryCondition): UpdateWhere[T, R] = {
new UpdateWhere[T, R](table, qb.where(condition(table).clause))
def and[RR](condition: T => SecondaryQueryCondition): ConditionalUpdateQuery[T, R] = {
new ConditionalUpdateQuery[T, R](table, qb.and(condition(table).clause))
}
}

class ConditionalUpdateWhereQuery[T <: CassandraTable[T, R], R](table: T, val qb: Update.Conditions)
extends SharedQueryMethods[ConditionalUpdateWhereQuery[T, R], Update.Conditions](qb) {

def and[RR](condition: T => SecondaryQueryCondition): ConditionalUpdateQuery[T, R] = {
new ConditionalUpdateQuery[T, R](table, qb.and(condition(table).clause))
}
}

class UpdateQuery[T <: CassandraTable[T, R], R](table: T, val qb: Update)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package com.newzly.phantom.dsl.query

import org.scalatest.{ FlatSpec, Matchers, ParallelTestExecution }
import com.datastax.driver.core.utils.UUIDs
import com.newzly.phantom.Implicits._
import com.newzly.phantom.tables.{ Primitives, SecondaryIndexTable, TimeSeriesTable }
import com.newzly.util.testing.Sampler

class CASConditionalQueriesTest extends FlatSpec with Matchers {
it should "allow using a non-index column in a conditional update clause" in {
"Primitives.update.where(_.pkey eqs Sampler.getARandomString).onlyIf(_.long eqs 5L)" should compile
}

it should " not allow using a PartitionKey in a conditional clause" in {
"Primitives.update.where(_.pkey eqs Sampler.getARandomString).onlyIf(_.pkey eqs Sampler.getARandomString)" shouldNot compile
}

it should " not allow using a PrimaryKey in a conditional clause " in {
"TwoKeys.update.where(_.pkey eqs Sampler.getARandomString).onlyIf(_.intColumn1 eqs 5)" shouldNot compile
}

it should " not allow using an Index in a conditional clause " in {
"SecondaryIndexTable.update.where(_.id eqs UUIDs.timeBased()).onlyIf(_.secondary eqs UUIDs.timeBased())" shouldNot compile
}

it should " not allow using an Index in the second part of a conditional clause " in {
"SecondaryIndexTable.update.where(_.id eqs UUIDs.timeBased()).onlyIf(_.name eqs Sampler.getARandomString).and(_.secondary eqs UUIDs.timeBased())" shouldNot compile
}

it should " allow using a non Clustering column from a TimeSeries table in a conditional clause" in {
"TimeSeriesTable.update.where(_.id eqs UUIDs.timeBased()).onlyIf(_.name eqs Sampler.getARandomString)" should compile
}

it should " not allow using a ClusteringColumn in a conditional clause" in {
"TimeSeriesTable.update.where(_.id eqs UUIDs.timeBased()).onlyIf(_.timestamp eqs new DateTime)" shouldNot compile
}

it should " not allow using a ClusteringColumn in the second part of a conditional clause" in {
"TimeSeriesTable.update.where(_.id eqs UUIDs.timeBased()).onlyIf(_.name eqs Sampler.getARandomString).and(_.timestamp eqs new DateTime)" shouldNot compile
}

it should "allow using multiple non-primary conditions in a CAS clase" in {
"Primitives.update.where(_.pkey eqs Sampler.getARandomString).onlyIf(_.long eqs 5L).and(_.boolean eqs false)" should compile
}

it should "not allow using an index column condition in the AND part of a CAS clause" in {
"Primitives.update.where(_.pkey eqs Sampler.getARandomString).onlyIf(_.long eqs 5L).and(_.pkey eqs Sampler.getARandomString)" shouldNot compile
}

it should "allow using 3 separate CAS conditions in an update query" in {
"Primitives.update.where(_.pkey eqs Sampler.getARandomString).onlyIf(_.long eqs 5L).and(_.boolean eqs false).and(_.int eqs 10)" should compile
}

it should "not allow using 3 separate CAS conditions in an update query with the 3rd condition on an indexed column" in {
"Primitives.update.where(_.pkey eqs Sampler.getARandomString).onlyIf(_.long eqs 5L).and(_.boolean eqs false).and(_.pkey eqs Sampler.getARandomString)" shouldNot compile
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ package com.newzly.phantom.dsl.query
import org.scalatest.{ FlatSpec, Matchers, ParallelTestExecution }
import com.datastax.driver.core.utils.UUIDs
import com.newzly.phantom.Implicits._
import com.newzly.phantom.tables.{ Articles, Recipes }
import com.newzly.phantom.tables.{ Articles, Primitives, Recipes }
import com.newzly.util.testing.Sampler

class QuerySerializationTest extends FlatSpec with Matchers {
Expand Down Expand Up @@ -65,4 +65,33 @@ class QuerySerializationTest extends FlatSpec with Matchers {
).where(_.url eqs someId).qb.toString shouldBe s"SELECT url,description,ingredients FROM Recipes WHERE url='$someId';"
}

it should "corectly serialise a simple conditional update query" in {
val qb = Primitives.update.where(_.pkey eqs "test").onlyIf(_.boolean eqs false).qb.toString
qb shouldEqual s"UPDATE Primitives WHERE pkey='test' IF boolean=false;"
}

it should "corectly serialise a multi-part conditional update query" in {
val qb = Primitives.update.where(_.pkey eqs "test").onlyIf(_.boolean eqs false).and(_.long eqs 5L).qb.toString
qb shouldEqual s"UPDATE Primitives WHERE pkey='test' IF boolean=false AND long=5;"
}

it should "corectly serialise a conditional update query with a single List column based clause" in {
val qb = Recipes.update.where(_.url eqs "test")
.modify(_.description setTo Some("blabla"))
.onlyIf(_.ingredients eqs List("1", "2", "3"))
.qb.toString

qb shouldEqual "UPDATE Recipes SET description='blabla' WHERE url='test' IF ingredients=['1','2','3'];"
}

it should "corectly serialise a multi-part conditional update query with a List column part" in {
val qb = Recipes.update.where(_.url eqs "test")
.modify(_.description setTo Some("blabla"))
.onlyIf(_.ingredients eqs List("1", "2", "3"))
.and(_.description eqs Some("test"))
.qb.toString

qb shouldEqual "UPDATE Recipes SET description='blabla' WHERE url='test' IF ingredients=['1','2','3'] AND description='test';"
}

}
Loading

0 comments on commit ce36e91

Please sign in to comment.