Documentation

CRM_Utils_SQL_Select extends CRM_Utils_SQL_BaseParamQuery
in package

Object-oriented SQL builder for SELECT queries.

This class is foundational to CiviCRM's query functionality for the API, SearchKit, ScheduledReminders, MailingRecipients, etc.

Usage:

$select = CRM_Utils_SQL_Select::from('civicrm_activity act')
    ->join('absence', 'inner join civicrm_activity absence on absence.id = act.source_record_id')
    ->where('activity_type_id = #type', array('type' => 234))
    ->where('status_id IN (#statuses)', array('statuses' => array(1,2,3))
    ->where('subject like @subj', array('subj' => '%hello%'))
    ->where('!dynamicColumn = 1', array('dynamicColumn' => 'coalesce(is_active,0)'))
    ->where('!column = @value', array(
       'column' => $customField->column_name,
       'value' => $form['foo']
     ))
echo $select->toSQL();

Design principles:

  • Portable
    • No knowledge of the underlying SQL API (except for escaping -- CRM_Core_DAO::escapeString)
    • No knowledge of the underlying data model
  • SQL clauses correspond to PHP functions ($select->where("foo_id=123"))
  • Variable escaping is concise and controllable based on prefixes, eg
    • similar to Drupal's t()
    • use "@varname" to insert the escaped value
    • use "!varname" to insert raw (unescaped) values
    • use "#varname" to insert a numerical value (these are validated but not escaped)
    • to disable any preprocessing, simply omit the variable list
    • control characters (@!#) are mandatory in expressions but optional in arg-keys
  • Variables may be individual values or arrays; arrays are imploded with commas
  • Conditionals are AND'd; if you need OR's, do it yourself
  • Use classes/functions with documentation (rather than undocumented array-trees)
  • For any given string, interpolation is only performed once. After an interpolation, a string may never again be subjected to interpolation.

The "interpolate-once" principle can be enforced by either interpolating on input xor output. The notations for input and output interpolation are a bit different, and they may not be mixed.

// Interpolate on input. Set params when using them.
$select->where('activity_type_id = #type', array(
  'type' => 234,
));

// Interpolate on output. Set params independently.
$select
    ->where('activity_type_id = #type')
    ->param('type', 234),
Tags
copyright

CiviCRM LLC https://civicrm.org/licensing

Table of Contents

Constants

INTERPOLATE_AUTO  = 'auto'
Determine mode automatically. When the first attempt is made to use input-interpolation (eg `where(..., array(...))`) or output-interpolation (eg `param(...)`), the mode will be set. Subsequent calls will be validated using the same mode.
INTERPOLATE_INPUT  = 'in'
Interpolate values as soon as they are passed in (where(), join(), etc).
INTERPOLATE_OUTPUT  = 'out'
Interpolate values when rendering SQL output (toSQL()).

Properties

$strict  : bool
Public to work-around PHP 5.3 limit.
$allowLiterals  : mixed
$mode  : mixed
$params  : array<string|int, mixed>
$distinct  : mixed
$from  : mixed
$groupBys  : mixed
$havings  : mixed
$insertInto  : mixed
$insertIntoFields  : mixed
$insertVerb  : mixed
$joins  : mixed
$limit  : mixed
$offset  : mixed
$onDuplicates  : mixed
$orderBys  : mixed
$selects  : mixed
$setAlias  : mixed
$setOps  : mixed
$wheres  : mixed

Methods

__construct()  : mixed
Create a new SELECT query.
allowLiterals()  : mixed
copy()  : CRM_Utils_SQL_Select
Make a new copy of this query.
distinct()  : CRM_Utils_SQL_Select
Return only distinct values
escapeString()  : string
execute()  : CRM_Core_DAO
Execute the query.
fragment()  : CRM_Utils_SQL_Select
Create a partial SELECT query.
from()  : CRM_Utils_SQL_Select
Create a new SELECT query.
fromSet()  : CRM_Utils_SQL_Select
Create a new SELECT-like query by performing set-operations (e.g. UNION).
getFrom()  : string
getWhere()  : array<string|int, mixed>
groupBy()  : CRM_Utils_SQL_Select
Group results by adding extra items to the GROUP BY clause.
having()  : CRM_Utils_SQL_Select
Limit results by adding extra condition(s) to the HAVING clause
insertIgnoreInto()  : CRM_Utils_SQL_Select
Wrapper function of insertInto fn but sets insertVerb = "INSERT IGNORE INTO "
insertInto()  : CRM_Utils_SQL_Select
Insert the results of the SELECT query into another table.
insertIntoField()  : CRM_Utils_SQL_Select
interpolate()  : string
Given a string like "field_name = @value", replace "@value" with an escaped SQL string
isEmpty()  : bool
join()  : CRM_Utils_SQL_Select
Add a new JOIN clause.
limit()  : CRM_Utils_SQL_Select
Set a limit on the number of records to return.
merge()  : CRM_Utils_SQL_Select
Merge something or other.
offsetExists()  : bool
Has an offset been set.
offsetGet()  : mixed
Get the value of a SQL parameter.
offsetSet()  : void
Set the value of a SQL parameter.
offsetUnset()  : void
Unset the value of a SQL parameter.
onDuplicate()  : CRM_Utils_SQL_Select
For INSERT INTO...SELECT...' queries, you may give an "ON DUPLICATE UPDATE" clause.
orderBy()  : CRM_Utils_SQL_Select
Sort results by adding extra items to the ORDER BY clause.
param()  : CRM_Utils_SQL_Select
Set one (or multiple) parameters to interpolate into the query.
replaceInto()  : mixed
Wrapper function of insertInto fn but sets insertVerb = "REPLACE INTO "
select()  : CRM_Utils_SQL_Select
Specify the column(s)/value(s) to return by adding to the SELECT clause
setOp()  : $this
Add a set operation.
strict()  : self
Enable (or disable) strict mode.
syncInto()  : $this
Take the results of the SELECT query and copy them into another table.
toSQL()  : string
union()  : $this
Add a union to the list of set operations.
where()  : CRM_Utils_SQL_Select
Limit results by adding extra condition(s) to the WHERE clause

Constants

INTERPOLATE_AUTO

Determine mode automatically. When the first attempt is made to use input-interpolation (eg `where(..., array(...))`) or output-interpolation (eg `param(...)`), the mode will be set. Subsequent calls will be validated using the same mode.

public mixed INTERPOLATE_AUTO = 'auto'

INTERPOLATE_INPUT

Interpolate values as soon as they are passed in (where(), join(), etc).

public mixed INTERPOLATE_INPUT = 'in'

Default.

Pro: Every clause has its own unique namespace for parameters. Con: Probably slower. Advice: Use this when aggregating SQL fragments from agents who maintained by different parties.

INTERPOLATE_OUTPUT

Interpolate values when rendering SQL output (toSQL()).

public mixed INTERPOLATE_OUTPUT = 'out'

Pro: Probably faster. Con: Must maintain an aggregated list of all parameters. Advice: Use this when you have control over the entire query.

Properties

$strict

Public to work-around PHP 5.3 limit.

public bool $strict = \NULL

$distinct

private mixed $distinct = \NULL

$groupBys

private mixed $groupBys = []

$havings

private mixed $havings = []

$insertInto

private mixed $insertInto = \NULL

$insertIntoFields

private mixed $insertIntoFields = []

$insertVerb

private mixed $insertVerb = 'INSERT INTO '

$joins

private mixed $joins = []

$limit

private mixed $limit = \NULL

$offset

private mixed $offset = \NULL

$onDuplicates

private mixed $onDuplicates = []

$orderBys

private mixed $orderBys = []

$selects

private mixed $selects = []

$setAlias

private mixed $setAlias

$wheres

private mixed $wheres = []

Methods

__construct()

Create a new SELECT query.

public __construct(string $from[, array<string|int, mixed> $options = [] ]) : mixed
Parameters
$from : string

Table-name and optional alias.

$options : array<string|int, mixed> = []

allowLiterals()

public allowLiterals([bool $allowLiterals = TRUE ]) : mixed
Parameters
$allowLiterals : bool = TRUE

escapeString()

public escapeString(string|null $value) : string
Parameters
$value : string|null
Return values
string

SQL expression, e.g. "it's great" (with-quotes) or NULL (without-quotes)

execute()

Execute the query.

public execute([string|null $daoName = NULL ][, bool $i18nRewrite = TRUE ]) : CRM_Core_DAO

To examine the results, use a function like fetch(), fetchAll(), fetchValue(), or fetchMap().

Parameters
$daoName : string|null = NULL

The return object should be an instance of this class. Ex: 'CRM_Contact_BAO_Contact'.

$i18nRewrite : bool = TRUE

If the system has multilingual features, should the field/table names be rewritten?

Tags
see
CRM_Core_DAO::executeQuery
see
CRM_Core_I18n_Schema::rewriteQuery
Return values
CRM_Core_DAO

from()

Create a new SELECT query.

public static from(string $from[, array<string|int, mixed> $options = [] ]) : CRM_Utils_SQL_Select
Parameters
$from : string

Table-name and optional alias.

$options : array<string|int, mixed> = []
Return values
CRM_Utils_SQL_Select

fromSet()

Create a new SELECT-like query by performing set-operations (e.g. UNION).

public static fromSet([array<string|int, mixed> $options = [] ]) : CRM_Utils_SQL_Select

For example, if you want to query two tables and treat the results as one combined-set, then this is s a set-operation.

$queryA = CRM_Utils_SQL_Select::from('table_a'); $queryB = CRM_Utils_SQL_Select::from('table_b'); $querySet = CRM_Utils_SQL_Select::fromSet()->union('DISTINCT', [$queryA, $queryB])->toSQL();

Parameters
$options : array<string|int, mixed> = []

Ex: ['setAlias' => 'uniondata']

Return values
CRM_Utils_SQL_Select

getFrom()

public getFrom() : string
Return values
string

getWhere()

public getWhere() : array<string|int, mixed>
Return values
array<string|int, mixed>

groupBy()

Group results by adding extra items to the GROUP BY clause.

public groupBy(string|array<string|int, mixed> $exprs[, null|array<string|int, mixed> $args = NULL ]) : CRM_Utils_SQL_Select
Parameters
$exprs : string|array<string|int, mixed>

list of SQL expressions

$args : null|array<string|int, mixed> = NULL

use NULL to disable interpolation; use an array of variables to enable

Return values
CRM_Utils_SQL_Select

having()

Limit results by adding extra condition(s) to the HAVING clause

public having(string|array<string|int, mixed> $exprs[, null|array<string|int, mixed> $args = NULL ]) : CRM_Utils_SQL_Select
Parameters
$exprs : string|array<string|int, mixed>

list of SQL expressions

$args : null|array<string|int, mixed> = NULL

use NULL to disable interpolation; use an array of variables to enable

Return values
CRM_Utils_SQL_Select

insertIgnoreInto()

Wrapper function of insertInto fn but sets insertVerb = "INSERT IGNORE INTO "

public insertIgnoreInto(string $table[, array<string|int, mixed> $fields = [] ]) : CRM_Utils_SQL_Select
Parameters
$table : string

The name of the other table (which receives new data).

$fields : array<string|int, mixed> = []

The fields to fill in the other table (in order).

Return values
CRM_Utils_SQL_Select

insertInto()

Insert the results of the SELECT query into another table.

public insertInto(string $table[, array<string|int, mixed> $fields = [] ]) : CRM_Utils_SQL_Select
Parameters
$table : string

The name of the other table (which receives new data).

$fields : array<string|int, mixed> = []

The fields to fill in the other table (in order).

Tags
see
insertIntoField
Return values
CRM_Utils_SQL_Select

interpolate()

Given a string like "field_name = @value", replace "@value" with an escaped SQL string

public interpolate(string $expr, null|array<string|int, mixed> $args[, string $activeMode = self::INTERPOLATE_INPUT ]) : string
Parameters
$expr : string

SQL expression

$args : null|array<string|int, mixed>

a list of values to insert into the SQL expression; keys are prefix-coded: prefix '@' => escape SQL prefix '#' => literal number, skip escaping but do validation prefix '!' => literal, skip escaping and validation if a value is an array, then it will be imploded

PHP NULL's will be treated as SQL NULL's. The PHP string "null" will be treated as a string.

$activeMode : string = self::INTERPOLATE_INPUT
Return values
string

isEmpty()

public isEmpty([array<string|int, mixed>|null $parts = NULL ]) : bool
Parameters
$parts : array<string|int, mixed>|null = NULL

List of fields to check (e.g. 'selects', 'joins'). Defaults to all.

Return values
bool

join()

Add a new JOIN clause.

public join(string|null $name, string|array<string|int, mixed> $exprs[, array<string|int, mixed>|null $args = NULL ]) : CRM_Utils_SQL_Select

Note: To add multiple JOINs at once, use $name===NULL and pass an array of $exprs.

Parameters
$name : string|null

The effective alias of the joined table.

$exprs : string|array<string|int, mixed>

The complete join expression (eg "INNER JOIN mytable myalias ON mytable.id = maintable.foo_id").

$args : array<string|int, mixed>|null = NULL
Return values
CRM_Utils_SQL_Select

offsetExists()

Has an offset been set.

public offsetExists(string $offset) : bool
Parameters
$offset : string
Return values
bool

offsetGet()

Get the value of a SQL parameter.

public offsetGet(string $offset) : mixed
  $select['cid'] = 123;
  $select->where('contact.id = #cid');
  echo $select['cid'];
Parameters
$offset : string
Tags
see
param()
see
ArrayAccess::offsetGet
Attributes
#[ReturnTypeWillChange]

offsetSet()

Set the value of a SQL parameter.

public offsetSet(string $offset, mixed $value) : void
  $select['cid'] = 123;
  $select->where('contact.id = #cid');
  echo $select['cid'];
Parameters
$offset : string
$value : mixed

The new value of the parameter. Values may be strings, ints, or arrays thereof -- provided that the SQL query uses appropriate prefix (e.g. "@", "!", "#").

Tags
see
param()
see
ArrayAccess::offsetSet

offsetUnset()

Unset the value of a SQL parameter.

public offsetUnset(string $offset) : void
Parameters
$offset : string
Tags
see
param()
see
ArrayAccess::offsetUnset

onDuplicate()

For INSERT INTO...SELECT...' queries, you may give an "ON DUPLICATE UPDATE" clause.

public onDuplicate(string|array<string|int, mixed> $exprs[, null|array<string|int, mixed> $args = NULL ]) : CRM_Utils_SQL_Select
Parameters
$exprs : string|array<string|int, mixed>

list of SQL expressions

$args : null|array<string|int, mixed> = NULL

use NULL to disable interpolation; use an array of variables to enable

Return values
CRM_Utils_SQL_Select

orderBy()

Sort results by adding extra items to the ORDER BY clause.

public orderBy(string|array<string|int, mixed> $exprs[, null|array<string|int, mixed> $args = NULL ][, int $weight = 0 ]) : CRM_Utils_SQL_Select
Parameters
$exprs : string|array<string|int, mixed>

list of SQL expressions

$args : null|array<string|int, mixed> = NULL

use NULL to disable interpolation; use an array of variables to enable

$weight : int = 0
Return values
CRM_Utils_SQL_Select

param()

Set one (or multiple) parameters to interpolate into the query.

public param(array<string|int, mixed>|string $keys[, null|mixed $value = NULL ]) : CRM_Utils_SQL_Select
Parameters
$keys : array<string|int, mixed>|string

Key name, or an array of key-value pairs.

$value : null|mixed = NULL

The new value of the parameter. Values may be strings, ints, or arrays thereof -- provided that the SQL query uses appropriate prefix (e.g. "@", "!", "#").

Return values
CRM_Utils_SQL_Select

replaceInto()

Wrapper function of insertInto fn but sets insertVerb = "REPLACE INTO "

public replaceInto(string $table[, array<string|int, mixed> $fields = [] ]) : mixed
Parameters
$table : string

The name of the other table (which receives new data).

$fields : array<string|int, mixed> = []

The fields to fill in the other table (in order).

select()

Specify the column(s)/value(s) to return by adding to the SELECT clause

public select(string|array<string|int, mixed> $exprs[, null|array<string|int, mixed> $args = NULL ]) : CRM_Utils_SQL_Select
Parameters
$exprs : string|array<string|int, mixed>

list of SQL expressions

$args : null|array<string|int, mixed> = NULL

use NULL to disable interpolation; use an array of variables to enable

Return values
CRM_Utils_SQL_Select

setOp()

Add a set operation.

public setOp(string $setOperation, array<string|int, CRM_Utils_SQL_Select>|CRM_Utils_SQL_Select $subQueries) : $this

Ex: CRM_Utils_SQL_Select::fromSet()->setOp('INTERSECT', [$subQuery1, $subQuery2])

Parameters
$setOperation : string

Ex: 'UNION DISTINCT', 'UNION ALL'. TODO: 'INTERSECT', 'EXCEPT' when moving to MySQL 8.

$subQueries : array<string|int, CRM_Utils_SQL_Select>|CRM_Utils_SQL_Select
Tags
see
https://dev.mysql.com/doc/refman/8.0/en/set-operations.html
Return values
$this

strict()

Enable (or disable) strict mode.

public strict([bool $strict = TRUE ]) : self

In strict mode, unknown variables will generate exceptions.

Parameters
$strict : bool = TRUE
Return values
self

syncInto()

Take the results of the SELECT query and copy them into another table.

public syncInto(string $table, array<string|int, mixed>|string $keys, array<string|int, mixed> $mapping[, null|array<string|int, mixed> $args = NULL ]) : $this

If the same record already exists in the other table (based on primary-key or unique-key), then update the corresponding record.

Parameters
$table : string

The table to write data into.

$keys : array<string|int, mixed>|string

List of PK/unique fields NOTE: This must match the unique-key that was declared in the schema.

$mapping : array<string|int, mixed>

List of values to select and where to send them.

For example, consider: ['relationship_id' => 'rel.id']

This would select the value of 'rel.id' and write to 'relationship_id'.

$args : null|array<string|int, mixed> = NULL

Use NULL to skip interpolation; use an array of variables to enable.

Return values
$this

toSQL()

public toSQL() : string
Return values
string

SQL statement

union()

Add a union to the list of set operations.

public union(string $type, array<string|int, CRM_Utils_SQL_Select>|CRM_Utils_SQL_Select $subQueries) : $this

Ex: CRM_Utils_SQL_Select::fromSet()->union([$subQuery1, $subQuery2]) Ex: CRM_Utils_SQL_Select::fromSet()->union($subQuery1)->union($subQuery2);

Parameters
$type : string

"DISTINCT"|"ALL"

$subQueries : array<string|int, CRM_Utils_SQL_Select>|CRM_Utils_SQL_Select
Return values
$this

where()

Limit results by adding extra condition(s) to the WHERE clause

public where(string|array<string|int, mixed> $exprs[, null|array<string|int, mixed> $args = NULL ]) : CRM_Utils_SQL_Select
Parameters
$exprs : string|array<string|int, mixed>

list of SQL expressions

$args : null|array<string|int, mixed> = NULL

use NULL to disable interpolation; use an array of variables to enable

Return values
CRM_Utils_SQL_Select

        
On this page

Search results