Pimcore 3.1.1 ALTER TABLE BUG - alter-table

I installed Pimcore 3.1.1 and I have lot of issue with message like:
(
[message] => SQLSTATE[42000]: Syntax error or access violation: 1091 Can't DROP 'p_index_person__id'; check that column/key exists, query was: ALTER TABLE `object_store_3` DROP INDEX `p_index_person__id`;
[method] => query
[arguments] => Array
(
[0] => ALTER TABLE `object_store_3` DROP INDEX `p_index_person__id`;
)
)
(
[message] => SQLSTATE[42000]: Syntax error or access violation: 1091 Can't DROP 'p_index_person__type'; check that column/key exists, query was: ALTER TABLE `object_store_3` DROP INDEX `p_index_person__type`;
[method] => query
[arguments] => Array
(
[0] => ALTER TABLE `object_store_3` DROP INDEX `p_index_person__type`;
)
)
(
[message] => SQLSTATE[42000]: Syntax error or access violation: 1091 Can't DROP 'p_index_Options'; check that column/key exists, query was: ALTER TABLE `object_store_12` DROP INDEX `p_index_Options`;
[method] => query
[arguments] => Array
(
[0] => ALTER TABLE `object_store_12` DROP INDEX `p_index_Options`;
)
)
Same errors are reported in Pimcore forum at the bottom of the post.
Is there an issue about this ? Currently, I can't work with Pimcore. Every change in object structure corrupts the data.
Any advice ?
UPDATE #001 :
I have tried Johan's solutions :
First one
Backup your entire system
Export class defintions from within admin
Import class definitions from within admin, save class
Second
Export the class definitios from within admin
Remove files in website/var/classes
Import your class definitions again
I always have the same errors in log with alter table.
When I try to add an ObjectBricks to my object, I see this :
Thanks for your help.
Have a nice day.

you could try to
Backup your entire system
Export class defintions from within admin
Import class definitions from within admin, save class
If that does not do the trick then you could try to (be sure you did a backup Before and know your recover steps)
Export the class definitios from within admin
Remove files in website/var/classes
Import your class definitions again
/Johan

Related

"Syntax error or access violation: 1064" When changing column type from string to integer [LARAVEL MIGRATION]

In the down() function of my migration i have the following line:
$table->integer('placeholder')->change();
Here I try to change the column type 'number' from string(750 characters) to integer. Whenever I try to run this rollback, I get hit with:
SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax
This also happens when I try to change the column to something else (such as a boolean). Setting the amount of characters from 750 to 191, so: $table->string('placeholder',191)->change(); does work.
The table I'm working in currently does not contain any data & i'm using the utf8mb4 character-set
Are you sure your column name is number? It is a keyword in mysql and such column names cannot be used unless you quote it like `number`. It is not a good practice to use such keywords as a column name.
Perhaps in the current table you have filled in the column 'placeholder' that does not correspond to the new rules of this column.
Create a migration with new temporary column $ table-> string
('temp_placeholder', 191)
Write a seeder to transfer data from the 'placeholder' column to 'temp_placeholder', taking into account the new specified rules for the column.
Create a migration to delete the 'placeholder' column and rename the 'temp_placeholder' column to 'placeholder'

Laravel Drop Renamed index

I created an index with laravel index()
$table->index(['group_tasks_outline_agreement_uuid'], 'gt_oa_uuid');
I have been tried to drop this idex with dropIndex()
$table->dropIndex(['group_tasks_outline_agreement_uuid']);
or
$table->dropIndex(['gt_oa_uuid']);
it shows the error msg : Syntax error or access violation: 1091 Can't DROP INDEX hps_purchase_order_hps_purchase_order_uuid_index; check that it exists
It should be
$table->index(['group_tasks_outline_agreement_uuid'], 'group_tasks_outline_agreement_gt_oa_uuid_index');

Laravel test preserving records in SQLite while rolling back migrations?

I am working on a Laravel 5.2 app. I am trying to set up testing using an SQLite in-memory database.
I'm aware of the SQLite problems related to changing columns that are NOT NULL without specifying a default, (for example described in this question). An apparent workaround is to make the field first nullable, and then immediately undo that, in a separate transaction. So I've spent many hours going over all my migrations and doing things like:
Schema::table('customers', function (Blueprint $table) {
$table->string('first', 128)->after('id')->nullable();
});
Schema::table('customers', function (Blueprint $table) {
$table->string('first', 128)->after('id')->nullable(false)->change();
});
I'm also aware of the SQLite problem where you can't drop more than 1 column per transaction (eg described here). I spent many more hours updating my migrations to do that.
All migrations now successfully run and rollback without errors using SQLite and :memory:; they also run fine in MySQL.
So I added a test, using migrations. The first and only thing the test does is use a Factory to create a customer:
<?php
namespace Tests\Unit;
use TestCase;
use Illuminate\Foundation\Testing\DatabaseMigrations;
class PromoTest extends TestCase
{
use DatabaseMigrations;
/** #test */
public function dummy_test() {
factory('App\Customer')->create();
print_r(\DB::select('select * from customers'));
}
}
The output of the query right after creating the customer shows that it worked fine (fake data comes from Faker):
$ ./vendor/bin/phpunit --filter PromoTest
PHPUnit 4.8.24 by Sebastian Bergmann and contributors.
EArray
(
[0] => stdClass Object
(
[id] => 1
[email] => nRyan#example.net
[zipcode] => 47049-6020
[subscribe] => 0
[created_at] => 2017-08-25 15:47:28
[updated_at] => 2017-08-25 15:47:28
[first] => Syble
[last] => Hahn
[phone] => (761)073-7794x8624
[invalid_email] =>
)
)
But immediately after that output, the test crashes and throws the following error:
SQLSTATE[23000]: Integrity constraint violation: 19 NOT NULL constraint failed: customers.name (SQL: INSERT INTO customers (id, email, zipcode, subscribe, created_at, updated_at, name) SELECT id, email, zipcode, subscribe, created_at, updated_at, name FROM __temp__customers)
Notice the name field causing the problem does not appear in the created record above. The name field did exist in this table in the past, but not any more - I removed it (with a migration) and now use first and last. And clearly that migration worked, as the record created, inserted and dumped out above has the right, current fields.
So why is Laravel trying to insert records into an older version of the table, after it has already successfully created a record in the current one?
I am only guessing, but it looks like after the test is done, and the migrations are being rolled back, the data is being preserved and copied or re-inserted into each historical iteration of the schema? There's no way that can work though ... ?
Has anyone seen this? Is it expected or am I doing something wrong?
UPDATE The problem goes away if I simply switch to using MySQL for the tests. Looks like I'll have to do that for now, as I'm stumped. I'd much rather use SQLite in memory as it is faster.

Trapping constraint errors in Sequel ORM before the server

I have a Ruby/Padrino project using Sequel ORM to access a legacy database in MySQL. The problem I am having is that several of the tables have a user editable column that is also a Primary Key.
I am trying to set up Sequel to catch any duplication errors within the application itself before MySQL can throw an error. I assumed that the validation helpers in Sequel could help me do that, but it appears they do not kick in before the data is saved.
My SQL table is defined as:
CREATE TABLE `dblocations` (
`code` varchar(3) NOT NULL,
`description` varchar(100) NOT NULL,
PRIMARY KEY (`code`)
)
and my Sequel models are defined as follows:
class Location < Sequel::Model(:dblocations)
plugins :validation_helpers
def validate
super
validates_presence [:code, :description]
validates_unique :code
end
end
the problem is now, when I try the following code to insert Location Code 'ABC' into the database (when there is already another row in there with the Code 'ABC'), Ruby throws the following error:
Location.insert(:code => "ABC", :description => "Test Location")
ERROR - Mysql2::Error: Duplicate entry 'ABC' for key 'PRIMARY': INSERT INTO `dblocations` (`code`, `description`) VALUES ('ABC', 'Test Location')
Sequel::UniqueConstraintViolation: Mysql2::Error: Duplicate entry 'ABC' for key 'PRIMARY'
Have I misconfigured my validations or is there another plugin I need to invoke?
insert is a dataset-level method, validations are model level. You probably want to use create instead of insert.

Binding on `statement` not supported in Eloquent 5.1?

I'm new to Laravel and trying to do a string query in Eloquent. I was trying to use DB::statement, but I kept getting errors about placeholders in the query string. It seems I either don't have the syntax right, or bindings are unimplemented or unsupported?
The reason I want to use statement is because I'm doing an INSERT... SELECT, which I haven't been able to find any documentation about in Eloquent.
Here's my code:
$ php artisan tinker
Psy Shell v0.5.2 (PHP 5.6.13-0+deb8u1 — cli) by Justin Hileman
>>> echo \DB::statement('CREATE DATABASE :db', [':db'=>'test']);
Illuminate\Database\QueryException with message 'SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 1 (SQL: CREATE DATABASE :db)'
>>> \DB::statement('CREATE DATABASE ?', ['test']);
Illuminate\Database\QueryException with message 'SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 1 (SQL: CREATE DATABASE test)'
These are the two syntax forms (? and :string) from PDO. Other methods in DB such as select and insert support this, according to the documentation.
The relevant parts of these errors are near '?' at line 1 (SQL: CREATE DATABASE :db) and near '?' at line 1 (SQL: CREATE DATABASE test). MySQL thinks there is an unbound ? in the query string. I didn't even use that syntax in the first query. I'm concluding from that that the bind() method did not correctly bind my placeholders.
This question on Laracasts is asking about the syntax, but there is no accepted answer.
Edit One answer says that statement() doesn't support CREATE. I tried some queries out with SELECT, and got the same results, with both placeholders:
>>> \DB::statement('SELECT 1 WHERE \'a\' = ?', array('a'));
Illuminate\Database\QueryException with message 'SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WHERE 'a' = ?' at line 1 (SQL: SELECT 1 WHERE 'a' = a)'
>>> \DB::statement('SELECT 1 WHERE \'a\' = :letter', array(':letter'=>'a'));
Illuminate\Database\QueryException with message 'SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'WHERE 'a' = ?' at line 1 (SQL: SELECT 1 WHERE 'a' = :letter)'
Actually, you can use create and drop query in DB::statement(), but named bindings is not used in that way.
Here are some queries that will success.
drop and create do not accept bindings.
>>> \Db::statement('create database test')
=> true
>>> \Db::statement('drop database test')
=> true
Do not use backslash and single quotes in the statement
>>> \Db::statement('insert into users (id, name) values (?, ?)', ['1', 'John'])
=> true
DB::statement() only return ture when success, so if you want to see select results, you should use DB::select()
>>> \Db::statement('select * from users')
=> true
>>> \Db::select('select * from users')
=> [
{#770
+"id": 1,
+"name": "John",
},
]
Remove leading : in the second argument.
>>> \Db::statement('update users set name = :name where id = :id', ['id' => 1, 'name' => 'John'])
=> true
You will get affect rows if you use DB::update and DB::delete
>>> \Db::delete('delete from users where id = :id', ['id' => 1])
=> 1
The errors you receive are only indirectly related with Laravels DB::statement() function. They all fail within that method at the line
return $me->getPdo()->prepare($query)->execute($bindings);
within the file vendor/laravel/framework/src/Illuminate/Database/Connection.php
Responsible for that failure is the resulting call to PDO::prepare()
The Docuemenation says:
Parameter markers can represent a complete data literal only. Neither part of literal, nor keyword, nor identifier, nor whatever arbitrary query part can be bound using parameters. For example, you cannot bind multiple values to a single parameter in the IN() clause of an SQL statement.
Also have a look at the user contributed notes at the above php.net documentation. Additionally have a look at Can PHP PDO Statements accept the table or column name as parameter?
Your create examples are not supported by PDO.
The reason your SELECT examples fail is simply due to an invalid syntax.
\DB::statement('SELECT 1 WHERE \'a\' = ?', array('a'))
You are simply missing the FROM clause. This example works perfeclty well at my test computer:
$ret = \DB::statement('SELECT 1 FROM `users` WHERE `username` = ?', ["gregor"]);
But
$ret = \DB::statement('SELECT 1 WHERE `username` = ?', ["testname"]);
Generates the exact error, you receive.
Also note, that \DB::statement does not return any ressources. It just indicates by returning true or false, whether the query suceeded.
Your option is to use DB::raw() within your insert() statement, if you want to use INSERT...SELECT. Some googling will help you, to find the proper solution. Maybe as Starting Points: Raw Queries in Laravel, or How to use raw queries in Laravel
What you're trying to do is passing the table name through binding.
DB::statement('select * from ?',['users'])
which according to this post, it's not possible.
of course if you want to sanitize the data you can use an array of short codes like so:
$tables = ['users','test','another'];
and the query would look something like:
$code = 0;
DB::statement("select * from $tables[$code] where a=?",[2]);
DB::statement("create table $tables[$code]");

Resources