teamtnt / laravel-scout-tntsearch-driver

Driver for Laravel Scout search package based on https://github.com/teamtnt/tntsearch
MIT License
1.1k stars 144 forks source link

SQLSTATE[HY000]: General error: 21 library routine called out of sequence #127

Closed jjag3r closed 6 years ago

jjag3r commented 6 years ago

I receive SQLSTATE[HY000]: General error: 21 library routine called out of sequence when reindexing models. This happens in TNTIndexer.php in saveWordList($stems) function. Anyone has any idea how to fix this?

mikebronner commented 6 years ago

I started receiving this today as well with one particular model. Any solution to this? This happens even when trying to save an empty model with no data, so I don't think it would be anything data-related.

nticaric commented 6 years ago

This might be a problem due to concurrency. Are you guys using a queue worker in the background that might be accessing the index?

mikebronner commented 6 years ago

@nticaric Not on my end. This would be a concurrency issue with the index database, right? This error ocurrs when doing a single save:

$order = new Order;
$order->save();

That's all it takes to trigger this issue. and my model looks like this:

<?php namespace App;

use App\Membership;
use App\User;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class Order extends BaseSearchableModel
{
    protected $fillable = [
        'amount_paid',
        'amount_uncollectable',
        'city',
        'comments',
        'country',
        'email',
        'first_name',
        'invoice_total',
        'item_total',
        'last_name',
        'module',
        'notes',
        'number',
        'organization',
        'payment_method',
        'paypal_code',
        'phone',
        'postal_code',
        'shipping_total',
        'state',
        'status',
        'street_address_1',
        'street_address_2',
        'transaction_type',
    ];

    public function createdBy() : BelongsTo
    {
        return $this->belongsTo(User::class, 'governor_created_by');
    }

    public function orderedBy() : BelongsTo
    {
        return $this->belongsTo(User::class, 'ordered_by');
    }

    public function membership() : BelongsTo
    {
        return $this->belongsTo(Membership::class);
    }

    public function toSearchableArray()
    {
        $data = $this->toArray();
        unset($data['created_by']);
        unset($data['ordered_by']);
        unset($data['membership']);

        return $data;
    }
}

BaseSearchableModel:

<?php namespace App;

use Laravel\Scout\Searchable;

class BaseSearchableModel extends BaseModel
{
    use Searchable;
}

BaseModel:

<?php namespace App;

use Illuminate\Database\Eloquent\Model;
use App\NullCarbon;

abstract class BaseModel extends Model
{
    public function getAttributeValue($key)
    {
        $value = parent::getAttributeValue($key);

        if (in_array($key, $this->getDates())
            && is_null($value)
        ) {
            return new NullCarbon;
        }

        return $value;
    }
}
nticaric commented 6 years ago

Which PHP version do you use?

mikebronner commented 6 years ago

PHP 7.2.0-1

Investigating @jjag3r's suggestion of the point of failure, I find the following between lines 444 and 447 in TNTIndex.php:

                $insertStmt->bindParam(":keyword", $key);
                $insertStmt->bindParam(":hits", $term['hits']);
                $insertStmt->bindParam(":docs", $term['docs']);
                $insertStmt->execute();

Dumping the content out (dd($insertStmt, $key, $term['hits'], $term['docs']);) shows the following data is being passed:

PDOStatement {#2710 ▼
  +queryString: "INSERT INTO wordlist (term, num_hits, num_docs) VALUES (:keyword, :hits, :docs)"
}
"membership"
"1"
"1"

There doesn't appear to be any issue there, that i can tell, from the data?

If I comment out the execute() line, the error goes away. (Obviously that breaks the indexing process, but it highlights the point of failure.)

mikebronner commented 6 years ago

Update I reverted this site back to PHP 7.1 and the error went away. Any suggestions on how to fix this in PHP 7.2? Thanks!

nticaric commented 6 years ago

Ok, it seems like the prepared statement is causing this. Googling the error it seems we need to call sqlite3_step(), but not sure how to do this using PDO

nticaric commented 6 years ago

Can you test

->execute()->finalize(); since I don't have php 7.2 installed

mikebronner commented 6 years ago

I changed line 447 to read $insertStmt->execute()->finalize(); but it still fails with

SQLSTATE[HY000]: General error: 21 library routine called out of sequence

I have no experience in sqlite PDO statements, but will be happy to try things out for you if you have more suggestions.

jjag3r commented 6 years ago

When I dd() query, the actual error is: PDOStatement {#2006 +queryString: "UPDATE wordlist SET num_docs = num_docs + :docs, num_hits = num_hits + :hits WHERE term = :keyword" errorInfo: array:3 [ 0 => "00000" 1 => 19 2 => "UNIQUE constraint failed: wordlist.term" ] }

nticaric commented 6 years ago

I found the change in sqlite3.c that broke it in version 7.2

https://github.com/php/php-src/commit/88d1a2c5aab441fd322683f8d21667932aeec636

But not sure what to do about it

nticaric commented 6 years ago

Can you try v3.0.6, hopefully it should be fixed

mikebronner commented 6 years ago

@nticaric Thanks! Will give it a shot in the morning :)

mikebronner commented 6 years ago

nticaric Unfortunately still erroring:

Error while saving wordlist: SQLSTATE[HY000]: General error: 21 library routine called out of sequence

That's using tntsearch 1.3.0 and laravel-scout-tntsearch-driver 3.0.6.

jjag3r commented 6 years ago

The error still persists on my side :/

victorpierredev commented 6 years ago

Any update on this issue? I'm still having the same problem. Thank you!

jjag3r commented 6 years ago

This has been fixed since last release.