Mysql, Check table and number of rows from C - mysql

I try to make function to check if table exists and to get total number of rows but I get result 1 instead of 99999.
So, what should I do here to work properly?
int sql_table_length(char* database, char* dtable, char* mysql_user_name, char* mysql_password)
{
int retval = 0;
MYSQL *conn;
conn = mysql_init(NULL);
if (conn)
{
if (mysql_real_connect(conn, "localhost", mysql_user_name, mysql_password, database, 0, NULL, 0)!=0)
{
char chktable[512] = {0};
sprintf(chktable,"%s%s%s", "SHOW TABLES LIKE '", dtable, "'");
mysql_query(conn, chktable);
if (mysql_store_result(conn))
{
MYSQL_RES *result;
char lngtable[512] = {0};
sprintf(lngtable, "%s%s", "SELECT COUNT(*) FROM ", dtable);
if (!(mysql_query(conn, lngtable)))
{
result = mysql_store_result(conn);
retval = mysql_num_rows(result); // here I get 1
mysql_free_result(result);
}
else retval = -4; //no rows
}
else retval = -3; //don't exist
}
else retval = -2; //can't connect
}
else retval = -1; //no connection
mysql_close(conn);
return retval;
}
Thanks!

Your query, SELECT COUNT(*) FROM table returns a single row containing the number of rows in the table. Instead of counting the number of rows in the result, you want to query the number that is returned.
You will want to do something like (untested):
MYSQL_STMT *stmt;
MYSQL_BIND bind;
long rows;
my_bool error; /* Omit at your own risk */
stmt = mysql_stmt_init(mysql)
mysql_stmt_prepare(stmt, lngtable, strlen(lngtable));
mysql_stmt_execute(stmt);
memset(&bind, 0, sizeof(bind));
bind.buffer_type = MYSQL_TYPE_LONG;
bind.buffer = (char *)&rows;
bind.error = &error; /* Omit at your own risk */
mysql_stmt_bind_result(stmt, &bind);
mysql_stmt_fetch(stmt);
printf("Number of rows: %ld\n", rows);
You should add error checking to all the mysql calls. See http://dev.mysql.com/doc/refman/5.0/en/mysql-stmt-fetch.html for more examples about binding parameters.
Alternatively, you can change your query to something like SELECT * FROM table and keep the rest of your code, but this is asking MySQL to do a lot more work, and the result will likely take longer.

After David's suggestion, I found a simpler and safer way to get the result. Maybe someone will need this:
int sql_table_length(char* database, char* dtable, char* mysql_user_name, char* mysql_password)
{
MYSQL *conn;
MYSQL_RES *result;
MYSQL_ROW rowdata;
int retval = 0;
conn = mysql_init(NULL);
if (conn)
{
if (mysql_real_connect(conn, "localhost", mysql_user_name, mysql_password, database, 0, NULL, 0)!=0)
{
char chktable[512] = {0};
sprintf(chktable,"%s%s%s", "SHOW TABLES LIKE '", dtable, "'");
if (!(mysql_query(conn, chktable)))
{
result = mysql_store_result(conn);
if (mysql_num_rows(result))
{
char lngtable[512] = {0};
sprintf(lngtable, "%s%s", "SELECT COUNT(*) FROM ", dtable);
if (!(mysql_query(conn, lngtable)))
{
result = mysql_store_result(conn);
if (result)
{
rowdata = mysql_fetch_row(result);
if (rowdata)
retval = atoi(rowdata[0]);
else retval = -7; // data error
}
else retval = -6; // result error
mysql_free_result(result);
}
else retval = -5; // can't select
}
else retval = -4; // table don't exist
}
else retval = -3; // can't query
}
else retval = -2; // can't connect
}
else retval = -1; // no server connection
mysql_close(conn);
return retval;
}
Any remarks on possible memory leaks (or other) are welcome!

Related

C mysql prepared statement inserting null character

I'm trying to set up a prepared statement based on some examples I found on the web. I just want to protect against SQL injections in the name= and description=, but the problem is that when the statement runs it inserts null data
char* my_str = "ABCDF";
char *stmt_str = "INSERT INTO notes (name, description) VALUES(?,?)";
MYSQL_STMT *stmt;
MYSQL_BIND ps_params[2];
my_bool is_null;
int status;
while(curr != NULL) {
stmt = mysql_stmt_init(con);
mysql_stmt_prepare(stmt, stmt_str, strlen(stmt_str));
memset(ps_params, 0, sizeof(ps_params));
/* set up CHAR parameter */
ps_params[0].buffer_type = MYSQL_TYPE_STRING;
//ps_params[0].buffer = (char *)&my_str;
ps_params[0].buffer = &my_str;
ps_params[0].buffer_length=strlen(my_str);
ps_params[0].is_null = 0;
ps_params[0].length = 0;
ps_params[1].buffer_type = MYSQL_TYPE_STRING;
//ps_params[1].buffer = (char *)&my_str;
ps_params[1].buffer = &my_str;
ps_params[1].buffer_length=strlen(my_str);
ps_params[1].is_null = 0;
ps_params[1].length = 0;
mysql_stmt_bind_param (stmt, ps_params);
mysql_stmt_execute(stmt);
Once it executed I see the following data ( It's a bunch of records in my DB ) after executing it many times
my_str is already a pointer to the string, you shouldn't take its address. You're storing the pointer's value rather than the string value.
ps_params[0].buffer = my_str;

Not able to detect integer values in where clause

I am trying to read column values into my array using mysql queries in C.
for(i=1;i<=15;i++)
{
if (mysql_query(conn, "select numberofskills from latest.skills where id = $i")) {
fprintf(stderr, "%s\n", mysql_error(conn));
exit(1);
}
res = mysql_use_result(conn);
while ((row = mysql_fetch_row(res)) != NULL){
j=0;
arr[j].n =atoi(row[0]);
printf("%d\n", arr[j].n);
j++;
}
I have an error saying "Unknown column '$i' in 'where clause'.
I tried all of these but nothing seems to work.
"select numberofskills from latest.skills where id = $i"
"select numberofskills from latest.skills where id = '$i'"
"select numberofskills from latest.skills where id = i"
$i will not replace the value of i. Instead you should format the string first with value of i replaced in it and then use the string in the mysql query.
In header file or in the beginning of the program, define the below macro:
#define MYSQL_QUERY_LENGTH 100
Inside your function where you are performing query, define the below variable:
char string[MYSQL_QUERY_LENGTH] = {};
Inside the for loop, format the string first:
snprintf(string, MYSQL_QUERY_LENGTH, "select numberofskills from latest.skills where id = %d", i);
Then, use the string in the query as below:
if (mysql_query(conn, string))
First you need to create query string variable with sprintf function where you can properly concatenate your query and variable
here is example
mysql and c -- use variable in query

Does MySQL support's creation of hidden column? [duplicate]

I am running a query on ID column but I don't want it to be visible in my frame/pane. How can I achieve this? Shall I make another table, is there a function in sql/mysql which allows to hide columns? I tried to google it but havent found anything yet.
Here is the code:
public void tableChanged(TableModelEvent e) {
int row = e.getFirstRow();
int col = e.getColumn();
model = (MyTableModel) e.getSource();
String stulpPav = model.getColumnName(col);
Object data = model.getValueAt(row, col);
Object studId = model.getValueAt(row, 0);
System.out.println("tableChanded works");
try {
new ImportData(stulpPav, data, studId);
} catch (ClassNotFoundException e1) {
e1.printStackTrace();
} catch (SQLException e1) {
e1.printStackTrace();
}
}
public class ImportData {
Connection connection = TableWithBottomLine.getConnection();
public ImportData(String a, Object b, Object c)
throws ClassNotFoundException, SQLException {
Statement stmt = null;
try {
String stulpPav = a;
String duom = b.toString();
String studId = c.toString();
System.out.println(duom);
connection.setAutoCommit(false);
stmt = connection.createStatement();
stmt.addBatch("update finance.fin set " + stulpPav + " = " + duom
+ " where ID = " + studId + ";");
stmt.executeBatch();
connection.commit();
} catch (BatchUpdateException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (stmt != null)
stmt.close();
connection.setAutoCommit(true);
System.out.println("Data was imported to database");
}
}
}
public class MyTableModel extends AbstractTableModel{
int rowCount;
Object data [][];
String columnNames [];
public MyTableModel() throws SQLException{
String query ="SELECT ID, tbl_Date as Date, Flat, Mobile, Food, Alcohol, Transport, Outdoor, Pauls_stuff, Income, Stuff FROM finance.fin";
ResultSet rs ;
Connection connection = TableWithBottomLine.getConnection();
Statement stmt = null;
stmt = connection.createStatement();
rs = stmt.executeQuery(query);
rs.last();
rowCount = rs.getRow();
data = new Object[rowCount][11];
rs = stmt.executeQuery(query);
for (int iEil = 0; iEil < rowCount; iEil++){
rs.next();
data[iEil][0] = rs.getInt("ID");
data[iEil][1] = rs.getDate("Date");
data[iEil][2] = rs.getFloat("Flat");
data[iEil][3] = rs.getFloat("Mobile");
data[iEil][4] = rs.getFloat("Food");
data[iEil][5] = rs.getFloat("Alcohol");
data[iEil][6] = rs.getFloat("Transport");
data[iEil][7] = rs.getFloat("Outdoor");
data[iEil][8] = rs.getFloat("Pauls_stuff");
data[iEil][9] = rs.getFloat("Income");
data[iEil][10] = rs.getFloat("Stuff");
}
String[] columnName = {"ID", "Date","Flat","Mobile"
,"Food","Alcohol","Transport", "Outdoor", "Pauls_stuff", "Income", "Stuff"};
columnNames = columnName;
}
This has solved my problem:
table.removeColumn(table.getColumnModel().getColumn(0));
I placed this in my class contructor. This lets remove the column from the view of the table but column 'ID' is still contained in the TableModel. I found that many people looking for an option to exclude specific column (like autoincrement) from SELECT statement in sql / mysql but the language itself doesn't have that feature. So I hope this solution will help others as well.
Don't put ID in the select part of the query
String query ="SELECT tbl_Date as Date, Flat, Mobile, Food, Alcohol, Transport,
Outdoor, Pauls_stuff, Income, Stuff FROM finance.fin";

"unknown column in field list" error when passing custom string into MariaDB/MySQL C connector API function

I am trying to make a function which requests the user to enter a new username and password, which then get stored in a MySQL/MariaDB database. I used strcat_s() and strcpy_s() to concatenate strings together to then get passed as a MySQL/MariaDB query in the C API. However, the result is an Unkown column 'foo' in 'field list' error. How can I fix this error? Below is my code.
void NEW_PLAYER(MYSQL *con)
{
const char *NAME = "foo";
const char *PASSWORD = "bar";
char ch = NULL;
unsigned int i = 0;
printf("%s\n", NAME);
printf("%s\n", PASSWORD);
char TEMP[150];
char str1[] = "INSERT INTO PLAYERS VALUES(";
strcpy_s(TEMP, str1);
strcat_s(TEMP, NAME);
strcat_s(TEMP, ", ");
strcat_s(TEMP, PASSWORD);
strcat_s(TEMP, " ,0, 0, 0, 0)");
printf("%s", TEMP);
// inserting null character at end
if (mysql_query(con, TEMP)) {
fprintf(stderr, "%s\n", mysql_error(con));
exit(-1);
}
}
Here are my results from this code
Strings must be quote, so you must quote 'foo' and 'bar' like this:
const char *NAME = "'foo'";
const char *PASSWORD = "'bar'";

mysql prepared statement : Update query

I am trying to execute a C program, using mysql C API, connecting to mysql with an update query and I am not getting any compilation or linking errors , but rows are not getting updated in the db table.
When I run this code I am getting empty values updated in emp. status field
#define STRING_SIZE 256
char* eStatus,myeStatus;
int myempid,empid;
int i;
for(i = 0; i < 5 ; i++){
const char* sqlQuery = "update employee_info set estatus = ? where empID = ?";
if (mysql_stmt_prepare(stmt, sqlQuery, strlen(sqlQuery))) {
fprintf(stderr, " mysql_stmt_prepare(), update failed\n");
fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
return -1;
}
memset(param, 0, sizeof(param)); /* zero the structures */
if (info.state == 2)
eStatus = "present";
else
eStatus = "absent";
empid = i;
// Init param structure
// Select
param[0].buffer_type = MYSQL_TYPE_STRING;
param[0].buffer = (void *) &eStatus;
param[0].buffer_length = STRING_SIZE;
param[0].is_null = 0;
param[0].length = &str_length;
param[1].buffer_type = MYSQL_TYPE_SHORT;
param[1].buffer = (void *) &myempID;
param[1].buffer_length = STRING_SIZE;
param[1].is_null = 0;
param[1].length = 0;
myeStatus = eStatus;
myempid = empid;
if (mysql_stmt_bind_param(stmt, param) != 0) {
fprintf(stderr, " mysql_stmt_bind_param() failed\n");
fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
return -1;
}
/* Execute the statement */
if (mysql_stmt_execute(stmt)) {
fprintf(stderr, " mysql_stmt_execute(), failed\n");
fprintf(stderr, " %s\n", mysql_stmt_error(stmt));
return -1;
}
} // end of for loop
Table schema in mysql
empid INT(11)
estatus varchar(10)
I am not able to figure out why status is not getting updated in mysql table. Is it a mismatch of datatypes, or values are not binded properly to sqlquery?
Any clue? Thanks.
You can find here : Writing into mysql database from a single board computer using c a complete example on how to use MYSQL C API to perform queries, if you still have some trouble, please post the whole code.
Why are you trying to use "where empID = ?". If you want it to run for every employee simply omit the where clause. If it is for a specific employee, then his id should be there.
There might be more issues, but this was the first one i found.
You might verify by trying to execute the same query on mysql command line prompt.
Edit: I also don't see any database connection being established and any info related to that. Some thing like
MYSQL *conn = mysql_init(NULL);
*conn = mysql_real_connect(*conn, DB_HOST, DB_USER, DB_PASS, DB_NAME, 0, NULL, flags);
if (*conn != NULL)
{
printf("Connection Successfull\n");
status = 0;
}