When using Foreign keys in Sqlite3 for ESP8266, I get Unable to prepare: file is encrypted or is not a database - sqlite

I am using ESP8266 and want to use a SQLite db stored in an SD.
Here is how I created the tables in SQL Online IDE:
CREATE TABLE "nfc_tag" (
"id" TEXT NOT NULL UNIQUE,
"value" TEXT NOT NULL,
PRIMARY KEY(id)
);
CREATE TABLE "tag_log" (
"tag_id" TEXT NOT NULL,
"datetime" TEXT NOT NULL,
);
And when I run:
int query_tag(const char *tag) {
const char *null;
// Prepare the statement
sqlite3_stmt *statement;
if (sqlite3_prepare_v2(db, "SELECT value FROM nfc_tag WHERE id = ?;", -1, &statement, &null) != SQLITE_OK) {
Serial.print("Unable to prepare: ");
Serial.println(sqlite3_errmsg(db));
return 0;
}
}
Everything is ok.
But I want tag_id to be a foreign key to id in nfc_tag, so I recreated the db and created the tables with this statement:
CREATE TABLE "nfc_tag" (
"id" TEXT NOT NULL UNIQUE,
"value" TEXT NOT NULL,
PRIMARY KEY(id)
);
PRAGMA foreign_keys = ON;
CREATE TABLE "tag_log" (
"tag_id" TEXT NOT NULL,
"datetime" TEXT NOT NULL,
FOREIGN KEY("tag_id") REFERENCES "nfc_tag"("id")
);
And now, when I run the same code, I get Unable to prepare: file is encrypted or is not a database
I have not encrypted the db, and I can open it in VSCode and DB Browser for SQLite, so I guess it is not encrypted. I don't know if it is because of the foreign key, but it shouldn't be a problem because of the PRAGMA statement.
Any help would be appreciated, thanks in advance!

Related

how to insert table on plugin activation?

i'm trying to create a table on plugin activation.
function insert_custom_table(){
global $wpdb;
require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
if (count($wpdb->get_var('SHOW TABLES LIKE "wp_custom_plugin"')) == 0){
$sql_query_to_create_table = "CREATE TABLE `wp_custom_plugin` (
id int NOT NULL IDENTITY(1, 1),
city_name char(128) NOT NULL,
lat decimal(9,6) NOT NULL,
long decimal(9,6) NOT NULL,
country_id int NOT NULL,
CONSTRAINT city_pk PRIMARY KEY (id)
)"
dbDelta( $sql_query_to_create_table );
}
}
register_activation_hook(__FILE__,'insert_custom_table');
you can see my code but I'm getting an error.
Parse error: syntax error, unexpected identifier "dbDelta" in C:\xampp\htdocs\composer\wp-content\plugins\aaqib\wp-aqib.php on line 98
i need your assistance
Just change the condition you have written.
for example:
if ($wpdb->get_var('SHOW TABLES LIKE "wp_custom_plugin"') !== 'wp_custom_plugin'){
// your code
}
Initially, the query gives you null, which is the invalid argument for the count function.
and the best practice is to use
$tablename = $wpdb->prefix . 'custom_plugin';
please read these documents.
https://www.php.net/manual/en/function.count.php
https://developer.wordpress.org/reference/functions/dbdelta/
and also you have some SQL Syntax errors in your code.
you use long as a column name, which is also a type for SQL.
also, IDENTITY is not valid syntax for MySQL.
you can try this.
CREATE TABLE `wp_custom_plugin` (
id int NOT NULL AUTO_INCREMENT,
city_name char(128) NOT NULL,
lat decimal(9,6) NOT NULL,
`long` decimal(9,6) NOT NULL,
country_id int NOT NULL,
PRIMARY KEY (`id`)
)

Why is this Knex migration not forcing a column to be unique?

I'm creating a SQLite database with this Knex migration. When I review the DB in SQLiteStudio, it doesn't indicate that the email column is unique. Is there a mistake I'm missing?
exports.up = function (knex) {
return knex.schema
.createTable('users', users => {
users.increments();
users.string('email', 128).unique().notNullable();
users.string('password', 256).notNullable();
})
Generated DDL code:
CREATE TABLE users (
id INTEGER NOT NULL
PRIMARY KEY AUTOINCREMENT,
email VARCHAR (128) NOT NULL,
password VARCHAR (256) NOT NULL
);
Alternatives I've tried that didn't work:
-Switching order of unique() and notNullable()
users.string('email', 128).notNullable().unique()
-Creating a separate line to add the Unique constraint
.createTable('users', users => {
users.increments();
users.string('email', 128).notNullable();
users.string('password', 256).notNullable();
users.unique('email');
})
It's unique, you're just not going to see it in the CREATE TABLE statement. SQLite sets a UNIQUE constraint by creating an index with the UNIQUE qualifier. Take the following Knex migration, for example:
exports.up = knex =>
knex.schema.debug().createTable("users", t => {
t.increments("id");
t.string("name").unique();
});
Note debug(), very handy if you want to see what SQL is being generated. Here's the debug output:
[
{
sql: 'create table `users` (`id` integer not null ' +
'primary key autoincrement, `name` ' +
'varchar(255))',
bindings: []
},
{
sql: 'create unique index `users_name_unique` on `users` (`name`)',
bindings: []
}
]
As you can see, a second statement is issued to create the UNIQUE constraint. If we now go and look at the database, we'll see something like:
07:48 $ sqlite3 dev.sqlite3
sqlite> .dump users
BEGIN TRANSACTION;
CREATE TABLE `users` (`id` integer not null primary key autoincrement,
`name` varchar(255));
CREATE UNIQUE INDEX `users_name_unique` on `users` (`name`);
COMMIT;
As an aside, you may wish to do more research about the possible length of user emails. See this answer as a starting point.

HSQL postgres dialog not recognized

I want to use HSQL for integration tests. Therefore I want to setup the test schema with exact the same script I use for production. This is in postgresql dialect. In the test script I tried to set the dialect but it doesn't seem to work.
At least for uuid datatype and constraints I get syntax error exceptions. E.g. I get a:
CREATE TABLE testtable ( id bigint NOT NULL, some_uuid uuid NOT NULL,
name character varying(32) NOT NULL, CONSTRAINT testtable PRIMARY KEY
(id) ) WITH ( OIDS=FALSE ); nested exception is
java.sql.SQLSyntaxErrorException: type not found or user lacks
privilege: UUID
for the following script:
SET DATABASE SQL SYNTAX PGS TRUE;
CREATE TABLE testtable
(
id bigint NOT NULL,
some_uuid uuid NOT NULL,
name character varying(32) NOT NULL,
CONSTRAINT testtable PRIMARY KEY (id)
)
WITH (
OIDS=FALSE
);
And I get:
Failed to execute SQL script statement #2 of class path resource
[setupTestData.sql]: CREATE TABLE testtable ( id bigint NOT NULL, name
character varying(32) NOT NULL, CONSTRAINT testtable PRIMARY KEY (id)
) WITH ( OIDS=FALSE ); nested exception is
java.sql.SQLSyntaxErrorException: unexpected token: (
for this script:
SET DATABASE SQL SYNTAX PGS TRUE;
CREATE TABLE testtable
(
id bigint NOT NULL,
--some_uuid uuid NOT NULL,
name character varying(32) NOT NULL,
CONSTRAINT testtable PRIMARY KEY (id)
)
WITH (
OIDS=FALSE
);
HSQLDB 2.3.4 and later supports UUID.
HSQLDB does not currently support the PostgreSQL extension WITH (ODS= FALSE)

(No such column).. But, it's there

Here's my tables:
CREATE TABLE IF NOT EXISTS message_threads (
thread_id integer primary key autoincrement NOT NULL,
user_id integer NOT NULL,
last_checked timestamp NOT NULL DEFAULT '0',
last_updated timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
)
CREATE TABLE IF NOT EXISTS messages (
message_id integer primary key autoincrement NOT NULL,
thread_id integer NOT NULL,message_type integer NOT NULL DEFAULT '0',
message_content varchar(500) NOT NULL,
message_date timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
sent integer NOT NULL DEFAULT '0'
);
Here's the error I'm getting:
Could not prepare statement (1 no such column: m.message_date)
Here's the query that I'm using (This query works in MySQL, as I tested it in PHPMyAdmin with a dummy table)
SELECT * FROM messages m, message_threads t
WHERE m.thread_id = t.thread_id
ORDER BY t.last_updated, t.thread_id, m.message_date;
I'm using WebSQL (which I think is SQLite)
FULL WebSQL CODE
$rootScope.database = openDatabase('application.db', '1.0', 'Application database', 1024 * 1024);
$rootScope.database.transaction(function(tx) {
tx.executeSql("CREATE TABLE IF NOT EXISTS message_threads (thread_id integer primary key autoincrement NOT NULL, user_id integer NOT NULL, last_checked timestamp NOT NULL DEFAULT '0', last_updated timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP);");
tx.executeSql("CREATE TABLE IF NOT EXISTS messages (message_id integer primary key autoincrement NOT NULL,thread_id integer NOT NULL,message_type integer NOT NULL DEFAULT '0',message_content varchar(500) NOT NULL, message_date timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, sent integer NOT NULL DEFAULT '0');");
});
// Empty messages/threads for testing purposes
$rootScope.database.transaction(function(tx) {
tx.executeSql("DELETE FROM messages;");
tx.executeSql("DELETE FROM message_threads;");
});
$rootScope.database.transaction(function(tx) {
tx.executeSql("INSERT INTO message_threads (user_id) VALUES (?);", [0]);
tx.executeSql("INSERT INTO messages (thread_id, message_content, sent) VALUES (?, ?, ?);", [1, "How are you doing?", 1]);
tx.executeSql("INSERT INTO messages (thread_id, message_content) VALUES (?, ?);", [1, "Good you?"]);
});
$rootScope.database.transaction(function(tx) {
tx.executeSql("SELECT * FROM messages m, message_threads t WHERE m.thread_id = t.thread_id ORDER BY t.last_updated, t.thread_id, m.message_date", [], function(tx, rs) {
console.log(JSON.stringify(rs));
}, function(tx, err) {
alert("Error: " + err.message);
});
});
I should add that the query works fine using DBBrowser for SQLite.
Chances are that your database has an older version of the table without the column.
CREATE TABLE IF NOT EXISTS only creates a new table with the given specification if a table by the same name does not exist. It does nothing to make sure the columns are there.
To fix it, either remove your database file, or use DROP TABLE to get rid of your old tables before recreating them.
I have created a fresh new sqlite database and tested both of your create queries using the plain command line sqlite.exe version 3.8.0.2 on windows 7. There were no errors.
Then I have used SQLiteStudio Version 3.0.6 and entered some dummy data and executed your select query. Again no issues.
The tools that I have used can only deal with sqlite. Therefore, it seems to me that there are some configuration issues with your tools.

LINQPad create sqlite database in C# query

The IQ Connection plugin for LINQPad that allows one to use SQLite has a checkbox for "Create database if missing" but that will only create an empty file. Is there anyway to build the tables automatically when the file doesn't exist?
Shouldn't there be a way to get the DataContext and create tables using that interface? Hopefully causing LINQPad to update its DataContext at the same time.
The best I've been able to do so far is below, creating DbCommands and executing them on the first run after deleting the sqlite file, then I have to refresh the database, and run it again.
void Main()
{
if (!File.Exists(this.Connection.ConnectionString.Split('=')[1]))
{
"CREATING DATABASE TABLES".Dump();
CREATE_TABLES();
}
else
{
"RUNNING CODE".Dump();
//Code goes here...
}
}
public void CREATE_TABLES()
{
this.Connection.Open();
System.Data.Common.DbCommand sup = this.Connection.CreateCommand();
sup.CommandText = #"create table MainTable
(
MainTableID INTEGER not null PRIMARY KEY AUTOINCREMENT,
FileName nvarchar(500) not null
)";
sup.ExecuteNonQuery();
sup.CommandText = #"create table SubTable
(
SubTableID int not null,
MainTableID int not null,
Count int not null,
primary key (SubTableID, MainTableID),
FOREIGN KEY(MainTableID) REFERENCES MainTable(MainTableID)
)";
//Apparently this version of sqlite doesn't support foreign keys really
sup.ExecuteNonQuery();
this.Connection.Close();
}
Just set the query language dropdown to 'SQL', type in the DDL and hit F5. For instance:
PRAGMA foreign_keys = ON
GO
create table Customer
(
ID int not null primary key,
Name nvarchar(30) not null
)
GO
create table Purchase
(
ID int not null primary key,
CustomerID int null references Customer (ID),
Date datetime not null,
Description varchar(30) not null,
Price decimal not null
)
(Note the syntax for creating foreign key constraints.)
Once you're done, right-click the connection in the Schema Explorer and choose 'Refresh'. You can then switch the query language back to C# Expression or C# Statements and start querying in a proper query language :)

Resources