Speed up MySQL Update - InnoDB - c++

I wouldn't think an update of 22*1000 values of type DOUBLE should take ~4 seconds. However that is what I am getting. The following is query is done 22 times. Perhaps this is actually on par? It doesn't satisfy my speed requirements then.
UPDATE [some table] SET [some column] = (CASE WHEN [column1] = i THEN [some number]
concatenated through i=1:1:1000, ending with END);
This statement takes ~4/22 seconds.
Remedies I have tried:
Lock table before update, and unlock after.
Thoughts to help(yet to try):
Reduce update into smaller update queries.
Additional Info:
Engine: InnoDB,
C++ Connector
EDIT 1
Code Excerpt:
Query ="LOCK TABLES CANS_SQL.SortingIndices WRITE;";
stmt = con->createStatement();
bool LOCKBIT = stmt->execute(Query);
delete stmt;
Query.clear();
Query = "UPDATE SortingIndices SET " + Objects.at(Typ).GetMetricNames().at(ObjMetIndex) + "_KVector = ( CASE ";
for (int k = 0; k<kvector.size()-1; k++)
{
while(true)
{
if(InsertCount<KvectorInsertPos.size())
{
if (KvectorInsertPos.at(InsertCount)==k)
{
Query += "WHEN Sort_ID = " + std::to_string(k+1+InsertCount) + " THEN " + std::to_string(KvectorInsertVal.at(InsertCount)+InsertCount) + " ";
InsertCount++;
}
else
break;
}
else
break;
}
Query += "WHEN Sort_ID = " + std::to_string(k+1+InsertCount) + " THEN " + std::to_string(kvector.at(k)+InsertCount) + " ";
}
while(true)
{
if(InsertCount<KvectorInsertPos.size())
{
if (KvectorInsertPos.at(InsertCount)==kvector.size()-1)
{
Query += "WHEN Sort_ID = " + std::to_string(kvector.size()+InsertCount) + " THEN " + std::to_string(KvectorInsertVal.at(InsertCount)+InsertCount) + " ";
InsertCount++;
}
else
break;
}
else
break;
}
Query += "WHEN Sort_ID = " + std::to_string(kvector.size()+InsertCount) + " THEN " + std::to_string(kvector.at(kvector.size()-1)+InsertCount) + " END ) ";
stmt = con->createStatement();
stmt->executeUpdate(Query);
delete stmt;
EDIT 2
Example Query:
Query = "UPDATE SortingIndices
SET X_Centroid_Sort_Index = (CASE
WHEN Sort_ID = 1 THEN 1.4324
WHEN Sort_ID = 2 THEN 4.234
WHEN Sort_ID = 3 THEN 324
...
WHEN Sort_ID = 1000 THEN 232.4 END);

Related

Mysql.h 0 results after query

I made this:
int querystate;
std::string pol;
std::string login;
std::cout << "login: ";
std::cin >> login;
pol = "select * from table where login = '" + login + "';";
querystate = mysql_query(conn, pol.c_str());
if (querystate != 0)
{
std::cout << mysql_error(conn);
}
res = mysql_store_result(conn);
while ((row = mysql_fetch_row(res)) != NULL)
{
std::cout << row[0] << " " << row[1] << " " << row[2];
}
It is possible to make something like this?
if (res == 0)
{
cout<<"there is 0 results";
}
I want to output text when query returns 0 results, for example:
there is no such login in the database.
First, your code is open to an SQL injection attack. You need to escape the login string using mysql_real_escape_string_quote(), eg:
std::string escapeStr(MYSQL *mysql, const std::string &str, char quoteChar)
{
std::string out((str.size()*2)+1, '\0');
unsigned long len = mysql_real_escape_string_quote(mysql, out.data(), str.c_str(), str.size(), quoteChar);
out.resize(len);
return out;
}
std::string pol = "select * from table where login = '" + escapeStr(conn, login, '\'') + "';";
Though, you really should be using a prepared statement instead, let MySQL handle the escaping for you.
Second, the mysql_query() documentation says:
To determine whether a statement returns a result set, call mysql_field_count(). See Section 5.4.23, “mysql_field_count()”.
Where the mysql_field_count() documentation says:
The normal use of this function is when mysql_store_result() returned NULL (and thus you have no result set pointer). In this case, you can call mysql_field_count() to determine whether mysql_store_result() should have produced a nonempty result. This enables the client program to take proper action without knowing whether the query was a SELECT (or SELECT-like) statement. The example shown here illustrates how this may be done.
See Section 3.6.8, “NULL mysql_store_result() Return After mysql_query() Success”.
And that last document says:
It is possible for mysql_store_result() to return NULL following a successful call to to the server using mysql_real_query() or mysql_query(). When this happens, it means one of the following conditions occurred:
There was a malloc() failure (for example, if the result set was too large).
The data could not be read (an error occurred on the connection).
The query returned no data (for example, it was an INSERT, UPDATE, or DELETE).
You can always check whether the statement should have produced a nonempty result by calling mysql_field_count(). If mysql_field_count() returns zero, the result is empty and the last query was a statement that does not return values (for example, an INSERT or a DELETE). If mysql_field_count() returns a nonzero value, the statement should have produced a nonempty result. See the description of the mysql_field_count() function for an example.
So, for example:
std::string login;
std::cout << "login: ";
std::cin >> login;
std::string pol = "select * from table where login = '" + escapeStr(conn, login, '\'') + "';";
if (mysql_query(conn, pol.c_str()) != 0)
{
std::cout << mysql_error(conn);
}
else if ((res = mysql_store_result(conn)) != NULL)
{
while ((row = mysql_fetch_row(res)) != NULL)
{
std::cout << row[0] << " " << row[1] << " " << row[2];
}
mysql_free_result(res);
}
else if (mysql_field_count(conn) == 0)
{
std::cout << "there are 0 results";
}
else
{
std::cout << mysql_error(conn);
}
Alternatively, the documentation also says:
An alternative is to replace the mysql_field_count(&mysql) call with mysql_errno(&mysql). In this case, you are checking directly for an error from mysql_store_result() rather than inferring from the value of mysql_field_count() whether the statement was a SELECT.
std::string login;
std::cout << "login: ";
std::cin >> login;
std::string pol = "select * from table where login = '" + escapeStr(conn, login, '\'') + "';";
if (mysql_query(conn, pol.c_str()) != 0)
{
std::cout << mysql_error(conn);
}
else if ((res = mysql_store_result(conn)) != NULL)
{
while ((row = mysql_fetch_row(res)) != NULL)
{
std::cout << row[0] << " " << row[1] << " " << row[2];
}
mysql_free_result(res);
}
else if (mysql_errno(conn) == 0)
{
std::cout << "there are 0 results";
}
else
{
std::cout << mysql_error(conn);
}
From the documentation available in this site https://dev.mysql.com/doc/c-api/5.7/en/mysql-fetch-row.html
When used after mysql_store_result(), mysql_fetch_row() returns NULL if there are no more rows to retrieve.
so use that to verify whether the data has rows or not. Since doing this once would have fetched a row already, you need to print them immediately before trying to get another row from the DB.
row = mysql_fetch_row(res)
if( row == NULL ) // This verifies whether data is NULL or not
cout << " There is no Results "<<endl
else {
do
{
std::cout << row[0] << " " << row[1] << " " << row[2];
}
while (row = mysql_fetch_row(res)) != NULL)
}

Data management outputted from a transaction

I have a smart contract in which I simulate an event through a set that manually inputs certain data like this: (I use Remix)
[ "From", "to", "object", [ "rules1", "rules2"]], [[1, "data1"], [2, "data2"], [3, "data3"]]
This is my code:
pragma experimental "v0.5.0";
pragma experimental ABIEncoderV2;
contract StructContract {
struct Certificate{
uint id;
string data;
}
struct StructEvent {
string _from;
string _to;
string _object;
string[] _rules;
}
StructEvent structEvent;
Certificate[] certificate;
function setEvent(StructEvent eventS,Certificate[] eventC) public{
certificate.length=0;
structEvent = eventS;
for(uint i=0;i<(eventC.length);i++){
certificate.push(Certificate(eventC[i].id,eventC[i].data));
}
}
function getStruct() view public returns(StructEvent){
return(structEvent);
}
function getCertificate() view public returns(Certificate[]){
return(certificate);
}
function returnAllData() view public returns(StructEvent,Certificate[]){
return(structEvent,certificate);
}
}
once this is done, what I expect is that these data are put into a transaction that is then uploaded to blockchain. Then I have to take the data in these transactions to perform checks on them.
So I need to have data that are put on blockchain, as a solution to this problem I created this code: (I use web3 1.0.0-beta.36)
function printTransaction(txHash) {
web3.eth.getTransaction(txHash, function (error, tx) {
if (tx != null) {
var inputData = tx.input;
try {
var myContract = new web3.eth.Contract(abi, tx.to);
var result = web3.eth.abi.decodeParameters(['tuple(string,string,string,string[])',
'tuple(uint,string)[]'], inputData.slice(10));
var data1 = result[0];
var data2 = result[1];
console.log("\n\n");
console.log("--- transactions ---");
console.log(" tx hash : " + tx.hash + "\n"
+ " nonce : " + tx.nonce + "\n"
+ " blockHash : " + tx.blockHash + "\n"
+ " blockNumber : " + tx.blockNumber + "\n"
+ " transactionIndex: " + tx.transactionIndex + "\n"
+ " from : " + tx.from + "\n"
+ " to : " + tx.to + "\n"
+ " value : " + tx.value + "\n"
+ " gasPrice : " + tx.gasPrice + "\n"
+ " gas : " + tx.gas + "\n"
+ " input : " + tx.input + "\n"
+ " decodeinput : " + "\n"
+ " Struct : " + data1 + "\n"
+ " Certificates : " + data2);
web3.eth.getAccounts(function (err, account) {
myContract.methods.setEvent(data1, data2).send({ from: account[0], gas: 3000000 }, function (err, resul) {
if (err) {
console.log("err");
} else {
console.log("\n\n");
console.log("--- data ---");
myContract.methods.returnAllData().call().then(console.log);
}
});
});
} catch (Error) { }
}
});
}
What I decided to do is create, in a js file, a method that was able to take the transactions, decode the input related to the data contained in it and pass this data, through the send, to my smart contract in which it will be used.
these methods that I created represent the right solution? or I have to use another kind of approach, another method to do this?
Thanks in advance.

Why won't my function execute

I'm relatively new to python and the only other experience I've had is C++. Whenever I define a function in Python, I can't seem to execute it.
This my current code for my assignment, if possible I just want to know why my code won't execute
def birthexp(birthyear):
product = birthyear**birthyear
length = len(str(product))
onesCount = str(product).count("1")
threeCount = str(product).count("3")
fiveCount = str(product).count("5")
sevenCount = str(product).count("7")
nineCount = str(product).count("9")
sumCount = onesCount+threeCount+fiveCount+sevenCount+nineCount
oneRation = onesCount/float(length)*100
threeRatio = threeCount/float(length)*100
fiveRatio = fiveCount/float(length)*100
sevenRatio = sevenCount/float(length)*100
nineRatio = nineCount/float(length)*100
totalRatio = sumCount/float(length)*100
print(str(product) + ": product after multiplying the birth year to itself.")
print(str(onesCount) + ": number of ones found at a rate of " +str(oneRation)+ "percent.")
print(str(threeCount) + ": number of threes found at a rate of " +str(threeRatio)+ "percent")
print(str(fiveCount) + ": number of fives found at a rate of " +str(fiveRatio)+ "percent")
print(str(sevenCount) + ": number of sevens found at a rate of " +str(sevenRatio)+ "percent")
print(str(nineCount) + ": number of nine found at a rate of " +str(nineRatio)+ "percent")
print(str(sumCount) + ": total odd numbers found at a rate of " +str(totalRatio)+ "percent")
birthyear(1990)
You have a typo in this line totalRatio = sumCount/floar(length)*100. You need float instead of floar.
Secondly, you have loads of missing parenthesis in almost all lines with the print function.
If you want the function to return value, you should use return instead of print's:
return (str(product)
+ ": product after multiplying the birth year to itself.\n"
+ str(onesCount)
+ ": number of ones found at a rate of " + str(oneRation) + "percent.\n"
+ str(threeCount)
+ ": number of threes found at a rate of " + str(threeRatio) + "percent\n"
+ str(fiveCount)
+ ": number of fives found at a rate of " + str(fiveRatio) + "percent\n"
+ str(sevenCount)
+ ": number of sevens found at a rate of " + str(sevenRatio) + "percent\n"
+ str(nineCount)
+ ": number of nine found at a rate of " + str(nineRatio) + "percent\n"
+ str(sumCount)
+ ": total odd numbers found at a rate of " + str(totalRatio) + "percent\n")

Issues with strings and char arrays in C++

I'm writing a registry generator as a part of a bigger program. I'm very new in C++, but good at other programming languages like PHP.
I'll start by providing the code of the problematic function:
void generacionAleatoria() {
string r_marca, r_nom, r_apellido;
char r_patente[6];
int num_rand;
registroAuto r_auto;
string nombres[8] = {
"Juan", "Pedro", "Roberto", "Miguel", "Guillermo", "Emilio", "Roque", "Gustavo"
} ;
string apellidos[8] = {
"Messi", "Maradona", "Gardel", "Heredia", "Pimpinela", "Nadal", "Mascherano", "Troilo"
};
string marcas[12] = {
"Volvo", "Renault", "Audi", "Ford", "Fiat", "Chevrolet", "Nissan", "Volkswagen", "Mercedes Benz", "Rolls Royce", "Delorean", "Aston Martin"
};
char letras_patentes[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char numeros_patentes[] = "0123456789";
for (int i = 0; i < cantidad_autos; i++) {
r_marca = marcas[rand() % (sizeof(marcas)/sizeof(marcas[0]) - 1)];
r_nom = nombres[rand() % (sizeof(nombres)/sizeof(nombres[0]) - 1)];
r_apellido = apellidos[rand() % (sizeof(apellidos)/sizeof(apellidos[0]) - 1)];
for(int m = 0; m < 3; ++m) {
r_patente[m] = letras_patentes[rand() % (sizeof(letras_patentes) - 1)];
}
for(int n = 3; n < 6; n++) {
r_patente[n] = numeros_patentes[rand() % (sizeof(numeros_patentes) - 1)];
}
strcpy(r_auto.patente,r_patente);
strcpy(r_auto.marca,r_marca.c_str());
strcpy(r_auto.apellido,r_apellido.c_str());
strcpy(r_auto.nom,r_nom.c_str());
fwrite(&r_auto,sizeof(registroAuto),1,archivo);
if (ver_variables_testeo) {
//cout << (i+1) << ") " << r_auto.patente<<endl;
cout << (i+1) << ") " << r_auto.marca << " - " << r_auto.patente << " - " << r_auto.nom << " " << r_auto.apellido << endl; //Para testear
}
}
}
This creates 100 structs of the following type:
struct registroAuto {
char marca[15];
char patente[6];
char nom[25];
char apellido[25];
};
In case you're wondering, this is meant to be a registry of Uber drivers and their cars: brand, license plate, name and surname. Well, it's not really a registry, it's college homework.
The problem is that when I print out the contents of my new struct, the license plate and the name will be together, as in:
100) Fiat - KWQ293Maria - Maria Gardel
You can see by the position of the hyphens, that the license plate is now "KWQ293Maria", even though it is an array of 6 chars!
A reminder of the cout command:
cout << (i+1) << ") " << r_auto.marca << " - " << r_auto.patente << " - " << r_auto.nom << " " << r_auto.apellido << endl;
I did some tests, but I don't know what to do with the results.
1: commenting out the strcopy of the name fixes the issue
strcpy(r_auto.patente,r_patente);
strcpy(r_auto.marca,r_marca.c_str());
strcpy(r_auto.apellido,r_apellido.c_str());
//strcpy(r_auto.nom,r_nom.c_str());
As you can see, this is the last of the 4 statements in my original code, so I don't know why it would affect r_auto.patente.
Can you please help me? I'm guessing there's a key concept of char array handling that I missed out on in class :-(
When using character arrays as strings they need to be terminated by a null character '\0'. So when you construct your number-plate you need to make the array 7 characters long.
struct registroAuto {
char marca[15];
char patente[7]; // 6 for numbers, 1 for terminator '\0'
char nom[25];
char apellido[25];
};
Same with your working variable:
char r_patente[7];
And you need to manually add the null-terminator when you create the number:
for(int m = 0; m < 3; ++m) {
r_patente[m] = letras_patentes[rand() % (sizeof(letras_patentes) - 1)];
}
for(int n = 3; n < 6; n++) {
r_patente[n] = numeros_patentes[rand() % (sizeof(numeros_patentes) - 1)];
}
r_patente[6] = '\0'; // add the null terminator

Try catch trouble in netbeans

I'm trying to create a search engine that gets information from my SQL database. Right now I'm struggling to make the combobox and textfield work. So far I can only make the first part of the code work, it allows the user to search for a name in the database. The rest however doesn't work at all, resulting in just an empty window where the info should pop up.
Here are some translations of the Swedish words present in the code:
Namn - Name
sokt - Searched
ANSTALLD - Employee
Aid - Employee id
telefon - phone
try
{
if(jComboBoxSokAID.getSelectedItem().equals("Namn"))
{
String namn = jTextFieldSokText.getText();
String namnQuery = "select * from ANSTALLD where namn = '" + namn + "'";
try
{
HashMap <String, String> soktNamn = idb.fetchRow(namnQuery);
jTextAreaSpecialistInfo.setText("Namn: " + soktNamn.get("namn") + "\n" + "Aid: " + soktNamn.get ("aid") + "\n" + "Telefon: " + soktNamn.get ("telefon") + "\n" + "Mail: " + soktNamn.get ("mail"));
if(jComboBoxSokAID.getSelectedItem().equals("Mail"))
{
String mail = jTextFieldSokText.getText();
String mailQuery = "select * from ANSTALLD where mail = '" + mail + "'";
try
{
HashMap <String, String> soktMail = idb.fetchRow(mailQuery);
jTextAreaSpecialistInfo.setText("Namn: " + soktMail.get("namn") + "\n" + "Aid: " + soktMail.get ("aid") + "\n" + "Telefon: " + soktMail.get ("telefon") + "\n" + "Mail: " + soktMail.get ("mail"));
if(jComboBoxSokAID.getSelectedItem().equals("Telefon"))
{
String telefon = jTextFieldSokText.getText();
String telefonQuery = "select * from ANSTALLD where telefon = '" + telefon + "'";
try
{
HashMap <String, String> soktTelefon = idb.fetchRow(telefonQuery);
jTextAreaSpecialistInfo.setText("Namn: " + soktTelefon.get("namn") + "\n" + "Aid: " + soktTelefon.get ("aid") + "\n" + "Telefon: " + soktTelefon.get ("telefon") + "\n" + "Mail: " + soktTelefon.get ("mail"));
if(jComboBoxSokAID.getSelectedItem().equals("AID"))
{
String AID = jTextFieldSokText.getText();
String AIDQuery = "select * from ANSTALLD where aid = '" + AID + "'";
try
{
HashMap <String, String> soktAID = idb.fetchRow(AIDQuery);
jTextAreaSpecialistInfo.setText("Namn: " + soktAID.get("namn") + "\n" + "Aid: " + soktAID.get ("aid") + "\n" + "Telefon: " + soktAID.get ("telefon") + "\n" + "Mail: " + soktAID.get ("mail"));
}
catch (InformatikException e)
{
if(jComboBoxSokAID == null)
jTextAreaSpecialistInfo.setText("Sökningen gav inga resultat");
}
}
}
catch (InformatikException e)
{
}
}
}
catch (InformatikException e)
{
}
}
}
catch (InformatikException e)
{
}
Don't write code this way.
Never have empty catch blocks.
I prefer to have a single try/catch in a method. Nesting them this way is an indication that you ought to refactor a method that's doing too much.
You've mingled persistence and UI code together in the worst way possible. Tease them apart so you can test and use them separately.
You don't close any database resources. This will come to grief.