SQLite connection string cannot contain a comma? - sqlite

I'm getting an error from SQLite when the connection string contains a comma. I don't have full control over where the database will end up, so it's possible a user will place it into a directory containing arbitrary characters. In this case, it appears that the presence of a comma (,) in the path causes an error when connecting. Here is the connection string:
Data Source=C:/Users/Dan/AppData/LocalLow/Gravia Software, LLC/Gravia/exampleDatabase.db;
This results in the following exception when trying to connect:
ArgumentException: Invalid ConnectionString format for parameter "LLC/Gravia/exampleDatabase.db"
It appears that the presence of the comma in the connection string is the issue. I've tried escaping the command (\,), wrapping the whole thing in quotes, but it doesn't seem to matter. Any ideas?
Edit:
The actual code I was executing comes from this page: https://ornithoptergames.com/how-to-set-up-sqlite-for-unity/
var dbPath = "URI=file:" + Application.persistentDataPath + "/exampleDatabase.db";
using (var conn = new SqliteConnection(dbPath)) {
conn.Open(); // Error occurs here
// etc
}
I tried changing out URI=file: for Data Source=, as the result was the same.

Try this ?
"Data Source=" + "C:/Users/Dan/AppData/LocalLow/Gravia Software," + "LLC/Gravia/exampleDatabase.db";

I solved this way:
var currDir = Directory.GetCurrentDirectory();
Directory.SetCurrentDirectory(Path.GetDirectoryName(Application.streamingAssetsPath + "/DB/"));
SqliteConnection dbcon = null;
try
{
dbcon = new SqliteConnection(_Connection);
dbcon.Open();
}
catch (Exception e)
{
Debug.Log(e.Message);
return null;
}
finally
{
Directory.SetCurrentDirectory(currDir);
}

You can escape unsupported characters in ODBC connection variables using curly-brackets ({}).
So wrap your variable, like below
Data Source={C:/Users/Dan/AppData/LocalLow/Gravia Software, LLC/Gravia/exampleDatabase.db};
Source

Related

SQLite via JDBC: SQLITE_BUSY when inserting after selecting

I'm getting the error code SQLITE_BUSY when trying to write to a table after selecting from it. The select statement and result is properly closed prior to my insert.
If I'm removing the select part the insert works fine. And this is what I'm not getting. According to the documentation SQLITE_BUSY should mean that a different process or connection (which is definetly not the case here) is blocking the database.
There's no SQLite manager running. Also jdbcConn is the only connection to the database I have. No parallel running threads aswell.
Here's my code:
try {
if(!jdbcConn.isClosed()) {
ArrayList<String> variablesToAdd = new ArrayList<String>();
String sql = "SELECT * FROM VARIABLES WHERE Name = ?";
try (PreparedStatement stmt = jdbcConn.prepareStatement(sql)) {
for(InVariable variable : this.variables.values()) {
stmt.setString(1, variable.getName());
try(ResultSet rs = stmt.executeQuery()) {
if(!rs.next()) {
variablesToAdd.add(variable.getName());
}
}
}
}
if(variablesToAdd.size() > 0) {
String sqlInsert = "INSERT INTO VARIABLES(Name, Var_Value) VALUES(?, '')";
try(PreparedStatement stmtInsert = jdbcConn.prepareStatement(sqlInsert)) {
for(String name : variablesToAdd) {
stmtInsert.setString(1, name);
int affectedRows = stmtInsert.executeUpdate();
if(affectedRows == 0) {
LogManager.getLogger().error("Error while trying to add missing database variable '" + name + "'.");
}
}
}
jdbcConn.commit();
}
}
}
catch(Exception e) {
LogManager.getLogger().error("Error creating potentially missing database variables.", e);
}
This crashes on int affectedRows = stmtInsert.executeUpdate();. Now if I remove the first block (and manually add a value to the variablesToAdd list) the value inserts fine into the database.
Am I missing something? Am I not closing the ResultSet and PreparedStatement properly? Maybe I'm blind to my mistake from looking at it for too long.
Edit: Also executing the select in a separate thread does the trick. But that can't be the solution. Am I trying to insert into the database too fast after closing previous statements?
Edit2: I came across a busy_timeout, which promised to make updates/queries wait for a specified amount of time before returning with SQLITE_BUSY. I tried setting the busy timeout like so:
if(jdbcConn.prepareStatement("PRAGMA busy_timeout = 30000").execute()) {
jdbcConn.commit();
}
The executeUpdate() function still immedeiately returns with SQLITE_BUSY.
I'm dumb.
I was so thrown off by the fact that removing the select statement worked (still not sure why that worked, probably bad timing) that I missed a different thread using the same file.
Made both threads use the same java.sql.Connection and everything works fine now.
Thank you for pushing me in the right direction #GordThompson. Wasn't aware of the jdbc:sqlite::memory: option which led to me finding the issue.

asp.net RowFilter comparing string with int

Im having an issue with this , Im new to asp.net and really dont have much understanding with their syntax, I do understand the error but have no idea how to implement a fix:
ProductTable.RowFilter = "ProductID ='" & ddlCategory.SelectedValue & "'"
The error im recieving is : cannot perform '=' operation on system.int32 and system.string data view
my productID data type is : int;
Now i dont see how im comparing a string vs int, ddlCatergory selected index would also return a value... besides the point...im completely stuck.
any help is appreciated.
Using windows 8, VS 2012 , SQL database.
ddlCategory.SelectedValue is likely to be string given the SelectedValue attribute of the drop down list is a string, you are also assigning it as a string e.g. the filter value could end up being something like "ProductID ='123'" where 123 is the SelectedValue.
Assuming that SelectedValue is never null or empty I would use something like:
ProductTable.RowFilter = string.format("ProductID = {0}", ddlCategory.SelectedValue);
If it could be empty then I would do something along these lines:
if(string.IsNullOrEmpty(ddlCategory.SelectedValue))
{
ProductTable.RowFilter ="";
}
else {
ProductTable.RowFilter = string.format("ProductID = {0}", ddlCategory.SelectedValue);
}
OR
int tempInt;
if(int.TryParse(ddlCategory.SelectedValue,out tempInt))
{
ProductTable.RowFilter = string.format("ProductID = {0}", tempInt);
}
I've written the above in C# (not syntax checked though sorry!) though it would be easy enough to convert it to VB if necessary.
You should try by removing single quotes after = sign, so it give something like this
ProductTable.RowFilter = "ProductID = " + ddlCategory.SelectedValue

C# - Insert Multiple Records at once to AS400

I have a problem like this:
1. I retrieve data from MySQL using C# ASP .Net. -- done --
2. All data from no.1 will be inserted into table on AS400. -- I got an error on this step --
Error message says that ERROR [42000] [IBM][System i Access ODBC Driver][DB2 for i5/OS]SQL0104 - Token ; was not valid. Valid tokens: <END-OF-STATEMENT>.. It's true that I used semicolon to separate queries with each others, but it's not allowed. I've Googling but I can't find the solution.
My question is what the <END-OF-STATEMENT> means of that error message..?
Here is my source code.
private static void doInsertDOCADM(MySqlConnection conn)
{
// Get Temporary table
String query = "SELECT * FROM TB_T_DOC_TEMPORARY_ADM";
DataTable dt = CSTDDBUtil.ExecuteQuery(query);
OdbcConnection as400Con = null;
as400Con = CSTDDBUtil.GetAS400Connection();
as400Con.Open();
if (dt != null && dt.Rows.Count > 0)
{
int counter = 1, maxInsertLoop = 50;
using (OdbcCommand cmd = new OdbcCommand())
{
cmd.Connection = as400Con;
foreach (DataRow dr in dt.Rows)
{
cmd.CommandText += "INSERT INTO DCDLIB.WDFDOCQ VALUES " + "(?,?,?,?);";
cmd.Parameters.Add("1", OdbcType.VarChar).Value = dr["PROD_MONTH"].ToString();
cmd.Parameters.Add("2", OdbcType.VarChar).Value = dr["NEW_MAIN_DEALER_CD"].ToString();
cmd.Parameters.Add("3", OdbcType.VarChar).Value = dr["MODEL_SERIES"].ToString();
cmd.Parameters.Add("4", OdbcType.VarChar).Value = dr["MODEL_CD"].ToString();
if (counter < maxInsertLoop)
{
counter++;
}
else
{
counter = 1;
cmd.ExecuteNonQuery();
cmd.CommandText = "";
cmd.Parameters.Clear();
}
}
if (counter > 1) cmd.ExecuteNonQuery();
}
}
Notes: I used this way (Collect some queries first, and then execute those query) to improve the performance of my application.
As Clockwork-Muse pointed out, the problem is that you can only run a single SQL statement in a command. The iSeries server does not handle multiple statements at once.
If your iSeries server is running V6R1 or later, you can use block inserts to insert multiple rows. I'm not sure if you can do so through the ODBC driver, but since you have Client Access, you should be able to install the iSeries ADO.NET driver. There are not many differences between the ADO.NET iSeries driver and the ODBC one, but with ADO.NET you get access to iSeries specific functions.
With the ADO.NET driver, multiple insert become a simple matter of :
using (iDB2Connection connection = new iDB2Connection(".... connection string ..."))
{
// Create a new SQL command
iDB2Command command =
new iDB2Command("INSERT INTO MYLIB.MYTABLE VALUES(#COL_1, #COL_2", connection);
// Initialize the parameters collection
command.DeriveParameters();
// Insert 10 rows of data at once
for (int i = 0; i < 20; i++)
{
// Here, you set your parameters for a single row
command.Parameters["#COL_1"].Value = i;
command.Parameters["#COL_2"].Value = i + 1;
// AddBatch() tells the command you're done preparing a row
command.AddBatch();
}
// The query gets executed
command.ExecuteNonQuery();
}
}
There is also some reference code provided by IBM to do block inserts using VB6 and ODBC, but I'm not sure it can be easily ported to .NET : http://publib.boulder.ibm.com/infocenter/iseries/v5r4/index.jsp?topic=%2Frzaik%2Frzaikextfetch.htm
Hope that helps.
When it says <END-OF-STATEMENT> it means about what it says - it wants that to be the end of the executed statement. I don't recall if the AS/400 allows multiple statements per execution unit (at all), but clearly it's not working here. And the driver isn't dealing with it either.
Actually, you have a larger, more fundamental problem; specifically, you're INSERTing a row at a time (usually known as row-by-agonizing-row). DB2 allows a comma-separated list of rows in a VALUES clause (so, INSERT INTO <table_name> VALUES(<row_1_columns>), (<row_2_columns>)) - does the driver you're using allow you to provide arrays (either of the entire row, or per-column)? Otherwise, look into using extract/load utilities for stuff like this - I can guarantee you that this will speed up the process.

ado.net query removes file exention when adding string filename to the database

I am using the code below for saving uploaded picture and makigna thumbnail but it saves a filename without the extension to the database, therefore, I get broken links. How can I stop a strongly typed dataset and dataadapter to stop removing the file extension? my nvarchar field has nvarchar(max) so problem is not string length.
I realized my problem was the maxsize in the dataset column, not sql statement parameter, so I fixed it. You may vote to close on this question.
hasTableAdapters.has_actorTableAdapter adp1 = new hasTableAdapters.has_actorTableAdapter();
if (Convert.ToInt16(adp1.UsernameExists(username.Text)) == 0)
{
adp1.Register(username.Text, password.Text,
ishairdresser.Checked, city.Text, address.Text);
string originalfilename = Server.MapPath(" ") + "\\pictures\\" + actorimage.PostedFile.FileName;
string originalrelative = "\\pictures\\" + actorimage.FileName;
actorimage.SaveAs(originalfilename);
string thumbfilename = Server.MapPath(" ") + "\\pictures\\t_" + actorimage.PostedFile.FileName;
string thumbrelative = "\\pictures\\t_" + actorimage.FileName;
Bitmap original = new Bitmap(originalfilename);
Bitmap thumb=(Bitmap)original.GetThumbnailImage(100, 100,
new System.Drawing.Image.GetThumbnailImageAbort(ThumbnailCallback),
IntPtr.Zero);
thumb=(Bitmap)original.Clone(
new Rectangle(new Point(original.Width/2,original.Height/2), new Size(100,100)),
System.Drawing.Imaging.PixelFormat.DontCare);
/*
bmpImage.Clone(cropArea,bmpImage.PixelFormat);
*/
thumb.Save(thumbfilename);
adp1.UpdatePicture(originalrelative, thumbrelative, username.Text);
LoginActor();
Response.Redirect("Default.aspx");
}
}
Looks like the problem is you are using HttpPostedFile.FileName property, which returns fully-qualified file name on the client. So, this code string originalfilename = Server.MapPath(" ") + "\\pictures\\" + actorimage.PostedFile.FileName; generates something like this:
c:\inetpub\pictures\c:\Users\Username\Pictures\image1.jpg
Use FileUpload.FileName property everywhere and you will probably get what you want.
Use this to get Image or file extension :
string Extension = System.IO.Path.GetExtension(FileUpload.FileName);

java.io.FileNotFoundException?

i have written the code of jsp,servlet for uploading the Doc file in database.
here is my code,but i am getting the error like this==java.io.FileNotFoundException: insert into resume(resume) values(?) (The filename, directory name, or volume label syntax is incorrect) .please help me how to remove this error???
try
{
Class.forName("net.sourceforge.jtds.jdbc.Driver").newInstance();
con=DriverManager.getConnection("jdbc:jtds:sqlserver://W2K8SERVER:1433/career","sa","Alpha#123" );
pst = con.prepareStatement("select * from data1 where email=? and password=?");
pst = con.prepareStatement
("insert into resume(resume) "+ "values(?)");
File re = new File("" + pst);
fis = new FileInputStream(re);
pst.setBinaryStream(3, (InputStream)fis, (int)(re.length()));
pst.setString (1,upload);
//rs = pst.executeQuery();
while (rs.next())
cnt ++;
int s = pst.executeUpdate();
if(s>0) {
System.out.println("Uploaded successfully !");
}
else {
System.out.println("unsucessfull to upload image.");
}
rs.close();
pst.close();
con.close();
}
It is because insert into resume(resume) values(?) is probably not the name of a file on your disk.
pst = con.prepareStatement ("insert into resume(resume) "+ "values(?)");
File re = new File("" + pst);
You are creating a File from ""+ pst, which is the result of toString() being called on a PreparedStatement. Did you put in the "" to get rid of the informative compilation error?
You probably have the real filename in some other variable.
File re = new File(theRealFileNameVariable);
File re = new File("" + pst);
please make sure the "pst" value is a valid file path, apparently the value "insert into resume(resume) values(?)" is not a valid file path
The java.io.File class has four (4) constructors
File(File parent, String child)
File(String pathname)
File(String parent, String child)
File(URI uri)
In your case you are trying to pass to the constructor an object or type java.sql.PreparedStatement that you trying to cast into a String. I don't see how (even if you arrived to convert pst into a string) pst will reference a path to a file. Please go back and read a little bit about java.io.
.

Resources