/*
* $Id: mysql.c,v 1.10 2000/07/22 06:13:16 danny Exp $
*
* This file is part of Oleo, the GNU spreadsheet.
*
* Copyright © 1999-2000 by the Free Software Foundation, Inc.
* Written by Danny Backx <danny@gnu.org>.
*
* This program 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 2 of the License, or
* (at your option) any later version.
*
* This program 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, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
static char rcsid[] = "$Id: mysql.c,v 1.10 2000/07/22 06:13:16 danny Exp $";
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef WITH_DMALLOC
#include <dstdlib.h>
#endif
#include "global.h"
#include "oleosql.h"
#include "cmd.h"
#include "io-term.h"
#include "mysql.h"
#ifdef HAVE_LIBMYSQLCLIENT
#include <stdio.h>
#include <stdlib.h>
#include <mysql/mysql.h>
/*
* Define some MySQL access functions for Oleo
*/
#include "funcdef.h"
#include "sysdef.h"
#include "global.h"
#include "cell.h"
#include "eval.h"
#include "errors.h"
/*
* Declarations necessary for defining an Oleo function
*/
struct value
{
int type;
union vals x;
};
#define Float x.c_d
#define String x.c_s
#define Int x.c_l
#define Value x.c_i
#define Rng x.c_r
/*
* Forward declarations
*/
static void do_mysql_query(struct value *);
static void do_mysql_read(struct value *);
static void do_mysql_write(struct value *);
/*
* Define Oleo functions
*/
struct function mysql_functions[] = {
{ C_FN1, X_A1, "S", do_mysql_query, "mysql_query" },
{ C_FN1, X_A1, "S", do_mysql_read, "mysql_read" },
{ C_FN1, X_A1, "S", do_mysql_write, "mysql_write" },
{ 0, 0, "", 0, 0 }
};
int init_mysql_function_count(void)
{
return sizeof(mysql_functions) / sizeof(struct function) - 1;
}
/*
* This function should just retrieve a single value from the dbms.
*/
static void
do_mysql_query(struct value *p)
{
char *sql = p[0].String;
MYSQL db;
MYSQL_RES *res;
MYSQL_ROW row;
MYSQL_FIELD *field;
int r, i, j, nrows;
char *result;
double d;
AllocateDatabaseGlobal();
if (Global->DatabaseGlobal == NULL) {
io_error_msg("Need to initialize database");
return;
}
if (Global->DatabaseGlobal->name == 0 || Global->DatabaseGlobal->user == 0) {
io_error_msg("Database Access requires db name and user name");
return;
}
if (mysql_connect(&db, Global->DatabaseGlobal->host, Global->DatabaseGlobal->user, "")
== NULL) {
io_error_msg("MySQL error '%s'\n", mysql_error(&db));
return; /* FIX ME */
}
r = mysql_select_db(&db, Global->DatabaseGlobal->name);
if (r != 0) {
io_error_msg("MySQL error '%s'\n", mysql_error(&db));
return; /* FIX ME */
}
r = mysql_query(&db, sql);
if (r != 0) {
io_error_msg("MySQL error '%s'\n", mysql_error(&db));
return; /* FIX ME */
}
res = mysql_store_result(&db);
if (mysql_num_fields(res) != 1) {
/* There's more than one, or less than one, result. */
io_error_msg("MySQLQuery: number of results (%d) should be one\n", nrows);
return; /* FIX ME */
}
field = mysql_fetch_field(res);
nrows = mysql_num_rows(res);
if (nrows != 1) {
/* There's more than one, or less than one, result. */
io_error_msg("MySQLQuery: number of results (%d) should be one\n", nrows);
return; /* FIX ME */
}
row = mysql_fetch_row(res);
switch (field->type) {
case FIELD_TYPE_CHAR:
case FIELD_TYPE_NULL:
case FIELD_TYPE_TIMESTAMP:
case FIELD_TYPE_DATE:
case FIELD_TYPE_TIME:
case FIELD_TYPE_DATETIME:
case FIELD_TYPE_VAR_STRING:
case FIELD_TYPE_STRING:
p->type = TYP_STR;
p->String = strdup(row[0]);
break;
case FIELD_TYPE_DECIMAL:
case FIELD_TYPE_FLOAT:
case FIELD_TYPE_DOUBLE:
case FIELD_TYPE_LONGLONG:
case FIELD_TYPE_INT24:
default:
p->type = TYP_FLT;
d = atof(row[0]);
p->Float = d;
break;
case FIELD_TYPE_SHORT:
case FIELD_TYPE_LONG:
p->type = TYP_INT;
sscanf(row[0], "%d", &i);
p->Int = i;
break;
case FIELD_TYPE_TINY_BLOB:
case FIELD_TYPE_MEDIUM_BLOB:
case FIELD_TYPE_LONG_BLOB:
case FIELD_TYPE_BLOB:
break;
}
mysql_free_result(res);
mysql_close(&db);
return;
}
static void
do_mysql_read(struct value *p)
{
/*
* This doesn't do a thing.
*
* A database query is only triggered on request from the user.
*/
}
static void
do_mysql_write(struct value *p)
{
/*
* This doesn't do a thing.
*
* A database query is only triggered on request from the user.
*/
}
/*
* This function reads a block of data from an SQL statement
* into the spreadsheet.
*/
void
MySQLRead(void)
{
MYSQL db;
MYSQL_RES *res;
MYSQL_ROW row;
MYSQL_FIELD *field;
int r, i, j, nrows;
enum enum_field_types *types_list;
char *sql = "select * from koers";
int in_row = curow, in_col = cucol;
if (mysql_connect(&db, "localhost", "danny", "") == NULL) {
fprintf(stderr, "MySQL error '%s'\n", mysql_error(&db));
return;
}
r = mysql_select_db(&db, "test");
if (r != 0) {
fprintf(stderr, "MySQL error '%s'\n", mysql_error(&db));
return;
}
r = mysql_query(&db, sql);
if (r != 0) {
fprintf(stderr, "MySQL error '%s'\n", mysql_error(&db));
return;
}
res = mysql_store_result(&db);
types_list = malloc(mysql_num_fields(res));
for (j=0; j<mysql_num_fields(res); j++) {
field = mysql_fetch_field(res);
(void) quote_new_value(in_row, j+in_col, field->name);
types_list[j] = field->type;
}
nrows = mysql_num_rows(res);
for (i=0; i<mysql_num_rows(res); i++) {
row = mysql_fetch_row(res);
for (j=0; j<mysql_num_fields(res); j++) {
switch (types_list[j]) {
case FIELD_TYPE_CHAR:
case FIELD_TYPE_NULL:
case FIELD_TYPE_TIMESTAMP:
case FIELD_TYPE_DATE:
case FIELD_TYPE_TIME:
case FIELD_TYPE_DATETIME:
case FIELD_TYPE_VAR_STRING:
case FIELD_TYPE_STRING:
#ifdef VERBOSE
fprintf(stderr, "Cell[%d,%d] = '%s'\n", i+1+in_row, j+in_col, row[j]);
#endif
(void)quote_new_value(i+1+in_row, j+in_col, row[j]);
break;
case FIELD_TYPE_DECIMAL:
case FIELD_TYPE_SHORT:
case FIELD_TYPE_LONG:
case FIELD_TYPE_FLOAT:
case FIELD_TYPE_DOUBLE:
case FIELD_TYPE_LONGLONG:
case FIELD_TYPE_INT24:
default:
#ifdef VERBOSE
fprintf(stderr, "Cell[%d,%d] = %s\n", i+1+in_row, j+in_col, row[j]);
#endif
(void)new_value(i+1+in_row, j+in_col, row[j]);
break;
case FIELD_TYPE_TINY_BLOB:
case FIELD_TYPE_MEDIUM_BLOB:
case FIELD_TYPE_LONG_BLOB:
case FIELD_TYPE_BLOB:
break;
}
}
}
mysql_free_result(res);
mysql_close(&db);
free(types_list);
Global->modified = 1;
recalculate(1);
return;
}
#endif /* HAVE_LIBMYSQLCLIENT */
/*
* The functions below need to exist even if we don't have MySQL
*/
void AllocateDatabaseGlobal(void)
{
if (Global->DatabaseGlobal == NULL) {
Global->DatabaseGlobal = (struct DatabaseGlobalType *)
malloc(sizeof(struct DatabaseGlobalType));
memset(Global->DatabaseGlobal, 0, sizeof(struct DatabaseGlobalType));
}
}
void DatabaseSetName(const char *name)
{
if (Global->DatabaseGlobal->name)
free(Global->DatabaseGlobal->name);
Global->DatabaseGlobal->name = strdup(name);
}
void DatabaseSetHost(const char *host)
{
if (Global->DatabaseGlobal->host)
free(Global->DatabaseGlobal->host);
Global->DatabaseGlobal->host = strdup(host);
}
void DatabaseSetUser(const char *user)
{
if (Global->DatabaseGlobal->user)
free(Global->DatabaseGlobal->user);
Global->DatabaseGlobal->user = strdup(user);
}
int
DatabaseInitialised(void)
{
if (Global->DatabaseGlobal)
return 1;
return 0;
}
char *
DatabaseGetName(void)
{
if (Global->DatabaseGlobal)
return Global->DatabaseGlobal->name;
return NULL;
}
char *
DatabaseGetHost(void)
{
if (Global->DatabaseGlobal)
return Global->DatabaseGlobal->host;
return NULL;
}
char *
DatabaseGetUser(void)
{
if (Global->DatabaseGlobal)
return Global->DatabaseGlobal->user;
return NULL;
}
#ifndef HAVE_LIBMYSQLCLIENT
#include "eval.h"
/*
* Define Oleo functions
*/
struct function mysql_functions[] = {
{ 0, 0, "", 0, 0 }
};
int init_mysql_function_count(void)
{
return sizeof(mysql_functions) / sizeof(struct function) - 1;
}
#endif /* HAVE_LIBMYSQLCLIENT */
syntax highlighted by Code2HTML, v. 0.9.1