j4mie / idiorm

A lightweight nearly-zero-configuration object-relational mapper and fluent query builder for PHP5.

Home Page:http://j4mie.github.com/idiormandparis/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Raw update queries

Htarlov opened this issue · comments

I'm not sure if it should be posted as an issue or as a feature request. I have problem to use raw queries to send update query to the database. For example I need to change many rows at once with simple where condition.
It would be great if one could use it like that:

ORM::for_table('person')->raw_query('UPDATE worker SET income = :income WHERE job = :job',array('job' => $job, 'income' => $income))->save();

But save doesn't send it.
find_one / find_many runs that query, but with problems with null parameters (I had to set null and it set 0) and with PDO error at the end.

I think this feature will help those who need to update on many rows - without refactoring much in the library.

There is a simple modification that gives this possibility and works well for me.

One needs to add a method like that:

public function raw_merge() {
    if ($this->_is_raw_query) {
        self::_log_query($this->_raw_query, $this->_raw_parameters);
        $statement = self::$_db->prepare($this->_raw_query);
        if (is_array($this->_raw_parameters) && count($this->_raw_parameters) > 0)
            $success = $statement->execute($this->_raw_parameters);
        else
            $success = $statement->execute();
        return $success;
    }
}

I also add a factory method for instances used only to use raw update/delete/"custom" queries:

public static function raw_instance() {
    self::_setup_db();
    return new self(NULL);
}

Then I can use it like that (queries presented I thought out right now "from cosmos" - not very real ones but present possibilities that this change gives):

ORM::raw_instance()->raw_query('UPDATE worker SET income = :income WHERE job = :job',array('job' => $job, 'income' => $income))->raw_merge();

or like that:

ORM::raw_instance()->raw_query('UPDATE document SET md5 = MD5(text) WHERE group = ?',array($group))->raw_merge();

or:

ORM::raw_instance()->raw_query('DELETE FROM page WHERE NOT EXISTS (SELECT ID FROM page_group WHERE page_group.page_id = page.id) OR page.delete_me = 1')->raw_merge();

etc.

I thought of putting this code into save method but "save" on delete query doesnt sound well.
This could be improved so method would return FALSE on fail and number of changed rows on success. But I didn't have time nor need to put this improvement.

Thanks for this! Works perfectly for running a mass-update query (or any SQL for which you don't care about the result).

Great solution, but how to fix log?
ORM::for_table('apns_messages_recepients')->raw_query('UPDATE apns_messages_recepientsSETstatus= :status WHEREid = :id', array('id' => $error['MESSAGE']->getCustomIdentifier(), 'status'=> 'failed'))->raw_merge();

And in ORM::get_query_log() i see ``[5] => UPDATE apns_messages_recepients SET `status` = :status WHERE `id` = :id`

I am still not sure I see the advantage here of adding this complexity. Seems to me that using the PDO instance directly for these operations would work. I can't even really see any keystrokes being saved here. Is there something I am missing?

The following code is quite neat and tidy:

$pdo = ORM::get_db();
$raw_query = ''UPDATE document SET md5 = MD5(text) WHERE group = ?'';
$raw_parameters = array($group);
$statement = $pdo->prepare($raw_query);
$statement->execute($raw_parameters);

If this is to make it into Idiorm's core then it needs to become a whole lot more elegant in its implementation. So that you end up with something like:

ORM::raw_exec(
    'UPDATE document SET md5 = MD5(text) WHERE group = ?',
    array($group)
);

Then again maybe I am missing something that you guys are gaining by having ORM::raw_instance->raw_query->raw_merge. If I am then please do say otherwise please comment on the acceptability of the aforementioned raw_exec construct.

@treffynnon, I think you're correct about implementation, and put something together along those lines, complete with query logging and a (somewhat farcical) unit test.

tag/idiorm@13d291f

Closed in commit f6d7861