R RMySQL not escaping table name, conflicts with MySQL reserved keyword - r

Code:
dbWriteTable(con, name=symbol, value=df, row.names=FALSE, append=TRUE)
Error in mysqlExecStatement(conn, statement, ...) :
RS-DBI driver: (could not run statement: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'SSL
(
Date text,
Open double,
High double,
Low double,
Close double,
Volum' at line 1)
The issue is the ticker symbol "SSL" is also a MySQL keyword. It seems RMySQL is not escaping the table name?
Just to add, same problem with tickers "ALL" and "KEY", also reserved words. So I just need to figure out how to properly escape the table name with RMySQL, but so far am coming up empty.
Edit to add: I realize it is possible to use dbSendQuery but really want to make use of dbWriteTable instead. I am really surprised that the table name is not properly backticked automatically?
Edit to add more: I also tried name=paste0(dbname,".",symbol) for example, which works with MySQL to get past the reserved words, but what I found is that the dbWriteTable function uses the dbExistsTable() function built-in, and that function does not work with the change.
I could rewrite the dbExistsTable function to overwrite built-in as a workaround, but I do not know how to get the dbname from the dbConnect() function to become inherited. Still looking into this...

Related

What syntax am I missing?

I am a completely new to SQL and I am follow a tutorial verbatim to try and create a new table in my first database. However I am getting the following error.
USE menu;
CREATE TABLE Burgers
(
`Burger Number` TINYINT,
Burger VARCHAR(50),
Price DECIMAL(5,2),
Description VARCHAR(300),
);
Yields SQL Error 1064:
SQL Error (1064): You have an errror in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ')' at line 8
I made sure to use commas to separate each column and used parenthesis to what I understand is the proper way to do so. I am not sure if version is relevant but I am using version 10.5.8 of MariaDB. Any insight is appreciated!
You have one comma too many.
...
Description VARCHAR(300),
);
You need commas between each column, index, or constraint within the CREATE TABLE statement, except for the last one before the closing parenthesis.
It should be like this:
...
Description VARCHAR(300)
);
General tip about syntax errors: They tell you exactly where to look for the problem, because it reports the place in your SQL statement where the syntax parser got confused.
In this case it reported:
...right syntax to use near ')' at line 8
This tells you the problem is at that point in the syntax. The ) didn't belong there, because the syntax was expecting something else. Because commas separate columns, it was expecting another column definition following a comma.

loading in a MySQL table called "order" with RMySQL

I'm currently trying to connect my R session to a MySQL server using the RMySQL package.
One of the tables on the server is called "order", I already searched how you can import a table called order with MySQL (by putting it into ''), yet the syntax does not work for the RMySQL query.
when I run the following statement:
order_query = dbSendQuery(mydb,"SELECT * FROM 'order'")
It returns the following error:
Error in .local(conn, statement, ...) : could not run statement:
You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use
near ''order'' at line 1
Anyone knows how to get around this in R?
Single quotes in MySQL indicate string literals, and you should not be putting them around your table names. Try the query without the quotes:
order_query = dbSendQuery(mydb,"SELECT * FROM `order`")
If you did, for some reason, need to escape your table name, then use backticks, e.g.
SELECT * FROM `some table` -- table name with a space (generally a bad thing)
Edit:
As #Ralf pointed out, in this case you do need backticks because ORDER is a MySQL keyword and you should not be using it to name your tables and columns.

how to encode R strings so that they are read into MySQL without encoding errors

Consider this:
> scr<-paste("INSERT INTO ques2_log (freeze_time) value(",sQuote(now()),")")
> scr
#> "INSERT INTO ques2_log (freeze_time) value( ‘2017-06-13 23:46:16’ )"
If we feed this simple SQL script into a MySQL DB as follows:
dbExecute(db,scr1)
The MySQL DB throws the following error:Error in .local(conn, statement, ...) : could not run statement: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '��2017-06-13 23:44:13’ )' at line 1
I have tested the SQL script by typing by hand and it works.
It is also clear that the single quote is the unexpected character.
I looked up some online articles on character encoding and tried
enc2utf8(scr) before feeding to the DB through RMySQL commands. No effect. Same error.
I also read this and ran
ALTER DATABASE ques2_log CHARACTER SET utf8 COLLATE utf8_general_ci;
But the error remains.
Just use regular single quotes, as in:
paste0("'",date(),"'")
sQuote produces distinct left and right "smart" quotes, as documented in ?sQuote:
Single or double quote text by combining with appropriate single or
double left and right quotation marks.
...and additionally, the documentation makes clear that the intended purpose of this function is for formatting text for displaying user facing messages on screen:
The purpose of the functions is to provide a simple means of markup
for quoting text to be used in the R output, e.g., in warnings or
error messages.
So it generally shouldn't be used for processing text to be used programmatically.

Bracket-escaped table names with dplyr

I'm programmatically fetching a bunch of datasets, many of them having silly names that begin with numbers and have special characters like minus signs in them. Because none of the datasets are particularly large, and I wanted the benefit R making its best guess about data types, I'm (ab)using dplyr to dump these tables into SQLite.
I am using square brackets to escape the horrible table names, but this doesn't seem to work. For example:
data(iris)
foo.db <- src_sqlite("foo.sqlite3", create = TRUE)
copy_to(foo.db, df=iris, name="[14m3-n4m3]")
This results in the error message:
Error in sqliteSendQuery(conn, statement, bind.data) : error in statement: no such table: 14m3-n4m3
This works if I choose a sensible name. However, due to a variety of reasons, I'd really like to keep the cumbersome names. I am also able to create such a badly-named table directly from sqlite:
sqlite> create table [14m3-n4m3](foo,bar,baz);
sqlite> .tables
14m3-n4m3
Without cracking into things too deeply, this looks like dplyr is handling the square brackets in some way that I cannot figure out. My suspicion is that this is a bug, but I wanted to check here first to make sure I wasn't missing something.
EDIT: I forgot to mention the case where I just pass the janky name directly to dplyr. This errors out as follows:
library(dplyr)
data(iris)
foo.db <- src_sqlite("foo.sqlite3", create = TRUE)
copy_to(foo.db, df=iris, name="14M3-N4M3")
Error in sqliteSendQuery(conn, statement, bind.data) :
error in statement: unrecognized token: "14M3"
This is a bug in dplyr. It's still there in the current github master. As #hadley indicates, he has tried to escape things like table names in dplyr to prevent this issue. The current problem you're having arises from lack of escaping in two functions. Table creation works fine when providing the table name unescaped (and is done with dplyr::db_create_table). However, the insertion of data to the table is done using DBI::dbWriteTable which doesn't support odd table names. If the table name is provided to this function escaped, it fails to find it in the list of tables (the first error you report). If it is provided escaped, then the SQL to do the insertion is not synatactically valid.
The second issue comes when the table is updated. The code to get the field names, this time actually in dplyr, again fails to escape the table name because it uses paste0 rather than build_sql.
I've fixed both errors at a fork of dplyr. I've also put in a pull request to #hadley and made a note on the issue https://github.com/hadley/dplyr/issues/926. In the meantime, if you wanted to you could use devtools::install_github("NikNakk/dplyr", ref = "sqlite-escape") and then revert to the master version once it's been fixed.
Incidentally, the correct SQL-99 way to escape table names (and other identifiers) in SQL is with double quotes (see SQL standard to escape column names?). MS Access uses square brackets, while MySQL defaults to backticks. dplyr uses double quotes, per the standard.
Finally, the proposal from #RichardScriven wouldn't work universally. For example, select is a perfectly valid name in R, but is not a syntactically valid table name in SQL. The same would be true for other reserved words.

swi-prolog odbc error while inserting into postgresql

I have the following problem and I'm begging for help: I'm using swi-prolog and odbc interface to connect to postgresql database. Problem occurs when I try to insert in database. SELECT works fine but INSERT doesn't work. Does anybody know what am I doing wrong.
Here's my simple test code:
:-use_module(library(odbc)).
connect(C):-
odbc_connect(baza, C, [user(Mat),
password(lozinka), alias(baza), open(once)]).
sel(R) :-
odbc_query(baza,
'SELECT * FROM pacijent',
R).
ins:-
odbc_query(baza, 'INSERT INTO pacijent (name, surname, passw, number) VALUES ("James", "Bond", 007, 007)').
This is the error when i try to insert:
?- ins.
ERROR: ODBC: State S1000: [unixODBC]ERROR: column "James" does not exist at character 30;
Error while executing the query
Also i tried to insert through psql console and everything works fine, but as said problem is when inserting from prolog.
Please help, im stuck here.
Thanks
A suggestion: proper escaping, don't know if it'll be enough though. I'd turn
"James", "Bond"
into
\'James\', \'Bond\'
The problem is you've passed the column data for columns name and surname in double quotes instead of single quotes. Most databases use " (double quotes) for identifiers like table and column names and ' (single quotes) for data. How you ensure that in prolog I don't know.
I suspect you'll want to quote the other 2 columns as well.
In ODBC you'd use SQLGetInfo and get SQL_IDENTIFIER_QUOTE_CHAR which will usually return double quotes meaning to quote identifiers use these quotes.

Resources