I'm trying to create a database with a table using sqlite3 on my C program, however the database is always created as empty, though it was created non-empty using the sqlite shell,
here is my code below:
int main(void)
{
printf("hello\n");
sqlite3 *sqdb;
sqlite3_initialize();
const char* db = "test";
sqlite3_open(db, &sqdb);
const char* stmt = "CREATE TABLE IF NOT EXISTS testtable(creationdate DATE, data VARCHAR);";
sqlite3_stmt *ppstmt;
if (sqlite3_prepare_v2(sqdb, stmt, -1, &ppstmt, 0)!=SQLITE_OK)printf("error!\n");
sqlite3_finalize(ppstmt);
getch();
return 0;
}
please help me to solve the problem.
sqlite3_prepare_v2() alone just compiles the SQL but does not run it. Call sqlite3_step() on the compiled statement to run it, or use sqlite3_exec() that combines prepare+step+finalize into one function call.
Try this:
int main(void)
{
printf("hello\n");
sqlite3 *sqdb;
int ret;
sqlite3_initialize();
const char* db = "test.sqlite3";
sqlite3_open(db, &sqdb);
const char* stmt = "CREATE TABLE IF NOT EXISTS testtable(creationdate DATE, data VARCHAR);";
sqlite3_stmt *ppstmt=NULL;
ret=sqlite3_exec(sqdb,stmt,0,0,0);
if(ret!=SQLITE_OK)printf("error!\n");
else printf("Table added\n");
sqlite3_finalize(ppstmt);
sqlite3_close(sqdb);
return 0;
}
Please do remember to close the DB after operation.
Related
I know that tdengine support schemaless insert. And there are three line protocols that tdengine supports. The follow is the sample code from taosdata's website schemaless chapeter.
#include <stdlib.h>
#include <stdio.h>
#include <taos.h>
int main() {
const char* host = "127.0.0.1";
const char* user = "root";
const char* passwd = "taosdata";
// connect to server
TAOS* taos = taos_connect(host, user, passwd, "test", 0);
// prepare the line string
char* lines1[] = {
"stg,t1=3i64,t2=4f64,t3=\"t3\" c1=3i64,c3=L\"passit\",c2=false,c4=4f64 1626006833639000000",
"stg,t1=4i64,t3=\"t4\",t2=5f64,t4=5f64 c1=3i64,c3=L\"passitagin\",c2=true,c4=5f64,c5=5f64 1626006833641000000"
};
// schema-less insert
TAOS_RES* res = taos_schemaless_insert(taos, lines1, 2, TSDB_SML_LINE_PROTOCOL, TSDB_SML_TIMESTAMP_NANO_SECONDS);
if (taos_errno(res) != 0) {
printf("failed to insert schema-less data, reason: %s\n", taos_errstr(res));
}
taos_free_result(res);
// close the connection
taos_close(taos);
return (code);
}
I know this will create the stable "stg" and create substable for the incoming data record. I want to ask can I control the subtable's name and how to configure the name?
No, you cannot configure subtable name in TDengine database
Please refer this link for how subtable name is generated: https://docs.tdengine.com/reference/schemaless/#main-processing-logic-for-schemaless-writing
In my C program I have to check if count of a table in database is one or zero and to do that i am executing query as follows:
char *sql = "SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name=family;";
int table_count = sqlite3_exec(db, sql, 0, 0, &err_msg);
printf("\n%d\n", table_count);
I'm expecting table_count to be 1 as only one table exists with name family but printf outputs table_count as '21' which is incorrect. How can we get the COUNT(*) value from C/C++ API in C program the right/correct way?
After reading SQLite Documentation and following other kind implicit/explicit suggestions in the comments on the question, I have realized my mistakes in that code snippet quoted in the question.
Mistake 1:
I did not implement callback function to receive the result set after the SQL query gets executed. [Have implemented this callback: see checkTable_Callback in code below]
Mistake 2:
That output of '21' is actually the error code and as per the SQLite documentation that error code corresponds to SQLite_MISUSE Which was being generated, perhaps, because I was using a separate function to open my test database file and instance of that opened database, i assume, stayed inside that openDb function, and when i used another function checkTableCount from where i took that messy snippet to quote in my question, there db instance perhaps was null, hence 21. Experts can elaborate further if that's why i was receiving error code 21. Anyways, now i have fixed that function and made that openDb return an opened db instance (better word?) and now 21 error is gone. [see code below]
Here is fixed and 'adapted-for-my-case' code
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "sqlite3.h" /* sqlite3.dll and sqlite3.h both reside in
my <program_source.c>'s folder */
static int checkTable_Callback(
void *unnecessary_here,
int number_of_columns_in_result_row, /* will always be 1 in this case */
char **value_of_count, /* will be either 0 or 1 in this case */
char **label_for_count) { /* will be COUNT(*) normally,
but modified via 'AS table_tablename' in this case*/
printf("COUNT(*) %s\t=>\t%s\n", label_for_count[0], value_of_count[0] );
return 0;
} // end of checkTable_Callback()
char * build_sql(const char *sql_partA, const char *sql_partB) {
size_t size = strlen(sql_partA) + strlen(sql_partB);
char *sql_final = malloc(size + 1);
strcpy(sql_final, sql_partA);
strcat(sql_final, sql_partB);
return sql_final; /* allocated memory to be freed at the end of calling function */
} // end of build_sql()
checkTableCount(sqlite3 *db, char *tablename) {
char *sql = build_sql(
build_sql(
build_sql(
build_sql(
"SELECT COUNT(*) AS table_",
tablename),
" FROM sqlite_master WHERE type='table' AND name='"),
tablename),
"';");
sqlite3_exec(db, sql, checkTable_Callback, 0, NULL);
/* error checking sacrificed for brevity of sample */
free(sql);
}// end of checkTableCount()
sqlite3 * openDb(char * db_name){
sqlite3 *db;
int result_code = sqlite3_open(db_name, &db);
if( result_code != 0 )
fprintf(stderr, "\tError: %s\n\n", sqlite3_errmsg(db));
return db;
} // end of openDb()
int main() {
sqlite3 * db = openDb("testing.db"); /* testing.db already has one table 'family'*/
checkTableCount(db, "family");
checkTableCount(db, "fam"); /* no such table exist */
sqlite3_close(db);
return 0;
} // end of main()
Now this quoted 'adapted-for-my-case' code rightly and correctly outputs the COUNT(*) as follows:
OUTPUT
COUNT(*) table_family => 1
COUNT(*) table_fam => 0
Note that I didn't bother to write a for-loop inside my callback function named checkTable_Callback to iterate through columns as shown in the official sample of callback function on this page because of the fact that our expected result row is certainly going to be only one containing only one column with label modified, via 'AS' clause, into 'table_tablename'. If not modified via 'AS clause', the returned column label would be 'COUNT(*)' in the result row.
I am doing C interface with firebird databases. I did some query operations. I would like to know how to read the result size?
Below is the code. I have created and inserted some values into the table.I would like to read the size of the result.
#include <stdio.h>
#include "/Library/Frameworks/Firebird.framework/Versions/A/Headers/ibase.h"
static char *createTable="CREATE TABLE newex (Id int)"; //query for creating data table
static char *Insertvalues="INSERT INTO newex values (1)";//doing insertion into the
//above created table
int SQLOpen(void)
{
ISC_STATUS status_vector[20];
isc_tr_handle transactionHandle = NULL; //transaction handle
isc_db_handle database = SQLGetDatabase();//database handle
char logInData [256], *dpb, *p;
short bufferLength;
User_Credentials credentials;
sprintf(logInData, "%c%c%c%c%c%c%s%c%c%s", isc_dpb_version1,
isc_dpb_num_buffers,
1,
90,
isc_dpb_user_name,
strlen("SYSDBA"),
"SYSDBA",
isc_dpb_password,
strlen("masterkey"),
"masterkey"); //passing user //credentials to connect to the database
bufferLength = strlen(logInData);
if (isc_attach_database(status_vector, strlen(DATABASE_PATH), DATABASE_PATH, &DatabaseHandle,bufferLength, logInData)) // connecting to database
{
SQLTestForErrors(status_vector);
throw(ConnectionError, "");
}
return 1;
}
char** SQLQuery(char *query, uint maxRows)
{
isc_tr_handle transactionHandle = NULL;
isc_db_handle database = SQLGetDatabase();
short bufferLength;
char dpb_buffer[256], *dpb, *p;
ISC_STATUS status_vector[20];
isc_start_transaction(status_vector, &transactionHandle, 1, &database, 0, NULL);
if (isc_dsql_execute_immediate(status_vector, &database, &transactionHandle, 0, query, 1, NULL)) //query operations 'create/insert'
{
SQLTestForErrors(status_vector);
throw(QueryError, "");
}
isc_commit_transaction(status_vector, &transactionHandle);
return testString;
}
int main()
{
//struct Folder_table;
e4c_using_context(E4C_TRUE)
{
SQLOpen();
SQLQuery(createTable);
SQLQuery(Insertvalues);
}
}
You can't in advance: the result set is materialized while you are reading rows (using isc_fetch): the final number of rows is not known until you have read all rows (at which point you can either have counted it yourself, or query it with an info request).
However I notice that you try to use isc_dsql_execute_immediate. You can only use isc_dsql_execute_immediate for ddl and for queries that produce one row (you need to prepare and execute for multiple rows).
I was trying to run test_onefile.c example from sqlite3 VFS examples, and I get the following failure:
test_onefile: test_onefile.c:693: fsDelete: Assertion `strpcmp("-journal", &zPath[nName])==0' failed.
I'm running the code as follows:
int retval;
fs_register();
int q_cnt = 5,q_size = 150,ind = 0;
char **queries = (char**) malloc(sizeof(char) * q_cnt * q_size);
sqlite3_stmt *stmt;
sqlite3 *handle;
retval = sqlite3_open_v2( "sampledb.sqlite2", &handle, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE , "fs");
if(retval)
{
printf("Database connection failed\n");
return -1;
}
printf("Connection successful\n");
// Create the SQL query for creating a table
char create_table[100] = "CREATE TABLE IF NOT EXISTS users (uname TEXT,pass TEXT NOT NULL,activated INTEGER)";
// Execute the query for creating the table
retval = sqlite3_exec(handle,create_table,0,0,0);
// Insert first row and second row
queries[ind++] = "INSERT INTO users VALUES('manish','mani',1)";
retval = sqlite3_exec(handle,queries[ind-1],0,0,0);
queries[ind++] = "INSERT INTO users VALUES('mehul','pulsar',0)";
retval = sqlite3_exec(handle,queries[ind-1],0,0,0);
Edit:
The file it fails on is sampledb.sqlite2-wal, clearly not a journal file. However, I don't understand how it reached it.
Edit2:
Well, after removing the assertion in source file:
assert(strcmp("-journal", &zPath[nName])==0);
The code seems to work. However, I'm not a big fan of assertion deletion, as clearly it would lead to some unexpected behavior. The author had a reason to use the assertion.
The VFS implemented by test_onefile.c is quite old, and therefore does not support the additional files required for WAL mode.
To make it work with a modern SQLite, the fsDelete function should just ignore attempts to delete -wal or -shm files.
Using the C api with sqlite (v 3.7.13), I'm trying to list all attached databases of the current connection:
sqlite3_stmt* pCompiledSql;
if(SQLITE_OK == sqlite3_prepare_v2(database, "PRAGMA database_list;", -1, &pCompiledSql, nullptr))
{
while(SQLITE_ROW == sqlite3_step(pCompiledSql))
{
const char* pName = reinterpret_cast<const char*>(sqlite3_column_text(pCompiledSql, 1));
const char* pFile = reinterpret_cast<const char*>(sqlite3_column_text(pCompiledSql, 2));
// Using pName and PFile...
}
}
Where database is a handle to an existing database with several databases attached. The same code works fine with statements like "SELECT * FROM testtable;"
However with the pragma call the first step call will just return an SQLITE_DONE straight away.
I'm pretty sure I'm ovelooking something obvious but without much experience with SQLite I'm stuck now... What can possibly go wrong here?
The fourth parameter of sqlite3_prepare_v2 is a pointer to the statement pointer, so it must not be pCompiledSql but &pCompiledSql.
Your compiler should have warned you about this.