Home modules.gotpike.org
Username: Password: [Create Account]
[Forgot Password?]

Modules

ADT
Database
GTK2
GUI
IP
PiJAX
Public
Sql
Stdio
Subversion
System
Tools
Xosd
lua
v4l2
wx

Recent Changes

Public.Parser.XML2 1.50
Public.ZeroMQ 1.1
Public.Template.Mustache 1.0
Public.Protocols.XMPP 1.4
Sql.Provider.jdbc 1.0

Popular Downloads

Public.Parser.JSON2 1.0
Public.Parser.JSON 0.2
GTK2 2.23
Public.Web.FCGI 1.8
Public.Parser.XML2 1.48


Module Information
Sql.Provider.MySQL
Viewing contents of Sql_Provider_MySQL-0.1/mysql.cmod

/* =================================================================
 * Interface for MySQL 5.0 with support for prepared statements
 *
 * Johan Björklund 
 */

#include "global.h"
#include "interpret.h"
#include "module_support.h"

#include 
#include 
#include 
#include 
#include 

#include "array.h"
#include "mapping.h"
#include "multiset.h"
#include "svalue.h"
#include "stralloc.h"

/*
 * structure for holding a result set
 */
struct mysql_result {
  MYSQL_RES                 *m_resultset;       /* MySQL result set */
  MYSQL_BIND                *m_cols;            /* columns of the result set */
  MYSQL_FIELD               *m_fields;
  unsigned long             *m_col_len;         /* lengths of the columns */
  my_bool                   *m_col_is_null;
  struct pike_string       **m_col_names;       /* cache these */
  void                     **buffers;
  INT16                     *ptypes;            /* pike types */
  unsigned long              m_numcols;         /* number of columns in result set */
  unsigned long              m_rowsaffected;
};

/*
 * internal structure for holding a prepared statement
 */
struct mysql_stmt {
  MYSQL_STMT               *m_stmt;            /* MySQL prepared statement */
  MYSQL_BIND               *m_bindparams;      /* prepared statement parameters */
  unsigned long             m_parcnt;          /* number of prepared statement parameters */
  unsigned long            *m_par_len;         /* lengths of the columns */
  my_bool                  *m_par_is_null;
  struct mysql_result       m_result;          /* result set for prepared statement (if query) */
  MYSQL                    *m_connection;
};


/* ===============================================
 * Error handling
 */

void throw_error (struct mysql_stmt *o, const char *error_msg) {
  Pike_error(error_msg);
}

/* initialized in INIT {} */
struct svalue str_year;
struct svalue str_mon;
struct svalue str_mday;
struct svalue str_hour;
struct svalue str_min;
struct svalue str_sec;

#define GET_INT(m, key, to) ((to = low_mapping_lookup(m, key)) && (to->type == PIKE_T_INT)) ? to->u.integer : 0

MYSQL_TIME *get_ts_from_mapping(struct mapping *m)
{
  MYSQL_TIME *ts = calloc(1, sizeof(MYSQL_TIME));
  struct svalue *to;
  ts->year = GET_INT(m, &str_year, to);
  ts->month = GET_INT(m, &str_mon, to);
  ts->day = GET_INT(m, &str_mday,  to);
  ts->hour = GET_INT(m, &str_hour, to);
  ts->minute = GET_INT(m, &str_min, to);
  ts->second = GET_INT(m, &str_sec, to);
  return ts;
}

struct mapping *push_mapping_from_ts(MYSQL_TIME *ts)
{
  fprintf(stderr, "\tpush_mapping_from_ts\n");
  push_constant_text("year");
  push_int(ts->year);
  push_constant_text("mon");
  push_int(ts->month);
  push_constant_text("mday");
  push_int(ts->day);
  push_constant_text("hour");
  push_int(ts->hour);
  push_constant_text("min");
  push_int(ts->minute);
  push_constant_text("sec");
  push_int(ts->second);
  f_aggregate_mapping(12);
}

void stmt_prepare_parameter (MYSQL_BIND *m_param,
			     struct svalue *sval)
{
  *m_param->is_null = 0;

  switch(sval->type) {
  case PIKE_T_INT:
    m_param->buffer_length = sizeof(INT_TYPE);
    m_param->buffer = &sval->u.integer;
    switch(sizeof(INT_TYPE)) {
    case 8: m_param->buffer_type = MYSQL_TYPE_LONGLONG; break;
    case 4: m_param->buffer_type = MYSQL_TYPE_LONG;
    }
    m_param->is_unsigned = 0;
    break;
  case PIKE_T_STRING:
    m_param->buffer_length = sval->u.string->len * (sval->u.string->size_shift+1);
    m_param->buffer_type = MYSQL_TYPE_VAR_STRING;
    switch(sval->u.string->size_shift) {
    case 2: m_param->buffer = STR2(sval->u.string); break;
    case 1: m_param->buffer = STR1(sval->u.string); break;
    case 0: m_param->buffer = STR0(sval->u.string);
    }
    break;
  case PIKE_T_FLOAT:
    m_param->buffer_length = sizeof(FLOAT_TYPE);
    m_param->buffer_type = MYSQL_TYPE_DOUBLE;
    m_param->is_unsigned = 0;
    m_param->buffer = &(sval->u.float_number);
    break;
  case PIKE_T_MAPPING:
    /* assume date/time mapping */
    m_param->buffer_type = MYSQL_TYPE_DATETIME;
    m_param->buffer = (void*) get_ts_from_mapping(sval->u.mapping);
    break;
  case PIKE_T_OBJECT:
  case PIKE_T_ZERO:
  default:
    fprintf(stderr, "\t parameter\tNULL\n");
    m_param->buffer_type = MYSQL_TYPE_NULL;
    *m_param->is_null = 1;
    break;
  }
}

void stmt_bind_parameters (struct mysql_stmt *o, struct svalue *params, int args)
{
  if (args != o->m_parcnt)
    Pike_error("Incorrect number of parameters");

  int i;
  for (i=0; i < o->m_parcnt; i++)
    stmt_prepare_parameter(&o->m_bindparams[i], ¶ms[i]);

  if (mysql_stmt_bind_param(o->m_stmt, o->m_bindparams))
    throw_error(o, mysql_stmt_error(o->m_stmt));
}

void prepare_statement (struct mysql_stmt *o,
			struct pike_string *statement)
{
  char *char_statement;

  switch(statement->size_shift) {
  case 2: char_statement = (char *) STR2(statement); break;
  case 1: char_statement = (char *) STR1(statement); break;
  case 0: char_statement = (char *) STR0(statement);
  }

  // fprintf(stderr, "\tprepare_statement\n");
  // fprintf(stderr, "\t\tq = \"%s\"\n", char_statement);

  if (mysql_stmt_prepare(o->m_stmt, char_statement, statement->len))
    throw_error(o, mysql_stmt_error(o->m_stmt));

  my_bool t = 1;
  mysql_stmt_attr_set(o->m_stmt, STMT_ATTR_UPDATE_MAX_LENGTH, &t);

  o->m_parcnt = mysql_stmt_param_count(o->m_stmt);
  o->m_bindparams = calloc(o->m_parcnt, sizeof(MYSQL_BIND));
  o->m_par_is_null = calloc(o->m_parcnt, sizeof(my_bool));

  // fprintf(stderr, "\t\tm_parcnt = %d\n", o->m_parcnt);

  int i;
  for (i=0; i < o->m_parcnt; i++) {
    o->m_bindparams[i].length = &o->m_bindparams[i].buffer_length;
    o->m_bindparams[i].is_null = &o->m_par_is_null[i];
  }
}

void free_statement (struct mysql_stmt *o)
{
  free(o->m_par_is_null);
  free(o->m_bindparams);

  /* If the connection is down, this must not be done since it will already have been released */
  if (o->m_stmt)
    mysql_stmt_close(o->m_stmt);
  
  free(o);
}

void result_map_type (MYSQL_BIND *v, INT16 *ptype, MYSQL_FIELD *field)
{
  v->buffer_length = field->max_length;
  v->buffer_type = field->type;
  switch (field->type) {
  case MYSQL_TYPE_TINY          :
  case MYSQL_TYPE_SHORT         :
  case MYSQL_TYPE_LONG          :
  case MYSQL_TYPE_LONGLONG      : *ptype = PIKE_T_INT;   break;
  case MYSQL_TYPE_FLOAT         :
  case MYSQL_TYPE_DOUBLE        : *ptype = PIKE_T_FLOAT; break;
  case MYSQL_TYPE_TIME          :
  case MYSQL_TYPE_DATE          :
  case MYSQL_TYPE_DATETIME      :
  case MYSQL_TYPE_TIMESTAMP     : *ptype = PIKE_T_MAPPING;
    v->buffer_length = sizeof(MYSQL_TIME);
    break;
  case MYSQL_TYPE_STRING        : 
  case MYSQL_TYPE_VAR_STRING    :
  case MYSQL_TYPE_TINY_BLOB     :
  case MYSQL_TYPE_BLOB          :
  case MYSQL_TYPE_MEDIUM_BLOB   :
  case MYSQL_TYPE_LONG_BLOB     :
  default                       : *ptype = PIKE_T_STRING;
  }
}

void register_resultset (struct mysql_stmt *stmt)
{
  unsigned int i;
  struct mysql_result *o = &stmt->m_result;

  o->m_fields      = mysql_fetch_fields(o->m_resultset);
  o->m_numcols     = mysql_num_fields(o->m_resultset);
  o->m_cols        = calloc(o->m_numcols, sizeof(MYSQL_BIND));
  o->m_col_is_null = calloc(o->m_numcols, sizeof(my_bool));
  o->m_col_names   = calloc(o->m_numcols, sizeof(void*));
  o->buffers       = calloc(o->m_numcols, sizeof(void*));
  o->ptypes        = calloc(o->m_numcols, sizeof(INT16));

  for (i = 0; i < o->m_numcols; i++) {
    MYSQL_FIELD *field = &o->m_fields[i];
    o->m_col_names[i] = make_shared_string(field->name);

    MYSQL_BIND *m_col = &o->m_cols[i];
    m_col->is_null = &o->m_col_is_null[i];

    result_map_type(m_col, &o->ptypes[i], field);
    m_col->buffer = (void *) malloc(m_col->buffer_length);
    if(o->ptypes[i] == PIKE_T_STRING)
      m_col->length = malloc(sizeof(unsigned long));
  }

  if (mysql_stmt_bind_result(stmt->m_stmt, o->m_cols))
    throw_error(stmt, mysql_stmt_error(stmt->m_stmt));  
}

void free_result (struct mysql_result *r)
{
  int i;
  if (r->m_cols) {

    for(i=0; im_numcols; i++) {
      free_string(r->m_col_names[i]);
      free(r->m_cols[i].buffer);
      if(r->ptypes[i] == PIKE_T_STRING)
	free(r->m_cols[i].length);
    }

    free(r->m_col_is_null);
    free(r->m_col_names);
    free(r->m_cols);
    free(r->ptypes);
  }
}

void execute_statement (struct mysql_stmt *o)
{
  // fprintf(stderr, "\texecute_statement\n");

  if (mysql_stmt_execute(o->m_stmt)) {
    fprintf(stderr, "\t errno = %d\n", mysql_stmt_errno(o->m_stmt));
    throw_error(o, mysql_stmt_error(o->m_stmt));
  }

  o->m_result.m_rowsaffected = mysql_stmt_affected_rows(o->m_stmt);
  o->m_result.m_resultset = mysql_stmt_result_metadata(o->m_stmt);

  if (o->m_result.m_resultset) {
    if (mysql_stmt_store_result(o->m_stmt))
      throw_error(o, mysql_stmt_error(o->m_stmt));
    register_resultset (o);
  }
}

void push_bind_value (MYSQL_BIND *res, INT16 ptype)
{
  if (*res->is_null) {
    push_int(0);
  } else {
    switch(ptype) {
    case PIKE_T_INT     :
      switch(res->buffer_type) {
      case MYSQL_TYPE_TINY     : push_int( (INT_TYPE) *((char*) res->buffer)          ); break;
      case MYSQL_TYPE_SHORT    : push_int( (INT_TYPE) *((short int*) res->buffer)     ); break;
      case MYSQL_TYPE_LONG     : push_int( (INT_TYPE) *((int*) res->buffer)           ); break;
      case MYSQL_TYPE_LONGLONG : push_int( (INT_TYPE) *((long long int*) res->buffer) ); break;
      } break;
    case PIKE_T_FLOAT   : push_float  ( *((FLOAT_TYPE*) res->buffer) );                   break;
    case PIKE_T_MAPPING : push_mapping_from_ts((MYSQL_TIME*) res->buffer);      break;
      /*    case PIKE_T_STRING  : push_string ( make_shared_binary_string(res->buffer, *res->length)); break; */
    case PIKE_T_STRING  : push_string ( make_shared_binary_string(res->buffer, *res->length) ); break;
    default             : fprintf(stderr, "unhandled sval->type = %d\n", ptype); push_int(0);
    }
  }
 
}

void push_result_array (struct mysql_stmt *stmt) {
  int rows=0;
  int rc;
  int i;
  struct mysql_result *result = &stmt->m_result;

  while ((rc = mysql_stmt_fetch(stmt->m_stmt)) == 0) {

    for (i=0; i < result->m_numcols; i++) {
      ref_push_string(result->m_col_names[i]);
      push_bind_value(&result->m_cols[i], result->ptypes[i]);
    }

    f_aggregate_mapping(result->m_numcols*2);
    rows++;
  }
  
  if(rc != MYSQL_NO_DATA) {
    fprintf(stderr, "\t\tpush_result_array error rc = %d\n", rc);
    throw_error(stmt, mysql_stmt_error(stmt->m_stmt));
  }

  debug_f_aggregate(rows);
}

/* ===============================================
 * PreparedStatement class
 *
 * =============================================== */

#define THISOBJ (Pike_fp->current_object)

PIKECLASS PreparedStatement {
  CVAR struct mysql_stmt   *stmt;
  CVAR struct object       *m_connection;

  PIKEFUN int getLastInsertedKey () {
    RETURN mysql_stmt_insert_id(THIS->stmt->m_stmt);
  }
  
  PIKEFUN void create () {
    Pike_error("Must be created by Mysql.Mysql()->compile_query()\n");
  }

  PIKEFUN object get_connection () {
    RETURN THIS->m_connection;
  }

  INIT {
    THIS->stmt = NULL;
    THIS->m_connection = NULL;
  }

  EXIT {
    // fprintf(stderr, "exit from MySQL.PreparedStatement\n");
    if (THIS->stmt)
      free_statement(THIS->stmt);
    if (THIS->m_connection)
      free_object(THIS->m_connection);

  }
}

/* ===============================================
 * Resultset class
 *
 * =============================================== */

PIKECLASS MysqlResult {
  CVAR struct object     *connection;
  CVAR struct mysql_stmt *stmt;

  /* Get specification of all remaining fields.
   * Returns an array with one mapping for every remaining field in the result table.
   */
  PIKEFUN array(int|mapping(string:mixed)) fetch_fields () {
    int column;

    for (column = 0; column < THIS->stmt->m_result.m_numcols; column++) {
      push_text("name");
      push_string(THIS->stmt->m_result.m_col_names[column]);

      push_text("type");
      switch (THIS->stmt->m_result.m_fields[column].type) {
      case MYSQL_TYPE_TINY          :
      case MYSQL_TYPE_SHORT         :
      case MYSQL_TYPE_LONG          :
      case MYSQL_TYPE_LONGLONG      : push_text("int");	      break;
      case MYSQL_TYPE_FLOAT         :
      case MYSQL_TYPE_DOUBLE        : push_text("float");     break;
      case MYSQL_TYPE_STRING        : 
      case MYSQL_TYPE_VAR_STRING    :
      case MYSQL_TYPE_TINY_BLOB     :
      case MYSQL_TYPE_BLOB          :
      case MYSQL_TYPE_MEDIUM_BLOB   :
      case MYSQL_TYPE_LONG_BLOB     : push_text("string");   break;
      case MYSQL_TYPE_TIME          :
      case MYSQL_TYPE_DATE          :
      case MYSQL_TYPE_DATETIME      :
      case MYSQL_TYPE_TIMESTAMP     : push_text("datetime"); break;
      default                       : push_text("weird");    break;
      }
      f_aggregate_mapping(2);
    }
    RETURN aggregate_array(column);
  }

  /* Fetch the next row from the result.
   * Returns an array with the contents of the next row in the result.
   * Advances the row cursor to the next now.
   * Returns 0 (zero) at the end of the table.
   */
  PIKEFUN array(mixed) fetch_row () {
    int rc;
    /*
    if ((rc = MySQL_ResultSet_next (THIS->result->m_resultset)) == MySQL_NO_DATA_FOUND)
      RETURN NULL;

    MYSQL_ROW *rowset = NULL;
    if(mysql_stmt_fetch_row(THIS->result->m_resultset))
      throw_error(THIS->stmt, mysql_stmt_error(THIS->stmt));

    int column;
    struct svalue *sval = calloc(1, sizeof(struct svalue));
    for (column=0; column < THIS->result->m_numcols; column++) {
      push_bind_value ( ... );
    }
    free(sval);
    */

    RETURN aggregate_array (THIS->stmt->m_result.m_numcols);
  }
  
  /* Skip to specified field.
   * Places the field cursor at the specified position.
   * This affects which field mysql_THIS->resultfetch_field() will return next.
   * Fields are numbered starting with 0.
   */
  PIKEFUN void field_seek (int field_no) {
    /*
    if (MySQL_ResultSet_absolute(THIS->result->m_resultset, field_no) != MySQL_OK) {
      mysql_error (MySQL_ResultSet_getError(THIS->result->m_resultset));
    }
    */
  }

  /* Number of fields in the result. */
  PIKEFUN int num_fields () {
    RETURN THIS->stmt->m_result.m_numcols;
  }

  /* Number of rows in the result. */
  PIKEFUN int num_rows () {
    RETURN mysql_num_rows(THIS->stmt->m_result.m_resultset);
  }

  /* Skip ahead rows rows. */
  PIKEFUN void seek (int rows) {
    mysql_stmt_data_seek (THIS->stmt->m_stmt, rows);
    /* FIXME: if(error) */
  }

  PIKEFUN int affected_rows () {
    RETURN THIS->stmt->m_result.m_rowsaffected;
  }

  PIKEFUN void create () {
    Pike_error("Must be created by Mysql.Mysql()->big_query()\n");
  }

  EXIT {
    free_result(&THIS->stmt->m_result);
    free_statement(THIS->stmt);
    sub_ref(THIS->connection);
  }
}

/* ===============================================
 * Connection class
 *
 * =============================================== */

PIKECLASS MySQL {
  CVAR MYSQL         *m_connection;       /* MySQL connection */
  CVAR unsigned long  m_client_flag;      /* connection properties */

  CVAR struct pike_string *hostname;
  CVAR struct pike_string *database;
  CVAR struct pike_string *username;
  CVAR struct pike_string *password;

  PIKEFUN void autocommit(int(0..1) mode) {
    if(mysql_autocommit(THIS->m_connection, mode))
      throw_error(NULL, mysql_error(THIS->m_connection));
  }

  PIKEFUN void commit() {
    if(mysql_commit(THIS->m_connection))
      throw_error(NULL, mysql_error(THIS->m_connection));
  }

  PIKEFUN void rollback() {
    if(mysql_rollback(THIS->m_connection))
      throw_error(NULL, mysql_error(THIS->m_connection));
  }

  PIKEFUN void create_db() {
    
  }

  PIKEFUN void drop_db() {
    
  }

  /* ===============================================
   * Queries
   */
  struct mysql_stmt *create_statement (struct pike_string *q) {
    struct mysql_stmt *stmt = xalloc(sizeof(struct mysql_stmt));

    stmt->m_result.m_resultset = NULL;
    stmt->m_connection = THIS->m_connection;

    stmt->m_stmt = mysql_stmt_init(THIS->m_connection);
    if(!stmt->m_stmt) {
      free(stmt);
      Pike_error("mysql_stmt_init() failed.\n");
    }
    prepare_statement(stmt, q);

    return stmt;
  }

  PIKEFUN object(PreparedStatement) compile_query (string q) {
    struct object *stmt = low_clone(PreparedStatement_program);
    call_c_initializers(stmt);

    OBJ2_PREPAREDSTATEMENT(stmt)->stmt = create_statement(q);
    OBJ2_PREPAREDSTATEMENT(stmt)->m_connection = THISOBJ;
    add_ref(THISOBJ);

    RETURN stmt;
  }

  PIKEFUN mixed query (string|object q, void|mixed ... rest) {
    struct mysql_stmt *stmt = NULL;

    if (q->type == PIKE_T_OBJECT) {
      if(q->u.object->prog != PreparedStatement_program)
	Pike_error("Query object must be created by Mysql.Mysql->compile_query()\n");
      stmt = OBJ2_PREPAREDSTATEMENT(q->u.object)->stmt;
    } else 
      stmt = create_statement(q->u.string);

    if (args > 1)
      stmt_bind_parameters(stmt, rest, args-1);

    execute_statement(stmt);

    pop_n_elems(args);

    /* make resultmapping */
    if(stmt->m_result.m_resultset) {
      push_result_array(stmt);
      free_result(&stmt->m_result);
    }

    if (q->type == PIKE_T_STRING)
      free_statement(stmt);
    else
      mysql_stmt_reset(stmt->m_stmt);

  }

  /*
   * Returns a resultset object
   */
  PIKEFUN object(MysqlResult) big_query(string|object q, void|mixed ... rest)  {

    struct mysql_stmt *stmt = NULL;
    struct array      *bindings = NULL;

    if (q->type == PIKE_T_OBJECT) {
      if(q->u.object->prog != PreparedStatement_program)
	Pike_error("Query object must be created by Mysql.Mysql->compile_query()\n");
      stmt = OBJ2_PREPAREDSTATEMENT(q->u.object)->stmt;
    } else 
      stmt = create_statement(q->u.string);

    if (args > 1)
      stmt_bind_parameters(stmt, rest, args-1);

    execute_statement(stmt);

    pop_n_elems(args);

    struct svalue *ret = malloc(sizeof(struct svalue));
    ret->subtype = 0;

    if (stmt->m_result.m_resultset) {
      ret->u.object = low_clone(MysqlResult_program);
      call_c_initializers(ret->u.object);
      ret->type = PIKE_T_OBJECT;
      OBJ2_MYSQLRESULT(ret->u.object)->stmt = stmt;
      OBJ2_MYSQLRESULT(ret->u.object)->connection = THISOBJ;
      add_ref(THISOBJ);
    } else {
      ret->type = PIKE_T_ZERO;
      free_result(&stmt->m_result);
    }

    if (q->type == PIKE_T_STRING)
      free_statement(stmt);

    push_svalue(ret);
    free(ret);
  }

  PIKEFUN void create (void|string hname,
		       string db,
		       string uname,
		       string pw,
		       void|mapping options) {

    
    unsigned char *hostname;
    char *database;
    unsigned char *username;
    unsigned char *password;
    unsigned int port;

    /*
    int i;
    struct svalue *val;
    if(options && options->type == PIKE_T_MAPPING) {
      for (i = 0; i < sizeof(mysql_optionlist)/sizeof(char*); i++) {
	if ( (val = simple_mapping_string_lookup (options->u.mapping, mysql_optionlist[i] )) &&
	     (val->type == PIKE_T_STRING) )	  
      }
    }
    */

    THIS->m_connection = mysql_init(NULL);
    
    if(!THIS->m_connection)
      Pike_error("Cannot get MYSQL structure");

    if ((hname) &&
	(hname->len > 0) &&
	(hname->size_shift == 0) ) {
      THIS->hostname = hname;
      add_ref(THIS->hostname);
      hostname = STR0(hname);
    } else {
      hostname = (unsigned char*) "localhost";
    }

    if (db->len > 0) {
      if ( (db->size_shift == 0) ) {
	THIS->database = db;
	add_ref(THIS->database);
	database = (char*) STR0(db);
      } else
	Pike_error("Wide character database name not supported\n");
    } else {
      database = NULL;
    }

    switch(uname->size_shift) {
    case 0: username = STR0(uname); break;
    case 1: username = (unsigned char*) STR1(uname); break;
    case 2: username = (unsigned char*) STR2(uname); break;
    }
    THIS->username = uname;
    add_ref(THIS->username);

    switch(pw->size_shift) {
    case 0: password = STR0(pw); break;
    case 1: password = (unsigned char*) STR1(THIS->password); break;
    case 2: password = (unsigned char*) STR2(THIS->password); break;
    }
    THIS->password = pw;
    add_ref(THIS->password);

    if(!mysql_real_connect(THIS->m_connection,
			   (char*) hostname,
			   (char*) username,
			   (char*) password,
			   (char*) database,
			   port,
			   NULL,
			   THIS->m_client_flag))
      throw_error (NULL, mysql_error(THIS->m_connection));
  }
  
  INIT {
    if (mysql_thread_init())
      Pike_error("mysql_thread_init() failed");

    THIS->hostname = NULL;
    THIS->database = NULL;
    THIS->username = NULL;
    THIS->password = NULL;

    THIS->m_connection = NULL;
    THIS->m_client_flag = CLIENT_MULTI_STATEMENTS;
  }

  EXIT {
    // fprintf(stderr, "exit from MySQL\n");
    if (THIS->m_connection)
      mysql_close(THIS->m_connection);

    if (THIS->hostname)
      free_string(THIS->hostname);
    if (THIS->database)
      free_string(THIS->database);
    if (THIS->username)
      free_string(THIS->username);
    if (THIS->password)
      free_string(THIS->password);

    mysql_thread_end();
  }
}

INIT
{
  str_year.u.string = make_shared_string("year");
  str_mon.u.string = make_shared_string("mon");
  str_mday.u.string = make_shared_string("mday");
  str_hour.u.string = make_shared_string("hour");
  str_min.u.string = make_shared_string("min");
  str_sec.u.string = make_shared_string("sec");

  str_year.type =
    str_mon.type =
    str_mday.type =
    str_hour.type =
    str_min.type =
    str_sec.type = PIKE_T_STRING;

  mysql_library_init(0, NULL, NULL);
}

EXIT
{
  mysql_library_end();

  free_string(str_year.u.string);
  free_string(str_mon.u.string);
  free_string(str_mday.u.string);
  free_string(str_hour.u.string);
  free_string(str_min.u.string);
  free_string(str_sec.u.string);

}


gotpike.org | Copyright © 2004 - 2019 | Pike is a trademark of Department of Computer and Information Science, Linköping University