c++ Mysql, can not close a Mysql connection - mysql

I have a function that receives parameters (schema name, column name etc) and updates a Mysql table, the problem is that when I use two Mysql commands inside this function (below), one to set the schema and one to update the table, the Close connection command at the end `(conDataBase3->Close();) does not work.
I am checking the number of open connections in the Mysql console (SHOW FULLPROCESSLIST) before and after running the function. any solutions or explanations? thanks
int simple_1::update_table_with_value(gcroot<String^ > schema, gcroot<String^ > table_name, int numerator, gcroot<String^ > field_to_update, double value_to_update)
{
gcroot<MySqlConnection^ > conDataBase3;
conDataBase3 = gcnew MySqlConnection(constring);
conDataBase3->Open();
try{
String ^ schema_name = "Use " + schema + " ;";
MySqlCommand ^cmdDataBase3 = gcnew MySqlCommand(schema_name, conDataBase3);
MySqlCommand ^cmdDataBase4 = gcnew MySqlCommand(schema_name, conDataBase3);
cmdDataBase3->ExecuteNonQuery();
String ^ temp1 = "UPDATE ";
String ^ temp2 = table_name;
String ^ temp3 = " SET ";
String ^ temp4 = field_to_update;
String ^ temp6 = "=(#value1) WHERE numerator = (#value2)";
String ^ temp8 = temp1 + temp2 + temp3 + temp4 + temp6;
// end of the writing part
cmdDataBase4 = gcnew MySqlCommand(temp8, conDataBase3);
cmdDataBase4->Parameters->AddWithValue("#value1", value_to_update);
cmdDataBase4->Parameters->AddWithValue("#value2", numerator);
cmdDataBase4->Prepare();
cmdDataBase4->ExecuteNonQuery();
}//try
catch (Exception^ ex)
{
System::Windows::Forms::MessageBox::Show(ex->Message);
}
conDataBase3->Close();
int answer = 0;
return (answer);
}

ok found the answer, I needed to disable the pooling option otherwise closing the connection still keeps the socket open..
found it here: http://bugs.mysql.com/bug.php?id=24138 see the last 2 lines.
The way to disable the pooling :
http://www.connectionstrings.com/mysql-connector-net-mysqlconnection/disable-connection-pooling/

Related

Can I run a function for the Lua shell prompt?

I can set the prompt with _PROMPT = "> ", but can I make the prompt update every time?
I tried this, but it doesn't work:
i = 0
function inc()
i = i + 1
return i
end
_PROMPT = inc
This shows _PROMPT, but nothing related:
for k, v in pairs(_G) do
print(k)
end
The primary prompt is the value of the global variable _PROMPT, if this value is a string; otherwise, the default prompt is used.
https://www.lua.org/manual/5.1/lua.html
You assigned a function to _PROMPT.
I tried
_PROMPT = {no = 0}; setmetatable (_PROMPT, {__tostring = function (self) self.no = self.no + 1; return tostring (self.no) .. ' >' end})
, but no luck, although _PROMPT was incremented every time I typed = _PROMPT.
UPD Yet this can be done! In Lua mailing list I was advised to use
setmetatable(_ENV, {__index = function(t, k) if k == '_PROMPT' then t._N = (t._N or 0) + 1; return t._N .. ' >' end end})
It works. This effectively is a way to override any global in a deeper sense than simply to assign a new value to it, or make a set of global variables effectively infinite.
You can start Lua in interactive mode with a one-liner:
lua -i -e "setmetatable(_ENV, {__index = function(t, k) if k == '_PROMPT' then t._N = (t._N or 0) + 1; return t._N .. ' >' end end})"
I found out a method with debug.sethook().
It sounds a bit strange but it is really simple ;-)
Here we go...
# /usr/bin/lua -i
Lua 5.3.5 Copyright (C) 1994-2018 Lua.org, PUC-Rio
> debug.sethook(function(...) _PROMPT=os.date('%H:%M:%S # ') end,'r')
10:49:42 # -- Hiting ENTER some times
10:51:00 #
10:51:01 #
10:51:05 #
( Done with Lua 5.3.5 and tested 5.4 - Should work with 5.1 but not tested )
The 'r' means: Fire on each return
EDIT
Another way directly with _PROMPT and _PROMPT2...
-- Simple method for changing and/or time logging the prompts
_PROMPT=setmetatable({},{__index=table})
_PROMPT2=setmetatable({},{__index=table})
getmetatable(_PROMPT).__tostring=function()
_PROMPT:insert(os.date('%H:%M:%S',os.time())..'> ')
return string.format('%s',_PROMPT:concat(#_PROMPT,#_PROMPT))
end
getmetatable(_PROMPT2).__tostring=function()
_PROMPT2:insert(os.date('%H:%M:%S',os.time())..'>> ')
return string.format('%s',_PROMPT2:concat(#_PROMPT2,#_PROMPT2))
end
...using __tostring and __index has table metamethods.
...much fun and stay healthy.

Groovy withBatch is really slow

I'm trying to use Groovy withBatch function and it's really slow (15 sec). I've tried with different batch sizes (10, 400 ...) and it always take a lot of time doing each batch.
It's the second query that I write with it and there are both slow.
Here's my code. Is there a bug in it or am I using it the wrong way ?
static updateCSProducts(def conn, def webProductRows){
conn.withBatch(400, """
UPDATE cscart_products p
SET usergroup_ids=:usergroup_ids,
b2b_group_ids=:b2b_group_ids,
b2b_desc_hide=:b2b_desc_hide
WHERE product_code = :product_code
OR product_id = (SELECT product_id FROM cscart_product_options_inventory WHERE product_code = :product_code)
""") { ps ->
webProductRows.each({row ->
ProductType type = ProductType.fromCode(row.type)
String userGroupIds = type.getProductAvailabilityUserGroup().collect{it.getId()}.join(",")
String b2bGroupIds = type.getB2bUserGroup().collect{it.getId()}.join(",")
boolean b2bDescHide = !type.getB2bUserGroup().isEmpty()
println row.id + " " + userGroupIds + " " + b2bGroupIds + " " + b2bDescHide
ps.addBatch(product_code:row.id, usergroup_ids:userGroupIds, b2b_group_ids:b2bGroupIds, b2b_desc_hide:b2bDescHide)
})
}
}
I'm using MySql as Database. When I'm looking at SQL connections, I don't really see any connection running a query while I'm waiting for the next batch.
EDIT:
I've removed the queries and it still very slow.
Heres the updated version:
conn.withBatch(400, """
UPDATE cscart_products p
SET usergroup_ids=:usergroup_ids,
b2b_group_ids=:b2b_group_ids,
b2b_desc_hide=:b2b_desc_hide
WHERE p.product_code = :product_code
""") { ps ->
webProductRows.each({row ->
ProductType type = ProductType.fromCode(row.type)
String userGroupIds = type.getProductAvailabilityUserGroup().collect{it.getId()}.join(",")
String b2bGroupIds = type.getB2bUserGroup().collect{it.getId()}.join(",")
String b2bDescHide = !type.getB2bUserGroup().isEmpty() ? 'Y' : 'N'
println row.id + " " + userGroupIds + " " + b2bGroupIds + " " + b2bDescHide
ps.addBatch(product_code:row.id, usergroup_ids:userGroupIds, b2b_group_ids:b2bGroupIds, b2b_desc_hide:b2bDescHide)
})
}
You're running tons of queries on each and every update. You'd be better off retrieving a list of data and then looping over that. It's not withBatch that's the bottleneck, it's your implementation.

Jdbc and MySql not wanting to play nicely together

I have been working on a java application that has a connection to a mysql database. I can connect and run queries but when I try to take a string and run it as a sql query I get this error.
Exception in thread "main" com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: 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 'INSERT INTO usageData (`COMID`,`Year`,`Month`,`kwhr`,`co2`)
VALUES ('15650', '2' at line 3
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:409)
at com.mysql.jdbc.Util.getInstance(Util.java:384)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1054)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3566)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3498)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1959)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2113)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2562)
at com.mysql.jdbc.StatementImpl.executeUpdate(StatementImpl.java:1664)
at com.mysql.jdbc.StatementImpl.executeUpdate(StatementImpl.java:1583)
Bellow is the code that I'm using to connect to the database
public static void main(String[] args) throws Exception {
String dbms = "mysql";
String serverName = "localhost";
String portNumber = "8889";
String DBName = "ConnectDatabase";
String user = "root";
String password = "root";
ArrayList<Integer> yearList = new ArrayList<Integer>();
ArrayList<CustomerRecord> customerRecordList = getCustomerRecords(args[0], yearList);
ArrayList<ClimateRecord> climateRecordList = getClimateRecords(args[1]);
StringBuffer buf = new StringBuffer();
for (CustomerRecord record : customerRecordList) {
buf.append(customerRecord2SQL(record));
}
for (int i = (climateRecordList.size() - 1); i >= 0; i--) {
//for (ClimateRecord record : climateRecordList) {
ClimateRecord record = climateRecordList.get(i);
buf.append(climateRecord2SQL(record));
}
buf.append(cityStats(dbms,serverName,portNumber,DBName,user,password));
buf.append(zipStats(dbms,serverName,portNumber,DBName,user,password));
System.out.println(buf.toString());
//here is the code to go ahead and update the database
Connection con = null;
con = DriverManager.getConnection("jdbc:" + dbms + "://" + serverName + ":" + portNumber + "/" + DBName + "?user="+user+"&password=" + password);
Statement stmt = con.createStatement();
stmt.executeUpdate(buf.toString());
BufferedWriter out = new BufferedWriter(new FileWriter(args[2]));
out.write(buf.toString());
out.close();
}
This is not a connection issue. It means that something is wrong with your SQL statement. Try copying the statement as is and executing it directly in the database. See what is wrong and then correct it in the Java code.
I notice that the single quotes around the field names look fancy. That might be a problem.
Here's what was happening and what everyone else failed to realize. JDBC will not do more than one query at a time I was trying to run several million queries contained in a string buffer which wouldn't work.
Your query should be 'INSERT INTO usageData VALUES (COMID,Year,Month,kwhr,co2);
and btw COMID,year...what are these..?? and why fancy quotes...??

mysql call to libmysql.dll to get my app to automatically reconnect after mysql timeout

I am using autohotkey to make mysql calls. The mysql interface was deciphered by referencing a visual basic api to mysql.
I am using the mysql connect calls referenced in this post: http://www.autohotkey.com/forum/viewtopic.php?t=12482
I would like to add a dllcall to replicate this perl call to mysql_options...
mysql_options(mysql, MYSQL_OPT_RECONNECT, &true);
It is my understanding that this call would enable my program to gracefully reconnect to mysql after the standard 8 hour mysql timeout. I want my application to remain up indefinitely.
Here is my code. A reference on googles source code libary suggests that the reconnect constant is 20. Everything works except the mysql_opt_reconnect call.
Can anyone help me determine the proper call to libmysql.dll to get my app to automatically reconnect after mysql timeout has occurred?
;============================================================
; mysql.ahk
;
; Provides a set of functions to connect and query a mysql database
;============================================================
FileInstall, libmysql.dll, %A_AppData%\libmysql.dll, 1
;============================================================
; Connect to mysql database and return db handle
;
; host = DTWRO-WS0061
; user = alan
; password = *******
; database = rush
;============================================================
dbConnect(host,user,password,database){
if (A_IsCompiled) {
ExternDir := A_AppData
} else {
ExternDir := A_WorkingDir
}
hModule := DllCall("LoadLibrary", "Str", ExternDir "\libmySQL.dll")
If (hModule = 0)
{
MsgBox 16, MySQL Error 233, Can't load libmySQL.dll from directory %ExternDir%
ExitApp
}
db := DllCall("libmySQL.dll\mysql_init", "UInt", 0)
If (db = 0)
{
MsgBox 16, MySQL Error 445, Not enough memory to connect to MySQL
ExitApp
}
; figure out how to turn on reconnect call!
; mysql_options(mysql, MYSQL_OPT_RECONNECT, &true);
value := DllCall("libmySQL.dll\mysql_options"
, "UInt", db
, "UInt", 20 ; is this the correct constant which represents MYSQL_OPT_RECONNECT?... see below
, "UInt", 1) ; true
connection := DllCall("libmySQL.dll\mysql_real_connect"
, "UInt", db
, "Str", host ; host name
, "Str", user ; user name
, "Str", password ; password
, "Str", database ; database name
, "UInt", 3306 ; port
, "UInt", 0 ; unix_socket
, "UInt", 0) ; client_flag
If (connection = 0)
{
HandleMySQLError(db, "Cannot connect to database")
Return
}
serverVersion := DllCall("libmySQL.dll\mysql_get_server_info", "UInt", db, "Str")
;MsgBox % "Ping database: " . DllCall("libmySQL.dll\mysql_ping", "UInt", db) . "`nServer version: " . serverVersion
return db
}
;============================================================
; mysql error handling
;============================================================
HandleMySQLError(db, message, query="") { ; the equal sign means optional
errorCode := DllCall("libmySQL.dll\mysql_errno", "UInt", db)
errorStr := DllCall("libmySQL.dll\mysql_error", "UInt", db, "Str")
MsgBox 16, MySQL Error: %message%, Error %errorCode%: %errorStr%`n`n%query%
Return
}
;============================================================
; mysql get address
;============================================================
GetUIntAtAddress(_addr, _offset)
{
local addr
addr := _addr + _offset * 4
Return *addr + (*(addr + 1) << 8) + (*(addr + 2) << 16) + (*(addr + 3) << 24)
}
;============================================================
; process query
;============================================================
dbQuery(_db, _query)
{
local resultString, result, requestResult, fieldCount
local row, lengths, length, fieldPointer, field
query4error := RegExReplace(_query , "\t", " ") ; convert tabs to spaces so error message formatting is legible
result := DllCall("libmySQL.dll\mysql_query", "UInt", _db , "Str", _query)
If (result != 0) {
errorMsg = %_query%
HandleMySQLError(_db, "dbQuery Fail", query4error)
Return
}
requestResult := DllCall("libmySQL.dll\mysql_store_result", "UInt", _db)
if (requestResult = 0) { ; call must have been an insert or delete ... a select would return results to pass back
return
}
fieldCount := DllCall("libmySQL.dll\mysql_num_fields", "UInt", requestResult)
Loop
{
row := DllCall("libmySQL.dll\mysql_fetch_row", "UInt", requestResult)
If (row = 0 || row == "")
Break
; Get a pointer on a table of lengths (unsigned long)
lengths := DllCall("libmySQL.dll\mysql_fetch_lengths" , "UInt", requestResult)
Loop %fieldCount%
{
length := GetUIntAtAddress(lengths, A_Index - 1)
fieldPointer := GetUIntAtAddress(row, A_Index - 1)
VarSetCapacity(field, length)
DllCall("lstrcpy", "Str", field, "UInt", fieldPointer)
resultString := resultString . field
If (A_Index < fieldCount)
resultString := resultString . "|" ; seperator for fields
}
resultString := resultString . "`n" ; seperator for records
}
; remove last newline from resultString
resultString := RegExReplace(resultString , "`n$", "")
Return resultString
}
It took me while to think outside the box, but I finally found a solution that works very well.
I simply added a settimer command to re-connect to the mysql database after 8 hours. 8 hours is the default database connection timeout.
Now the AHK app can remain running indefinitely and is always connected to the database!
Even better... I used an oop class to retain the mysql connection parameters, so that when the mysql connection timed out and a new mysql call is made, it can automatically reconnect.

c# console application backup mysql

I try to use this code as a console application so that I can back up mydatabase automatics
I am not sure what wrong with it
static void Main(string[] args)
{
try
{
DateTime backupTime = DateTime.Now;
int year = backupTime.Year;
int month = backupTime.Month;
int day = backupTime.Day;
int hour = backupTime.Hour;
int minute = backupTime.Minute;
int second = backupTime.Second;
int ms = backupTime.Millisecond;
String tmestr = backupTime.ToString();
tmestr = "C:\\" + year + "-" + month + "-" + day + "-" + hour + "-" + minute + ".sql";
StreamWriter file = new StreamWriter(tmestr);
ProcessStartInfo proc = new ProcessStartInfo();
string cmd = string.Format(#"-u{0} -p{1} -h{2} {3} > {4};", "root", "", "localhost", "dbfile", "backup.sql");
proc.FileName = "mysqldump";
proc.RedirectStandardInput = false;
proc.RedirectStandardOutput = true;
proc.Arguments = cmd;//"-u root -p smartdb > testdb.sql";
proc.UseShellExecute = false;
Process p = Process.Start(proc);
string res;
res = p.StandardOutput.ReadToEnd();
file.WriteLine(res);
p.WaitForExit();
file.Close();
}
catch (IOException ex)
{
MessageBox.Show("Disk full or other IO error , unable to backup!");
}
}
Since I'm not sure what kind of error you're geting, atleast this could be changed.
string cmd = string.Format(#"-u{0} -p{1} -h{2} {3} > {4};", "root", "", "localhost", "dbfile", "backup.sql");
Later you commented it should be -u root -p smartdb > testdb.sql";
except the above, is missing the space after the -u so I'd change it to:
string cmd = string.Format(#"-u {0} -p {1} -h {2} {3} > {4};", "root", "", "localhost", "dbfile", "backup.sql");
Why are you creating a StreamWriter and trying to get the output of mysqldump, Why not just tell mysqldump to write to the backup file itself?
string cmd = string.Format(#"-u{0} -p{1} -h{2} {3} > ""{4}"";",
"root", "", "localhost", "dbfile", tmestr);
for starters i would change how you're outputting the information. You're essentially opening a file so you can redirect the backup utility's output to that file. The > in your process call is for that very purpose. Just change your "backup.sql" parameter to tmestr.
Also, because the output is already being redirected to a file, your process won't have anything to return. But because we're now having it dump to the correct path, this should be irrelevant.
One final change, add a space between your -u{0} so it's -u {0}. And the same with -h{2}.
In summary:
remove StreamWriter and all variables associated to it
modify the String.Format in your process arguments to use `tmestr
add spaces in your cmd variable for -u&-h
And you should be good-to-go (assuming it's not a problem with locating the mysqldump executable.