Sqlite 'Unrecognized token: ":" C++ - c++

I'm not sure what to do with this as I can't remove the colon from my SQL string.
Basically I am trying to execute an SQL string in Sqlite using the below code.
string database_name = "C:/Programs_C++/Project/Databases/dbase.db";
string exec_string = "SELECT * FROM " + database_name + " WHERE type='table'";
dbase_return=sqlite3_open_v2(database_name.c_str(),&db_handle,SQLITE_OPEN_READWRITE,NULL);
dbase_return_tbl=sqlite3_get_table(db_handle,exec_string.c_str(),&result,&row,&column,&error_msg);
//But I get the error: unrecognized token: ":" ?
How do I get around this? Thanks

You can SELECT from a table, not from a database.
First open the database (using the filename), then execute a valid SQL statement like
SELECT * FROM myTable;
SELECT * FROM C:/Programs_C++/Project/Databases/dbase.db WHERE type = 'table' is not valid SQL. If you are trying to get a list of all tables, you cannot do it that way.

It looks like you have URI filenames switched on - this can be done at compile time or runtime (probably compile time for you if you didn't know about it).
If URI filenames are switched on, you need to change your filename to something like:
file:///C:/Programs_C++/Project/Databases/dbase.db
Edit: If you want to switch it off, I don't think you can do it for this one call (as the call takes a flag as part of the parameters which can only switch it on). Instead you can disable it globally by calling
sqlite3_config(SQLITE_CONFIG_URI, 0)
which tells sqlite to disable the URI filename convention globally. Note: you only need to call this once and it is not thread safe, so probably just put this at the start of your program.
However, it might be worth investigating if URI filenames are useful to you before switching them off entirely.

Related

ODBC SQL Server Unicode Bug?

Background:
We have an application that uses the ODBC API to interact with Access and SQL Server (dynamically, depending on user's configuration).
I have discovered a bug which might be in the ODBC SQL driver, or may be a misconfiguration issue with the ODBC DSN we create, or may be a bug somehow in our code.
When a document is edited and saved, we query the database to see if this file has a corresponding record in the database - if so, we update the record with the updated data from the document; if not, we do an insert to create the necessary record for it.
We use the filename as the unique primary key on our table, and this works fine normally.
The bug is that if the filename contains characters outside of the current ANSI code page, then the select indicates no matches:
SQL: SELECT * FROM "My Designs" WHERE "PATHNAME" = '\\FILE-SERVER\Home Folders\User Files\狭すぎて丸め処理が出来ません!!.foo' [# matches = 0]
However, when the insert is attempted, we get a unique key violation (of course) - since there already is a record with that filename.
Database error: Violation of PRIMARY KEY constraint 'PK__My Desig__1B3D5B4BF643706B'. Cannot insert duplicate key in object 'dbo.My Designs'. The duplicate key value is (\\FILE-SERVER\Home Folders\User Files\狭すぎて丸め処理が出来ません!!.foo).
The statement has been terminated.
I've been over the code with a fine-tooth comb, and I can see nothing wrong. :(
The SQL statement that is being generated produces the correct Unicode output of the filename. Our application is compiled for Unicode. The column is SQL_WVARCHAR in ODBC speak.
I've tried adding AutoTranslate=no to the DSN configuration string, but that appears to have no effect.
I've tried logging the database connection from ODBC control panel. Sadly, that interface produces an ANSI log file - so I cannot verify UNICODE / ANSI issues using that tool.
Questions:
Is there a tool I can use to verify that these statements are being
created / issued correctly by the ODBC driver to the SQL Server
database?
Is there a better way to use ODBC so that the driver doesn't get canoodled by a simple UNICODE string in a SELECT query vs. an INSERT request?
Any other ideas for how to approach this problem (short of replacing our technology)
In the select statement, make sure you enclose the where clause string with a N to tell SQL it's unicode:
..."PATHNAME" = N'\\FILE-SERVER\Home Folders\User Files\狭すぎて丸め処理が出来ません!!.foo'
Also, MFC converts the data to MCBS or UNICODE depending on your configuration. Make sure you use CStringT in recordset.

How to load custom sql functions with django

I am trying to use Django's initial SQL data functionality to create an SQL function. The docs state I can do this:
https://docs.djangoproject.com/en/1.6/howto/initial-data/#providing-initial-sql-data
Django provides a hook for passing the database arbitrary SQL that’s executed just after the CREATE TABLE statements when you run migrate. You can use this hook to populate default records, or you could also create SQL functions, views, triggers, etc.
After some googling I found that django's customsql code splits any sql files and runs them line by line, creating this error,
Failed to install custom SQL for myapp.somemodel model: unterminated dollar-quoted string at or near "$$ BEGIN;"
Is there an accepted work around for this? Or a better way to load custom sql functions?
Yeah, I've seen this problem before. If you stick a multi-line function in your app's sql/<modelname>.sql like so:
CREATE OR REPLACE FUNCTION increment(i integer) RETURNS integer AS $$
BEGIN
RETURN i + 1;
END;
$$ LANGUAGE plpgsql;
you'll get the error you saw, namely something like:
Failed to install custom SQL for mysite.Poll model: unterminated dollar-quoted string at or near "$$ BEGIN RETURN i + 1;"
LINE 1: ... FUNCTION increment(i integer) RETURNS integer AS $$ BEGIN R...
I think you should be able to work around the problem by squeezing the function definition all onto one line, e.g.
CREATE OR REPLACE FUNCTION increment(i integer) RETURNS integer AS $$BEGIN RETURN i + 1; END; $$ LANGUAGE plpgsql;
Looks like this bug affects any multi-line functions (both dollar-quoted and single-quoted). I tested on Django 1.6, no idea if it's been fixed already.

Handling invalid dates in Oracle

I am writing simple SELECT queries which involve parsing out date from a string.
The dates are typed in by users manually in a web application and are recorded as string in database.
I am having CASE statement to handle various date formats and use correct format specifier accordingly in TO_DATE function.
However, sometimes, users enter something that's not a valid date(e.g. 13-31-2013) by mistake and then the entire query fails. Is there any way to handle such rougue records and replace them with some default date in query so that the entire query does not fail due to single invalid date record?
I have already tried regular expressions but they are not quite reliable when it comes to handling leap years and 30/31 days in months AFAIK.
I don't have privileges to store procedures or anything like that. Its just plain simple SELECT query executed from my application.
This is a client task..
The DB will give you an error for an invalid date (the DB does not have a "TO_DATE_AND_FIX_IF_NOT_CORRECT" function).
If you've got this error- it means you already tried to cast something to an invalid date.
I recommend doing the migration to date on your application server, and in the case of exception from your code - send a default date to the DB.
Also, that way you send to the DB an object of type DbDate and not a string.
That way you achieve two goals:
1. The dates will always be what you want them to be (from the client).
2. You close the door for SQL Injection attacks.
It sounds like in your case you should write the function I mentioned...
it should look something like that:
Create or replace function TO_DATE_SPECIAL(in_date in varchar2) return DATE is
ret_val date;
begin
ret_val := to_date(in_date,'MM-DD-YYYY');
return ret_val;
exception
when others then
return to_date('01-01-2000','MM-DD-YYYY');
end;
within the query - instead of using "to_date" use the new function.
that way instead of failing - it will give you back a default date.
-> There is not IsDate function .. so you'll have to create an object for it...
I hope you've got the idea and how to use it, if not - let me know.
I ended up using crazy regex that checks leap years, 30/31 days as well.
Here it is:
((^(0?[13578]|1[02])[\/.-]?(0?[1-9]|[12][0-9]|3[01])[\/.-]?(18|19|20){0,1}[0-9]{2}$)|(^(0?[469]|11)[\/.-]?(0?[1-9]|[12][0-9]|30)[\/.-]?(18|19|20){0,1}[0-9]{2}$)|(^([0]?2)[\/.-]?(0?[1-9]|1[0-9]|2[0-8])[\/.-]?(18|19|20){0,1}[0-9]{2}$)|(^([0]?2)[\/.-]?29[\/.-]?(((18|19|20){0,1}(04|08|[2468][048]|[13579][26]))|2000|00)$))
It is modified version of the answer by McKay here.
Not the most efficient but it works. I'll wait to see if I get a better alternative.

Using a single ADO Query to copy data from a text file into another ODBC source

This may seem a odd question as I have a solution, I just dont understand why and that limits me.
I am copying data from various sources into SQL and am using a ADO connection in C++ Builder XE2.
When the data is from MSAccess or MSExcel the code is similar to the following:
//SetupADO..
ADOConn->ConnectionString="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:/temp/testdb.mdb";
//Then open it..
ADOConn->Connected = true;
//Build SQL
UnicodeString sSQL = "SELECT * INTO [ODBC;DSN=PostgreSQL30;DATABASE=admin_db;SERVER=192.168.1.10;PORT=5432;UID=user1;PWD=pass1;SSLmode=disable;ReadOnly=0;Protocol=7.4;].[table1] FROM [accesstb]";
//And finally I use the EXCEUTE() function of the ADO Connection
ADOConn->Execute(sSQL, iRA, TExecuteOptions() << TExecuteOption::eoExecuteNoRecords);
This works fine for Excel too but not for CSV files. I'm using the same driver must can only get it working by changing the syntax around.
//SetupADO..
ADOConn->ConnectionString="Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\\temp;Extended Properties=\"Text;HDR=Yes;\";Persist Security Info=False";
//Then open it..
ADOConn->Connected = true;
//Build SQL with the IN keyword and start internal ODBC connection with 2 single quotes
UnicodeString sSQL = "SELECT * INTO [table1] IN '' [ODBC;DSN=PostgreSQL30;DATABASE=admin_db;SERVER=192.168.1.10;PORT=5432;UID=user1;PWD=pass1;SSLmode=disable;ReadOnly=0;Protocol=7.4;] FROM [test.csv]";
//And finally EXCEUTE() again
ADOConn->Execute(sSQL, iRA, TExecuteOptions() << TExecuteOption::eoExecuteNoRecords);
When using the same SQL as the Access query the error "Query input must contain at least one table or query" would be returned.
Intrestingly, one escaped quote, i.e. \' fails when used in place of the 2 single ones. I have also tried writing to another Access database in case the problem was with PG but I had the same results.
Can someone tell me why the IN keywork is required and what the single quotes do?
Extended Properties=\"Text;HDR=Yes;\" specifies text as the datasource, so the connection string is different. IN '' tells the database to map table1 to the first column of the CSV file, since there is no relational model in CSV.
References
Importing CSV Data and saving it in database - CodeProject

cant figure this error out

Can you guys see any obvious error in this query? The error im getting is: `Unknown column 003ADF50 in field list. 003ADF50 wtf?
query << "UPDATE `record` SET `record` = " << lastRecord << ", `time` = " << time;
What looks to be happening here is that one of those values that you're injecting into your sql is coming up as 003ADF50. (Probably the time value?)
Brendan Long is correct: you should be using prepared statements to properly handle parameters in your SQL. Manually concatenating strings leads to quoting problems like you see here, which can be serious security problems in your code. The specific quoting problem you're running into here is that the parameters aren't quoted in your resulting query string. If you were typing the SQL manually into the mysql client, you'd say something like:
UPDATE `record` set `record` = 'foo';
If instead you left out the quotes on 'foo', you'd have:
UPDATE `record` set `record` = foo;
which is trying to set the record column to the value of the foo column, rather than the literal string 'foo'. The same thing is happening with the SQL you're generating from your C++. Trying to solve this by manually adding quotes isn't a good idea -- what happens when the string parameter contains a quote character? The best thing to do is to use prepared statements.
Also, Google "little bobby tables" for a well-known XKCD comic about sql parameter injection, and consider what would happen if Bobby Tables' name found its way into one of your program's variables.