This code looks like using all the system memory. Why does it happend?
sql::Statement *Query;
sql::ResulSet *Result;
while(1){
Query = con->createStatement();
Result = Query->executeQuery("SELECT `Some` FROM `Table` LIMIT 1");
Result->next();
Result->close();
Query->close();
cout << "console message..." << endl;
//delete Query; SEGFAULT
}
If i comment all the lines except the cout the memory doesn't get filled. But using the SQL looks like Query = con->createStatement; is not replacing the old Query value and Result = bla; is not replacing the old value
createStatement() and executeQuery are creating new objects (which are the ones you store in Query and Result. Unless you explicitly delete them, they will remain in memory.
Add
delete Result;
delete Query;
To your loop.
BTW, this is in the connector documentation (together with sample code).
Well it looks like there is no info on google. I found what was the problem.
as SJuan76 said each call to createStatement and to executeQuery is a new object
So i started to do a lot of tryes and i figure out of the following
Use createStatement just once
Before deleting Result check if it's open and close
Delete Respuesta
Only delete con and Query at the end of the program auto_ptr(is your friend sometimes)
So the code to get the "forever running" program to use always the same memory shoud look like this
sql::Statement *Query;
sql::ResulSet *Result;
Query = con->createStatement();
while(1){
if(!Result->isClosed()) Result->close();
delete Result;
Result = Query->executeQuery("SELECT `Some` FROM `Table` LIMIT 1");
Result->next();
cout << "console message..." << endl;
}
Related
I have been trying to load an SQL database into a datatable in C++, however; it doesn't seem to want to work. The connection is working though, as DataReader works. Here is my code
void importDatabase() {
SqlConnection con;
SqlDataAdapter^ da;
SqlCommand cmd;
DataTable^ dt;
int count = 1;
try {
con.ConnectionString = "Data Source=MYNAME\\SQLEXPRESS;Initial Catalog=VinylRecords;Integrated Security=True";
cmd.CommandText = "SELECT * FROM Records";
cmd.Connection = %con;
con.Open();
da = gcnew SqlDataAdapter(%cmd);
dt = gcnew DataTable("Records");
Console::Write(da->ToString());
da->Fill(dt);
for (int i = 0; i < dt->Rows->Count - 1; i++) {
String^ value_string;
value_string = dt->Rows[i]->ToString();
Console::WriteLine(dt->Rows[i]->ToString());
count++;
}
cout << "There are " << count << " many records";
}
catch (Exception^ ex) {
Console::WriteLine(ex->ToString());
}
}
Please note, that I slightly altered the source name to post here, but only the first part.
What is wrong with my code?
So, the problem is here:
dt->Rows[i]->ToString()
Rows[i] is a Row object. And the Row class's ToString() method always prints out the fully qualified typename, which is what you are seeing. So this is technically working just fine. What you will need to do to get something useful is: you will need to access a specific column in that row and get it's value, then output that.
Something along the lines of:
foreach (DataRow dr in dt.Rows)
{
Console.Write(dr.Field<int>("ColumnOne"));
Console.Write(" | ");
Console.WriteLine(dr.Field<string>("ColumnTwo"));
}
I am not entirely sure on the syntax for accessing a specific cell inside of a DataTable when using C++\CLI. So I have provided the C# equivalent to explain why it is you were getting output of managed type names (e.g. "System.Data.DataRow") instead of the info inside of the Row's columns.
Also, I noticed you tagged this question with "mysql", but you are using the ADO.NET System.Data.SqlClient namespace. The SqlDataReader and SqlDataAdapter classes only work with TSQL (Microsoft's SQL Server databases) If you are actually connecting to a mysql database you will want to use the System.Data.OdbcDataAdapter class. You can read a little more here: https://msdn.microsoft.com/en-us/library/ms254931.aspx
I created a new TYPE in Oracle in order to have parity between my table and a local c++ object (I am using OCCI interface for C++).
In the code I use
void insertRowInTable ()
{
string sqlStmt = "INSERT INTO MY_TABLE_T VALUES (:x)";
try{
stmt = con->createStatement (sqlStmt);
ObjectDefinition *o = new ObjectDefinition ();
o->setA(0);
o->setB(1);
o->setC(2);
stmt->setObject (1, o);
stmt->executeUpdate ();
cout << "Insert - Success" << endl;
delete (o);
}catch(SQLException ex)
{
//exception code
}
The code compiles, connects to db but throws the following exception
Exception thrown for insertRow Error number: 947 ORA-00947: not enough
values
Do I have a problematic "sqlStmt"? Is something wrong with the syntax or the binding?
Of course I have already setup an environment and connection
env = Environment::createEnvironment (Environment::OBJECT);
occiobjm (env);
con = env->createConnection (user, passwd, db);
How many columns are in the table? The error message indicates that you didn't provide enough values in the insert statement. If you only provide a VALUES clause, all columns in the table must be provided. Otherwise you need to list each of the columns you're providing values for:
string sqlStmt = "INSERT INTO MY_TABLE_T (x_col) VALUES (:x)";
Edit:
The VALUES clause is listing placeholder arguments. I think you need to list one for each value passed, e.g.:
string sqlStmt = "INSERT INTO MY_TABLE_T (GAME_ID, VERSION) VALUES (:x1,:x2)"
Have a look at occidml.cpp in the Oracle OCCI docs for an example.
I have 2 variables, and I want to insert their values into a MySQL database, but I don't know how to do this.
Here is the all of my code so far, please correct/advise:
void RegistrationForm::Register()
{
istifadeciAdi.GetWindowText(i_ad);
par.GetWindowText(i_par);
parTekrar.GetWindowText(i_par_tekrar);
if (istifadeciAdi.GetWindowTextLength() != 0) // if you can please write this line better.
{
if (i_parol == i_parol_tekrar)
{
MySQL_Driver *driver;
Connection *dbConn;
Statement *statement;
//ResultSet *result; // I don't need this line any more
//PreparedStatement *ps;
driver = get_mysql_driver_instance();
dbConn = driver->connect("host", "u", "c");
dbConn->setSchema("mfc_app_database");
statement = dbConn->createStatement();
statement->executeQuery("INSERT INTO users(`username`, `password`) VALUES (/* how to use i_ad and i_par as variable to set column value? */)"); // executes the user "input"
/*ps = dbConn->prepareStatement("INSERT INTO users(`username`, `password`, `name`) VALUES (?)");
ps->setString(1, "cccc");
ps->setString(2, "ffff);*/
//delete result;
//delete[] result;
/*delete ps;
delete[] ps;*/
delete statement;
delete[] statement; // don't use this line in your program as me
delete dbConn;
delete[] dbConn; // don't use this line in your program as me
}
else
MessageBox(L"Şifrə dəqiq təkrar olunmalıdır.", L"Xəbərdarlıq", MB_ICONWARNING);
}
else
AfxMessageBox(L"Boş qoymaq olmaz.");
}
Edit
There's no any error. But when I clicked the (Register) button it says:
Program stopped working
and after clicking the Debug button it takes me to line which insert query I wrote.
p.s Sorry for my poor English.
Use CString to make query.
For example:
CString strQuery;
strQuery.Format(_T("INSERT INTO users(`username`, `password`) VALUES ('%s', '%s')"),i_ad, i_par);
Before using this query string in executeQuery (or in other query commands) you must convert it to std::string. Because, execute, executeQuery and executeUpdate commands only accepts the std::string.So, add this lines:
CT2CA tempString(query);
std::string query(tempString);
And use this string in your execute command
statement->executeQuery(query);
The docs for that MySQL connector say to use statement::execute() for queries that don't return a resultset, and statement::executeQuery() when there is a single row resultset.
So for SQL INSERT INTO maybe your problem is that you should be using execute.
I want to run SQL script from a C++ program. my code goes like this:
int main()
{
//.....
sql_stmt = "Insert into t1 values ('qwerty');\nInsert into t1 values ('dothar');"
"//and many more INSERT statements";
sql_stmt = "DECLARE\nrollback_check_counter number;\n"
"BEGIN\n"
"rollback_check_counter :=1;\n"
"SAVEPOINT sp_1;\nIF rollback_check_counter = 1 THEN\n"
"BEGIN\n"+sql_stmt+"EXCEPTION\n"
"WHEN PROGRAM_ERROR THEN\n"
"rollback_check_counter :=0;\n"
"ROLLBACK TO sp_1;\n"
"WHEN OTHERS THEN\n"
"rollback_check_counter :=0;\n"
"ROLLBACK TO sp_1;\n"
"END;\n"
"END IF;\n"
"commit;\n"
"END;";
try
{
Connection *conn = env->createConnection(user,passwd); //error prone
Statement *stmt = conn->createStatement();
stmt->setSQL(sql_stmt);
row_count = stmt->execute(); //stmt->execute(sql_stmt);
Connection::conn->terminateStatement(Statement *stmt);
//con->terminateStatement(stmt);
env->terminateConnection(conn);
Environment::terminateEnvironment(env);
}
catch(SQLException& ex)
{}
//.....
return 0;
}
Although when i run these insert statement only they fairly run well but when i forms a SQL Script structure they seems to fail. I want to do so because i want to implement rollback. What am i missing? Could anyone suggest any alternative to implement it.
There are ; missing after both ROLLBACK TO sp_1
I'd need some advice how to handle transactions with Informix CSDK and OIC++.
conn is a open connection object. Select works find. The database here is setup with logging — as I found out while update stmt on its own does nothing.
Here's what I tried:
conn.SetTransaction( ITConnection::BEGIN );
qtext = "UPDATE transit_kunde_s SET erledigt='Y' WHERE transitkunde='"+ts+"'";
cout << qtext << endl;
code = query_up.ExecForStatus(qtext.c_str());
cout << "code " << code << endl;
conn.SetTransaction( ITConnection::COMMIT );
okay once again I answer myself...
from Informix C++ DocNotes
Operations can now be performed on large objects within a fetched row even though the connection is still checked out (locked). A connection is checked out after the ITQuery::ExecForIteration() method returns multiple rows in the result set. It remains checked out until either the last row in the result set has been fetched with ITQuery::NextRow() or the query processing has been terminated by calling ITQuery::Finish(). While a connection is checked out, no other query can be executed on that connection.
So as I am in the while loop of one query result iteration I need for another update query a new connection
// already have 2 connection objects: conn, conn2
ITQuery query(conn);
ITQuery query_up(conn2);
string qtext;
qtext = "SELECT * FROM transit_kunde_s WHERE erledigt='N' ORDER BY transitkunde";
okay = query.ExecForIteration(qtext.c_str());
while (row = query.NextRow()) {
// do stuff
// NOW WANT TO DO ANOTHER QUERY? --> NEED ANOTHER CONNECTION!!
ok_ta = conn2.SetTransaction( ITConnection::BEGIN);
qtext = "UPDATE transit_kunde_s SET erledigt='Y' WHERE transitkunde='"+ts+"'";
code = query_up.ExecForStatus(qtext.c_str());
ok_ta = conn2.SetTransaction( ITConnection::COMMIT );
}
// we see later the 1st query to be finished here
query.Finish();