'expr' => [],
'suffix' => NULL,
];
- if ($param['expr'] && isset($prefix) || in_array('', $param['prefix']) || !$param['optional']) {
- $this->args[$idx]['expr'] = $this->captureExpressions($arg, $param['expr'], $param['must_be'], $param['cant_be']);
+ if ($param['max_expr'] && isset($prefix) || in_array('', $param['prefix']) || !$param['optional']) {
+ $exprs = $this->captureExpressions($arg, $param['must_be'], $param['cant_be']);
+ if (count($exprs) < $param['min_expr'] || count($exprs) > $param['max_expr']) {
+ throw new \API_Exception('Incorrect number of arguments for SQL function ' . static::getName());
+ }
+ $this->args[$idx]['expr'] = $exprs;
$this->args[$idx]['suffix'] = $this->captureKeyword($param['suffix'], $arg);
}
}
* Shifts 0 or more expressions off the argument string and returns them
*
* @param string $arg
- * @param int $limit
* @param array $mustBe
* @param array $cantBe
* @return array
* @throws \API_Exception
*/
- private function captureExpressions(&$arg, $limit, $mustBe, $cantBe) {
+ private function captureExpressions(&$arg, $mustBe, $cantBe) {
$captured = [];
$arg = ltrim($arg);
while ($arg) {
$this->fields = array_merge($this->fields, $expr->getFields());
$captured[] = $expr;
// Keep going if we have a comma indicating another expression follows
- if (count($captured) < $limit && substr($arg, 0, 1) === ',') {
+ if (substr($arg, 0, 1) === ',') {
$arg = ltrim(substr($arg, 1));
}
else {
// Merge in defaults to ensure each param has these properties
$params[] = $param + [
'prefix' => [],
- 'expr' => 1,
+ 'min_expr' => 1,
+ 'max_expr' => 1,
'suffix' => [],
'optional' => FALSE,
'must_be' => [],
protected static $params = [
[
- 'expr' => 1,
'optional' => FALSE,
'must_be' => ['SqlField', 'SqlNumber'],
],
protected static $params = [
[
'prefix' => ['', 'DISTINCT', 'ALL'],
- 'expr' => 1,
'must_be' => ['SqlField'],
],
];
protected static $params = [
[
- 'expr' => 99,
+ 'max_expr' => 99,
'optional' => FALSE,
],
];
protected static $params = [
[
- 'expr' => 99,
+ 'max_expr' => 99,
'optional' => FALSE,
'must_be' => ['SqlField', 'SqlString'],
],
protected static $params = [
[
'prefix' => ['', 'DISTINCT', 'ALL'],
- 'expr' => 1,
+ 'max_expr' => 1,
'must_be' => ['SqlField', 'SqlWild'],
'cant_be' => [],
],
protected static $params = [
[
- 'expr' => 99,
+ 'max_expr' => 99,
'optional' => FALSE,
],
];
protected static $params = [
[
'prefix' => ['', 'DISTINCT', 'ALL'],
- 'expr' => 1,
+ 'max_expr' => 1,
'must_be' => ['SqlField', 'sqlFunction'],
'optional' => FALSE,
],
[
'prefix' => ['ORDER BY'],
- 'expr' => 1,
+ 'max_expr' => 1,
'suffix' => ['', 'ASC', 'DESC'],
'must_be' => ['SqlField'],
'optional' => TRUE,
],
[
'prefix' => ['SEPARATOR'],
- 'expr' => 1,
+ 'max_expr' => 1,
'must_be' => ['SqlString'],
'optional' => TRUE,
// @see self::formatOutput()
protected static $params = [
[
- 'expr' => 3,
+ 'min_expr' => 3,
+ 'max_expr' => 3,
'optional' => FALSE,
],
];
protected static $params = [
[
- 'expr' => 1,
'optional' => FALSE,
],
];
protected static $params = [
[
- 'expr' => 99,
+ 'max_expr' => 99,
'optional' => FALSE,
],
];
protected static $params = [
[
- 'expr' => 1,
'optional' => FALSE,
'must_be' => ['SqlField', 'SqlString'],
],
protected static $params = [
[
'prefix' => ['', 'DISTINCT', 'ALL'],
- 'expr' => 1,
'must_be' => ['SqlField'],
],
];
protected static $params = [
[
'prefix' => ['', 'DISTINCT', 'ALL'],
- 'expr' => 1,
'must_be' => ['SqlField'],
],
];
protected static $params = [
[
- 'expr' => 2,
+ 'min_expr' => 2,
+ 'max_expr' => 2,
'optional' => FALSE,
],
];
protected static $params = [
[
- 'expr' => 1,
'optional' => FALSE,
'must_be' => ['SqlField', 'SqlString'],
],
[
- 'expr' => 1,
'optional' => FALSE,
'must_be' => ['SqlField', 'SqlString'],
],
[
- 'expr' => 1,
'optional' => FALSE,
'must_be' => ['SqlField', 'SqlString'],
],
protected static $params = [
[
- 'expr' => 1,
'optional' => FALSE,
'must_be' => ['SqlField', 'SqlNumber'],
],
[
- 'expr' => 1,
'optional' => TRUE,
'must_be' => ['SqlNumber'],
],
protected static $params = [
[
'prefix' => ['', 'DISTINCT', 'ALL'],
- 'expr' => 1,
'must_be' => ['SqlField'],
],
];
protected static $params = [
[
- 'expr' => 1,
'optional' => FALSE,
'must_be' => ['SqlField', 'SqlString'],
],
$this->assertArrayHasKey('SUM', $functions);
$this->assertArrayNotHasKey('', $functions);
$this->assertArrayNotHasKey('SqlFunction', $functions);
- $this->assertEquals(1, $functions['MAX']['params'][0]['expr']);
+ $this->assertEquals(1, $functions['MAX']['params'][0]['min_expr']);
+ $this->assertEquals(1, $functions['MAX']['params'][0]['max_expr']);
}
public function testGroupAggregates() {
$this->assertEquals(FALSE, $result[$aids[2]]['duration_isnull']);
}
+ public function testIncorrectNumberOfArguments() {
+ try {
+ Activity::get(FALSE)
+ ->addSelect('IF(is_deleted) AS whoops')
+ ->execute();
+ $this->fail('Api should have thrown exception');
+ }
+ catch (\API_Exception $e) {
+ $this->assertEquals('Incorrect number of arguments for SQL function IF', $e->getMessage());
+ }
+
+ try {
+ Activity::get(FALSE)
+ ->addSelect('NULLIF(is_deleted, 1, 2) AS whoops')
+ ->execute();
+ $this->fail('Api should have thrown exception');
+ }
+ catch (\API_Exception $e) {
+ $this->assertEquals('Incorrect number of arguments for SQL function NULLIF', $e->getMessage());
+ }
+ }
+
}