Icinga / Icinga/ipl-sql

Filter expressions

Open
#30 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement
Dominant language
PHP
Stars
4
Forks
2
PR merge metrics
No merged PRs in 30d

Description

With 8ce7d5c, 12a46ca and 0a68c04 I've added classes that resemble specific SQL where expressions. But these are currently implemented in a way they play fine with other code handling filters. (e.g. ipl\Orm\Compat\FilterProcessor) This leads to unnecessary cases like this and of course bogus interface implementations. (All of them have either no value or no column)

What I'd like to see is a more generic filter object that can handle all of these cases (plus more) and plays fine with other code handling filter objects. Heck, it should even be possible to still make use of things like RewriteFilter objects so that the columns and values of a expression are processed.

My first concept of this object looks like this:

namespace ipl\Sql\Filter;

use ipl\Sql\ExpressionInterface;
use ipl\Stdlib\Filter;

class Expression implements ExpressionInterface, Filter\Rule
{
    protected $statement;

    protected $columns;

    public function __construct($statement, array $columns)
    {
        $this->statement = $statement;
        $this->columns = $columns;
    }

    public function getStatement()
    {
        return sprintf($this->statement, ...$this->getColumns());
    }

    public function getColumns()
    {
        return array_keys($this->columns);
    }

    public function setColumns(array $columns)
    {
        $this->columns = $columns;

        return $this;
    }

    public function getValues()
    {
        return array_values($this->columns);
    }
}

Usage would look this way:

use ipl\Sql\Filter\Expression;

// ipl\Sql\Select objects would need to be handled just like columns, because objects can't be keys.....
$exists = new Expression('EXISTS(%s)', [ipl\Sql\Select]);
$notExists = new Expression('NOT EXISTS(%s)', [ipl\Sql\Select]);

// Values are processed just as usual, columns will be inserted into the statement by the object itself.
// Separating them anyway allows pre-processing to happen.
$isNull = new Expression('%s IS NULL', ['id' => null]);
$case = new Expression('CASE WHEN %s = ? OR %s = ? THEN 1 ELSE 0 END', ['name' => 'foo', 'name' => 'bar']);

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with ipl\Orm\Compat\FilterProcessor and the existing filter and expression interfaces referenced in the issue. Compare the proposed ipl\Sql\Filter\Expression examples with how columns, values, and RewriteFilter objects are processed. Done means a generic filter object supports the described expression cases without special-case handling or bogus interface implementations.

Written by the indexing model from the issue text.

Assessment

Tech stack
php
Domain
database
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.