Laravel Artisan Migrate Drop Column using Sqlite throws exception - sqlite

I'm trying to set up some unit tests in a legacy Laravel project. This project has a lot of migration scripts creating and updating the database. This migrations work fine on a MySQL database, however I don't want to persist a test database so I'm using the standard .env.testing configuration of a Sqlite database:
One of the migration files contains the following:
public function up()
{
Schema::table('product_variants', function (Blueprint $table) {
$table->dropColumn(['sku']);
});
}
While this migration works in MySQL, when I try to run the migration in test mode (i.e. in Sqlite) I get the following message:
Reading the Laravel Docs, it's not supported to remove multiple columns from a Sqlite connection, so I converted the array param to a string (['sku'] into 'sku') but that did not change anything.
How do I get the migration to work in Sqlite?
Edit
Following the comment by BkiD (the column is indexed), I have attempted to identify what the index name of the column is using the following code:
$sm = Schema::getConnection()->getDoctrineSchemaManager();
$indexesFound = $sm->listTableIndexes('product_variants');
var_dump($indexesFound);die;
I was expecting an array of generated names, specifically I was expecting to see product_variants_sku_unique. What I actually got was an empty array: array(0){}
Edit2
Tried manually dropping the index anyway:
Schema::table('product_variants', function (Blueprint $table) {
$table->dropUnique('product_variants_sku_unique');
});
Any other name throws a message that the index does not exist. Since this is not throwing an error, I assume the index exists, even if the previous code does not return it. So. I'm "dropping" the index then trying to drop the sku column, but still getting the same message.

Have you tried something like this?
Schema::table('products', function (Blueprint $table) {
$table->dropColumn('name', 'description', 'price');
});
or this, seem's like not the best practice but hopefully works:
collect([
['old_a', 'new_a'],
['old_b', 'new_b'],
['old_c', 'new_c']])->map(function ($old_new) {
Schema::table('thetable', function (Blueprint $table) use ($old_new) {
$table->renameColumn($old_new[0], $old_new[1]);
});
});

So from what I understand, you're using Laravel 9.x and running sqlite 3.37.2 and you definitely have the Doctrine/dbal package installed.
My first question is - is this the complete migration? If not, please post the entire thing here.
If yes - please check your other migrations to look for references to this particular column.
If you look at the error, the error is coming from Index::_addColumn() , which means you probably have - an index declared for usage in mysql.
The doctrine/dbal package cannot rename/handle/drop SQLite columns that have an index
So your solution could be to either -
Drop the index in the laravel migration (provided you don't need it for MySQL as well - probably the case since you're dropping the column)
OR
Use a condition like this (in the migration file where the index was first created - incase you want to be able to rename or continue using the index in mysql) -
if (config('DB_CONNECTION') === 'mysql') {
$table->index('sku');
}
PS: The doctrine/dbal github repo has issues like these that have since been closed since the package has fixed this in newer versions - I'm guessing you probably aren't on the latest by default.

There is a warning in the laravel doc's that:
Dropping or modifying multiple columns within a single migration while using a SQLite database is not supported.
So, try to split your migrations.
public function up()
{
Schema::table('product_variants', function (Blueprint $table) {
$table->dropColumn('sku');
});
Schema::table('product_variants', function (Blueprint $table) {
$table->dropColumn('vku');
});
}
I know that it is a bad idea, but this can be a possible solution for your current issue. Hope, it works for you.

Related

"Syntax error or access violation" - in migration from Schema:: facade, but statement executes without error

I have a migration written that executes just fine on my test database - did dozens of tests runs without issue. I run it on a clone of my prod database and all of a sudden I'm having all sorts of problems. I'm beginning to think its a database config or permissions issue, but I'm logged into this clone as root, so I'm not even sure where to start looking...
If I copy the mysql statement from the error (...and fix the missing data) the statement executes without issue.
ALTER TABLE `retail_items-tmp_09-10-2020` CHANGE original_inventory initial_inventory INT DEFAULT NULL;
The offending line:
Schema::table('retail_items-tmp_09-10-2020', function($table) {
$table->renameColumn('original_inventory','initial_inventory');
});
The Error:
[PDOException (42000)]
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 '-tmp_09-10-2020 CHANGE original_inventory initial_inventory INT DEFAULT NULL' at line 1
The migration:
public function up()
{
/* 1. Backup Existing Tables */
DB::statement('CREATE TABLE `retail_items-tmp_09-10-2020` LIKE `retail_items`; ');
DB::statement('CREATE TABLE `ARCH__retail_items_09-10-2020` LIKE `retail_items`; ');
DB::statement('INSERT INTO `retail_items-tmp_09-10-2020` SELECT * FROM `retail_items`; ');
DB::statement('INSERT INTO `ARCH__retail_items_09-10-2020` SELECT * FROM `retail_items`;');
/* 2. Update structure */
Schema::table('retail_items-tmp_09-10-2020', function($table) {
$table->renameColumn('original_inventory','initial_inventory');
});
Schema::table('retail_items-tmp_09-10-2020', function($table) {
$table->integer('event_ID')->length(11)->unsigned()->nullable();
$table->foreign('event_ID')->references('event_ID')->on('events');
});
/* 3. Update structure that would have been destructive prior to step 3 */
// When I had this piece of code included, it resulted in the same error "Syntax error or access violation..." this worked in testing, but throws errors on Prod, changed to DB:statement below with success.
// Schema::table('retail_items-tmp_09-10-2020', function($table) {
// $table->smallInteger('flag')->unsigned()->nullable(false)->default(0)->change();
// });
$query = "ALTER TABLE `retail_items-tmp_09-10-2020` CHANGE `flag` `flag` SMALLINT(11) DEFAULT 0 NOT NULL; ";
DB::statement($query);
}
I've been stuck on this for a bit, so any theories, places to look, etc would be appreciated.
(I have another migration that renames the temp table at the end of this. I have a few migrations and data operations that all together take ~ 10+ min to execute with the piece of code that I'm launching this with, so the temp tables are necessary to prevent downtime when launching in production)
I still ended up having more troubleshooting/ other roadblocks on this issue, so this only removed one...
Even though they were properly quoted, I read a number of S.O. posts on the subject and as Webtect suggests I did end up simply removing all the dashes and things worked much more consistently and reliably. I'm still feel like it's a mystery as to why this happened because I've used hyphens in dates like this before - properly quoted - without issue. But this one sure threw me for a loop. I think I will entirely stop the practice of using hyphens in dated-table-names going forward. They seem to cause more headaches than the improved readability warrants.

Navigations can only target entity types with keys

I am working on a project with a 'database first' approach rest API backend. I am using ASP .Net Core 3.1 and Entity Framework 3.1.1.
I ran a script to scaffold the database into the models and db context class. However, some of the model building functions have tables/models without keys x.hasnokey(). I thought this would be fine but I get an error trying to hit the endpoint that states
ERROR : InvalidOperationException:
The navigation '' cannot be added because it targets the keyless entity type 'AAA'
Navigations can only target entity types with keys
This happens in a few different locations and this originally ran okay in the past. This is running on SQL Server 2012 (version 11). I am not sure how I can solve this issue, I have limited entity/sql experience and I just don't know where to begin. Here is the offending lines (inside DB Context):
modelBuilder.Entity<AAA>(entity =>
{
entity.HasNoKey();
entity.ToTable("BBB_AAA");
entity.HasOne(d => d.BBB)
.WithMany(p => p.AAA)
.HasForeignKey(d => d.CCC)
.OnDelete(DeleteBehavior.ClientSetNull)
...
}
The script I used to scaffold the models and db context was (generic version):
PM> Scaffold-DbContext "Server=.\SQLExpress;Database=SchoolDB;Trusted_Connection=True;" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Models
I believe this might be that the database that was originally created about 10-15 years ago, cannot be made into an ORM so easily as I would have hoped. It could also a versioning issue, the scaffolding script I ran is incorrect, or if I just am out of my depth but I would appreciate being pointed in the right direction. Thank you!
This error usually comes because of Primary Key issue.
In my Case I was running this query and result was same problem you mentioned
var exists = await _dbDontext.Students.FindAsync(Id);
My Student table has relations with other tables and one of other tables was missing Primary Key.
So two Possible Solutions .
Solution 1 :
Make Primary Key column in your table that is mentioned in your error.
Solution 2 :
If things are complicated , just delete the table and Re Create It. It would work fine
I think you have two options,
1- Go and add key to the table.
2- check the following link
https://learn.microsoft.com/en-us/ef/core/modeling/keyless-entity-types
Thanks

Drupal 8: Mismatched entity and/or field definitions

While trying to understand why my view is not displaying, I noticed the following error in the log:
I do not think it is possible to delete the URL alias from Taxonomy terms. At least I cannot find how to do this.
I have, however gone through ALL of my taxonomy terms and removed the value for this field.
I have also done the following with Pathauto:
Also, I have checked the report located at admin/reports/fields and can confirm that there are no entities that use a field called URL alias.
I have gone through each content item and ensured that they have the following setting (anyone know how to do this in bulk?). But still the error remains.
Anyone know then how I can fix this strange error?
Im not entirely sure what this command does, but it fixed the error:
drush updb --entity-updates
Since https://www.drupal.org/node/2554097, the magic in Drupal core that took care of updating entity definitions is gone. drush updb --entiy-updates is an alternative to this but it is not a silver bullet. Instead, it is safer to write database updates.
Taking the screenshot at the top as an example, here is a database update that would delete those two field definitions:
/**
* Fix taxonomy and node field definitions.
*
*/
function mymodule_update_8101() {
$manager = \Drupal::entityDefinitionUpdateManager();
if ($field = $manager->getFieldStorageDefinition('alias', 'node')) {
$manager->uninstallFieldStorageDefinition($field);
}
if ($field = $manager->getFieldStorageDefinition('alias', 'term')) {
$manager->uninstallFieldStorageDefinition($field);
}
}
Have a look at the rest of the available methods at https://www.drupal.org/node/2554097 in order to write database updates for each scenario.
use the entity_update module or the devel_entity_updates module

TypeError: Cannot read property 'openDatabase' of undefined

I want to work with sqlite with cordova framework for the first time. As I've read on a tutorial I should use ngcordova like this:
var db = null;
app.controller('mainCtrl', function ($scope, $ionicSideMenuDelegate) {
$scope.toggleLeft = function () {
$ionicSideMenuDelegate.toggleLeft();
}
$scope.toggleRight = function () {
$ionicSideMenuDelegate.toggleRight();
}
})
.controller('home_ctrl', function ($scope, $cordovaSQLite) {
db = $cordovaSQLite.openDB({name: "my.db"});
//db = $window.opendb({name: "my.db"});
$cordovaSQLite.execute(db, "CREATE TABLE IF NOT EXISTS people(id integer primary key, firstname text, lastname text)")
})
;
When I run this code an error says:
TypeError: Cannot read property 'openDatabase' of undefined
In some articles like this: How do I use the ngCordova sqlite service and the Cordova-SQLitePlugin with Ionic Framework?
recommends to use commands like this: ionic start myApp sidemenu
I don't know what is it, I just use cordova command like: cordova run android or cordova create my_project
What should I do to run my create a table from my cordova project?
You might take a look at this tutorial:
https://www.thepolyglotdeveloper.com/2014/11/use-sqlite-instead-local-storage-ionic-framework/
When you see this error:
TypeError: Cannot read property 'openDatabase' of undefined
It is happening for one of a few reasons:
You are not wrapping the $cordovaSQLite methods in the $ionicPlatform.ready() function.
You are trying to test this native plugin from a web browser.
You have not actually installed the base SQLite plugin into your project.
The most common reasons for this error are #1 and #2. Native plugins, must be used only after the application is confirmed ready, thus the $ionicPlatform.ready() method. Since native plugins use native code, you cannot test them from your web browser.
Read through the tutorial I linked because it should help you.
Regards,
Actually, I opened an old project and I get this error only when I run the project with -cls (because of liverelaod). But I have a small bug to fix there so I didn't investigate it too much(just fix it without livereload). But maybe this little hint helps somebody.

Silex: Routing with optional parameter not working

My route has three parameter, userid is always required, a and b are optional parameter. Either a or (a and b) or (neither a nor b) may be given:
$app->get('/show/{userid}/{a}/{b}/', function($userid, $a,$b) use($app) {
...
})->value('a', 'defaultValueA')->value('b', 'defaultValueB');
So I want to match the following urls:
show/12345
show/12345/paramA
show/12345/paramA/paramB
My code only works for the last version where all parameters are given. What is wrong?
Update:
I started a brand new project and tested my approach again. Worked. I copied my .htaccess into the brand new project. Still worked. So my (very general) question is: What else could affect the routing in a Silex project?
I was using the translation service in Silex and copied by accident too much from the usage example from http://silex.sensiolabs.org/doc/providers/translation.html into my code. So my route definition above was catched by this definition defined earlier in the set-up.
$app->get('/{_locale}/{message}/{name}', function ($message, $name) use ($app) {
return $app['translator']->trans($message, array('%name%' => $name)); });

Resources