Skip to content

Commit

Permalink
Merge branch 'master' into postgres-renderDelete
Browse files Browse the repository at this point in the history
  • Loading branch information
jczuchnowski committed Nov 25, 2020
2 parents 754baae + d9d6a86 commit ace0f7a
Show file tree
Hide file tree
Showing 9 changed files with 554 additions and 95 deletions.
7 changes: 5 additions & 2 deletions core/jvm/src/main/scala/zio/sql/expr.scala
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,9 @@ trait ExprModule extends NewtypesModule with FeaturesModule with OpsModule {
def <=[F2, A1 <: A, B1 >: B](that: Expr[F2, A1, B1]): Expr[F :||: F2, A1, Boolean] =
Expr.Relational(self, that, RelationalOp.LessThanEqual)

def like[F2, A1 <: A, B1 >: B](that: Expr[F2, A1, B1]): Expr[F :||: F2, A1, Boolean] =
Expr.Relational(self, that, RelationalOp.Like)

def &[F2, A1 <: A, B1 >: B](that: Expr[F2, A1, B1])(implicit ev: IsIntegral[B1]): Expr[F :||: F2, A1, B1] =
Expr.Binary(self, that, BinaryOp.AndBit[B1]())

Expand Down Expand Up @@ -264,8 +267,8 @@ trait ExprModule extends NewtypesModule with FeaturesModule with OpsModule {
val Cos = FunctionDef[Double, Double](FunctionName("cos"))
val Exp = FunctionDef[Double, Double](FunctionName("exp"))
val Floor = FunctionDef[Double, Double](FunctionName("floor"))
//val Log = FunctionDef[Double, Double](FunctionName("log")) //not part of SQL 2011 spec
val Ln = FunctionDef[Double, Double](FunctionName("ln"))
val Log = FunctionDef[(Double, Double), Double](FunctionName("log"))
val Mod = FunctionDef[(Double, Double), Double](FunctionName("mod"))
val Power = FunctionDef[(Double, Double), Double](FunctionName("power"))
val Round = FunctionDef[(Double, Int), Double](FunctionName("round"))
Expand All @@ -284,7 +287,7 @@ trait ExprModule extends NewtypesModule with FeaturesModule with OpsModule {
val OctetLength = FunctionDef[String, Int](FunctionName("octet_length"))
val Overlay = FunctionDef[(String, String, Int, Option[Int]), String](FunctionName("overlay"))
val Position = FunctionDef[(String, String), Int](FunctionName("position"))
val Replace = FunctionDef[(String, String), String](FunctionName("replace"))
val Replace = FunctionDef[(String, String, String), String](FunctionName("replace"))
val Rtrim = FunctionDef[String, String](FunctionName("rtrim"))
val Substring = FunctionDef[(String, Int, Option[Int]), String](FunctionName("substring"))
//TODO substring regex
Expand Down
3 changes: 3 additions & 0 deletions core/jvm/src/main/scala/zio/sql/ops.scala
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@ trait OpsModule extends TypeTagModule {
case object NotEqual extends RelationalOp {
override val symbol: String = "<>"
}
case object Like extends RelationalOp {
override val symbol: String = "like"
}
}

}
4 changes: 4 additions & 0 deletions core/jvm/src/test/scala/zio/sql/LogicalOpsSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@ class LogicalOpsSpec extends DefaultRunnableSpec {
test("not works on boolean column") {
val selectNotDeleted = selectAll.where(deleted.not)
assert(selectNotDeleted)(anything)
},
test("like works on a string column") {
val query = selectAll.where(name like "%")
assert(query)(anything)
}
)
}
27 changes: 23 additions & 4 deletions jdbc/src/main/scala/zio/sql/jdbc.scala
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package zio.sql

import java.sql._

import java.io.IOException
import java.time.{ OffsetDateTime, OffsetTime, ZoneId, ZoneOffset }

import zio.{ Chunk, Has, IO, Managed, ZIO, ZLayer, ZManaged }
import zio.blocking.Blocking
Expand Down Expand Up @@ -198,15 +198,34 @@ trait Jdbc extends zio.sql.Sql {
column.fold(resultSet.getTimestamp(_), resultSet.getTimestamp(_)).toLocalDateTime().toLocalTime()
)
case TLong => tryDecode[Long](column.fold(resultSet.getLong(_), resultSet.getLong(_)))
case TOffsetDateTime => ???
case TOffsetTime => ???
case TOffsetDateTime =>
tryDecode[OffsetDateTime](
column
.fold(resultSet.getTimestamp(_), resultSet.getTimestamp(_))
.toLocalDateTime()
.atOffset(ZoneOffset.UTC)
)
case TOffsetTime =>
tryDecode[OffsetTime](
column
.fold(resultSet.getTime(_), resultSet.getTime(_))
.toLocalTime
.atOffset(ZoneOffset.UTC)
)
case TShort => tryDecode[Short](column.fold(resultSet.getShort(_), resultSet.getShort(_)))
case TString => tryDecode[String](column.fold(resultSet.getString(_), resultSet.getString(_)))
case TUUID =>
tryDecode[java.util.UUID](
java.util.UUID.fromString(column.fold(resultSet.getString(_), resultSet.getString(_)))
)
case TZonedDateTime => ???
case TZonedDateTime =>
tryDecode[java.time.ZonedDateTime](
java.time.ZonedDateTime
.ofInstant(
column.fold(resultSet.getTimestamp(_), resultSet.getTimestamp(_)).toInstant,
ZoneId.of(ZoneOffset.UTC.getId)
)
)
case TDialectSpecific(_) => ???
case t @ Nullable() => extractColumn(column, resultSet, t.typeTag, false).map(Option(_))
}
Expand Down
92 changes: 56 additions & 36 deletions postgres/src/main/scala/zio/sql/postgresql/PostgresModule.scala
Original file line number Diff line number Diff line change
@@ -1,79 +1,99 @@
package zio.sql.postgresql

import java.time.LocalDate

import java.time.{ Instant, LocalDate, LocalTime, ZonedDateTime }
import zio.sql.Jdbc

/**
*/
trait PostgresModule extends Jdbc { self =>

object PostgresFunctionDef {
val CurrentDate = FunctionDef[Nothing, LocalDate](FunctionName("current_date"))
val Initcap = FunctionDef[String, String](FunctionName("initcap"))
val Repeat = FunctionDef[(String, Int), String](FunctionName("repeat"))
val Reverse = FunctionDef[String, String](FunctionName("reverse"))
val TrimScale = FunctionDef[Double, Double](FunctionName("trim_scale"))
val Hex = FunctionDef[Int, String](FunctionName("to_hex"))
val Left = FunctionDef[(String, Int), String](FunctionName("left"))
val Length = FunctionDef[String, Int](FunctionName("length"))
val MinScale = FunctionDef[Double, Int](FunctionName("min_scale"))
val Radians = FunctionDef[Double, Double](FunctionName("radians"))
val Right = FunctionDef[(String, Int), String](FunctionName("right"))
val StartsWith = FunctionDef[(String, String), Boolean](FunctionName("starts_with"))
val Translate = FunctionDef[(String, String, String), String](FunctionName("translate"))
val Trunc = FunctionDef[Double, Double](FunctionName("trunc"))
val Sind = FunctionDef[Double, Double](FunctionName("sind"))
val GCD = FunctionDef[(Double, Double), Double](FunctionName("gcd"))
val LCM = FunctionDef[(Double, Double), Double](FunctionName("lcm"))
val CBRT = FunctionDef[Double, Double](FunctionName("cbrt"))
val Degrees = FunctionDef[Double, Double](FunctionName("degrees"))
val Div = FunctionDef[(Double, Double), Double](FunctionName("div"))
val Factorial = FunctionDef[Int, Int](FunctionName("factorial"))
val Localtime = FunctionDef[Nothing, LocalTime](FunctionName("localtime"))
val LocaltimeWithPrecision = FunctionDef[Int, LocalTime](FunctionName("localtime"))
val Localtimestamp = FunctionDef[Nothing, Instant](FunctionName("localtimestamp"))
val LocaltimestampWithPrecision = FunctionDef[Int, Instant](FunctionName("localtimestamp"))
val Md5 = FunctionDef[String, String](FunctionName("md5"))
val ParseIdent = FunctionDef[String, String](FunctionName("parse_ident"))
val Chr = FunctionDef[Int, String](FunctionName("chr"))
val CurrentDate = FunctionDef[Nothing, LocalDate](FunctionName("current_date"))
val Initcap = FunctionDef[String, String](FunctionName("initcap"))
val Repeat = FunctionDef[(String, Int), String](FunctionName("repeat"))
val Reverse = FunctionDef[String, String](FunctionName("reverse"))
val TrimScale = FunctionDef[Double, Double](FunctionName("trim_scale"))
val Hex = FunctionDef[Int, String](FunctionName("to_hex"))
val Left = FunctionDef[(String, Int), String](FunctionName("left"))
val Length = FunctionDef[String, Int](FunctionName("length"))
val MinScale = FunctionDef[Double, Int](FunctionName("min_scale"))
val Radians = FunctionDef[Double, Double](FunctionName("radians"))
val Right = FunctionDef[(String, Int), String](FunctionName("right"))
val StartsWith = FunctionDef[(String, String), Boolean](FunctionName("starts_with"))
val Translate = FunctionDef[(String, String, String), String](FunctionName("translate"))
val Trunc = FunctionDef[Double, Double](FunctionName("trunc"))
val Sind = FunctionDef[Double, Double](FunctionName("sind"))
val GCD = FunctionDef[(Double, Double), Double](FunctionName("gcd"))
val LCM = FunctionDef[(Double, Double), Double](FunctionName("lcm"))
val CBRT = FunctionDef[Double, Double](FunctionName("cbrt"))
val Degrees = FunctionDef[Double, Double](FunctionName("degrees"))
val Div = FunctionDef[(Double, Double), Double](FunctionName("div"))
val Factorial = FunctionDef[Int, Int](FunctionName("factorial"))
val Random = FunctionDef[Nothing, Double](FunctionName("random"))
val LPad = FunctionDef[(String, Int, String), String](FunctionName("lpad"))
val RPad = FunctionDef[(String, Int, String), String](FunctionName("rpad"))
val ToTimestamp = FunctionDef[Long, ZonedDateTime](FunctionName("to_timestamp"))
}

private def buildExpr[A, B](expr: self.Expr[_, A, B], builder: StringBuilder): Unit = expr match {
case Expr.Source(tableName, column) =>
case Expr.Source(tableName, column) =>
val _ = builder.append(tableName).append(".").append(column.name)
case Expr.Unary(base, op) =>
case Expr.Unary(base, op) =>
val _ = builder.append(" ").append(op.symbol)
buildExpr(base, builder)
case Expr.Property(base, op) =>
case Expr.Property(base, op) =>
buildExpr(base, builder)
val _ = builder.append(" ").append(op.symbol)
case Expr.Binary(left, right, op) =>
case Expr.Binary(left, right, op) =>
buildExpr(left, builder)
builder.append(" ").append(op.symbol).append(" ")
buildExpr(right, builder)
case Expr.Relational(left, right, op) =>
case Expr.Relational(left, right, op) =>
buildExpr(left, builder)
builder.append(" ").append(op.symbol).append(" ")
buildExpr(right, builder)
case Expr.In(value, set) =>
case Expr.In(value, set) =>
buildExpr(value, builder)
buildReadString(set, builder)
case Expr.Literal(value) =>
case Expr.Literal(value) =>
val _ = builder.append(value.toString) //todo fix escaping
case Expr.AggregationCall(param, aggregation) =>
case Expr.AggregationCall(param, aggregation) =>
builder.append(aggregation.name.name)
builder.append("(")
buildExpr(param, builder)
val _ = builder.append(")")
case Expr.FunctionCall0(function) =>
case Expr.FunctionCall0(function) if function.name.name == "localtime" =>
val _ = builder.append(function.name.name)
case Expr.FunctionCall0(function) if function.name.name == "localtimestamp" =>
val _ = builder.append(function.name.name)
case Expr.FunctionCall0(function) if function.name.name == "current_date" =>
val _ = builder.append(function.name.name)
case Expr.FunctionCall0(function) if function.name.name == "current_timestamp" =>
val _ = builder.append(function.name.name)
case Expr.FunctionCall1(param, function) =>
case Expr.FunctionCall0(function) =>
builder.append(function.name.name)
builder.append("(")
val _ = builder.append(")")
case Expr.FunctionCall1(param, function) =>
builder.append(function.name.name)
builder.append("(")
buildExpr(param, builder)
val _ = builder.append(")")
case Expr.FunctionCall2(param1, param2, function) =>
case Expr.FunctionCall2(param1, param2, function) =>
builder.append(function.name.name)
builder.append("(")
buildExpr(param1, builder)
builder.append(",")
buildExpr(param2, builder)
val _ = builder.append(")")
case Expr.FunctionCall3(param1, param2, param3, function) =>
case Expr.FunctionCall3(param1, param2, param3, function) =>
builder.append(function.name.name)
builder.append("(")
buildExpr(param1, builder)
Expand All @@ -82,7 +102,7 @@ trait PostgresModule extends Jdbc { self =>
builder.append(",")
buildExpr(param3, builder)
val _ = builder.append(")")
case Expr.FunctionCall4(param1, param2, param3, param4, function) =>
case Expr.FunctionCall4(param1, param2, param3, param4, function) =>
builder.append(function.name.name)
builder.append("(")
buildExpr(param1, builder)
Expand Down
19 changes: 10 additions & 9 deletions postgres/src/test/resources/shop_schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ create table customers
first_name varchar not null,
last_name varchar not null,
verified boolean not null,
dob date not null
dob date not null,
created_timestamp_string varchar not null,
created_timestamp timestamp with time zone default now()
);

create table orders
Expand Down Expand Up @@ -37,15 +39,14 @@ create table order_details
unit_price money not null
);


insert into customers
(id, first_name, last_name, verified, dob)
(id, first_name, last_name, verified, dob, created_timestamp_string, created_timestamp)
values
('60b01fc9-c902-4468-8d49-3c0f989def37', 'Ronald', 'Russell', true, '1983-01-05'),
('f76c9ace-be07-4bf3-bd4c-4a9c62882e64', 'Terrence', 'Noel', true, '1999-11-02'),
('784426a5-b90a-4759-afbb-571b7a0ba35e', 'Mila', 'Paterso', true, '1990-11-16'),
('df8215a2-d5fd-4c6c-9984-801a1b3a2a0b', 'Alana', 'Murray', true, '1995-11-12'),
('636ae137-5b1a-4c8c-b11f-c47c624d9cdc', 'Jose', 'Wiggins', false, '1987-03-23');
('60b01fc9-c902-4468-8d49-3c0f989def37', 'Ronald', 'Russell', true, '1983-01-05', '2020-11-21T19:10:25+00:00', '2020-11-21 19:10:25+00'),
('f76c9ace-be07-4bf3-bd4c-4a9c62882e64', 'Terrence', 'Noel', true, '1999-11-02', '2020-11-21T15:10:25-04:00', '2020-11-21 15:10:25-04'),
('784426a5-b90a-4759-afbb-571b7a0ba35e', 'Mila', 'Paterso', true, '1990-11-16', '2020-11-22T02:10:25+07:00', '2020-11-22 02:10:25+07'),
('df8215a2-d5fd-4c6c-9984-801a1b3a2a0b', 'Alana', 'Murray', true, '1995-11-12', '2020-11-21T12:10:25-07:00', '2020-11-21 12:10:25-07'),
('636ae137-5b1a-4c8c-b11f-c47c624d9cdc', 'Jose', 'Wiggins', false, '1987-03-23', '2020-11-21T19:10:25+00:00', '2020-11-21 19:10:25+00');

insert into products
(id, name, description, image_url)
Expand Down Expand Up @@ -189,4 +190,4 @@ values
('852E2DC9-4EC3-4225-A6F7-4F42F8FF728E', 'D5137D3A-894A-4109-9986-E982541B434F', 1, 45.45),
('D6D8DDDC-4B0B-4D74-8EDC-A54E9B7F35F7', 'D5137D3A-894A-4109-9986-E982541B434F', 2, 50.00),
('2C3FC180-D0DF-4D7B-A271-E6CCD2440393', 'D5137D3A-894A-4109-9986-E982541B434F', 2, 50.00),
('5883CB62-D792-4EE3-ACBC-FE85B6BAA998', 'D5137D3A-894A-4109-9986-E982541B434F', 1, 55.00);
('5883CB62-D792-4EE3-ACBC-FE85B6BAA998', 'D5137D3A-894A-4109-9986-E982541B434F', 1, 55.00);
Loading

0 comments on commit ace0f7a

Please sign in to comment.