SlideShare ist ein Scribd-Unternehmen logo
1 von 77
Downloaden Sie, um offline zu lesen
QB
A QUERY BUILDER FOR
THE REST OF US
WHAT THIS TALK IS NOT:
> Database performance tips
> How to integrate qb in your application*
> About a new ORM Engine (though qb is be the backend for
one)
* WE'LL TOUCH ON THIS A TINY BIT
WHAT THIS TALK IS:
> How to abstract your SQL statements from your
database grammar
> Help to stop concatenating SQL strings
> Ideas for new patterns to manage complex SQL
WHO AM I?
ERIC PETERSON
!
Utah
"
Ortus
#
ForgeBox, ColdBox Elixir
$
Prolific Module Author
%
1 wife, 2 kids, (1 on the way)
WHAT IS QB?
WHAT IS QB?
QUERYBUILDER & SCHEMABUILDER
> A fluent, chainable syntax for building SQL statements
> An abstraction around different database engines
> An abstraction around queryExecute
> Heavily inspired by Eloquent from Laravel
WHY CREATE QB?
TELL ME IF YOU'VE SEEN
THIS ONE BEFORE
function find( slug, createdBy, popular /* ..and so forth. */ ) {
var q = new Query(); //
!
var sql = "SELECT id, slug, createdBy, updatedDate";
// need this for one of two arguments
if ( ! isNull( popular ) ) {
// fun fact, I was missing a comma here from a previous presentation
// this wouldn't have even worked!
sql &= ", COUNT(*) AS installCount";
}
sql &= " FROM entries"; // now we can add the from
if ( ! isNull( popular ) ) {
sql &= " JOIN installs ON entries.id = installs.entryId";
}
// need some sort of initial where statement
// otherwise we have to worry about `WHERE` vs `AND`
sql &= " WHERE 1 = 1";
if ( ! isNull( slug ) ) {
q.addParam(
name = "slug",
cfsqltype = "CF_SQL_VARCHAR",
value = "%#slug#%",
);
sql &= " AND slug LIKE :slug"; // don't forget the leading space!!
}
if ( ! isNull( createdBy ) ) {
q.addParam(
name = "createdBy",
cfsqltype = "CF_SQL_INTEGER",
value = "%#createdBy#%",
);
sql &= " AND createdBy = :createdBy";
}
if ( ! isNull( popular ) ) {
sql &= " GROUP BY id, slug, createdBy, updatedDate";
}
// make sure to put the order by at the end.
if ( ! isNull( popular ) ) {
sql &= " ORDER BY installCount DESC";
} else {
sql &= " ORDER BY updatedDate DESC";
}
q.setSql( sql );
return q.execute().getResult();
}
WHAT PAIN POINTS DO WE SEE?
> Manually concatenating SQL strings
> Repeating checks in multiple places
> if statements mean no chainability
WHAT COULD THIS LOOK
LIKE WITH QB?
function find( slug, createdBy, popular, count /* ..and so forth. */ ) {
return builder
.from( "entries" )
.select( [ "id", "slug", "createdBy", "updatedDate" ] )
.when( ! isNull( slug ), function( query ) {
query.where( "slug", "like", "%#slug#%" );
} )
.when( ! isNull( createdBy ), function( query ) {
query.where( "createdBy", createdBy );
} )
.when( ! isNull( popular ), function( query ) {
query
.addSelect( query.raw( "COUNT(*) AS installCount" ) )
.join( "installs", "entries.id", "installs.entryId" )
.groupBy( [ "id", "slug", "createdBy", "updatedDate" ] );
} )
.when( ! isNull( popular ), function( query ) {
query.orderBy("installCount", "desc");
}, function( query ) {
query.orderBy("updatedDate", "desc");
} )
.get();
}
AND TRUST ME, WE CAN (AND WILL)
MAKE THAT EVEN BETTER!
QB IS VALUABLE FOR SMALL SQL
STATEMENTS AS WELL!
SPOT THE PROBLEM
function loadPosts() {
return queryExecute("SELECT * FROM `posts`");
}
THE SYNTAX IS DATABASE
ENGINE SPECIFIC
THIS IS AN ALTERNATIVE SYNTAX FOR
OTHER ENGINES
function loadPosts() {
return queryExecute('SELECT * FROM "posts"');
}
IN QB, BOTH OF THESE STATEMENTS ARE COVERED
WITH THIS:
function loadPosts() {
return builder.from("posts").get();
}
AND THAT'S JUST THE TIP
OF THE ICEBERG
SO, WHY CREATE QB?
> Reduce typos
> Bridge database engine idiosyncrasies
> Stop concatentating SQL strings
> Create expressive fluent statements instead of code
littered with if statements
> Enable new Object-Oriented patterns with SQL
statements
QB BUILDING BLOCKS
> Query Builder / Schema Builder
> Grammars
> Query Utils
CONFIGURATION
DEFAULT GRAMMAR
CONFIGURATION
DEFAULT GRAMMAR
CONFIGURATION
Bundled grammars include:
MSSQLGrammar, MySQLGrammar,
OracleGrammar, PostgresGrammar
(We would love your help adding more.)
RETURN FORMAT
CONFIGURATION
> Return a query
> Return an array (default)
> Return something custom!
moduleSettings = {
qb = {
returnFormat = function( query ) {
return application.wirebox.getInstance(
name = "CFCollection",
initArguments = { collection = query }
);
}
}
}
CONFIGURATION
Configure your settings through the moduleSettings
struct in config/ColdBox.cfc.
component {
function configure() {
moduleSettings = {
qb = {
defaultGrammar = "MySQLGrammar"
}
}
}
}
QUERYBUILDER
SYNTAX
AN OVERVIEW
FROM
query.from( "posts" );
> Specifies the base table for the query
SELECT
query.select( "id" );
> Default is *
> Takes a single value, list, or array
> Overwrites any existing selected columns
ADDSELECT
query.addSelect( "id" );
> Adds a column to the select list
> If the selection is currently *, then the added column
will be the only column selected.
JOIN
query.from( "posts" )
.join( "users", "posts.user_id", "=", "users.id" );
> Add a join statement to the query
> Simple syntax for simple joins
> Complex joins can be specified using a callback
WHERE
query.where( "title", "=", "My Title" );
> Adds a where statement to the query
> Automatically params the value passed
> Accepts any SQL operator like <=, <>, or LIKE
WHERE MAGIC
query.where( "title", "My Title" )
Can skip the second parameter if you want the operator
to be =
MORE WHERE MAGIC
query.whereTitle( "My Title" )
onMissingMethod lets you write really terse equality
where statements
NESTED WHERE
query.from( "users" )
.where( "email", "foo" )
.orWhere( function( q ) {
q.where( "name", "bar" )
.where( "age", ">=", "21" );
} );
Becomes
SELECT *
FROM `users`
WHERE `email` = ?
OR ( `name` = ? AND `age` >= ? )
WHERECOLUMN
query.whereColumn( "updated_date", ">", "created_date" );
> Compares two columns
> Accepts any SQL operator like <=, <>, or LIKE
WHEREIN
query.whereIn( "id", [ 1, 45, 101 ] );
> Adds a where in statement to the query
> Automatically params the values passed
OTHER WHERE METHODS
query.whereBetween( "createdDate", startDate, endDate );
query.whereNull( "deletedDate" );
query.whereExists( function( q ) {
q.select( q.raw( 1 ) ).from( "products" )
.where( "products.id", "=", q.raw( """orders"".""id""" ) );
} );
WHERE METHODS WRAP-UP
There are corresponding orWhere and whereNot
methods for each where method.
GROUPBY
query.groupBy( "id" );
> Adds a group by statement
> Further calls add to any existing groupings
> Takes a single value, list, or array
HAVING
query.from( "users" )
.groupBy( "email" )
.having( builder.raw( "COUNT(email)" ), ">", 1 );
> Adds a having statement
> Works pretty much like a where statement
ORDERBY
query.orderBy( "id", "desc" );
> Adds a order by statement
> Further calls add to any existing orders
> Takes a single value, list, or array
LIMIT & OFFSET
query.limit( 1 ).offset( 5 );
> Adds a limit and offset to the query
> This one is a great example where normalizing database
engines is super nice.
MYSQL
LIMIT
SELECT * FROM `users` LIMIT 3
LIMIT & OFFSET
SELECT * FROM `users` LIMIT 15 OFFSET 30
POSTGRES
LIMIT
SELECT * FROM "users" LIMIT 3
LIMIT & OFFSET
SELECT * FROM "users" LIMIT 15 OFFSET 30
MSSQL
LIMIT
SELECT TOP (3) * FROM [users]
LIMIT & OFFSET
SELECT * FROM [users]
ORDER BY 1
OFFSET 30 ROWS
FETCH NEXT 15 ROWS ONLY
ORACLE
LIMIT
SELECT * FROM (
SELECT results.*, ROWNUM AS "QB_RN"
FROM (SELECT * FROM "USERS") results
) WHERE "QB_RN" <= 3
LIMIT & OFFSET
SELECT * FROM (
SELECT results.*, ROWNUM AS "QB_RN"
FROM (SELECT * FROM "USERS") results
) WHERE "QB_RN" > 30 AND "QB_RN" <= 45
RAW
query.select( query.raw( "COUNT(*) AS post_count" ) );
> The qb escape hatch
> Outputs exactly the text you give it
WHEN
query.when( rc.isActive, function( q ) {
q.where( "is_active", 1 );
}, function( q ) {
q.whereNull( "is_active" );
} );
> Control flow for chainable methods
TOSQL
query.from( "users" ).toSQL()
> Builds the query into a SQL statement
> Bindings will be available in the getBindings method
GET
query.from( "users" ).get();
> Builds and executes the current query
> Can accept columns as a shortcut
> Also accepts any options that can be passed to
queryExecute
FIND
query.from( "users" ).find( 1 );
> Shortcut method for retrieving records by primary key
> Default idColumn is id
> idColumn can be specified as second argument
FIRST
query.from( "users" ).first();
> Adds a limit( 1 ) to your query
> Also returns the struct value, not an array of one
> Returns an empty struct if nothing is found
EXISTS
query.from( "logins" )
.where( "user_id", user.getId() )
.exists();
> Returns a boolean
> Works with any configured query
> Just call exists instead of get
COUNT, MAX, MIN, SUM
(AGGREGATES)
query.from( "users" )
.max( "last_logged_in" );
> Returns a single value from query
> Takes the column to perform the operation on
VALUE
query.from( "users" )
.where( "id", "=", rc.id )
.value( "username" );
> Fetches only one record (like first)
> Returns the value of the column specified
VALUES
query.from( "users" )
.values( "username" );
> Returns an array of all matched records
> Returns only the value of the column specified in the
array
INSERT
query.from( "users" ).insert( {
"username" = "johndoe",
"email" = "john@example.com",
"password" = bcryptedPassword
} );
> Inserts data into a table
BATCH INSERT
query.from( "users" ).insert( [
{
"username" = "johndoe",
"email" = "john@example.com",
"password" = bcryptedPassword
},
{
"username" = "janedoe",
"email" = "jane@example.com",
"password" = bcryptedPassword
}
] );
> Uses the database-specific batch insert syntax
UPDATE
query.from( "users" )
.whereId( rc.id )
.update( { "password" = newPassword } );
> Updates all matched rows, so be careful
> Works off of the built query
UPDATEORINSERT
query.from( "users" )
.whereId( rc.id )
.updateOrInsert( {
"username" = "johndoe",
"email" = "john@example.com",
"password" = bcryptedPassword
} );
> Updates or inserts dependening on if the query exists
DELETE
query.from( "users" )
.whereConfirmed( 0 )
.delete();
> Deletes all matched rows, so be careful
> Works off of the built query
WHEW... !
QueryFilters
EXAMPLE
QueryFilters EXAMPLE
// AbstractQueryFilters.cfc
component {
property name="query";
function apply( required query, rc = {} ) {
variables.query = arguments.query;
for ( var key in rc ) {
if ( variables.keyExists( key ) && isCustomFunction( variables[ key ] ) ) {
var func = variables[ key ];
func( rc[ key ] );
}
}
return variables.query;
}
}
QueryFilters EXAMPLE
// EntryFilters.cfc
component extends="AbstractQueryFilters" {
function slug( slug ) {
query.where( "slug", "like", "%#slug#%" );
}
function createdBy( authorName ) {
query.where( "createdBy", createdBy );
}
function popular() {
query.addSelect( query.raw( "COUNT(*) AS installCount" ) )
.join( "installs", "entries.id", "installs.entryId" )
.groupBy( [ "entries.id", "slug", "createdBy", "updatedDate" ] )
.orderBy( "installCount", "desc" );
}
}
QueryFilters EXAMPLE
// handlers/Entries.cfc
component {
property name="EntryFilters" inject="id";
function index(event, rc, prc) {
var query = getInstance( "Builder@qb" );
query.select( [ "entries.id", "slug", "createdBy", "updatedDate" ] )
.from( "entries" )
.orderBy( "updatedDate", "desc" );
EntryFilters.apply( query, rc );
prc.entries = query.get();
}
}
SEE?
I TOLD YOU WE'D MAKE
THAT EVEN BETTER!
DEMO!
CONTRIBUTING
GRAMMARS
CONTRIBUTING
DOCS
CONTRIBUTING
WHO KNOWS WHAT YOU WILL
CREATE WITH THIS?
THANKS!
> qb docs
> qb on ForgeBox
> me on Twitter (_elpete)
> me on ForgeBox (elpete))
> CFML Slack (elpete)

Weitere ähnliche Inhalte

Was ist angesagt?

Python in the database
Python in the databasePython in the database
Python in the databasepybcn
 
Auto-GWT : Better GWT Programming with Xtend
Auto-GWT : Better GWT Programming with XtendAuto-GWT : Better GWT Programming with Xtend
Auto-GWT : Better GWT Programming with XtendSven Efftinge
 
Get database properties using power shell in sql server 2008 techrepublic
Get database properties using power shell in sql server 2008   techrepublicGet database properties using power shell in sql server 2008   techrepublic
Get database properties using power shell in sql server 2008 techrepublicKaing Menglieng
 
Administering and Monitoring SolrCloud Clusters
Administering and Monitoring SolrCloud ClustersAdministering and Monitoring SolrCloud Clusters
Administering and Monitoring SolrCloud Clusterslucenerevolution
 
Test driven development (java script & mivascript)
Test driven development (java script & mivascript)Test driven development (java script & mivascript)
Test driven development (java script & mivascript)Miva
 
MySQL User Conference 2009: Python and MySQL
MySQL User Conference 2009: Python and MySQLMySQL User Conference 2009: Python and MySQL
MySQL User Conference 2009: Python and MySQLTed Leung
 
Cassandra Day NYC - Cassandra anti patterns
Cassandra Day NYC - Cassandra anti patternsCassandra Day NYC - Cassandra anti patterns
Cassandra Day NYC - Cassandra anti patternsChristopher Batey
 
Flashback (Practical Test)
Flashback (Practical Test)Flashback (Practical Test)
Flashback (Practical Test)Anar Godjaev
 
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...Domenic Denicola
 
Cassandra Summit 2015
Cassandra Summit 2015Cassandra Summit 2015
Cassandra Summit 2015jbellis
 
Cassandra summit keynote 2014
Cassandra summit keynote 2014Cassandra summit keynote 2014
Cassandra summit keynote 2014jbellis
 
ElasticSearch for .NET Developers
ElasticSearch for .NET DevelopersElasticSearch for .NET Developers
ElasticSearch for .NET DevelopersBen van Mol
 
#36.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_재직자환급교육,실업자교육,국비지원교육, 자바교육,구...
#36.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_재직자환급교육,실업자교육,국비지원교육, 자바교육,구...#36.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_재직자환급교육,실업자교육,국비지원교육, 자바교육,구...
#36.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_재직자환급교육,실업자교육,국비지원교육, 자바교육,구...탑크리에듀(구로디지털단지역3번출구 2분거리)
 
Cassandra nice use cases and worst anti patterns
Cassandra nice use cases and worst anti patternsCassandra nice use cases and worst anti patterns
Cassandra nice use cases and worst anti patternsDuyhai Doan
 
Lean React - Patterns for High Performance [ploneconf2017]
Lean React - Patterns for High Performance [ploneconf2017]Lean React - Patterns for High Performance [ploneconf2017]
Lean React - Patterns for High Performance [ploneconf2017]Devon Bernard
 

Was ist angesagt? (20)

Python in the database
Python in the databasePython in the database
Python in the database
 
Auto-GWT : Better GWT Programming with Xtend
Auto-GWT : Better GWT Programming with XtendAuto-GWT : Better GWT Programming with Xtend
Auto-GWT : Better GWT Programming with Xtend
 
Gwt and Xtend
Gwt and XtendGwt and Xtend
Gwt and Xtend
 
Python database access
Python database accessPython database access
Python database access
 
Python database interfaces
Python database  interfacesPython database  interfaces
Python database interfaces
 
Get database properties using power shell in sql server 2008 techrepublic
Get database properties using power shell in sql server 2008   techrepublicGet database properties using power shell in sql server 2008   techrepublic
Get database properties using power shell in sql server 2008 techrepublic
 
Administering and Monitoring SolrCloud Clusters
Administering and Monitoring SolrCloud ClustersAdministering and Monitoring SolrCloud Clusters
Administering and Monitoring SolrCloud Clusters
 
Test driven development (java script & mivascript)
Test driven development (java script & mivascript)Test driven development (java script & mivascript)
Test driven development (java script & mivascript)
 
MySQL User Conference 2009: Python and MySQL
MySQL User Conference 2009: Python and MySQLMySQL User Conference 2009: Python and MySQL
MySQL User Conference 2009: Python and MySQL
 
Cassandra Day NYC - Cassandra anti patterns
Cassandra Day NYC - Cassandra anti patternsCassandra Day NYC - Cassandra anti patterns
Cassandra Day NYC - Cassandra anti patterns
 
Flashback (Practical Test)
Flashback (Practical Test)Flashback (Practical Test)
Flashback (Practical Test)
 
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
Callbacks, Promises, and Coroutines (oh my!): Asynchronous Programming Patter...
 
Cassandra Summit 2015
Cassandra Summit 2015Cassandra Summit 2015
Cassandra Summit 2015
 
Cassandra summit keynote 2014
Cassandra summit keynote 2014Cassandra summit keynote 2014
Cassandra summit keynote 2014
 
ElasticSearch for .NET Developers
ElasticSearch for .NET DevelopersElasticSearch for .NET Developers
ElasticSearch for .NET Developers
 
#36.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_재직자환급교육,실업자교육,국비지원교육, 자바교육,구...
#36.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_재직자환급교육,실업자교육,국비지원교육, 자바교육,구...#36.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_재직자환급교육,실업자교육,국비지원교육, 자바교육,구...
#36.스프링프레임워크 & 마이바티스 (Spring Framework, MyBatis)_재직자환급교육,실업자교육,국비지원교육, 자바교육,구...
 
Scala active record
Scala active recordScala active record
Scala active record
 
Cassandra nice use cases and worst anti patterns
Cassandra nice use cases and worst anti patternsCassandra nice use cases and worst anti patterns
Cassandra nice use cases and worst anti patterns
 
greenDAO
greenDAOgreenDAO
greenDAO
 
Lean React - Patterns for High Performance [ploneconf2017]
Lean React - Patterns for High Performance [ploneconf2017]Lean React - Patterns for High Performance [ploneconf2017]
Lean React - Patterns for High Performance [ploneconf2017]
 

Ähnlich wie QB Into the Box 2018

ITB2019 Faster DB Development with QB - Andrew Davis
ITB2019 Faster DB Development with QB - Andrew DavisITB2019 Faster DB Development with QB - Andrew Davis
ITB2019 Faster DB Development with QB - Andrew DavisOrtus Solutions, Corp
 
PerlApp2Postgresql (2)
PerlApp2Postgresql (2)PerlApp2Postgresql (2)
PerlApp2Postgresql (2)Jerome Eteve
 
Linuxfest Northwest 2022 - MySQL 8.0 Nre Features
Linuxfest Northwest 2022 - MySQL 8.0 Nre FeaturesLinuxfest Northwest 2022 - MySQL 8.0 Nre Features
Linuxfest Northwest 2022 - MySQL 8.0 Nre FeaturesDave Stokes
 
Cfml features modern coding into the box 2018
Cfml features modern coding into the box 2018Cfml features modern coding into the box 2018
Cfml features modern coding into the box 2018Ortus Solutions, Corp
 
ShmooCon 2009 - (Re)Playing(Blind)Sql
ShmooCon 2009 - (Re)Playing(Blind)SqlShmooCon 2009 - (Re)Playing(Blind)Sql
ShmooCon 2009 - (Re)Playing(Blind)SqlChema Alonso
 
My sql with querys
My sql with querysMy sql with querys
My sql with querysNIRMAL FELIX
 
Learn PHP Lacture2
Learn PHP Lacture2Learn PHP Lacture2
Learn PHP Lacture2ADARSH BHATT
 
SQL for Web APIs - Simplifying Data Access for API Consumers
SQL for Web APIs - Simplifying Data Access for API ConsumersSQL for Web APIs - Simplifying Data Access for API Consumers
SQL for Web APIs - Simplifying Data Access for API ConsumersJerod Johnson
 
Mysqlppt
MysqlpptMysqlppt
MysqlpptReka
 

Ähnlich wie QB Into the Box 2018 (20)

ITB2019 Faster DB Development with QB - Andrew Davis
ITB2019 Faster DB Development with QB - Andrew DavisITB2019 Faster DB Development with QB - Andrew Davis
ITB2019 Faster DB Development with QB - Andrew Davis
 
PerlApp2Postgresql (2)
PerlApp2Postgresql (2)PerlApp2Postgresql (2)
PerlApp2Postgresql (2)
 
JDBC – Java Database Connectivity
JDBC – Java Database ConnectivityJDBC – Java Database Connectivity
JDBC – Java Database Connectivity
 
Sql Injection Myths and Fallacies
Sql Injection Myths and FallaciesSql Injection Myths and Fallacies
Sql Injection Myths and Fallacies
 
Sql injection
Sql injectionSql injection
Sql injection
 
Linuxfest Northwest 2022 - MySQL 8.0 Nre Features
Linuxfest Northwest 2022 - MySQL 8.0 Nre FeaturesLinuxfest Northwest 2022 - MySQL 8.0 Nre Features
Linuxfest Northwest 2022 - MySQL 8.0 Nre Features
 
Cfml features modern coding into the box 2018
Cfml features modern coding into the box 2018Cfml features modern coding into the box 2018
Cfml features modern coding into the box 2018
 
ShmooCon 2009 - (Re)Playing(Blind)Sql
ShmooCon 2009 - (Re)Playing(Blind)SqlShmooCon 2009 - (Re)Playing(Blind)Sql
ShmooCon 2009 - (Re)Playing(Blind)Sql
 
My sql
My sqlMy sql
My sql
 
My sql with querys
My sql with querysMy sql with querys
My sql with querys
 
MySql slides (ppt)
MySql slides (ppt)MySql slides (ppt)
MySql slides (ppt)
 
Learn PHP Lacture2
Learn PHP Lacture2Learn PHP Lacture2
Learn PHP Lacture2
 
SQL for Web APIs - Simplifying Data Access for API Consumers
SQL for Web APIs - Simplifying Data Access for API ConsumersSQL for Web APIs - Simplifying Data Access for API Consumers
SQL for Web APIs - Simplifying Data Access for API Consumers
 
Raj mysql
Raj mysqlRaj mysql
Raj mysql
 
Html web sql database
Html web sql databaseHtml web sql database
Html web sql database
 
Mysqlppt
MysqlpptMysqlppt
Mysqlppt
 
Sqlapi0.1
Sqlapi0.1Sqlapi0.1
Sqlapi0.1
 
PHP with MYSQL
PHP with MYSQLPHP with MYSQL
PHP with MYSQL
 
Mysqlppt
MysqlpptMysqlppt
Mysqlppt
 
Sql injection
Sql injectionSql injection
Sql injection
 

Mehr von Ortus Solutions, Corp

BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEOrtus Solutions, Corp
 
Secure your Secrets and Settings in ColdFusion
Secure your Secrets and Settings in ColdFusionSecure your Secrets and Settings in ColdFusion
Secure your Secrets and Settings in ColdFusionOrtus Solutions, Corp
 
Daniel Garcia ContentBox: CFSummit 2023
Daniel Garcia ContentBox: CFSummit 2023Daniel Garcia ContentBox: CFSummit 2023
Daniel Garcia ContentBox: CFSummit 2023Ortus Solutions, Corp
 
ITB_2023_Human-Friendly_Scheduled_Tasks_Giancarlo_Gomez.pdf
ITB_2023_Human-Friendly_Scheduled_Tasks_Giancarlo_Gomez.pdfITB_2023_Human-Friendly_Scheduled_Tasks_Giancarlo_Gomez.pdf
ITB_2023_Human-Friendly_Scheduled_Tasks_Giancarlo_Gomez.pdfOrtus Solutions, Corp
 
ITB_2023_CommandBox_Multi-Server_-_Brad_Wood.pdf
ITB_2023_CommandBox_Multi-Server_-_Brad_Wood.pdfITB_2023_CommandBox_Multi-Server_-_Brad_Wood.pdf
ITB_2023_CommandBox_Multi-Server_-_Brad_Wood.pdfOrtus Solutions, Corp
 
ITB_2023_The_Many_Layers_of_OAuth_Keith_Casey_.pdf
ITB_2023_The_Many_Layers_of_OAuth_Keith_Casey_.pdfITB_2023_The_Many_Layers_of_OAuth_Keith_Casey_.pdf
ITB_2023_The_Many_Layers_of_OAuth_Keith_Casey_.pdfOrtus Solutions, Corp
 
ITB_2023_Relationships_are_Hard_Data_modeling_with_NoSQL_Curt_Gratz.pdf
ITB_2023_Relationships_are_Hard_Data_modeling_with_NoSQL_Curt_Gratz.pdfITB_2023_Relationships_are_Hard_Data_modeling_with_NoSQL_Curt_Gratz.pdf
ITB_2023_Relationships_are_Hard_Data_modeling_with_NoSQL_Curt_Gratz.pdfOrtus Solutions, Corp
 
ITB_2023_Extend_your_contentbox_apps_with_custom_modules_Javier_Quintero.pdf
ITB_2023_Extend_your_contentbox_apps_with_custom_modules_Javier_Quintero.pdfITB_2023_Extend_your_contentbox_apps_with_custom_modules_Javier_Quintero.pdf
ITB_2023_Extend_your_contentbox_apps_with_custom_modules_Javier_Quintero.pdfOrtus Solutions, Corp
 
ITB_2023_25_Most_Dangerous_Software_Weaknesses_Pete_Freitag.pdf
ITB_2023_25_Most_Dangerous_Software_Weaknesses_Pete_Freitag.pdfITB_2023_25_Most_Dangerous_Software_Weaknesses_Pete_Freitag.pdf
ITB_2023_25_Most_Dangerous_Software_Weaknesses_Pete_Freitag.pdfOrtus Solutions, Corp
 
ITB_2023_Practical_AI_with_OpenAI_-_Grant_Copley_.pdf
ITB_2023_Practical_AI_with_OpenAI_-_Grant_Copley_.pdfITB_2023_Practical_AI_with_OpenAI_-_Grant_Copley_.pdf
ITB_2023_Practical_AI_with_OpenAI_-_Grant_Copley_.pdfOrtus Solutions, Corp
 
ITB_2023_When_Your_Applications_Work_As_a_Team_Nathaniel_Francis.pdf
ITB_2023_When_Your_Applications_Work_As_a_Team_Nathaniel_Francis.pdfITB_2023_When_Your_Applications_Work_As_a_Team_Nathaniel_Francis.pdf
ITB_2023_When_Your_Applications_Work_As_a_Team_Nathaniel_Francis.pdfOrtus Solutions, Corp
 
ITB_2023_Faster_Apps_That_Wont_Get_Crushed_Brian_Klaas.pdf
ITB_2023_Faster_Apps_That_Wont_Get_Crushed_Brian_Klaas.pdfITB_2023_Faster_Apps_That_Wont_Get_Crushed_Brian_Klaas.pdf
ITB_2023_Faster_Apps_That_Wont_Get_Crushed_Brian_Klaas.pdfOrtus Solutions, Corp
 
ITB_2023_Chatgpt_Box_Scott_Steinbeck.pdf
ITB_2023_Chatgpt_Box_Scott_Steinbeck.pdfITB_2023_Chatgpt_Box_Scott_Steinbeck.pdf
ITB_2023_Chatgpt_Box_Scott_Steinbeck.pdfOrtus Solutions, Corp
 
ITB_2023_CommandBox_Task_Runners_Brad_Wood.pdf
ITB_2023_CommandBox_Task_Runners_Brad_Wood.pdfITB_2023_CommandBox_Task_Runners_Brad_Wood.pdf
ITB_2023_CommandBox_Task_Runners_Brad_Wood.pdfOrtus Solutions, Corp
 
ITB_2023_Create_as_many_web_sites_or_web_apps_as_you_want_George_Murphy.pdf
ITB_2023_Create_as_many_web_sites_or_web_apps_as_you_want_George_Murphy.pdfITB_2023_Create_as_many_web_sites_or_web_apps_as_you_want_George_Murphy.pdf
ITB_2023_Create_as_many_web_sites_or_web_apps_as_you_want_George_Murphy.pdfOrtus Solutions, Corp
 
ITB2023 Developing for Performance - Denard Springle.pdf
ITB2023 Developing for Performance - Denard Springle.pdfITB2023 Developing for Performance - Denard Springle.pdf
ITB2023 Developing for Performance - Denard Springle.pdfOrtus Solutions, Corp
 

Mehr von Ortus Solutions, Corp (20)

BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASEBATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
BATTLEFIELD ORM: TIPS, TACTICS AND STRATEGIES FOR CONQUERING YOUR DATABASE
 
Ortus Government.pdf
Ortus Government.pdfOrtus Government.pdf
Ortus Government.pdf
 
Luis Majano The Battlefield ORM
Luis Majano The Battlefield ORMLuis Majano The Battlefield ORM
Luis Majano The Battlefield ORM
 
Brad Wood - CommandBox CLI
Brad Wood - CommandBox CLI Brad Wood - CommandBox CLI
Brad Wood - CommandBox CLI
 
Secure your Secrets and Settings in ColdFusion
Secure your Secrets and Settings in ColdFusionSecure your Secrets and Settings in ColdFusion
Secure your Secrets and Settings in ColdFusion
 
Daniel Garcia ContentBox: CFSummit 2023
Daniel Garcia ContentBox: CFSummit 2023Daniel Garcia ContentBox: CFSummit 2023
Daniel Garcia ContentBox: CFSummit 2023
 
ITB_2023_Human-Friendly_Scheduled_Tasks_Giancarlo_Gomez.pdf
ITB_2023_Human-Friendly_Scheduled_Tasks_Giancarlo_Gomez.pdfITB_2023_Human-Friendly_Scheduled_Tasks_Giancarlo_Gomez.pdf
ITB_2023_Human-Friendly_Scheduled_Tasks_Giancarlo_Gomez.pdf
 
ITB_2023_CommandBox_Multi-Server_-_Brad_Wood.pdf
ITB_2023_CommandBox_Multi-Server_-_Brad_Wood.pdfITB_2023_CommandBox_Multi-Server_-_Brad_Wood.pdf
ITB_2023_CommandBox_Multi-Server_-_Brad_Wood.pdf
 
ITB_2023_The_Many_Layers_of_OAuth_Keith_Casey_.pdf
ITB_2023_The_Many_Layers_of_OAuth_Keith_Casey_.pdfITB_2023_The_Many_Layers_of_OAuth_Keith_Casey_.pdf
ITB_2023_The_Many_Layers_of_OAuth_Keith_Casey_.pdf
 
ITB_2023_Relationships_are_Hard_Data_modeling_with_NoSQL_Curt_Gratz.pdf
ITB_2023_Relationships_are_Hard_Data_modeling_with_NoSQL_Curt_Gratz.pdfITB_2023_Relationships_are_Hard_Data_modeling_with_NoSQL_Curt_Gratz.pdf
ITB_2023_Relationships_are_Hard_Data_modeling_with_NoSQL_Curt_Gratz.pdf
 
ITB_2023_Extend_your_contentbox_apps_with_custom_modules_Javier_Quintero.pdf
ITB_2023_Extend_your_contentbox_apps_with_custom_modules_Javier_Quintero.pdfITB_2023_Extend_your_contentbox_apps_with_custom_modules_Javier_Quintero.pdf
ITB_2023_Extend_your_contentbox_apps_with_custom_modules_Javier_Quintero.pdf
 
ITB_2023_25_Most_Dangerous_Software_Weaknesses_Pete_Freitag.pdf
ITB_2023_25_Most_Dangerous_Software_Weaknesses_Pete_Freitag.pdfITB_2023_25_Most_Dangerous_Software_Weaknesses_Pete_Freitag.pdf
ITB_2023_25_Most_Dangerous_Software_Weaknesses_Pete_Freitag.pdf
 
ITB_2023_CBWire_v3_Grant_Copley.pdf
ITB_2023_CBWire_v3_Grant_Copley.pdfITB_2023_CBWire_v3_Grant_Copley.pdf
ITB_2023_CBWire_v3_Grant_Copley.pdf
 
ITB_2023_Practical_AI_with_OpenAI_-_Grant_Copley_.pdf
ITB_2023_Practical_AI_with_OpenAI_-_Grant_Copley_.pdfITB_2023_Practical_AI_with_OpenAI_-_Grant_Copley_.pdf
ITB_2023_Practical_AI_with_OpenAI_-_Grant_Copley_.pdf
 
ITB_2023_When_Your_Applications_Work_As_a_Team_Nathaniel_Francis.pdf
ITB_2023_When_Your_Applications_Work_As_a_Team_Nathaniel_Francis.pdfITB_2023_When_Your_Applications_Work_As_a_Team_Nathaniel_Francis.pdf
ITB_2023_When_Your_Applications_Work_As_a_Team_Nathaniel_Francis.pdf
 
ITB_2023_Faster_Apps_That_Wont_Get_Crushed_Brian_Klaas.pdf
ITB_2023_Faster_Apps_That_Wont_Get_Crushed_Brian_Klaas.pdfITB_2023_Faster_Apps_That_Wont_Get_Crushed_Brian_Klaas.pdf
ITB_2023_Faster_Apps_That_Wont_Get_Crushed_Brian_Klaas.pdf
 
ITB_2023_Chatgpt_Box_Scott_Steinbeck.pdf
ITB_2023_Chatgpt_Box_Scott_Steinbeck.pdfITB_2023_Chatgpt_Box_Scott_Steinbeck.pdf
ITB_2023_Chatgpt_Box_Scott_Steinbeck.pdf
 
ITB_2023_CommandBox_Task_Runners_Brad_Wood.pdf
ITB_2023_CommandBox_Task_Runners_Brad_Wood.pdfITB_2023_CommandBox_Task_Runners_Brad_Wood.pdf
ITB_2023_CommandBox_Task_Runners_Brad_Wood.pdf
 
ITB_2023_Create_as_many_web_sites_or_web_apps_as_you_want_George_Murphy.pdf
ITB_2023_Create_as_many_web_sites_or_web_apps_as_you_want_George_Murphy.pdfITB_2023_Create_as_many_web_sites_or_web_apps_as_you_want_George_Murphy.pdf
ITB_2023_Create_as_many_web_sites_or_web_apps_as_you_want_George_Murphy.pdf
 
ITB2023 Developing for Performance - Denard Springle.pdf
ITB2023 Developing for Performance - Denard Springle.pdfITB2023 Developing for Performance - Denard Springle.pdf
ITB2023 Developing for Performance - Denard Springle.pdf
 

Kürzlich hochgeladen

Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfAddepto
 
Search Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfSearch Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfRankYa
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxNavinnSomaal
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity PlanDatabarracks
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubKalema Edgar
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenHervé Boutemy
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...Fwdays
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
H2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo Day
H2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo DayH2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo Day
H2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo DaySri Ambati
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsMiki Katsuragi
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationSlibray Presentation
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piececharlottematthew16
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningLars Bell
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024Lonnie McRorey
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsRizwan Syed
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii SoldatenkoFwdays
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfHyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfPrecisely
 

Kürzlich hochgeladen (20)

Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdf
 
Search Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdfSearch Engine Optimization SEO PDF for 2024.pdf
Search Engine Optimization SEO PDF for 2024.pdf
 
SAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptxSAP Build Work Zone - Overview L2-L3.pptx
SAP Build Work Zone - Overview L2-L3.pptx
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity Plan
 
Unleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding ClubUnleash Your Potential - Namagunga Girls Coding Club
Unleash Your Potential - Namagunga Girls Coding Club
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache Maven
 
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks..."LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
"LLMs for Python Engineers: Advanced Data Analysis and Semantic Kernel",Oleks...
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
H2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo Day
H2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo DayH2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo Day
H2O.ai CEO/Founder: Sri Ambati Keynote at Wells Fargo Day
 
Vertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering TipsVertex AI Gemini Prompt Engineering Tips
Vertex AI Gemini Prompt Engineering Tips
 
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptxE-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
E-Vehicle_Hacking_by_Parul Sharma_null_owasp.pptx
 
Connect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck PresentationConnect Wave/ connectwave Pitch Deck Presentation
Connect Wave/ connectwave Pitch Deck Presentation
 
Story boards and shot lists for my a level piece
Story boards and shot lists for my a level pieceStory boards and shot lists for my a level piece
Story boards and shot lists for my a level piece
 
DSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine TuningDSPy a system for AI to Write Prompts and Do Fine Tuning
DSPy a system for AI to Write Prompts and Do Fine Tuning
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024
 
Scanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL CertsScanning the Internet for External Cloud Exposures via SSL Certs
Scanning the Internet for External Cloud Exposures via SSL Certs
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
 
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdfHyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
Hyperautomation and AI/ML: A Strategy for Digital Transformation Success.pdf
 

QB Into the Box 2018

  • 1. QB A QUERY BUILDER FOR THE REST OF US
  • 2. WHAT THIS TALK IS NOT: > Database performance tips > How to integrate qb in your application* > About a new ORM Engine (though qb is be the backend for one) * WE'LL TOUCH ON THIS A TINY BIT
  • 3. WHAT THIS TALK IS: > How to abstract your SQL statements from your database grammar > Help to stop concatenating SQL strings > Ideas for new patterns to manage complex SQL
  • 4. WHO AM I? ERIC PETERSON ! Utah " Ortus # ForgeBox, ColdBox Elixir $ Prolific Module Author % 1 wife, 2 kids, (1 on the way)
  • 6. WHAT IS QB? QUERYBUILDER & SCHEMABUILDER > A fluent, chainable syntax for building SQL statements > An abstraction around different database engines > An abstraction around queryExecute > Heavily inspired by Eloquent from Laravel
  • 8. TELL ME IF YOU'VE SEEN THIS ONE BEFORE
  • 9. function find( slug, createdBy, popular /* ..and so forth. */ ) { var q = new Query(); // ! var sql = "SELECT id, slug, createdBy, updatedDate"; // need this for one of two arguments if ( ! isNull( popular ) ) { // fun fact, I was missing a comma here from a previous presentation // this wouldn't have even worked! sql &= ", COUNT(*) AS installCount"; } sql &= " FROM entries"; // now we can add the from if ( ! isNull( popular ) ) { sql &= " JOIN installs ON entries.id = installs.entryId"; } // need some sort of initial where statement // otherwise we have to worry about `WHERE` vs `AND` sql &= " WHERE 1 = 1"; if ( ! isNull( slug ) ) { q.addParam( name = "slug", cfsqltype = "CF_SQL_VARCHAR", value = "%#slug#%", ); sql &= " AND slug LIKE :slug"; // don't forget the leading space!! } if ( ! isNull( createdBy ) ) { q.addParam( name = "createdBy", cfsqltype = "CF_SQL_INTEGER", value = "%#createdBy#%", ); sql &= " AND createdBy = :createdBy"; } if ( ! isNull( popular ) ) { sql &= " GROUP BY id, slug, createdBy, updatedDate"; } // make sure to put the order by at the end. if ( ! isNull( popular ) ) { sql &= " ORDER BY installCount DESC"; } else { sql &= " ORDER BY updatedDate DESC"; } q.setSql( sql ); return q.execute().getResult(); }
  • 10. WHAT PAIN POINTS DO WE SEE? > Manually concatenating SQL strings > Repeating checks in multiple places > if statements mean no chainability
  • 11. WHAT COULD THIS LOOK LIKE WITH QB?
  • 12. function find( slug, createdBy, popular, count /* ..and so forth. */ ) { return builder .from( "entries" ) .select( [ "id", "slug", "createdBy", "updatedDate" ] ) .when( ! isNull( slug ), function( query ) { query.where( "slug", "like", "%#slug#%" ); } ) .when( ! isNull( createdBy ), function( query ) { query.where( "createdBy", createdBy ); } ) .when( ! isNull( popular ), function( query ) { query .addSelect( query.raw( "COUNT(*) AS installCount" ) ) .join( "installs", "entries.id", "installs.entryId" ) .groupBy( [ "id", "slug", "createdBy", "updatedDate" ] ); } ) .when( ! isNull( popular ), function( query ) { query.orderBy("installCount", "desc"); }, function( query ) { query.orderBy("updatedDate", "desc"); } ) .get(); }
  • 13. AND TRUST ME, WE CAN (AND WILL) MAKE THAT EVEN BETTER!
  • 14. QB IS VALUABLE FOR SMALL SQL STATEMENTS AS WELL!
  • 15. SPOT THE PROBLEM function loadPosts() { return queryExecute("SELECT * FROM `posts`"); }
  • 16. THE SYNTAX IS DATABASE ENGINE SPECIFIC
  • 17. THIS IS AN ALTERNATIVE SYNTAX FOR OTHER ENGINES function loadPosts() { return queryExecute('SELECT * FROM "posts"'); }
  • 18. IN QB, BOTH OF THESE STATEMENTS ARE COVERED WITH THIS: function loadPosts() { return builder.from("posts").get(); }
  • 19. AND THAT'S JUST THE TIP OF THE ICEBERG
  • 20. SO, WHY CREATE QB? > Reduce typos > Bridge database engine idiosyncrasies > Stop concatentating SQL strings > Create expressive fluent statements instead of code littered with if statements > Enable new Object-Oriented patterns with SQL statements
  • 21. QB BUILDING BLOCKS > Query Builder / Schema Builder > Grammars > Query Utils
  • 24. DEFAULT GRAMMAR CONFIGURATION Bundled grammars include: MSSQLGrammar, MySQLGrammar, OracleGrammar, PostgresGrammar (We would love your help adding more.)
  • 25. RETURN FORMAT CONFIGURATION > Return a query > Return an array (default) > Return something custom!
  • 26. moduleSettings = { qb = { returnFormat = function( query ) { return application.wirebox.getInstance( name = "CFCollection", initArguments = { collection = query } ); } } }
  • 27. CONFIGURATION Configure your settings through the moduleSettings struct in config/ColdBox.cfc. component { function configure() { moduleSettings = { qb = { defaultGrammar = "MySQLGrammar" } } } }
  • 29. FROM query.from( "posts" ); > Specifies the base table for the query
  • 30. SELECT query.select( "id" ); > Default is * > Takes a single value, list, or array > Overwrites any existing selected columns
  • 31. ADDSELECT query.addSelect( "id" ); > Adds a column to the select list > If the selection is currently *, then the added column will be the only column selected.
  • 32. JOIN query.from( "posts" ) .join( "users", "posts.user_id", "=", "users.id" ); > Add a join statement to the query > Simple syntax for simple joins > Complex joins can be specified using a callback
  • 33. WHERE query.where( "title", "=", "My Title" ); > Adds a where statement to the query > Automatically params the value passed > Accepts any SQL operator like <=, <>, or LIKE
  • 34. WHERE MAGIC query.where( "title", "My Title" ) Can skip the second parameter if you want the operator to be =
  • 35. MORE WHERE MAGIC query.whereTitle( "My Title" ) onMissingMethod lets you write really terse equality where statements
  • 36. NESTED WHERE query.from( "users" ) .where( "email", "foo" ) .orWhere( function( q ) { q.where( "name", "bar" ) .where( "age", ">=", "21" ); } ); Becomes SELECT * FROM `users` WHERE `email` = ? OR ( `name` = ? AND `age` >= ? )
  • 37. WHERECOLUMN query.whereColumn( "updated_date", ">", "created_date" ); > Compares two columns > Accepts any SQL operator like <=, <>, or LIKE
  • 38. WHEREIN query.whereIn( "id", [ 1, 45, 101 ] ); > Adds a where in statement to the query > Automatically params the values passed
  • 39. OTHER WHERE METHODS query.whereBetween( "createdDate", startDate, endDate ); query.whereNull( "deletedDate" ); query.whereExists( function( q ) { q.select( q.raw( 1 ) ).from( "products" ) .where( "products.id", "=", q.raw( """orders"".""id""" ) ); } );
  • 40. WHERE METHODS WRAP-UP There are corresponding orWhere and whereNot methods for each where method.
  • 41. GROUPBY query.groupBy( "id" ); > Adds a group by statement > Further calls add to any existing groupings > Takes a single value, list, or array
  • 42. HAVING query.from( "users" ) .groupBy( "email" ) .having( builder.raw( "COUNT(email)" ), ">", 1 ); > Adds a having statement > Works pretty much like a where statement
  • 43. ORDERBY query.orderBy( "id", "desc" ); > Adds a order by statement > Further calls add to any existing orders > Takes a single value, list, or array
  • 44. LIMIT & OFFSET query.limit( 1 ).offset( 5 ); > Adds a limit and offset to the query > This one is a great example where normalizing database engines is super nice.
  • 45. MYSQL LIMIT SELECT * FROM `users` LIMIT 3 LIMIT & OFFSET SELECT * FROM `users` LIMIT 15 OFFSET 30
  • 46. POSTGRES LIMIT SELECT * FROM "users" LIMIT 3 LIMIT & OFFSET SELECT * FROM "users" LIMIT 15 OFFSET 30
  • 47. MSSQL LIMIT SELECT TOP (3) * FROM [users] LIMIT & OFFSET SELECT * FROM [users] ORDER BY 1 OFFSET 30 ROWS FETCH NEXT 15 ROWS ONLY
  • 48. ORACLE LIMIT SELECT * FROM ( SELECT results.*, ROWNUM AS "QB_RN" FROM (SELECT * FROM "USERS") results ) WHERE "QB_RN" <= 3 LIMIT & OFFSET SELECT * FROM ( SELECT results.*, ROWNUM AS "QB_RN" FROM (SELECT * FROM "USERS") results ) WHERE "QB_RN" > 30 AND "QB_RN" <= 45
  • 49. RAW query.select( query.raw( "COUNT(*) AS post_count" ) ); > The qb escape hatch > Outputs exactly the text you give it
  • 50. WHEN query.when( rc.isActive, function( q ) { q.where( "is_active", 1 ); }, function( q ) { q.whereNull( "is_active" ); } ); > Control flow for chainable methods
  • 51. TOSQL query.from( "users" ).toSQL() > Builds the query into a SQL statement > Bindings will be available in the getBindings method
  • 52. GET query.from( "users" ).get(); > Builds and executes the current query > Can accept columns as a shortcut > Also accepts any options that can be passed to queryExecute
  • 53. FIND query.from( "users" ).find( 1 ); > Shortcut method for retrieving records by primary key > Default idColumn is id > idColumn can be specified as second argument
  • 54. FIRST query.from( "users" ).first(); > Adds a limit( 1 ) to your query > Also returns the struct value, not an array of one > Returns an empty struct if nothing is found
  • 55. EXISTS query.from( "logins" ) .where( "user_id", user.getId() ) .exists(); > Returns a boolean > Works with any configured query > Just call exists instead of get
  • 56. COUNT, MAX, MIN, SUM (AGGREGATES) query.from( "users" ) .max( "last_logged_in" ); > Returns a single value from query > Takes the column to perform the operation on
  • 57. VALUE query.from( "users" ) .where( "id", "=", rc.id ) .value( "username" ); > Fetches only one record (like first) > Returns the value of the column specified
  • 58. VALUES query.from( "users" ) .values( "username" ); > Returns an array of all matched records > Returns only the value of the column specified in the array
  • 59. INSERT query.from( "users" ).insert( { "username" = "johndoe", "email" = "john@example.com", "password" = bcryptedPassword } ); > Inserts data into a table
  • 60. BATCH INSERT query.from( "users" ).insert( [ { "username" = "johndoe", "email" = "john@example.com", "password" = bcryptedPassword }, { "username" = "janedoe", "email" = "jane@example.com", "password" = bcryptedPassword } ] ); > Uses the database-specific batch insert syntax
  • 61. UPDATE query.from( "users" ) .whereId( rc.id ) .update( { "password" = newPassword } ); > Updates all matched rows, so be careful > Works off of the built query
  • 62. UPDATEORINSERT query.from( "users" ) .whereId( rc.id ) .updateOrInsert( { "username" = "johndoe", "email" = "john@example.com", "password" = bcryptedPassword } ); > Updates or inserts dependening on if the query exists
  • 63. DELETE query.from( "users" ) .whereConfirmed( 0 ) .delete(); > Deletes all matched rows, so be careful > Works off of the built query
  • 66. QueryFilters EXAMPLE // AbstractQueryFilters.cfc component { property name="query"; function apply( required query, rc = {} ) { variables.query = arguments.query; for ( var key in rc ) { if ( variables.keyExists( key ) && isCustomFunction( variables[ key ] ) ) { var func = variables[ key ]; func( rc[ key ] ); } } return variables.query; } }
  • 67. QueryFilters EXAMPLE // EntryFilters.cfc component extends="AbstractQueryFilters" { function slug( slug ) { query.where( "slug", "like", "%#slug#%" ); } function createdBy( authorName ) { query.where( "createdBy", createdBy ); } function popular() { query.addSelect( query.raw( "COUNT(*) AS installCount" ) ) .join( "installs", "entries.id", "installs.entryId" ) .groupBy( [ "entries.id", "slug", "createdBy", "updatedDate" ] ) .orderBy( "installCount", "desc" ); } }
  • 68. QueryFilters EXAMPLE // handlers/Entries.cfc component { property name="EntryFilters" inject="id"; function index(event, rc, prc) { var query = getInstance( "Builder@qb" ); query.select( [ "entries.id", "slug", "createdBy", "updatedDate" ] ) .from( "entries" ) .orderBy( "updatedDate", "desc" ); EntryFilters.apply( query, rc ); prc.entries = query.get(); } }
  • 69. SEE?
  • 70. I TOLD YOU WE'D MAKE THAT EVEN BETTER!
  • 71. DEMO!
  • 75.
  • 76. WHO KNOWS WHAT YOU WILL CREATE WITH THIS?
  • 77. THANKS! > qb docs > qb on ForgeBox > me on Twitter (_elpete) > me on ForgeBox (elpete)) > CFML Slack (elpete)