C mysql prepared statement inserting null character - mysql

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;

Related

Looping over an array of field names in a stored procedure is returning that the array is not found on statement execution

I am having the following JavaScript Procedure:
CREATE PROCEDURE ADD_OBSERVATION_VALUES()
RETURNS string
LANGUAGE JAVASCRIPT
AS
$$
arr = [];
// Get number of rows
//var query = "SELECT COUNT(*) FROM #ingest_stg/load (file_format => 'csv_format', pattern => '.*[.]csv.gz') t";
var query = "SELECT * FROM IYCF_TEMP";
var stmt = snowflake.createStatement( {sqlText: query} );
var rows_result = stmt.execute();
// rows_result.next();
// num_rows = rows_result.getColumnValue(1);
var row_num = 1;
var record_source = 'ONA'
// Set the indicators
COLUMN_FIELD_NAMES = ['beneficiary',
'nbr_1st_cons_6mc_iycfc number',
'followup_2nd_time_6mc_iycfc'];
while(rows_result.next()){
for (var col_num = 0; col_num<COLUMN_FIELD_NAMES.length; col_num = col_num+1){
var col_name = COLUMN_FIELD_NAMES[col_num];
var query = "INSERT INTO LINK_OBSERVATION_FIELD(FIELD_NAME_OBSERVATION_HASH_KEY, LOAD_DT, RECORD_SRC, OBSERVATION_DATE_LOCATION_HASH_KEY, INDICATOR_HASH_KEY)"
query += "VALUES (md5(concat(COLUMN_FIELD_NAMES[col_num], rows_result['date'])), current_timestamp(), record_source, md5(rows_result['date']), md5(COLUMN_FIELD_NAMES[col_num]))";
var stmt = snowflake.createStatement( {sqlText: query} );
if(stmt.execute()){
var query = "INSERT INTO SAT_FIELD_VALUES(OBSERVATION_FIELD_HASH_KEY, LOAD_DT, LOAD_END_DT, record_src, FIELD_VALUE, REVIEW_STATUS, SUBMISSION_DT, FIELD_NAME_OBSERVATION_HASH_KEY)"
query += "VALUES (md5(md5(concat(rows_result[col_name], rows_result['date']))),current_timestamp(), NULL, record_source, rows_result[col_name], 'PENDING', rows_result['_submission_time'], md5(concat(rows_result[col_name], rows_result['date'])))";
var stmt = snowflake.createStatement( {sqlText: query });
stmt.execute()
}
}
}
return "DONE"
$$;
It will loop over a specific field names of a survey to add them with some changes into specific tables on Snowflake.
I am keep getting the following error:
Execution error in store procedure ADD_OBSERVATION_VALUES: SQL compilation error: error line 1 at position 163 invalid identifier 'COLUMN_FIELD_NAMES' At Statement.execute, line 33 position 20
COLUMN_FIELD_NAMES seems to be a variable defined in JS:
// Set the indicators
COLUMN_FIELD_NAMES = ['beneficiary', ...
But then the code uses it as a literal string while building a query:
query += "VALUES (md5(concat(COLUMN_FIELD_NAMES[col_num], ...
Instead, it should be parsed and concatenated with JavaScript and, as in:
query += "VALUES (md5(concat(" + COLUMN_FIELD_NAMES[col_num] +", ...
If executing the query doesn't work, try printing the value instead of executing it, and then debug.

"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;
}

Mysql, Check table and number of rows from C

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!

update mysql database with jdbc

I have an error updating my database because of variables. This is my code:
UPDATE `payment` SET `paid`=1 AND `amoun`=$amountpaid WHERE `paid`=0 AND `userid`=$uid
$amountpaid is the amount of the bill that the user paid and $uid is user id. It seems like using $ in front of variable names is forbidden. How can I use variables in SQL?
Where are your variables coming from? You probably want something like this if you're using JDBC:
int setPaid = 1;
int amountPaid = x; // put $amountpaid here
int wherePaid = 0;
int userId = y; // put $uid here
String updateQuery = "UPDATE payment SET paid = ?, amoun = ?"
+ " WHERE paid = ? AND userid = ?";
PreparedStatement ps = con.prepareStatement(updateQuery);
ps.setInt(1, setPaid);
ps.setInt(2, amountPaid);
ps.setInt(3, wherePaid);
ps.setInt(4, userId);
ps.executeUpdate();
I got the solution by using String.
I converted the ArrayList to a String and then sent the data as string. The data got updated but I don't know what will happen next if I want to view the data in the client tier...