SlideShare a Scribd company logo
1 of 37
Download to read offline
Quill -
一個 Scala 的資料庫存取利器
鄭紹志 Vito Jeng
R&D, 亦思科技
vito@is-land.com.tw
@vitojeng
Join Scala Taiwan
● Gitter channel -
○ https://gitter.im/ScalaTaiwan/ScalaTaiwan/
● Facebook Group -
○ https://www.facebook.com/groups/ScalaTW/
● Meetup -
○ https://www.meetup.com/Scala-Taiwan-Meetup/
PostgreSQL dbsamples
● PostgreSQL dbsamples:
○ https://www.postgresql.org/ftp/projects/pgFoundry/dbsamples/
Quill intro
Compile-time query generation
quote {
}
Quotation
Compile-time query generation
Scala macros
Quill AST
(Abstract Syntax Tree)
SQL
statement
compiler
Quotation
Simplify mapping
case class City(id: Int,
name: String,
countryCode: String,
district: String,
population: Int)
case class CountryLanguage(
countryCode: String,
language: String,
isOfficial: Boolean,
percentage: Double
)
NamingStrategy
● LowerCase
Simplify mapping
Naming strategy countryCode country_code
LowerCase countrycode country_code
UpperCase COUNTRYCODE COUNTRY_CODE
SnakeCase country_code country_code
CamelCase countryCode countryCode
LiteralCase countryCode country_code
Compile-time query validation
● Query Probing - 支援在 Compile-time 進行 SQL 驗證
query[City]
.filter(c=> c.countryCode=="USA" && c.population > 1000000)
.map(c=> (c.id, c.name, c.population) )
At first glance
import io.getquill._
case class City(id: Int, name: String,
countryCode: String, district: String, population: Int)
val q = quote {
}
val ctx = new SqlMirrorContext(PostgresDialect, LowerCase)
import ctx._
val result = ctx.run(q)
Quotation
SQL statement
Quill AST
SELECT c.id, c.name, c.population
FROM city c
WHERE c.countrycode = 'USA'
AND c.population > 1000000
Try out in Scastie!
Quotation's AST(Abstract Syntax Tree)
Many databases(libraries) support
Async support
● Integrate wih
○ NDBC(Postgres)
○ JAsync(Mysql, Postgres)
○ Monix(Mysql, Postgres, Sqlite, H2, SQL Server, Oracle)
○ Finagle(Mysql, Postgres)
Restrictions
● Single database
● Return a flat relation type
● Limited operations
Quill basic operations
SQL Context
● 建立 Quotatiaon 之前必須先建立 Context 物件
● 自 config file 讀取設定檔, 建立 Context
○ 使用 typesafe config library
■ application.conf / application.properties
○ 使用 HikariCP library(Connection Pool)
○ val ctx = new PostgresJdbcContext(LowerCase, "ctx")
Schema customization
case class MyCity(id: Int, city_name: String,
country_code: String, district: String,
population: Int)
val schemaCity = quote {
querySchema[MyCity]("city",
_.country_code -> "countrycode",
_.city_name -> "name"
)
}
val queryCities = quote {
schemaCity.filter(c=>c.country_code=="TWN")
}
ctx.run(queryCities)
● 使用 querySchema 自訂 mapping 關係
Operations
● filter / map / flatMap / concatMap / sortBy / drop / take
● isEmpty / nonEmpty / contains / distinct
● groupBy
● aggregation: min / max / avg / sum / size
● union / unionAll(++)
Binding value - 帶入 Runtime 參數 (1)
● Quotation 無法直接引用外部的值
● Binding single value: use lift method
● Binding multiple values: use liftQuery method
def queryCountryCities(countryCode: String) = quote {
query[City].filter(c=>c.countryCode==countryCode)
}
Binding value - 帶入 Runtime 參數 (2)
def queryCountryCities(countryCode: String) = quote {
query[City].filter(c=>c.countryCode==lift(countryCode))
}
def queryCountryCities(countries: Seq[String]) = quote {
query[City].filter(c=> liftQuery(countries).contains(c.countryCode))
}
SELECT c.id, c.name, c.countrycode, c.district, c.population
FROM city c WHERE c.countrycode = ?
SELECT c.id, c.name, c.countrycode, c.district,
c.population FROM city c WHERE c.countrycode IN (?)
Joins
● Applicative Joins
○ Common used when join two tables
○ Support inner join / left join / right join / full join
● Implicit Joins
○ Used in for-comprehension syntax
○ Only can do inner-join
● Flat Joins
○ Used in for-comprehension syntax
○ Support inner join / left join
Joins - Applicative Join
val queryAsiaCities = quote {
query[City]
.join(query[Country])
.on { (ci, co) => ci.countryCode == co.code }
.filter { case (_, co) => co.continent=="Asia" }
.map { case (ci, co) => (co.name, ci.name) }
}
SELECT co.name, ci.name
FROM city ci
INNER JOIN country co ON ci.countrycode = co.code
WHERE co.continent = 'Asia'
Joins - Implicit Joins
val queryTaiwanCities = quote {
for {
ci <- query[City]
co <- query[Country].filter(co0=>co0.code=="TWN")
if (ci.countryCode==co.code)
cl <- query[CountryLanguage]
if (co.code==cl.countrycode)
} yield (ci.name, co.name, cl.language)
}
SELECT ci.name, co0.name, cl.language
FROM city ci, country co0, countrylanguage cl
WHERE co0.code = 'TWN'
AND ci.countrycode = co0.code
AND co0.code = cl.countrycode
Joins - Flat Join
val queryTaiwanCities = quote {
for {
co <- query[Country].filter(c=>c.code=="TWN")
ci <- query[City]
.leftJoin(co1=>co.code==co1.countryCode)
.filter(ci1=>ci1.exists(c=>c.population>1000000))
} yield {
(co, ci)
}
}
SELECT c.code, c.name, c.continent, c.region, c.surfacearea,
c.indepyear, c.population, c.lifeexpectancy, c.gnp, c.gnpold,
c.localname, c.governmentform, c.headofstate, c.capital,
c.code2,
co1.id, co1.name, co1.countrycode, co1.district, co1.population
FROM country c LEFT JOIN city co1 ON c.code = co1.countrycode
WHERE c.code = 'TWN' AND co1.population > 1000000
Demo
● 查詢某個國家
● 查詢某個國家的城巿
● 查詢亞洲四小龍的城巿
Actions - 新增/刪除/修改
query[City].filter(c => c.id==10000)
.delete
query[City].insert(City(10000, "my city", "MYC", "My District", 0))
query[City].filter(_.district == "My District")
.update(_.district -> "My Town")
DELETE FROM city WHERE id = 10000
INSERT INTO city (id,name,countrycode,district,population)
VALUES (10000, 'my city', 'MYC', 'My District', 0)
UPDATE city SET district = 'My Town' WHERE district = 'My District'
Actions - Batch update
● 使用 liftQuery
val cities = List(
City(10001, "my city1", "MYC", "My Town", 100000),
City(10002, "my city2", "MYC", "My Village", 120000),
City(10003, "my city3", "MYC", "My Borough", 140000)
)
val insertCities = quote {
liftQuery(cities).foreach(e=>query[City].insert(e))
}
val deleteCities = quote {
liftQuery(List(10001, 10002, 10003))
.foreach(id => query[City].filter(c=>c.id==id).delete)
}
INSERT INTO city (id,name,countrycode,district,population)
VALUES (?, ?, ?, ?, ?)
DELETE FROM city WHERE id = ?
Transaction
● JdbcContext provide transaction support(connection is thread-local)
val cities = List(
City(10001, "my city1", "MYC", "My Town", 100000),
City(10002, "my city2", "MYC", "My Village", 120000),
City(10003, "my city3", "MYC", "My Borough", 140000)
)
val insertCities = quote {
liftQuery(cities).foreach(e=>query[City].insert(e))
}
ctx.transaction {
ctx.run(insertCities)
throw new Exception("transaction failed!")
}
Dynamic query (1)
● Quill 在 compile time 階段無法 generate sql
val query: Quoted[EntityQuery[City]] = quote {
query[City].filter(c=>c.countryCode=="TWN")
} // Dynamic query
● 若 Quotation 指定 type:
Dynamic query (2)
● 使用 Dyanmic query API
val q = dynamicQuery[City].filter { c: Quoted[City] =>
c.countryCode == "TWN"
}
● 由 Quotation 轉換成 dynamic query
val queryCity = quote {
query[City]
}
val q = queryCity.dynamic.filter { c: Quoted[City] =>
quote { c.countryCode == "TWN" }
}
More
Infix - 無奈需要寫 SQL 時
● 使用 String Interpolator: infix
● 完整的 SQL
○ Map to case class / tuples
● 部份的 SQL
○ Quill Query 串接 SQL string
○ 呼叫 Database 提供的 funciton
Null (1)
case class Country(code: String,
: : :
indepYear: Option[Int],
population: Int,
lifeExpectancy: Option[Double],
: : :
CREATE TABLE country (
code character(3) NOT NULL,
: : :
indepyear smallint, // nullable
population integer NOT NULL,
lifeexpectancy real, // nullable
: : :
Null (2)
query[Country].filter(c=> c.indepYear.isDefined)
query[Country]
.map{c=> (c.name, c.indepYear.map(y=>s"Independent: $y"))
SELECT c.code, c.name, ...
FROM country c
WHERE c.indepyear IS NOT NULL
SELECT c.name, 'Independent: ' || c.indepyear
FROM country c
Query probing - 驗證 SQL 是否正確
● 在 Compile time 驗證 SQL 是否正確
● Enable query probing
○ 使用 QueryProbing trait
○ Context 須要先在另一個獨立的 project 被編譯
○ Sbt configuration
Some issues
● Query 太多導致 compile-time 變慢
● Cannot write generic function with Scala
● 在 IDE 開發使用 Query probing 可能導致 Too many clients
○ Caused by: com.zaxxer.hikari.pool.HikariPool$PoolInitializationException: Failed
to initialize pool: FATAL: sorry, too many clients already
● 有些難懂的 compile error
Q & A
Thank you !!

More Related Content

What's hot

Altitude San Francisco 2018: WebAssembly Tools & Applications
Altitude San Francisco 2018: WebAssembly Tools & ApplicationsAltitude San Francisco 2018: WebAssembly Tools & Applications
Altitude San Francisco 2018: WebAssembly Tools & ApplicationsFastly
 
Standing the Test of Time: The Date Provider Pattern
Standing the Test of Time: The Date Provider PatternStanding the Test of Time: The Date Provider Pattern
Standing the Test of Time: The Date Provider PatternDerek Lee Boire
 
Schema Design by Chad Tindel, Solution Architect, 10gen
Schema Design  by Chad Tindel, Solution Architect, 10genSchema Design  by Chad Tindel, Solution Architect, 10gen
Schema Design by Chad Tindel, Solution Architect, 10genMongoDB
 
openCypher Technology Compatibility Kit (TCK)
openCypher Technology Compatibility Kit (TCK)openCypher Technology Compatibility Kit (TCK)
openCypher Technology Compatibility Kit (TCK)openCypher
 
Visualization team presentation
Visualization team presentation Visualization team presentation
Visualization team presentation madhobilota
 
16 - Scala. Type of length-indexed vectors
16 - Scala. Type of length-indexed vectors16 - Scala. Type of length-indexed vectors
16 - Scala. Type of length-indexed vectorsRoman Brovko
 
Shapes and calculate (area and contour) / C++ oop concept
Shapes and calculate (area and contour) / C++ oop conceptShapes and calculate (area and contour) / C++ oop concept
Shapes and calculate (area and contour) / C++ oop conceptkinan keshkeh
 
Shapes and calculate (area and contour) / C++ oop concept
Shapes and calculate (area and contour) / C++ oop conceptShapes and calculate (area and contour) / C++ oop concept
Shapes and calculate (area and contour) / C++ oop conceptkinan keshkeh
 
Gc in golang
Gc in golangGc in golang
Gc in golangGenchi Lu
 
Brief intro to clojure
Brief intro to clojureBrief intro to clojure
Brief intro to clojureRoy Rutto
 
Functional Systems @ Twitter
Functional Systems @ TwitterFunctional Systems @ Twitter
Functional Systems @ TwitterC4Media
 
Is WebAssembly the killer of JavaScript?
Is WebAssembly the killer of JavaScript?Is WebAssembly the killer of JavaScript?
Is WebAssembly the killer of JavaScript?Boyan Mihaylov
 
Gc in golang
Gc in golangGc in golang
Gc in golangGenchi Lu
 

What's hot (20)

Scala.io
Scala.ioScala.io
Scala.io
 
Altitude San Francisco 2018: WebAssembly Tools & Applications
Altitude San Francisco 2018: WebAssembly Tools & ApplicationsAltitude San Francisco 2018: WebAssembly Tools & Applications
Altitude San Francisco 2018: WebAssembly Tools & Applications
 
Conversion of data types in java
Conversion of data types in javaConversion of data types in java
Conversion of data types in java
 
Standing the Test of Time: The Date Provider Pattern
Standing the Test of Time: The Date Provider PatternStanding the Test of Time: The Date Provider Pattern
Standing the Test of Time: The Date Provider Pattern
 
Schema Design by Chad Tindel, Solution Architect, 10gen
Schema Design  by Chad Tindel, Solution Architect, 10genSchema Design  by Chad Tindel, Solution Architect, 10gen
Schema Design by Chad Tindel, Solution Architect, 10gen
 
openCypher Technology Compatibility Kit (TCK)
openCypher Technology Compatibility Kit (TCK)openCypher Technology Compatibility Kit (TCK)
openCypher Technology Compatibility Kit (TCK)
 
A Shiny Example-- R
A Shiny Example-- RA Shiny Example-- R
A Shiny Example-- R
 
Visualization team presentation
Visualization team presentation Visualization team presentation
Visualization team presentation
 
201707 SER332 Lecture 15
201707 SER332 Lecture 15  201707 SER332 Lecture 15
201707 SER332 Lecture 15
 
ECMAScript 5: Новое в JavaScript
ECMAScript 5: Новое в JavaScriptECMAScript 5: Новое в JavaScript
ECMAScript 5: Новое в JavaScript
 
16 - Scala. Type of length-indexed vectors
16 - Scala. Type of length-indexed vectors16 - Scala. Type of length-indexed vectors
16 - Scala. Type of length-indexed vectors
 
Shapes and calculate (area and contour) / C++ oop concept
Shapes and calculate (area and contour) / C++ oop conceptShapes and calculate (area and contour) / C++ oop concept
Shapes and calculate (area and contour) / C++ oop concept
 
Shapes and calculate (area and contour) / C++ oop concept
Shapes and calculate (area and contour) / C++ oop conceptShapes and calculate (area and contour) / C++ oop concept
Shapes and calculate (area and contour) / C++ oop concept
 
Gc in golang
Gc in golangGc in golang
Gc in golang
 
Brief intro to clojure
Brief intro to clojureBrief intro to clojure
Brief intro to clojure
 
Functional Systems @ Twitter
Functional Systems @ TwitterFunctional Systems @ Twitter
Functional Systems @ Twitter
 
Multi qubit entanglement
Multi qubit entanglementMulti qubit entanglement
Multi qubit entanglement
 
Is WebAssembly the killer of JavaScript?
Is WebAssembly the killer of JavaScript?Is WebAssembly the killer of JavaScript?
Is WebAssembly the killer of JavaScript?
 
Why Grails?
Why Grails?Why Grails?
Why Grails?
 
Gc in golang
Gc in golangGc in golang
Gc in golang
 

Similar to Quill - 一個 Scala 的資料庫存取利器

Compose Async with RxJS
Compose Async with RxJSCompose Async with RxJS
Compose Async with RxJSKyung Yeol Kim
 
Community-driven Language Design at TC39 on the JavaScript Pipeline Operator ...
Community-driven Language Design at TC39 on the JavaScript Pipeline Operator ...Community-driven Language Design at TC39 on the JavaScript Pipeline Operator ...
Community-driven Language Design at TC39 on the JavaScript Pipeline Operator ...Igalia
 
Leveraging R in Big Data of Mobile Ads (R在行動廣告大數據的應用)
Leveraging R in Big Data of Mobile Ads (R在行動廣告大數據的應用)Leveraging R in Big Data of Mobile Ads (R在行動廣告大數據的應用)
Leveraging R in Big Data of Mobile Ads (R在行動廣告大數據的應用)Craig Chao
 
Introducing BinarySortedMultiMap - A new Flink state primitive to boost your ...
Introducing BinarySortedMultiMap - A new Flink state primitive to boost your ...Introducing BinarySortedMultiMap - A new Flink state primitive to boost your ...
Introducing BinarySortedMultiMap - A new Flink state primitive to boost your ...Flink Forward
 
ADG Poznań - Kotlin for Android developers
ADG Poznań - Kotlin for Android developersADG Poznań - Kotlin for Android developers
ADG Poznań - Kotlin for Android developersBartosz Kosarzycki
 
Streaming SQL for Data Engineers: The Next Big Thing? With Yaroslav Tkachenko...
Streaming SQL for Data Engineers: The Next Big Thing? With Yaroslav Tkachenko...Streaming SQL for Data Engineers: The Next Big Thing? With Yaroslav Tkachenko...
Streaming SQL for Data Engineers: The Next Big Thing? With Yaroslav Tkachenko...HostedbyConfluent
 
Streaming SQL for Data Engineers: The Next Big Thing?
Streaming SQL for Data Engineers: The Next Big Thing?Streaming SQL for Data Engineers: The Next Big Thing?
Streaming SQL for Data Engineers: The Next Big Thing?Yaroslav Tkachenko
 
Async Microservices with Twitter's Finagle
Async Microservices with Twitter's FinagleAsync Microservices with Twitter's Finagle
Async Microservices with Twitter's FinagleVladimir Kostyukov
 
Story of static code analyzer development
Story of static code analyzer developmentStory of static code analyzer development
Story of static code analyzer developmentAndrey Karpov
 
The Ring programming language version 1.5 book - Part 8 of 31
The Ring programming language version 1.5 book - Part 8 of 31The Ring programming language version 1.5 book - Part 8 of 31
The Ring programming language version 1.5 book - Part 8 of 31Mahmoud Samir Fayed
 
Patterns for slick database applications
Patterns for slick database applicationsPatterns for slick database applications
Patterns for slick database applicationsSkills Matter
 
All I know about rsc.io/c2go
All I know about rsc.io/c2goAll I know about rsc.io/c2go
All I know about rsc.io/c2goMoriyoshi Koizumi
 
Score (smart contract for icon)
Score (smart contract for icon) Score (smart contract for icon)
Score (smart contract for icon) Doyun Hwang
 
Monads - Dublin Scala meetup
Monads - Dublin Scala meetupMonads - Dublin Scala meetup
Monads - Dublin Scala meetupMikhail Girkin
 
Chainer-Compiler 動かしてみた
Chainer-Compiler 動かしてみたChainer-Compiler 動かしてみた
Chainer-Compiler 動かしてみたAkira Maruoka
 
Visual studio 2008
Visual studio 2008Visual studio 2008
Visual studio 2008Luis Enrique
 

Similar to Quill - 一個 Scala 的資料庫存取利器 (20)

Compose Async with RxJS
Compose Async with RxJSCompose Async with RxJS
Compose Async with RxJS
 
Community-driven Language Design at TC39 on the JavaScript Pipeline Operator ...
Community-driven Language Design at TC39 on the JavaScript Pipeline Operator ...Community-driven Language Design at TC39 on the JavaScript Pipeline Operator ...
Community-driven Language Design at TC39 on the JavaScript Pipeline Operator ...
 
Leveraging R in Big Data of Mobile Ads (R在行動廣告大數據的應用)
Leveraging R in Big Data of Mobile Ads (R在行動廣告大數據的應用)Leveraging R in Big Data of Mobile Ads (R在行動廣告大數據的應用)
Leveraging R in Big Data of Mobile Ads (R在行動廣告大數據的應用)
 
Linq
LinqLinq
Linq
 
Introducing BinarySortedMultiMap - A new Flink state primitive to boost your ...
Introducing BinarySortedMultiMap - A new Flink state primitive to boost your ...Introducing BinarySortedMultiMap - A new Flink state primitive to boost your ...
Introducing BinarySortedMultiMap - A new Flink state primitive to boost your ...
 
ADG Poznań - Kotlin for Android developers
ADG Poznań - Kotlin for Android developersADG Poznań - Kotlin for Android developers
ADG Poznań - Kotlin for Android developers
 
Streaming SQL for Data Engineers: The Next Big Thing? With Yaroslav Tkachenko...
Streaming SQL for Data Engineers: The Next Big Thing? With Yaroslav Tkachenko...Streaming SQL for Data Engineers: The Next Big Thing? With Yaroslav Tkachenko...
Streaming SQL for Data Engineers: The Next Big Thing? With Yaroslav Tkachenko...
 
Streaming SQL for Data Engineers: The Next Big Thing?
Streaming SQL for Data Engineers: The Next Big Thing?Streaming SQL for Data Engineers: The Next Big Thing?
Streaming SQL for Data Engineers: The Next Big Thing?
 
Async Microservices with Twitter's Finagle
Async Microservices with Twitter's FinagleAsync Microservices with Twitter's Finagle
Async Microservices with Twitter's Finagle
 
Story of static code analyzer development
Story of static code analyzer developmentStory of static code analyzer development
Story of static code analyzer development
 
Day 1
Day 1Day 1
Day 1
 
The Ring programming language version 1.5 book - Part 8 of 31
The Ring programming language version 1.5 book - Part 8 of 31The Ring programming language version 1.5 book - Part 8 of 31
The Ring programming language version 1.5 book - Part 8 of 31
 
Patterns for slick database applications
Patterns for slick database applicationsPatterns for slick database applications
Patterns for slick database applications
 
DIWE - Advanced PHP Concepts
DIWE - Advanced PHP ConceptsDIWE - Advanced PHP Concepts
DIWE - Advanced PHP Concepts
 
All I know about rsc.io/c2go
All I know about rsc.io/c2goAll I know about rsc.io/c2go
All I know about rsc.io/c2go
 
Score (smart contract for icon)
Score (smart contract for icon) Score (smart contract for icon)
Score (smart contract for icon)
 
CPP Homework Help
CPP Homework HelpCPP Homework Help
CPP Homework Help
 
Monads - Dublin Scala meetup
Monads - Dublin Scala meetupMonads - Dublin Scala meetup
Monads - Dublin Scala meetup
 
Chainer-Compiler 動かしてみた
Chainer-Compiler 動かしてみたChainer-Compiler 動かしてみた
Chainer-Compiler 動かしてみた
 
Visual studio 2008
Visual studio 2008Visual studio 2008
Visual studio 2008
 

More from vito jeng

Scala fun part: Reflection(runtime)
Scala fun part: Reflection(runtime)Scala fun part: Reflection(runtime)
Scala fun part: Reflection(runtime)vito jeng
 
Intellij IDEA Intro, Tips and Tricks
Intellij IDEA Intro, Tips and TricksIntellij IDEA Intro, Tips and Tricks
Intellij IDEA Intro, Tips and Tricksvito jeng
 
Streaming process with Kafka Connect and Kafka Streams
Streaming process with Kafka Connect and Kafka StreamsStreaming process with Kafka Connect and Kafka Streams
Streaming process with Kafka Connect and Kafka Streamsvito jeng
 
ScalaMatsuri 2017 Note
ScalaMatsuri 2017 NoteScalaMatsuri 2017 Note
ScalaMatsuri 2017 Notevito jeng
 
The SparkSQL things you maybe confuse
The SparkSQL things you maybe confuseThe SparkSQL things you maybe confuse
The SparkSQL things you maybe confusevito jeng
 
Scala introduction
Scala introductionScala introduction
Scala introductionvito jeng
 
JavaScript Web Development
JavaScript Web DevelopmentJavaScript Web Development
JavaScript Web Developmentvito jeng
 

More from vito jeng (7)

Scala fun part: Reflection(runtime)
Scala fun part: Reflection(runtime)Scala fun part: Reflection(runtime)
Scala fun part: Reflection(runtime)
 
Intellij IDEA Intro, Tips and Tricks
Intellij IDEA Intro, Tips and TricksIntellij IDEA Intro, Tips and Tricks
Intellij IDEA Intro, Tips and Tricks
 
Streaming process with Kafka Connect and Kafka Streams
Streaming process with Kafka Connect and Kafka StreamsStreaming process with Kafka Connect and Kafka Streams
Streaming process with Kafka Connect and Kafka Streams
 
ScalaMatsuri 2017 Note
ScalaMatsuri 2017 NoteScalaMatsuri 2017 Note
ScalaMatsuri 2017 Note
 
The SparkSQL things you maybe confuse
The SparkSQL things you maybe confuseThe SparkSQL things you maybe confuse
The SparkSQL things you maybe confuse
 
Scala introduction
Scala introductionScala introduction
Scala introduction
 
JavaScript Web Development
JavaScript Web DevelopmentJavaScript Web Development
JavaScript Web Development
 

Recently uploaded

Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software DevelopersVinodh Ram
 
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataAdobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataBradBedford3
 
Project Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationProject Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationkaushalgiri8080
 
Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...OnePlan Solutions
 
XpertSolvers: Your Partner in Building Innovative Software Solutions
XpertSolvers: Your Partner in Building Innovative Software SolutionsXpertSolvers: Your Partner in Building Innovative Software Solutions
XpertSolvers: Your Partner in Building Innovative Software SolutionsMehedi Hasan Shohan
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...gurkirankumar98700
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...stazi3110
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideChristina Lin
 
What are the features of Vehicle Tracking System?
What are the features of Vehicle Tracking System?What are the features of Vehicle Tracking System?
What are the features of Vehicle Tracking System?Watsoo Telematics
 
Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...aditisharan08
 
Asset Management Software - Infographic
Asset Management Software - InfographicAsset Management Software - Infographic
Asset Management Software - InfographicHr365.us smith
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityNeo4j
 
Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Andreas Granig
 
buds n tech IT solutions
buds n  tech IT                solutionsbuds n  tech IT                solutions
buds n tech IT solutionsmonugehlot87
 
The Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdfThe Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdfPower Karaoke
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...MyIntelliSource, Inc.
 
What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWave PLM
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantAxelRicardoTrocheRiq
 
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfThe Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfkalichargn70th171
 

Recently uploaded (20)

Professional Resume Template for Software Developers
Professional Resume Template for Software DevelopersProfessional Resume Template for Software Developers
Professional Resume Template for Software Developers
 
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer DataAdobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
Adobe Marketo Engage Deep Dives: Using Webhooks to Transfer Data
 
Project Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanationProject Based Learning (A.I).pptx detail explanation
Project Based Learning (A.I).pptx detail explanation
 
Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...
 
XpertSolvers: Your Partner in Building Innovative Software Solutions
XpertSolvers: Your Partner in Building Innovative Software SolutionsXpertSolvers: Your Partner in Building Innovative Software Solutions
XpertSolvers: Your Partner in Building Innovative Software Solutions
 
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
(Genuine) Escort Service Lucknow | Starting ₹,5K To @25k with A/C 🧑🏽‍❤️‍🧑🏻 89...
 
Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
Call Girls In Mukherjee Nagar 📱  9999965857  🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...Call Girls In Mukherjee Nagar 📱  9999965857  🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
Call Girls In Mukherjee Nagar 📱 9999965857 🤩 Delhi 🫦 HOT AND SEXY VVIP 🍎 SE...
 
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
Building a General PDE Solving Framework with Symbolic-Numeric Scientific Mac...
 
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop SlideBuilding Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
Building Real-Time Data Pipelines: Stream & Batch Processing workshop Slide
 
What are the features of Vehicle Tracking System?
What are the features of Vehicle Tracking System?What are the features of Vehicle Tracking System?
What are the features of Vehicle Tracking System?
 
Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...Unit 1.1 Excite Part 1, class 9, cbse...
Unit 1.1 Excite Part 1, class 9, cbse...
 
Asset Management Software - Infographic
Asset Management Software - InfographicAsset Management Software - Infographic
Asset Management Software - Infographic
 
EY_Graph Database Powered Sustainability
EY_Graph Database Powered SustainabilityEY_Graph Database Powered Sustainability
EY_Graph Database Powered Sustainability
 
Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024Automate your Kamailio Test Calls - Kamailio World 2024
Automate your Kamailio Test Calls - Kamailio World 2024
 
buds n tech IT solutions
buds n  tech IT                solutionsbuds n  tech IT                solutions
buds n tech IT solutions
 
The Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdfThe Evolution of Karaoke From Analog to App.pdf
The Evolution of Karaoke From Analog to App.pdf
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
 
What is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need ItWhat is Fashion PLM and Why Do You Need It
What is Fashion PLM and Why Do You Need It
 
Salesforce Certified Field Service Consultant
Salesforce Certified Field Service ConsultantSalesforce Certified Field Service Consultant
Salesforce Certified Field Service Consultant
 
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdfThe Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
The Essentials of Digital Experience Monitoring_ A Comprehensive Guide.pdf
 

Quill - 一個 Scala 的資料庫存取利器

  • 1. Quill - 一個 Scala 的資料庫存取利器 鄭紹志 Vito Jeng R&D, 亦思科技 vito@is-land.com.tw @vitojeng
  • 2. Join Scala Taiwan ● Gitter channel - ○ https://gitter.im/ScalaTaiwan/ScalaTaiwan/ ● Facebook Group - ○ https://www.facebook.com/groups/ScalaTW/ ● Meetup - ○ https://www.meetup.com/Scala-Taiwan-Meetup/
  • 3. PostgreSQL dbsamples ● PostgreSQL dbsamples: ○ https://www.postgresql.org/ftp/projects/pgFoundry/dbsamples/
  • 6. Compile-time query generation Scala macros Quill AST (Abstract Syntax Tree) SQL statement compiler Quotation
  • 7. Simplify mapping case class City(id: Int, name: String, countryCode: String, district: String, population: Int) case class CountryLanguage( countryCode: String, language: String, isOfficial: Boolean, percentage: Double ) NamingStrategy ● LowerCase
  • 8. Simplify mapping Naming strategy countryCode country_code LowerCase countrycode country_code UpperCase COUNTRYCODE COUNTRY_CODE SnakeCase country_code country_code CamelCase countryCode countryCode LiteralCase countryCode country_code
  • 9. Compile-time query validation ● Query Probing - 支援在 Compile-time 進行 SQL 驗證
  • 10. query[City] .filter(c=> c.countryCode=="USA" && c.population > 1000000) .map(c=> (c.id, c.name, c.population) ) At first glance import io.getquill._ case class City(id: Int, name: String, countryCode: String, district: String, population: Int) val q = quote { } val ctx = new SqlMirrorContext(PostgresDialect, LowerCase) import ctx._ val result = ctx.run(q) Quotation SQL statement Quill AST SELECT c.id, c.name, c.population FROM city c WHERE c.countrycode = 'USA' AND c.population > 1000000 Try out in Scastie!
  • 13. Async support ● Integrate wih ○ NDBC(Postgres) ○ JAsync(Mysql, Postgres) ○ Monix(Mysql, Postgres, Sqlite, H2, SQL Server, Oracle) ○ Finagle(Mysql, Postgres)
  • 14. Restrictions ● Single database ● Return a flat relation type ● Limited operations
  • 16. SQL Context ● 建立 Quotatiaon 之前必須先建立 Context 物件 ● 自 config file 讀取設定檔, 建立 Context ○ 使用 typesafe config library ■ application.conf / application.properties ○ 使用 HikariCP library(Connection Pool) ○ val ctx = new PostgresJdbcContext(LowerCase, "ctx")
  • 17. Schema customization case class MyCity(id: Int, city_name: String, country_code: String, district: String, population: Int) val schemaCity = quote { querySchema[MyCity]("city", _.country_code -> "countrycode", _.city_name -> "name" ) } val queryCities = quote { schemaCity.filter(c=>c.country_code=="TWN") } ctx.run(queryCities) ● 使用 querySchema 自訂 mapping 關係
  • 18. Operations ● filter / map / flatMap / concatMap / sortBy / drop / take ● isEmpty / nonEmpty / contains / distinct ● groupBy ● aggregation: min / max / avg / sum / size ● union / unionAll(++)
  • 19. Binding value - 帶入 Runtime 參數 (1) ● Quotation 無法直接引用外部的值 ● Binding single value: use lift method ● Binding multiple values: use liftQuery method def queryCountryCities(countryCode: String) = quote { query[City].filter(c=>c.countryCode==countryCode) }
  • 20. Binding value - 帶入 Runtime 參數 (2) def queryCountryCities(countryCode: String) = quote { query[City].filter(c=>c.countryCode==lift(countryCode)) } def queryCountryCities(countries: Seq[String]) = quote { query[City].filter(c=> liftQuery(countries).contains(c.countryCode)) } SELECT c.id, c.name, c.countrycode, c.district, c.population FROM city c WHERE c.countrycode = ? SELECT c.id, c.name, c.countrycode, c.district, c.population FROM city c WHERE c.countrycode IN (?)
  • 21. Joins ● Applicative Joins ○ Common used when join two tables ○ Support inner join / left join / right join / full join ● Implicit Joins ○ Used in for-comprehension syntax ○ Only can do inner-join ● Flat Joins ○ Used in for-comprehension syntax ○ Support inner join / left join
  • 22. Joins - Applicative Join val queryAsiaCities = quote { query[City] .join(query[Country]) .on { (ci, co) => ci.countryCode == co.code } .filter { case (_, co) => co.continent=="Asia" } .map { case (ci, co) => (co.name, ci.name) } } SELECT co.name, ci.name FROM city ci INNER JOIN country co ON ci.countrycode = co.code WHERE co.continent = 'Asia'
  • 23. Joins - Implicit Joins val queryTaiwanCities = quote { for { ci <- query[City] co <- query[Country].filter(co0=>co0.code=="TWN") if (ci.countryCode==co.code) cl <- query[CountryLanguage] if (co.code==cl.countrycode) } yield (ci.name, co.name, cl.language) } SELECT ci.name, co0.name, cl.language FROM city ci, country co0, countrylanguage cl WHERE co0.code = 'TWN' AND ci.countrycode = co0.code AND co0.code = cl.countrycode
  • 24. Joins - Flat Join val queryTaiwanCities = quote { for { co <- query[Country].filter(c=>c.code=="TWN") ci <- query[City] .leftJoin(co1=>co.code==co1.countryCode) .filter(ci1=>ci1.exists(c=>c.population>1000000)) } yield { (co, ci) } } SELECT c.code, c.name, c.continent, c.region, c.surfacearea, c.indepyear, c.population, c.lifeexpectancy, c.gnp, c.gnpold, c.localname, c.governmentform, c.headofstate, c.capital, c.code2, co1.id, co1.name, co1.countrycode, co1.district, co1.population FROM country c LEFT JOIN city co1 ON c.code = co1.countrycode WHERE c.code = 'TWN' AND co1.population > 1000000
  • 26. Actions - 新增/刪除/修改 query[City].filter(c => c.id==10000) .delete query[City].insert(City(10000, "my city", "MYC", "My District", 0)) query[City].filter(_.district == "My District") .update(_.district -> "My Town") DELETE FROM city WHERE id = 10000 INSERT INTO city (id,name,countrycode,district,population) VALUES (10000, 'my city', 'MYC', 'My District', 0) UPDATE city SET district = 'My Town' WHERE district = 'My District'
  • 27. Actions - Batch update ● 使用 liftQuery val cities = List( City(10001, "my city1", "MYC", "My Town", 100000), City(10002, "my city2", "MYC", "My Village", 120000), City(10003, "my city3", "MYC", "My Borough", 140000) ) val insertCities = quote { liftQuery(cities).foreach(e=>query[City].insert(e)) } val deleteCities = quote { liftQuery(List(10001, 10002, 10003)) .foreach(id => query[City].filter(c=>c.id==id).delete) } INSERT INTO city (id,name,countrycode,district,population) VALUES (?, ?, ?, ?, ?) DELETE FROM city WHERE id = ?
  • 28. Transaction ● JdbcContext provide transaction support(connection is thread-local) val cities = List( City(10001, "my city1", "MYC", "My Town", 100000), City(10002, "my city2", "MYC", "My Village", 120000), City(10003, "my city3", "MYC", "My Borough", 140000) ) val insertCities = quote { liftQuery(cities).foreach(e=>query[City].insert(e)) } ctx.transaction { ctx.run(insertCities) throw new Exception("transaction failed!") }
  • 29. Dynamic query (1) ● Quill 在 compile time 階段無法 generate sql val query: Quoted[EntityQuery[City]] = quote { query[City].filter(c=>c.countryCode=="TWN") } // Dynamic query ● 若 Quotation 指定 type:
  • 30. Dynamic query (2) ● 使用 Dyanmic query API val q = dynamicQuery[City].filter { c: Quoted[City] => c.countryCode == "TWN" } ● 由 Quotation 轉換成 dynamic query val queryCity = quote { query[City] } val q = queryCity.dynamic.filter { c: Quoted[City] => quote { c.countryCode == "TWN" } }
  • 31. More
  • 32. Infix - 無奈需要寫 SQL 時 ● 使用 String Interpolator: infix ● 完整的 SQL ○ Map to case class / tuples ● 部份的 SQL ○ Quill Query 串接 SQL string ○ 呼叫 Database 提供的 funciton
  • 33. Null (1) case class Country(code: String, : : : indepYear: Option[Int], population: Int, lifeExpectancy: Option[Double], : : : CREATE TABLE country ( code character(3) NOT NULL, : : : indepyear smallint, // nullable population integer NOT NULL, lifeexpectancy real, // nullable : : :
  • 34. Null (2) query[Country].filter(c=> c.indepYear.isDefined) query[Country] .map{c=> (c.name, c.indepYear.map(y=>s"Independent: $y")) SELECT c.code, c.name, ... FROM country c WHERE c.indepyear IS NOT NULL SELECT c.name, 'Independent: ' || c.indepyear FROM country c
  • 35. Query probing - 驗證 SQL 是否正確 ● 在 Compile time 驗證 SQL 是否正確 ● Enable query probing ○ 使用 QueryProbing trait ○ Context 須要先在另一個獨立的 project 被編譯 ○ Sbt configuration
  • 36. Some issues ● Query 太多導致 compile-time 變慢 ● Cannot write generic function with Scala ● 在 IDE 開發使用 Query probing 可能導致 Too many clients ○ Caused by: com.zaxxer.hikari.pool.HikariPool$PoolInitializationException: Failed to initialize pool: FATAL: sorry, too many clients already ● 有些難懂的 compile error
  • 37. Q & A Thank you !!