Sqlite error: Could not reset the virtual machine - c++

I am trying to read from a csv file and add each row to a database in c++. The csv file is in the form id,firstname,surname,job my code is:
while (file.good())
{
getline (file, id, ',');
getline (file, firstname, ',');
getline (file, surname, ',');
getline (file, job, ' ');
cur->set_sql( "INSERT INTO staff VALUES (?, ?, ?, ?);" );
cur->prepare();
cur->bind(1, id);
cur->bind(2, firstname);
cur->bind(3, surname);
cur->bind(4, job);
cur->step();
cur->reset();
}
but when I run the code it returns the error Sqlite error: Could not reset the virtual machine. I do not understand what this means or how to solve it. I searched the error on google but I can't find anything about it

Error comes from libsqlite.hpp (check search on github.com)
void reset(){
int rc = sqlite3_reset(this->_s);
if (rc != SQLITE_OK) {
exception e("Could not reset the virtual machine.");
throw e;
}
this->_valid = true;
this->_has_row = false;
this->_prepared = false;
}
I haven't digg into this but it looks like sqilte query contain error or can't run.

I found out how to solve this error. I realised I was programming on a virtual machine and all I needed to do was restart it. There was nothing wrong with my code!

Related

Use writer/reader for multiple fields

The following is my constructor for a Student object. I will be using a list of student. I need to store the list so even if the program is turned off, I can still access all the contents. The only way I could think of was to use reader/writer and a text file.
1) Is there a more efficient way to store this information?
2) If not, how can I use reader/writer to store each field?
public Student(String firstName, String lastName, String gender, String
state, String school, String lit, String wakeUp, String sleep, String
social,String contactInfo, String country, String major) {
this.firstName = firstName;
this.lastName = lastName;
this.gender = gender;
this.state = state;
this.school = school;
this.lit = lit;
this.wakeUp = wakeUp;
this.sleep = sleep;
this.social = social;
this.contactInfo = contactInfo;
this.country = country;
this.major = major;
}
The possibilities are really project specific and subjective.
Some possibilities include:
CSV file which makes it easy for exporting to other programs and parsing data
Online server which allows access from any computer that has the
program and an internet connection
Text file which works for local devices that won't require many
additions
It really just depends on how you want to implement it and what method suits your needs best.
To use reader/writer to store your fields, you could use the accessor methods of each variable to store them line by line in your text file. Below is some sample code to get you started on writing to the file:
PrintWriter outputStream = null;
try {
outputStream = new PrintWriter(new FileOutputStream(FILE_LOCATION));
}
catch (FileNotFoundException ex) {
JOptionPane optionPane = new JOptionPane("Unable to write to file\n " + FILE_LOCATION, JOptionPane.ERROR_MESSAGE);
JDialog dialog = optionPane.createDialog("Error!");
dialog.setAlwaysOnTop(true);
dialog.setVisible(true);
System.exit(0);
}
Iterator<YOUR_OBJECT> i = this.List.iterator();
YOUR_OBJECT temp = null;
while (i.hasNext()) {
temp = i.next();
if (temp instanceof YOUR_OBJECT) {
outputStream.println(temp.getAttribute());
}
}
outputStream.close();

Saving text in Sqlite3, c++

here is my second post in the community, excuse me if I'm forget to add something, just let me know:
I am trying to do a program in c++ able to save text (i want to save code) in a database using sqlite3. Currently I've made a wxWidget program that call some functions from a DLL and this ones interactuate with the database.
The database that I want to make is really simple, it has 3 columns in one table (id,name, ref). My problem comes when I want to save big amount of text that also contains simblos that can conflict with the sql queries (I would like to save files inside the database, for example in the "ref" column ).
I'm using mostly the sqlite3_exec function, because the functions sqlite3_prepare_v2, sqlite_bind, sqlite3_step crash me the DLL where I'm working.
My doubt: Can I directly save any text as big as I want, without taking care about if it has simbols or not? and how can I do it?.
More info: I am working in c++ with code:block(13.12) making a DLL of sqlite3 functions and using MinGW toolchain. (windows 7).
This is an example of an insert function that I'm using:
int DLL_EXPORT add_item(sqlite3* db, string tbname,string col,string item)
{
char* db_err = 0;
if (tbname==std::string()||col==std::string()||item==std::string())
throw std::invalid_argument( "stoi: invalid argument table name");
char buf[200];
sprintf(buf,"insert into %s (%s) values ('%s');", tbname.c_str(), col.c_str(),item.c_str());
int n = sqlite3_exec(db, buf, NULL, 0, &db_err);
dsperr(&db_err);
if( n != SQLITE_OK )
{
//throw something
}
return 0;
}
Thank you in advance.
Thank to CL. for the up commentary
// Add one text to a table
// The column must be specify
//
int DLL_EXPORT add_text(sqlite3* db, string tbname,string col,string id,string item)
{
char* db_err = 0;
if (tbname==std::string()||col==std::string()||item==std::string())
throw std::invalid_argument( "stoi: invalid argument table name");
char *zSQL = sqlite3_mprintf("UPDATE %q SET %q=(%Q) WHERE id=%q", tbname.c_str(),col.c_str() ,item.c_str(),id.c_str());
int n = sqlite3_exec(db, zSQL, NULL, 0, &db_err);
dsperr(&db_err);
sqlite3_free(zSQL);
if( n != SQLITE_OK )
{
// throw something
}
return 0;
}

SQLite UPDATE fails to overwrite existing value

I have the following problem that has me stumped. As a note to keep in mind, I am using a precompiled sqlite3.dll rather than Qt's built-in SQLite support.
Table creation code:
CREATE TABLE STUDY(
Name NOT NULL,
UserName NOT NULL REFERENCES USERS(UserName),
Description DEFAULT NULL,
PathToOsirixDB DEFAULT NULL,
PRIMARY KEY(Name, UserName)
)
The following C++ code fails to update the value in column PathToOsirixDB if it already contains a value.
It fails silently, with no error returned. That would imply that no rows are matched in the UPDATE. However, if I take the same UPDATE with valid entries for user and study to match a row and run it via either the SQLite Manager Firefox plugin, or the command line tool, it works properly.
void CStudyDatabase::SetOsirixDBForStudy(const QString user, const QString study, const QString path)
{
if (mp_db)
{
int before = sqlite3_total_changes(mp_db);
QString insert = QString("UPDATE STUDY SET PathToOsirixDB = '%1' WHERE Name = '%2' AND UserName = '%3'").arg(path, study, user);
if (!InsertData(insert))
{
int after = sqlite3_total_changes(mp_db);
if (after - before >= 1)
{
SetOsirixDB(path.toAscii().data());
emit ReturnOsirixDB(osirix_db);
}
else
{
emit DatabaseError(QString("Failed to update the target path."));
}
}
}
}
And for Insert Data
int CStudyDatabase::InsertData(const QString insert)
{
char *err_msg = 0;
int rc = sqlite3_exec(mp_db,
insert.toStdString().c_str(),
NULL,
this,
&err_msg);
if (rc)
SignalDatabaseError(&err_msg);
return rc;
}
Any insights are appreciated. Thank you.
UPDATE: added the following code to SetOsiriXDBForStudy to see if we actually find a row to update:
osirix_db = QString("");
QString query = QString("SELECT PathToOsirixDB FROM STUDY WHERE Name = '%1' AND UserName = '%2'").arg(study, user);
int rc = 0;
char *err_msg = 0;
rc = sqlite3_exec(mp_db,
query.toStdString().c_str(),
&OsirixDBCallback,
this,
&err_msg);
if (rc)
SignalDatabaseError(&err_msg);
if (!(QString(osirix_db).isEmpty()))
studyrowfound = true;
In this case, it leaves osirix_db as an empty string.
But, if I execute this function:
void CStudyDatabase::QueryOsirixDB(const QString user, const QString study)
{
int rc = 0;
char *err_msg = 0;
// we query the OrisixDB via the callback and then emit the signal if all went well
QString query = QString("SELECT PathToOsirixDB FROM STUDY WHERE Name = '%1' AND UserName = '%2'").arg(study, user);
rc = sqlite3_exec(mp_db,
query.toStdString().c_str(),
&OsirixDBCallback,
this,
&err_msg);
if (rc)
SignalDatabaseError(&err_msg);
if (QString(osirix_db).isEmpty())
emit NeedToSetOsirixDB(user, study, QString());
else
emit ReturnOsirixDB(osirix_db);
}
Then it does correctly retrieve the expected value into osirix_db.
Last update: found the problem. It was leading spaces on user and study. Had been staring at the same debugger statements for too long and glossed over the extra spaces. The failing SELECT was a big clue that there was something wrong in the construction of the SQL.
There were leading spaces on user and study. Had been staring at the same debugger statements for too long and glossed over the extra spaces. The failing SELECT was a big clue that there was something wrong in the construction of the SQL.

get data from file and vector

I want to retrieve all the data inside the text file, so I will read to vector 1st then display all the data out. The 1st data in the text file I can get it properly, but the 2nd data in the text file, the username can't be retrieve and it gone.
Here's the text file data...
1|admin|admin|admin|Male|123|123|123|
1|jeff|jeff|jeff|Male|123|123|123|
And after I display all the data out...it become like this
1 admin admin admin Male 123 123 123
1 jeff jeff Male 123 123 123
Can anyone help me to solve?? THANKS
void Admin::displayMemberInfo(vector <Member> &memberProfile)
{
if(loginSucceed == true)
{
int memberID, age;
string username, password, name, gender, contact, ic;
memberProfile.erase(memberProfile.begin(),memberProfile.end());
ifstream inMember("Member.txt");
while(!(inMember.eof()))
{
string name,gender,contact, ic, username, password;
int age,memberID;
string readID,readAge;
getline(inMember,readID,'|');
istringstream(readID)>>memberID;
getline(inMember,username,'|');
getline(inMember,password,'|');
getline(inMember,name,'|');
getline(inMember,gender,'|');
getline(inMember,readAge,'|');
istringstream(readAge)>>age;
getline(inMember,contact,'|');
getline(inMember,ic,'|');
inMember.ignore(numeric_limits<streamsize>::max(), '|');
//if(username != "")
//{
// Member member(memberID, username, password, name, gender,age, contact, ic);
// memberProfile.push_back(member);
//}
cout<<memberID<<username<<password<<name<<gender<<age<<contact<<ic<<endl;
}
inMember.close();
system("pause");
}
}
You need to change this line
inMember.ignore(numeric_limits<streamsize>::max(), '|');
to
inMember.ignore(numeric_limits<streamsize>::max(), '\n');
Oh yeah, I forgot, you redeclare variables.
Try this entire function and tell me if it works better:
void Admin::displayMemberInfo(/* vector <Member> &memberProfile */) {
int memberID, age;
string username, password, name, gender, contact, ic;
//memberProfile.erase(memberProfile.begin(),memberProfile.end());
ifstream inMember("Members.txt");
if(inMember.fail()) return;
while(!(inMember.eof())) {
string readID,readAge;
getline(inMember,readID,'|');
istringstream(readID)>>memberID;
getline(inMember,username,'|');
getline(inMember,password,'|');
getline(inMember,name,'|');
getline(inMember,gender,'|');
getline(inMember,readAge,'|');
istringstream(readAge)>>age;
getline(inMember,contact,'|');
getline(inMember,ic,'|');
inMember.ignore(numeric_limits<streamsize>::max(), '\n');
//if(username != "")
//{
// Member member(memberID, username, password, name, gender,age, contact, ic);
// memberProfile.push_back(member);
//}
cout<<memberID<<username<<password<<name<<gender<<age<<contact<<ic<<endl;
}
inMember.close();
system("pause");
}
You were also re-declaring variables in the function as well as the while loop.
I commented out the vector stuff for my test.
My input file is
1|admin|admin|admin|Male|123|123|123|
2|jeff|jeff|jeff|Male|123|123|123|
Terminated with a new line. The output is
1adminadminadminMale123123123
2jeffjeffjeffMale123123123

Regular Expression for validating Windows-based file paths including UNC paths

I wanted to validate a file name along with its full path. I tried certain Regular Expressions as below but none of them worked correctly.
^(?:[\w]\:|\\)(\\[a-z_\-\s0-9\.]+)+\.(txt|gif|pdf|doc|docx|xls|xlsx)$
and
^(([a-zA-Z]\:)|(\\))(\\{1}|((\\{1})[^\\]([^/:*?<>""|]*))+)$
etc...
My requirement is as mentioned below:
Lets say if the file name is "c:\Demo.txt" then it should check every possibilites like no double slash should be included(c:\\Demo\\demo.text) no extra colon like(c::\Demo\demo.text). Should accept UNC files like(\\staging\servers) and others validation as well. Please help. I am really stuck here.
Why are you not using the File class ?
Always use it !
File f = null;
string sPathToTest = "C:\Test.txt";
try{
f = new File(sPathToTest );
}catch(Exception e){
Console.WriteLine(string.Format("The file \"{0}\" is not a valid path, Error : {1}.", sPathToTest , e.Message);
}
MSDN : http://msdn.microsoft.com/en-gb/library/system.io.file%28v=vs.80%29.aspx
Maybe you're just looking for File.Exists ( http://msdn.microsoft.com/en-gb/library/system.io.file.exists%28v=vs.80%29.aspx )
Also take a look to the Path class ( http://msdn.microsoft.com/en-us/library/system.io.path.aspx )
The GetAbsolutePath could be one way to get what you want! ( http://msdn.microsoft.com/en-us/library/system.io.path.getfullpath.aspx )
string sPathToTest = "C:\Test.txt";
string sAbsolutePath = "";
try{
sAbsolutePath = Path.GetAbsolutePath(sPathToTest);
if(!string.IsNullOrEmpty(sAbsolutePath)){
Console.WriteLine("Path valid");
}else{
Console.WriteLine("Bad path");
}
}catch(Exception e){
Console.WriteLine(string.Format("The file \"{0}\" is not a valid path, Error : {1}.", sPathToTest , e.Message);
}
If you are interested only in the filename part (and not the whole path because you get the file via upload) then you could try something like this:
string uploadedName = #"XX:\dem<<-***\demo.txt";
int pos = uploadedName.LastIndexOf("\\");
if(pos > -1)
uploadedName = uploadedName.Substring(pos+1);
var c = Path.GetInvalidFileNameChars();
if(uploadedName.IndexOfAny(c) != -1)
Console.WriteLine("Invalid name");
else
Console.WriteLine("Acceptable name");
This will avoid the use of Exceptions as method to drive the logic of your code.