reactphp-dbal icon indicating copy to clipboard operation
reactphp-dbal copied to clipboard

Last inserted ID

Open bartvanhoutte opened this issue 5 years ago • 11 comments

How do you get the last inserted ID (auto increment) after inserting something into the DB?

bartvanhoutte avatar Apr 03 '20 13:04 bartvanhoutte

We should check how all implementations return this value and return a structure. Good point.

mmoreram avatar Apr 03 '20 21:04 mmoreram

In clue/reactphp-sqlite you can get the last inserted ID through $result->insertId in the resulting promise. I suggest to add a getLastInsertedId method to Result?

bartvanhoutte avatar Apr 04 '20 09:04 bartvanhoutte

@bartvanhoutte thanks for the response! I've implemented it on mysql and sqlite, but the problem we have is Postgresql. AFAIK, postgres has some specific behavior on this, so I need to check a bit more how to do it. Any clues?

-> Temporary PR - https://github.com/driftphp/reactphp-dbal/pull/16

mmoreram avatar Apr 04 '20 14:04 mmoreram

@mmoreram I've just tested #16 with SQLite and it works, so looks good to me. I'm afraid I can't help you with pgsql.

Small question on the side. I see $connection->update does not return a Result but $result->fetchAllRows() instead. Is there any reason for this? This seems to be null when updating a record using SQLite.

bartvanhoutte avatar Apr 06 '20 08:04 bartvanhoutte

@bartvanhoutte yes, you're right. We should change this behavior.

mmoreram avatar Apr 06 '20 08:04 mmoreram

https://stackoverflow.com/a/2944481/2159370 there is an answer for postgresql here. Let me know if I can help with anything.

developernaren avatar Apr 06 '20 14:04 developernaren

/**
     * @param string $table
     * @param array  $values
     *
     * @return PromiseInterface
     */
    public function insert(
        string $table,
        array $values
    ): PromiseInterface {

        $queryBuilder = $this
            ->createQueryBuilder()
            ->insert($table)
            ->values(array_combine(
                array_keys($values),
                array_fill(0, count($values), '?')
            ))
            ->setParameters(array_values($values));


        if($this->driver instanceof PostgreSQLDriver) {
            return $this->queryBySQL($queryBuilder->getSQL() . ' RETURNING id', $queryBuilder->getParameters());
        }

        return $this->query($queryBuilder);
    }

I tried this and this is returning correct result for insertId, I get an array with index id with correct inserted value.

developernaren avatar Apr 06 '20 15:04 developernaren

 /**
     * @param string $table
     * @param array  $values
     *
     * @return PromiseInterface
     */
    public function insert(
        string $table,
        array $values
    ): PromiseInterface {

        $queryBuilder = $this
            ->createQueryBuilder()
            ->insert($table)
            ->values(array_combine(
                array_keys($values),
                array_fill(0, count($values), '?')
            ))
            ->setParameters(array_values($values));

        if($this->driver instanceof PostgreSQLDriver) {
            $query = sprintf("SELECT COLUMN_NAME FROM information_schema.COLUMNS WHERE TABLE_NAME = '%s'", $table);
            return $this->queryBySQL($query)->then(function (Result $response) use($queryBuilder){
                $allRows = $response->fetchAllRows();
                $fields = array_map(function ($item){
                    return $item['column_name'];
                }, $allRows);

                return $this->queryBySQL($queryBuilder->getSQL() . ' RETURNING ' . implode(',', $fields), $queryBuilder->getParameters());
            });
        }

        return $this->query($queryBuilder);
    }

this seems to work perfectly, fetches the column as well.

developernaren avatar Apr 07 '20 11:04 developernaren

Any news to merge? Seems working fine?

alexmorbo avatar Jun 13 '20 14:06 alexmorbo

@alexmorbo I added some extra changes on the PR - https://github.com/driftphp/reactphp-dbal/pull/19

TBH, the PostgreSQL last id implementation is not the best one, but right now, is the one I see. If you want to review it, that would be great :)

mmoreram avatar Jun 18 '20 19:06 mmoreram

Is this issue not resolved already?

marinhekman avatar Nov 23 '22 14:11 marinhekman