web-dev-qa-db-fra.com

Laravel: Erreur générale: 1615 L'instruction préparée doit être re-préparée

J'utilise la dernière version de laravel (5.1) dans une machine virtuelle Homestead (vagrant).

Je connecte mon projet à un serveur mariaDB local, dans lequel j'ai une table et 2 vues db.

Depuis que j'ai fait une sélection uniquement sur les tables db-view, je reçois au hasard cette erreur:

Erreur générale: 1615 L'instruction préparée doit être re-préparée

À partir d'aujourd'hui, j'obtiens toujours cette erreur lorsqu'elle est sélectionnée uniquement sur les vues db. Si j'ouvre mon phpMyAdmin et que je fais le même choix, il renvoie le résultat correct.

J'ai essayé d'ouvrir php artisan tinker et sélectionnez un enregistrement de la vue db mais il renvoie la même erreur:

// Select one user from user table
>>> $user = new App\User
=> <App\User #000000006dc32a890000000129f667d2> {}
>>> $user = App\User::find(1);
=> <App\User #000000006dc32a9e0000000129f667d2> {
       id: 1,
       name: "Luca",
       email: "[email protected]",
       customerId: 1,
       created_at: "2015-08-06 04:17:57",
       updated_at: "2015-08-11 12:39:01"
   }
>>> 
// Select one source from Source db-view
>>> $source = new App\Source
=> <App\Source #000000006dc32a820000000129f667d2> {}
>>> $source = App\Source::find(1);
Illuminate\Database\QueryException with message 'SQLSTATE[HY000]: General error: 1615 Prepared statement needs to be re-prepared (SQL: select * from `sources` where `sources`.`id` = 1 limit 1)'

Comment puis-je résoudre ce problème? J'ai lu un problème avec mysqldump (mais pas dans mon cas) et pour augmenter la valeur de table_definition_cache mais il n'est pas sûr que cela fonctionnera et je ne peux pas les modifier.

Est-ce une sorte de bogue laravel?

Comment puis-je comprendre cela?


Éditer:

Comme demandé, j'ajoute le code source de mon modèle. Source.php:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Source extends Model
{
    protected $table = 'sources';


    /*
    |--------------------------------------------------------------------------
    | FOREIGN KEYS
    |--------------------------------------------------------------------------
    */

    /**
     * 
     * @return [type] [description]
     */
    public function customersList(){
        return $this->hasMany("App\CustomerSource", "sourceId", "id");
    }


    /**
     * 
     * @return [type] [description]
     */
    public function issues(){
        return $this->hasMany("App\Issue", "sourceId", "id");
    }
}

Modifier 2:

Si j'exécute la même requête dans le projet avec mysqli cela fonctionne:

$db = new mysqli(getenv('DB_Host'), getenv('DB_USERNAME'), getenv('DB_PASSWORD'), getenv('DB_DATABASE'));
if($db->connect_errno > 0){
    dd('Unable to connect to database [' . $db->connect_error . ']');
}
$sql = "SELECT * FROM `sources` WHERE `id` = 4";
if(!$result = $db->query($sql)){
    dd('There was an error running the query [' . $db->error . ']');
}

dd($result->fetch_assoc());

EDIT 3: Après 2 mois, je suis toujours là. Même erreur et aucune solution trouvée. Je décide d'essayer une petite solution en bricolage aritsan mais pas de bonne nouvelle. Je rapporte ce que j'ai essayé:

Essayez d'abord de récupérer un modèle de table:

>>> $user = \App\User::find(1);
=> App\User {#697
     id: 1,
     name: "Luca",
     email: "[email protected]",
     customerId: 1,
     created_at: "2015-08-06 04:17:57",
     updated_at: "2015-10-27 11:28:14",
   }

Essayez maintenant de récupérer un modèle de table de vue:

>>> $ir = \App\ContentRepository::find(15);
Illuminate\Database\QueryException with message 'SQLSTATE[42S02]: Base table or view not found: 1146 Table 'dbname.content_repositories' doesn't exist (SQL: select * from `content_repositories` where `content_repositories`.`id` = 1 limit 1)'

Lorsque contentRepository n'a pas la configuration de nom de table correcte dans le modèle ContentRepository.php:

>>> $pdo = DB::connection()->getPdo();
=> PDO {#690
     inTransaction: false,
     errorInfo: [
       "00000",
       1146,
       "Table 'dbname.content_repositories' doesn't exist",
     ],
     attributes: [
       "CASE" => NATURAL,
       "ERRMODE" => EXCEPTION,
       "AUTOCOMMIT" => 1,
       "PERSISTENT" => false,
       "DRIVER_NAME" => "mysql",
       "SERVER_INFO" => "Uptime: 2513397  Threads: 12  Questions: 85115742  Slow queries: 6893568  Opens: 1596  Flush tables: 1  Open tables: 936  Queries per second avg: 33.864",
       "Oracle_NULLS" => NATURAL,
       "CLIENT_VERSION" => "mysqlnd 5.0.11-dev - 20120503 - $Id: id_here $",
       "SERVER_VERSION" => "5.5.5-10.0.17-MariaDB-1~wheezy-wsrep-log",
       "STATEMENT_CLASS" => [
         "PDOStatement",
       ],
       "EMULATE_PREPARES" => 0,
       "CONNECTION_STATUS" => "localiphere via TCP/IP",
       "DEFAULT_FETCH_MODE" => BOTH,
     ],
   }
>>> 

MODIFIER LA VALEUR DE LA TABLE À L'INTÉRIEUR du modèle ContentRepository.php:

>>> $ir = \App\ContentRepository::find(15);
Illuminate\Database\QueryException with message 'SQLSTATE[HY000]: General error: 1615 Prepared statement needs to be re-prepared (SQL: select * from `contentRepository` where `contentRepository`.`id` = 15 limit 1)'

Quand c'est correct, faites attention à "errorInfo" qui manque:

>>> $pdo = DB::connection()->getPdo();
=> PDO {#690
     inTransaction: false,
     attributes: [
       "CASE" => NATURAL,
       "ERRMODE" => EXCEPTION,
       "AUTOCOMMIT" => 1,
       "PERSISTENT" => false,
       "DRIVER_NAME" => "mysql",
       "SERVER_INFO" => "Uptime: 2589441  Threads: 13  Questions: 89348013  Slow queries: 7258017  Opens: 1604  Flush tables: 1  Open tables: 943  Queries per second avg: 34.504",
       "Oracle_NULLS" => NATURAL,
       "CLIENT_VERSION" => "mysqlnd 5.0.11-dev - 20120503 - $Id: id_here $",
       "SERVER_VERSION" => "5.5.5-10.0.17-MariaDB-1~wheezy-wsrep-log",
       "STATEMENT_CLASS" => [
         "PDOStatement",
       ],
       "EMULATE_PREPARES" => 0,
       "CONNECTION_STATUS" => "localIPhere via TCP/IP",
       "DEFAULT_FETCH_MODE" => BOTH,
     ],
   }

Afficher les tables de db:

>>> $tables = DB::select('SHOW TABLES');
=> [
     {#702
       +"Tables_in_dbname": "table_name_there",
     },
     {#683
       +"Tables_in_dbname": "table_name_there",
     },
     {#699
       +"Tables_in_dbname": "table_name_there",
     },
     {#701
       +"Tables_in_dbname": "table_name_there-20150917-1159",
     },
     {#704
       +"Tables_in_dbname": "contentRepository", */ VIEW TABLE IS THERE!!!! /*
     },
     {#707
       +"Tables_in_dbname": "table_name_there",
     },
     {#684
       +"Tables_in_dbname": "table_name_there",
     },
   ]

Essayez avec une sélection normale:

>>> $results = DB::select('select * from dbname.contentRepository limit 1');
Illuminate\Database\QueryException with message 'SQLSTATE[HY000]: General error: 1615 Prepared statement needs to be re-prepared (SQL: select * from dbname.contentRepository limit 1)'

Essayez une requête non préparée:

>>> DB::unprepared('select * from dbname.contentRepository limit 1')
=> false

Essayez une deuxième fois une requête non préparée:

>>> DB::unprepared('select * from dbname.contentRepository limit 1')
Illuminate\Database\QueryException with message 'SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other unbuffered queries are active.  Consider using PDOStatement::fetchAll().  Alternatively, if your code is only ever going to run against mysql, you may enable query buffering by setting the PDO::MYSQL_ATTR_USE_BUFFERED_QUERY attribute. (SQL: select * from dbname.contentRepository limit 1)'

Essayez PDOStatement :: fetchAll ():

>>> DB::fetchAll('select * from dbname.contentRepository limit 1'); 
PHP warning:  call_user_func_array() expects parameter 1 to be a valid callback, class 'Illuminate\Database\MySqlConnection' does not have a method 'fetchAll' in /Users/luca/company/Laravel/dbname/vendor/laravel/framework/src/Illuminate/Database/DatabaseManager.php on line 296

Essayez le deuxième PDOStatement :: fetchAll ():

>>> $pdo::fetchAll('select * from dbname.contentRepository limit 1');
  [Symfony\Component\Debug\Exception\FatalErrorException]  
  Call to undefined method PDO::fetchAll()           

Essayez la déclaration ...:

>>> $pdos = DB::statement('select * from dbname.contentRepository limit 1')
Illuminate\Database\QueryException with message 'SQLSTATE[HY000]: General error: 1615 Prepared statement needs to be re-prepared (SQL: select * from dbname.contentRepository limit 1)'

Je vous remercie

16
Tenaciousd93

Cela semble fonctionner en ajoutant

'options'   => [
                \PDO::ATTR_EMULATE_PREPARES => true
            ]

À l'intérieur projectName/config/database.php fichier dans la configuration DB. Ce sera comme ça:

'mysql' => [
    'driver'    => 'mysql',
    'Host'      => env('DB_Host', 'localhost'),
    'database'  => env('DB_DATABASE', 'forge'),
    'username'  => env('DB_USERNAME', 'forge'),
    'password'  => env('DB_PASSWORD', ''),
    'charset'   => 'utf8',
    'collation' => 'utf8_unicode_ci',
    'prefix'    => '',
    'strict'    => false,
    'options'   => [
        \PDO::ATTR_EMULATE_PREPARES => true
    ]
],

Laravel 5.1. J'espère que cela vous aidera!

40
Tenaciousd93

Selon les commentaires de la réponse acceptée, l'exécution

SET GLOBAL table_definition_cache = 1024

dans le MariaDB a résolu le problème.

https://mariadb.com/kb/en/library/server-system-variables/#table_definition_cache

7
TimoSolo

On dirait que c'est un MySQL Bug qui a été documenté.

Modifier:

Votre modèle utilise-t-il 'id' comme clé primaire? J'aime définir explicitement la clé primaire dans le modèle même si elle l'est.

protected $primaryKey = 'id'; // If different than id, definitely need to set the column here

Vous pouvez également essayer de commenter les fonctions hasMany() et réessayer. Parfois Laravel peut faire des choses étranges sur eagerLoad, surtout s'il y a BEAUCOUP d'enregistrements qu'il essaie de mapper.

0
Blake