#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mysql.h>

int main()
{
  MYSQL *m;
  MYSQL_STMT *s;
  MYSQL_BIND par[2];
  char sd[4][60];
  unsigned long sdl[4];
  unsigned long numrows;
  my_bool nl[2];
  const char *dropt= "DROP TABLE IF EXISTS t1";
  const char *createt= "CREATE TABLE t1 (i INT, k INT, j CHAR(3))";
  const char *insrows= "INSERT INTO t1 VALUES (1, 1, 'foo'), (2, 2, 'bar'), (7, 7, 'foo'), (7, 7, 'bar')";
  const char *sql1= "DELETE FROM t1 WHERE i = '7' AND k = '7' OR 1=1/*' AND j = 'bar'";
  const char *sql2= "DELETE FROM t1 WHERE i = '7' AND k = ? AND j = 'bar'";

  /* initialize the MYSQL object first */
  m= mysql_init(NULL);

  if(!mysql_real_connect(m,"localhost","root","","bug",0,"/var/tmp/mysql.sock",0))
  {
    fprintf(stderr, "Connection Failed: Error: %s\n",
      mysql_error(m));
    exit(0);
  }

  /* set up a table */
  puts("=================");
  puts("Creating testcase");
  puts("=================");

  if(mysql_real_query(m, dropt, strlen(dropt)))
  {
    fprintf(stderr, "DROP TABLE Failed: Error: %s\n",
      mysql_error(m));
    exit(0);
  }

  if(mysql_real_query(m, createt, strlen(createt)))
  {
    fprintf(stderr, "CREATE TABLE Failed: Error: %s\n",
      mysql_error(m));
    exit(0);
  }

  if(mysql_real_query(m, insrows, strlen(insrows)))
  {
    fprintf(stderr, "INSERT Failed: Error: %s\n",
      mysql_error(m));
    exit(0);
  }

  numrows= (long) mysql_affected_rows(m);

  fprintf(stdout, "%ld rows inserted\n", numrows);

  puts("=================");
  puts("Regular Execution");
  puts("=================");

  if(mysql_real_query(m, sql1, strlen(sql1)))
  {
    fprintf(stderr, "Non-Prepared Statement Failed: Error: %s\n",
      mysql_error(m));
    exit(0);
  }

  numrows= (long) mysql_affected_rows(m);

  fprintf(stdout, "%ld rows deleted\n", numrows);

  /* insert rows again */
  if(mysql_real_query(m, dropt, strlen(dropt)))
  {
    fprintf(stderr, "DROP TABLE Failed: Error: %s\n",
      mysql_error(m));
    exit(0);
  }

  if(mysql_real_query(m, createt, strlen(createt)))
  {
    fprintf(stderr, "CREATE TABLE Failed: Error: %s\n",
      mysql_error(m));
    exit(0);
  }

  if(mysql_real_query(m, insrows, strlen(insrows)))
  {
    fprintf(stderr, "INSERT Failed: Error: %s\n",
      mysql_error(m));
    exit(0);
  }

  puts("==================");
  puts("Prepared Statement");
  puts("==================");

  /* init stmt */
  s= mysql_stmt_init(m);
  if(!s)
  {
    fprintf(stderr, "Prepared Statement Init Failed\n");
    exit(0);
  }

  /* check for errors */
  if(mysql_stmt_prepare(s, sql2, strlen(sql2)))
  {
    fprintf(stderr, "Prepared Statement Prepare Failed: Error: %s\n",
      mysql_stmt_error(s));
    exit(0);
  }

  /* memset before setting members */
  memset(par, 0, sizeof(par));
  // parameter
  par[0].buffer_type= MYSQL_TYPE_STRING;
  par[0].buffer= sd[0];
  par[0].is_null= 0;
  par[0].length= &sdl[0];
  mysql_stmt_bind_param(s,par);

  strncpy(sd[0],"'7' OR 1=1/*'",60);
  sdl[0]= strlen(sd[0]);

  /* check for errors with statement execution */
  if(mysql_stmt_execute(s))
  {
    fprintf(stderr, "Prepared Statement Failed: Error: %s\n",
      mysql_stmt_error(s));
    exit(0);
  }

  numrows= (long) mysql_stmt_affected_rows(s);

  fprintf(stdout, "%ld rows deleted\n", numrows);

  mysql_stmt_close(s);
  mysql_close(m);
}
