SQLite C interface doesn't create sqlite_master table - c++

It seems that SQLite C interface create database that doesn't contain sqlite_master table described in the documentation:
From within a C/C++ program (or a script using Tcl/Ruby/Perl/Python
bindings) you can get access to table and index names by doing a
SELECT on a special table named "SQLITE_MASTER". Every SQLite database
has an SQLITE_MASTER table that defines the schema for the database
The following code creates a database that doesn't contain such table (.tables command returns nothing):
#include <sqlite3.h>
int main()
{
sqlite3* db;
sqlite3_open("helper.db", &db);
sqlite3_close(db);
}
Why? What should I do to create it?

The .tables command does not show any of the internal tables, but they do exist:
sqlite> create table t(x);
sqlite> .tables
t
sqlite> select * from sqlite_master;
table|t|t|2|CREATE TABLE t(x)

Related

How do I create a table for all tables in MySQL

I’m using MySQL for C++ and I want to create a new table for all the tables in my second database. The code I have now is:
CREATE TABLE new_table LIKE original_table;
INSERT INTO new_table SELECT * FROM original_table;
I want to this to work like a loop where all the tables and data in those tables are created for every table and piece of data there is in my second database. Can someone help me?
We can use a stored procedure to do the job in a loop. I just wrote the code and tested it in workbench. Got all my tables(excluding view) from sakila database to my sakila_copy database:
use testdb;
delimiter //
drop procedure if exists copy_tables //
create procedure copy_tables(old_db varchar(20),new_db varchar(20))
begin
declare tb_name varchar(30);
declare fin bool default false;
declare c cursor for select table_name from information_schema.tables where table_schema=old_db and table_type='BASE TABLE';
declare continue handler for not found set fin=true;
open c;
lp:loop
fetch c into tb_name;
if fin=true then
leave lp;
end if;
set #create_stmt=concat('create table ',new_db,'.',tb_name,' like ',old_db,'.',tb_name,';') ;
prepare ddl from #create_stmt;
execute ddl;
deallocate prepare ddl;
set #insert_stmt=concat('insert into ',new_db,'.',tb_name,' select * from ',old_db,'.',tb_name,';');
prepare dml from #insert_stmt;
execute dml;
deallocate prepare dml;
end loop lp;
close c;
end//
delimiter ;
create database sakila_copy;
call testdb.copy_tables('sakila','sakila_copy');
-- after the call, check the tables in sakila_copy to find the new tables
show tables in sakila_copy;
Note: As I stated before, only base tables are copied. I deliberately skipped views, as they provide logical access to tables and hold no data themselves.

How to RENAME struct/array nested columns using ALTER TABLE in BigQuery?

Suppose we have the following table in BigQuery:
CREATE TABLE sample_dataset.sample_table (
id INT
,struct_geo STRUCT
<
country STRING
,state STRING
,city STRING
>
,array_info ARRAY
<
STRUCT<
key STRING
,value STRING
>
>
);
I want to rename the columns inside the STRUCT and the ARRAY using an ALTER TABLE command. It's possible to follow the Google documentation available here for normal columns ("non-nested" columns) i:
ALTER TABLE sample_dataset.sample_table
RENAME COLUMN id TO str_id
But when I try to run the same command for nested columns I got errors from BigQuery.
Running the command for a column inside a STRUCT gives me the following message:
ALTER TABLE sample_dataset.sample_table
RENAME COLUMN `struct_geo.country` TO `struct_geo.str_country`
Error: ALTER TABLE RENAME COLUMN not found: struct_geo.country.
The exact same message appears when I run the same statement, but targeting a column inside an ARRAY:
ALTER TABLE sample_dataset.sample_table
RENAME COLUMN `array_info.str_key` TO `array_info.str_key`
Error: ALTER TABLE RENAME COLUMN not found: array_info.str_key
I got stuck since the BigQuery documentation about nested columns (available here) lacks examples of ALTER TABLE statements and refers directly to the default documentation for non-nested columns.
I understand that I can rename the columns by simply creating a new table using a CREATE TABLE new_table AS SELECT ... and then passing the new column names as aliases, but this would run a query over the whole table, which I'd rather avoid since my original table weighs way over 10TB...
Thanks in advance for any tips or solutions!

'Can not create a Path from an empty string' Error for 'CREATE TABLE AS' in hive using S3 path

I am trying to create a table in Glue catalog with s3 path location from spark running in EMR using hive. I have tried the following commands, but getting the error:
pyspark.sql.utils.AnalysisException: u'java.lang.IllegalArgumentException: Can not create a Path from an
empty string;'
sparksession.sql("CREATE TABLE IF NOT EXISTS abc LOCATION 's3://my-bucket/test/' as (SELECT * from my_table)")
sparksession.sql("CREATE TABLE abcSTORED AS PARQUET LOCATION 's3://my-bucket/test/' AS select * from my_table")
sparksession.sql("CREATE TABLE abcas SELECT * from my_table USING PARQUET LOCATION 's3://my-bucket/test/'")
Can someone please suggest the parameters that I am missing?
The issue happens when a database is created without specified location:
CREATE DATABASE db_name;
To fix the issue, specify location when create database:
CREATE DATABASE db_name LOCATION 's3://my-bucket/db_path';
Then, create a table:
USE db_name;
CREATE TABLE IF NOT EXISTS abc LOCATION 's3://my-bucket/db_path/abc' as (SELECT * from my_table)

sqlite3 & python: get list of primary and foreign keys

I am very new to sql and intermediate at python. Using sqlite3, how can I get a print() list of of primary and foreign keys (per table) in my database?
Using Python2.7, SQLite3, PyCharm.
sqlite3.version = 2.6.0
sqlite3.sqlite_version = 3.8.11
Also note: when I set up the database, I enabled FKs as such:
conn = sqlite3.connect(db_file)
conn.execute('pragma foreign_keys=ON')
I tried the following:
conn=sqlite3.connect(db_path)
print(conn.execute("PRAGMA table_info"))
print(conn.execute("PRAGMA foreign_key_list"))
Which returned:
<sqlite3.Cursor object at 0x0000000002FCBDC0>
<sqlite3.Cursor object at 0x0000000002FCBDC0>
I also tried the following, which prints nothing (but I think this may be because it's a dummy database with tables and fields but no records):
conn=sqlite3.connect(db_path)
rows = conn.execute('PRAGMA table_info')
for r in rows:
print r
rows2 = conn.execute('PRAGMA foreign_key_list')
for r2 in rows2:
print r2
Unknown or malformed PRAGMA statements are ignored.
The problem with your PRAGMAs is that the table name is missing. You have to get a list of all tables, and then execute those PRAGMAs for each one:
rows = db.execute("SELECT name FROM sqlite_master WHERE type = 'table'")
tables = [row[0] for row in rows]
def sql_identifier(s):
return '"' + s.replace('"', '""') + '"'
for table in tables:
print("table: " + table)
rows = db.execute("PRAGMA table_info({})".format(sql_identifier(table)))
print(rows.fetchall())
rows = db.execute("PRAGMA foreign_key_list({})".format(sql_identifier(table)))
print(rows.fetchall())
SELECT
name
FROM
sqlite_master
WHERE
type ='table' AND
name NOT LIKE 'sqlite_%';
this sql will show all table in database, for eache table run sql PRAGMA table_info(your_table_name);, you can get the primary key of the table.
Those pictures show what sql result like in my database:
first sql result
second sql result

SQLite "On delete CASCADE" not cascading in Qt

I have a database in Qt.
it has four tables: maingroup, subgroup, parts, and position.this is my database:
CREATE TABLE `maingroup` (
`groupName`TEXT NOT NULL UNIQUE,
PRIMARY KEY(`groupName`)
);
CREATE TABLE `subgroup` (
`sub` TEXT NOT NULL UNIQUE,
`main` TEXT NOT NULL,
PRIMARY KEY(`sub`),
FOREIGN KEY(`main`) REFERENCES `maingroup`(`groupName`) ON DELETE CASCADE
);
CREATE TABLE `parts` (
`ID` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE,
`Part_Number` TEXT,
`Type` TEXT NOT NULL,
`Value` TEXT,
`Voltage` TEXT,
`Quantity` TEXT,
`Position` TEXT,
`Picture` TEXT,
FOREIGN KEY(`Position`) REFERENCES `Position`(`Poistion`) ON DELETE CASCADE,
FOREIGN KEY(`Type`) REFERENCES `subgroup`(`sub`) ON DELETE CASCADE
);
Type in table parts is foreign key refers to column sub from table subgroup.
main in table subgroup is foreign key refers to column groupname in table maingroup.
my problem is when I try (delete from maingroup WHERE groupName= 'dd';) in DB Browser it deletes both parent and children.
But in QT this command(myQuery.exec("delete from maingroup WHERE groupName= 'dd'");) just deletes the parent field in maingroup table and not the child in subgroup and part table and the main column in subgroup table refers to a field in maingroup table that does not exist.
what is wrong here?what should i do?
You need to turn on the foreign-key pragma by executing another statement before your DELETE statement.
QSqlQuery q;
q.exec("PRAGMA foreign_keys = ON");
q.exec("DELETE FROM ...");
This was able to cascade deletes, and should also be sufficient to solve other foreign-key related issues.
Credits to this forum.qt.io post.
In addition to #TrebledJ correct and very helpful answer it's worth to mention two additional characteristics about the foreign-key pragma (in connection with Qt):
1. The pragma can set via QSqlDatabase, too.
So the following code has the same effect as #TrebledJ's example:
auto database = QSqlDatabase::database();
database.exec("PRAGMA foreign_keys = ON");
QSqlQuery query(database); // query "inherits" the pragma from database
query.exec("DELETE FROM ...");
2. This behavior even applies if opening and using the database happens at different places in the program.
Still the same effect:
Somewhere in initialization code:
// this calls database.open() implicit because database was not open before.
auto database = QSqlDatabase::database();
QSqlDatabase::database();
database.exec("PRAGMA foreign_keys = ON");
// make sure database.close() is NOT called!
Somewhere else in code
// you'll get the instance of your initialization code because database is already open (so QSqlDatabase::database() implements a singleton pattern).
// so pragma foreign_keys is still set to "ON"
auto database = QSqlDatabase::database();
QSqlQuery query(database);
query.exec("DELETE FROM ...");
This might be important to know if you want to understand why the foreign_keys pragma seems to only sometimes apply in your project (and sometimes not).
What I did
So I came to the conclusion to make sure to have ONE distinct place in my code where to explicit open the database (and configure the connection):
QString dbConnectionName = "My project database";
auto database = QSqlDatabase::database(dbConnectionName, true);
// configure the pragmas here
At all other places I avoid to (accidentally) open the database:
auto database = QSqlDatabase::database(dbConnectionName, false);
// e.g. use the database via queries ...