/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*-  */
/*
 * mysql_blobs.c
 * Copyright (C) 2014 John Coppens <john@jcoppens.com>
 * 
 * blob_test is free software: you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the
 * Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * blob_test is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See the GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License along
 * with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

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

#define SIZE 	20000
#define USER    "user"
#define PASS    "pass"
#define DBASE   "localdata"

int16_t ints[SIZE],	     // Array of int16_t's to be written to a table 
        ints_read[SIZE];     // Space to read back the array from the table

MYSQL *con;

int
dbase_connected(void)	   // Connect to the database. Return TRUE if connected
{
  con = mysql_init(NULL);
  if (mysql_real_connect(con, "localhost", USER, PASS, DBASE, 
		0, NULL, CLIENT_MULTI_STATEMENTS) == NULL) {
    printf("%s\n", mysql_error(con));
    return(0);
  }
  
  return(1);
}

void
fill_ints(void)		// Fill the ints array with random 16-bit values
{
  int i;
  
  for (i = 0; i < SIZE; i++)
    ints[i] = random() & 0xffff;
}

int
arrays_equal(void)      // Compare ints and ints_read. Return TRUE if they
			// are completely equal.
{
  int i;
  
  for (i = 0; i < SIZE; i++)
    if (ints[i] != ints_read[i]) {
      printf("At %d: %04x <-> %04x\n", i, ints[i], ints_read[i]);
      return(0);
    }
  return(1);
}

void
show_hex(char *str)     // Show a (NULL-terminated) string as hex bytes
{
  int i;
  
  for (i = 0; str[i] != 0; i++) {
    if (i % 24 == 0)
      printf("\n");
    printf("%02x ", (unsigned char)str[i]);
  }
}

void
show_int(void)	      // Show the ints array (completely) as decimal numbers
{
  int i;
  
  for (i = 0; i < SIZE; i++) {
    if (i % 12 == 0)
      printf("\n");
    printf("%8d ", ints[i]);
  }
}

int
ints_saved(void)	// Store the ints array as a blob into the Ints
			// table. The Id field is always set to 1. Could be better
{
  char   *chunk, *st, *query;
  size_t ints_size = sizeof(ints), 
         st_len;
  int qlen;
  
  chunk = (char *)malloc(ints_size*2 + 1);
  st = "insert into Ints(Id, Data) values(1, '%s')";
  st_len = strlen(st);
  mysql_real_escape_string(con, chunk, (char *)ints, ints_size);
				// Note we have to call the escape function

  query = (char *)malloc(st_len + 2*ints_size+1); 
  qlen = snprintf(query, st_len + 2*ints_size+1, st, chunk);

  //printf("%s\n", query);      // Uncomment to print the query
  //show_hex(chunk);		// Uncomment to show the escaped chunk as hex
  show_int();			// Uncomment to show the ints array as integers
  if (mysql_real_query(con, query, qlen)) {
    printf("%s\n", mysql_error(con));
    return(0);
  };
  
  return(1);
}

int
ints_loaded(void)       // Read the integers back from the table, now into the
			// ints_read array.
{
  MYSQL_RES *result;
  
  if (mysql_query(con, "SELECT Data FROM Ints WHERE Id=1")) {
    printf("%s\n", mysql_error(con));
    return(0);
  }
  
  result = mysql_store_result(con);
  if (result == NULL) {
    printf("%s\n", mysql_error(con));
    return(0);
  }  

  MYSQL_ROW row = mysql_fetch_row(result);
  
  memcpy(ints_read, row[0], sizeof(ints));
  return(1);
}


int main()
{
  if (!dbase_connected())
    return(1);  // Can't connect
    
  fill_ints();
  if (!ints_saved())
    return(2);  // Can't save array as record
    
  if (!ints_loaded())
    return(3);  // Can't load array back
    
  if (!arrays_equal())
    return(4);  // Arrays are not equal
      
  return (0);
}