tinycobol/lib/filesql.c

1535 lines
38 KiB
C

/*
* Copyright (C) 2005 Walter Garrote
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2.1,
* or (at your option) any later version.
*
* This library 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; see the file COPYING.LIB. If
* not, write to the Free Software Foundation, Inc., 59 Temple Place,
* Suite 330, Boston, MA 02111-1307 USA
*/
//---------------------------------------------------------------------------
// Implemented by Walter Garrote
// Brazil - Goiania-GO
//---------------------------------------------------------------------------
#include "ncurses.h"
#include "htcoblib.h"
#include "filesql.h"
struct fields_sql *mount_fields;
struct fd_sql *mount_sql;
struct file_sql *mount_files;
int ALL_INDEX_FILES_TO_GATEWAY = 0;
// read /etc/tinysql and create struct
int tcob_read_tinysql(void) {
char linha[1025], linhar[1025], *var, *val, *cmp;
// struct file_sql *rf;
// struct file_sql *rf_new;
FILE *file;
file = fopen("/etc/tinysql", "r"); // try open /etc/tinysql
if(!file) {
#ifdef DEBUG_RTS
fprintf(stderr, "Failed to open /etc/tinysql\n");
#endif
return 0;
}
fgets(linha, 1024, file);
while(!feof(file)) {
clean_read_line(linha, linhar, 0);
if(strlen(linhar)) {
var = NULL; val = NULL; cmp = NULL;
var = strtok(linhar, " ");
if(var && strncmp(var, "#", 1) != 0) {
val = strtok(NULL, " ");
cmp = strtok(NULL, " ");
}
if(var && val) {
if(strcmp(var, "sql_server")==0) { // define server
sql_server = 0;
if(strcmp(val, "mysql")==0)
sql_server = ORG_MYSQL;
if(strcmp(val, "pgsql")==0)
sql_server = ORG_PGSQL;
}
if(strcmp(var, "sql_db")==0) { // define database
if(sql_db)
free(sql_db);
sql_db = malloc(sizeof(char) * (strlen(val) + 1));
strcpy(sql_db, val);
}
if(strcmp(var, "sql_host")==0) { // define host
if(sql_host)
free(sql_host);
sql_host = malloc(sizeof(char) * (strlen(val) + 1));
strcpy(sql_host, val);
}
if(strcmp(var, "sql_passwd")==0) { // define password
if(sql_passwd)
free(sql_passwd);
sql_passwd = malloc(sizeof(char) * (strlen(val) + 1));
strcpy(sql_passwd, val);
}
if(strcmp(var, "sql_user")==0) { // define user
if(sql_user)
free(sql_user);
sql_user = malloc(sizeof(char) * (strlen(val) + 1));
strcpy(sql_user, val);
}
if(strcmp(var, "fdsql")==0) { // define path for descriptions
if(sql_fdsql)
free(sql_fdsql);
sql_fdsql = malloc(sizeof(char) * (strlen(val) + 1));
strcpy(sql_fdsql, val);
}
if(strcmp(var, "file")==0) { // define files
if(strcmp(val, "all")==0)
ALL_INDEX_FILES_TO_GATEWAY = 1;
else
create_mount_files(val, cmp);
/* else {
rf = mount_files;
if(!rf) {
mount_files = malloc(sizeof(struct file_sql));
mount_files->original_name = malloc(sizeof(char) * strlen(val));
memmove(mount_files->original_name, val, strlen(val));
if(cmp) {
mount_files->table_name = malloc(sizeof(char) * strlen(cmp));
memmove(mount_files->table_name, cmp, strlen(cmp));
}
mount_files->next = NULL;
} else {
while(rf->next != NULL)
rf = rf->next;
rf_new = malloc(sizeof(struct file_sql));
rf_new->original_name = malloc(sizeof(char) * strlen(val));
memmove(rf_new->original_name, val, strlen(val));
if(cmp) {
rf_new->table_name = malloc(sizeof(char) * strlen(cmp));
memmove(rf_new->table_name, cmp, strlen(cmp));
}
rf_new->next = NULL;
rf->next = rf_new;
}
} */
}
}
}
fgets(linha, 1024, file);
}
fclose(file); // close /etc/tinysql
if(!sql_db) { // sql_db not specified in /etc/tiny
#ifdef DEBUG_RTS
fprintf(stderr, "Please specify sql_db in /etc/tinysql\n");
#endif
return 0;
}
if(!sql_fdsql) { // sql_fdsql not specified in /etc/tiny
#ifdef DEBUG_RTS
fprintf(stderr, "Please specify sql_fdsql in /etc/tinysql\n");
#endif
return 0;
}
if(!sql_server) // sql_server not specified int /etc/tiny, use default sql
sql_server = ORG_MYSQL;
if(!sql_host) // sql_host not specified in /etc/tiny, use default host
strcpy(sql_host, "localhost");
if(!sql_user) // sql_user not specified in /etc/tiny, use default user
strcpy(sql_user, "root");
return 1;
}
// put the file name in struct
void create_mount_files(char *file_name, char *tb_name) {
struct file_sql *rf;
struct file_sql *rf_new;
char *p, *table_name;
if(tb_name) // table name was passed ?
table_name = tb_name;
else { // create table name using filename
p = malloc(sizeof(char) * strlen(file_name) + 1);
strcpy(p, file_name);
p = strtok(p, "/");
while(p) {
table_name = p;
p = strtok(NULL, "/");
}
if(strchr(table_name, '.'))
table_name = strtok(table_name, ".");
}
rf = mount_files; // verify if the file was previous open and didn't closed
while(rf != NULL) {
if(strcmp(rf->original_name, file_name)==0)
return;
rf = rf->next;
}
rf = mount_files;
if(!rf) {
mount_files = malloc(sizeof(struct file_sql));
mount_files->original_name = malloc(sizeof(char) * strlen(file_name) + 1);
strcpy(mount_files->original_name, file_name);
mount_files->table_name = NULL;
if(table_name) {
mount_files->table_name = malloc(sizeof(char) * strlen(table_name) + 1);
strcpy(mount_files->table_name, table_name);
}
mount_files->next = NULL;
} else {
while(rf->next != NULL)
rf = rf->next;
rf_new = malloc(sizeof(struct file_sql));
rf_new->original_name = malloc(sizeof(char) * strlen(file_name) + 1);
strcpy(rf_new->original_name, file_name);
rf_new->table_name = NULL;
if(table_name) {
rf_new->table_name = malloc(sizeof(char) * strlen(table_name) + 1);
strcpy(rf_new->table_name, table_name);
}
rf_new->next = NULL;
rf->next = rf_new;
}
}
// campos que compoe a chave
void campos_chave(char *campos, struct fields_sql *fld, int level) {
int tem;
if(fld->size > 0 || fld->decimals > 0) { // field has no subfields
strcat(campos, fld->name);
return;
}
fld = fld->next;
tem = 0;
while(fld != NULL && fld->level > level) {
if(tem)
strcat(campos, ", ");
if(fld->size > 0 || fld->decimals > 0) {
strcat(campos, fld->name);
tem = 1;
}
fld = fld->next;
}
return;
}
// read fd and select of archive and create an struct for use
int tcob_sql_read_def(char *fd, struct file_desc *f) {
char *table, *path, *fname, linha[1025], linhar[1025], *nivel, *campo, *picture, *tamanho, *decimais;
struct fd_sql *pfd;
struct fd_sql *pfd_new;
struct fields_sql *fld;
struct fields_sql *fld_new;
struct fields_sql *fld_aux;
struct keys_sql *fdkey;
struct keys_sql *fdkey_new;
FILE *file;
int def_campo, level, offset;
struct altkey_desc *akd;
if(sql_fdsql == NULL) {
#ifdef DEBUG_RTS
fprintf(stderr, "Please, define the environment variable FdSQL\n");
#endif
return 0;
}
path = malloc(sizeof(char) * 127); *path = 0;
strcpy(path, sql_fdsql);
strcat(path, "/");
table = tcob_sql_table_name(fd);
pfd = mount_sql; /* point to the begin of table */
if(pfd == NULL) { // first table
mount_sql = malloc(sizeof(struct fd_sql));
mount_sql->sql_result = NULL;
mount_sql->file = f;
mount_sql->name = malloc(sizeof(char) * (strlen(table) + 1));
strcpy(mount_sql->name, table);
mount_sql->fields = NULL;
mount_sql->keys = NULL;
mount_sql->next = NULL;
pfd = mount_sql;
} else { // find
while(pfd != NULL && strcmp(pfd->name, table)) // verify if the table is present
pfd = pfd->next;
if(pfd != NULL) { /* present */
free_sql_db(pfd);
return 1;
}
pfd = mount_sql;
while(pfd->next != NULL) // search the end
pfd = pfd->next;
pfd_new = malloc(sizeof(struct fd_sql));
pfd_new->sql_result = NULL;
pfd_new->file = f;
pfd_new->name = malloc(sizeof(char) * (strlen(table) + 1));
strcpy(pfd_new->name, table);
pfd_new->fields = NULL;
pfd_new->keys = NULL;
pfd_new->next = NULL;
pfd->next = pfd_new;
pfd = pfd_new;
}
fname = malloc(sizeof(char) * (strlen(path) + strlen(table) + 9)); *fname = 0;
strcat(fname, path);
strcat(fname, table);
strcat(fname, ".sql_def");
file = fopen(fname, "r");
if(file == NULL) {
if(!tcob_sql_read_fd(path, table, f)) {
free(path);
free(fname);
return 0;
}
file = fopen(fname, "r");
}
fgets(linha, 1024, file);
while(!feof(file)) {
clean_read_line(linha, linhar, 1);
if(strlen(linhar)) {
def_campo = ((strncmp(linhar, ">key", 4) == 0)?0:1);
if(def_campo) {
nivel = NULL; campo = NULL;
picture = NULL; tamanho = NULL;
decimais = NULL;
nivel = strtok(linhar, " ");
campo = strtok(NULL, " ");
picture = strtok(NULL, " ");
tamanho = strtok(NULL, " ");
decimais = strtok(NULL, " ");
fld = pfd->fields;
if(fld == NULL) {
mount_fields = malloc(sizeof(struct fields_sql));
mount_fields->alt = NULL;
mount_fields->level = tcob_sql_int(nivel);
mount_fields->name = malloc(sizeof(char) * (strlen(campo) + 1));
strcpy(mount_fields->name, campo);
mount_fields->type = *picture;
mount_fields->size = tcob_sql_int(tamanho);
mount_fields->decimals = tcob_sql_int(decimais);
mount_fields->index = 0;
mount_fields->unique = 0;
mount_fields->next = NULL;
pfd->fields = mount_fields;
} else {
while(fld->next != NULL)
fld = fld->next;
fld_new = malloc(sizeof(struct fields_sql));
fld_new->alt = NULL;
fld_new->level = tcob_sql_int(nivel);
fld_new->name = malloc(sizeof(char) * (strlen(campo) + 1));
strcpy(fld_new->name, campo);
fld_new->type = *picture;
fld_new->size = tcob_sql_int(tamanho);
fld_new->decimals = tcob_sql_int(decimais);
fld_new->index = 0;
fld_new->unique = 0;
fld_new->next = NULL;
fld->next = fld_new;
}
} else {
strtok(linhar, " ");
campo = strtok(NULL, " ");
picture = strtok(NULL, " "); // index
tamanho = strtok(NULL, " "); // alternate
fld = pfd->fields;
offset = 0;
while(fld != NULL && strcmp(fld->name, campo)) { // verify if the table is present
fld = fld->next;
offset += (fld->size + fld->decimals);
}
if(fld == NULL) /* not present */
return 0;
offset -= (fld->size + fld->decimals);
for (akd = (struct altkey_desc *)(f+1); akd->offset != -1; akd++) { // who is alternate ?
if(akd->offset == offset)
fld->alt = akd;
}
level = fld->level;
if(pfd->keys == NULL) {
pfd->keys = malloc(sizeof(struct keys_sql));
fdkey = pfd->keys;
fdkey->next = NULL;
} else {
fdkey_new = malloc(sizeof(struct keys_sql));
fdkey_new->next = NULL;
fdkey->next = fdkey_new;
fdkey = fdkey_new;
}
fdkey->name = malloc(sizeof(char) * strlen(campo) + 1);
strcpy(fdkey->name, campo);
fdkey->type = tcob_sql_int(picture) + tcob_sql_int(tamanho);
fdkey->fields = malloc(sizeof(char) * 4096); *fdkey->fields = 0;
fld_aux = fld;
campos_chave(fdkey->fields, fld_aux, level);
do {
fld->index = tcob_sql_int(picture);
fld->unique = tcob_sql_int(tamanho);
fld = fld->next;
} while(fld != NULL && fld->level > level);
}
}
fgets(linha, 1024, file);
}
fclose(file);
free(fname);
free(path);
return 1;
}
// return integer
int tcob_sql_int(char *campo) {
int i, size;
size = 0;
for(i=0; i<strlen(campo); i++) {
if(isdigit(campo[i])) {
size *= 10;
size += (campo[i] - 48);
}
}
return size;
}
// Mount the table name
char * tcob_sql_table_name(char *fd) {
struct file_sql *mf;
mf = mount_files;
while(mf != NULL && !strncmp(mf->original_name, fd, strlen(fd))==0) {
mf = mf->next;
}
if(mf)
return mf->table_name;
else
return NULL;
}
// Le definicao do arquivo
int tcob_sql_read_fd(char *path, char *table, struct file_desc *f) {
char *file_name_input, *file_name_output, linaux[1025], linha[1025], linhar[1025], *nivel, *campo, *picture, *tamanho, *decimais;
FILE *file_input;
FILE *file_output;
int dup, nivelant, redefines, pic, filler;
file_name_input = malloc(sizeof(char) * (strlen(path) + strlen(table) + 5)); *file_name_input = 0;
file_name_output = malloc(sizeof(char) * (strlen(path) + strlen(table) + 9)); *file_name_output = 0;
strcat(file_name_input, path);
strcat(file_name_input, table);
strcat(file_name_output, file_name_input);
strcat(file_name_input, ".rg");
strcat(file_name_output, ".sql_def");
if((file_input = fopen(file_name_input, "r")) == NULL) {
#ifdef DEBUG_RTS
fprintf(stderr, "ERROR opening %s\n", file_name_input);
#endif
free(file_name_input);
free(file_name_output);
return 0;
}
if((file_output = fopen(file_name_output, "w")) == NULL) {
#ifdef DEBUG_RTS
fprintf(stderr, "ERROR creating %s\n", file_name_output);
#endif
fclose(file_input);
free(file_name_input);
free(file_name_output);
return 0;
}
redefines = 0;
filler = 0;
fgets(linha, 1024, file_input);
while(!feof(file_input)) {
while(!feof(file_input) && !strstr(linha, ".")) {
fgets(linaux, 1024, file_input);
strcat(linha, " ");
strcat(linha, linaux);
}
clean_read_line(linha, linhar, 1);
if(strlen(linhar) && (isdigit(linhar[0]) || linhar[0] == '>')) {
if(strstr(linhar, " redefines "))
redefines = 1;
if(strstr(linhar, " occurs ") && !redefines) { // occurs in redefines, no problem
#ifdef DEBUG_RTS
fprintf(stderr, "No support for occurs\n");
#endif
fclose(file_input);
fclose(file_output);
free(file_name_input);
free(file_name_output);
return 0;
}
if(!strstr(linhar, " redefines ") && !strstr(linhar, " occurs ")) {
nivel = NULL; campo = NULL;
picture = NULL; tamanho = NULL;
decimais = NULL;
pic = (strstr(linhar, " pic ")?1:0);
nivel = strtok(linhar, " ");
campo = strtok(NULL, " ");
if(strcmp(campo, "filler")==0)
sprintf(campo, "filler%i", filler++);
if(!redefines || (redefines && tcob_sql_int(nivel) <= nivelant)) {
nivelant = tcob_sql_int(nivel);
redefines = 0;
if(pic) {
strtok(NULL, " ");
picture = strtok(NULL, "(");
if(picture == "s9")
picture = "s";
tamanho = strtok(NULL, ")");
strtok(NULL, "(");
decimais = strtok(NULL, ")");
fprintf(file_output,"%s,%s,%s,%s,%s\n",nivel,campo,picture,tamanho,decimais);
} else
fprintf(file_output,"%s,%s,0,0,0\n",nivel,campo);
}
}
}
fgets(linha, 1024, file_input);
}
fclose(file_input);
strcpy(file_name_input, path);
strcat(file_name_input, table);
strcat(file_name_input, ".sel");
if((file_input = fopen(file_name_input, "r")) == NULL) {
fclose(file_output);
#ifdef DEBUG_RTS
fprintf(stderr, "ERROR opening %s\n", file_name_input);
#endif
free(file_name_input);
free(file_name_output);
return 0;
}
fgets(linha, 1024, file_input);
while(!feof(file_input)) {
clean_read_line(linha, linhar, 1);
if(strlen(linhar)) {
if(strstr(linhar, "alternate record key ")) {
dup = 0;
if(strstr(linhar, "with duplicates"))
dup = 1;
strtok(linhar, " ");
strtok(NULL, " ");
strtok(NULL, " ");
campo = strtok(NULL, " ");
if(strcmp(campo, "is")==0)
campo = strtok(NULL, " ");
fprintf(file_output,">key %s,2,%i\n", campo, dup);
} else {
if(strstr(linhar, "record key ")) {
strtok(linhar, " ");
strtok(NULL, " ");
// strtok(NULL, " ");
campo = strtok(NULL, " ");
if(strcmp(campo,"is")==0)
campo = strtok(NULL, " ");
fprintf(file_output,">key %s,1,0\n", campo);
}
}
}
fgets(linha, 1024, file_input);
}
fclose(file_input);
fclose(file_output);
free(file_name_input);
free(file_name_output);
return 1;
}
// clean the readed line
void clean_read_line(char *linha, char *linhar, int ponto) {
int i, bg, ed;
bg = 0; ed = 0;
for(i=0; i<strlen(linha); i++) {
linha[i] = tolower(linha[i]);
if(ponto && linha[i] == '.')
linha[i] = ' ';
switch(linha[i]) {
case '=':
case '\'':
case ',':
case '\r':
case '\n':
case '\t': linha[i] = ' ';
case ' ': if(bg > 1) {
if(ed == 0) {
ed = 1;
linhar[bg++] = ' ';
}
}
break;
default: if(linha[i] == '-') linha[i]='_';
linhar[bg++] = linha[i];
ed = 0;
break;
}
}
linhar[bg++] = 0;
return;
}
// create verb
int create_sql_db(char *fd) {
char *table, *query, bufs[10], bufd[10];
int tem;
struct fd_sql *pfd;
struct fields_sql *fld;
struct keys_sql *keys;
table = tcob_sql_table_name(fd);
pfd = mount_sql;
while(pfd != NULL && strcmp(pfd->name, table))
pfd = pfd->next;
if(pfd == NULL) // no table
return 0;
fld = pfd->fields;
if(fld == NULL) // no fields
return 0;
query = malloc(sizeof(char) * 4096); *query = 0;
free_sql_db(pfd);
strcpy(query, "drop table ");
strcat(query, table);
strcat(query, ";");
query_sql_db(NULL, query, 0);
strcpy(query, "create table ");
strcat(query, table);
strcat(query, " ( ");
tem = 0;
while(fld != NULL) {
if(fld->size > 0 || fld->decimals > 0) {
if(tem)
strcat(query, ", ");
strcat(query, fld->name);
sprintf(bufs, "%i", fld->size);
sprintf(bufd, "%i", fld->decimals);
switch(fld->type) {
case 'a':
case 'x': if((fld->size + fld->decimals) > 255)
strcat(query, " text");
else {
strcat(query, " char(");
strcat(query, bufs);
strcat(query, ")");
}
break;
case 's':
case '9':
#ifdef USE_MYSQL_GATEWAY
if(fld->decimals)
strcat(query, " float(");
else
if(fld->size > 9)
strcat(query, " bigint(");
else
strcat(query, " int(");
strcat(query, bufs);
if(fld->decimals) {
strcat(query, ",");
strcat(query, bufd);
}
#endif
#ifdef USE_PGSQL_GATEWAY
strcat(query, " numeric(");
strcat(query, bufs);
if(fld->decimals) {
strcat(query, ",");
strcat(query, bufd);
}
#endif
strcat(query, ")");
break;
}
tem = 1;
}
fld = fld->next;
}
strcat(query, " );");
//printf("%s\n",query); getchar();
// structure
if(!query_sql_db(NULL, query, 0))
return 0;
// monta chaves
keys = pfd->keys;
while(keys) {
switch(keys->type) {
case 1: // primary
#ifdef USE_MYSQL_GATEWAY
strcpy(query, "alter table ");
strcat(query, table);
strcat(query, " add primary key ( ");
strcat(query, keys->fields);
strcat(query, " );");
#endif
#ifdef USE_PGSQL_GATEWAY
strcpy(query, "create unique index _");
strcat(query, key->name);
strcat(query, " on ");
strcat(query, table);
strcat(query, " ( ");
strcat(query, keys->fields);
strcat(query, " );");
#endif
//printf("%s\n", query); getchar();
if(!query_sql_db(NULL, query, 0))
return 0;
break;
case 2: // unique key
#ifdef USE_MYSQL_GATEWAY
strcpy(query, "alter table ");
strcat(query, table);
strcat(query, " add unique _");
strcat(query, keys->name);
strcat(query, " ( ");
strcat(query, keys->fields);
strcat(query, " );");
#endif
#ifdef USE_PGSQL_GATEWAY
strcpy(query, "create unique index _");
strcat(query, key->name);
strcat(query, " on ");
strcat(query, table);
strcat(query, " ( ");
strcat(query, keys->fields);
strcat(query, " );");
#endif
//printf("%s\n", query); getchar();
if(!query_sql_db(NULL, query, 0))
return 0;
break;
case 3: // alternate with duplicates
#ifdef USE_MYSQL_GATEWAY
strcpy(query, "alter table ");
strcat(query, table);
strcat(query, " add index _");
strcat(query, keys->name);
strcat(query, " ( ");
strcat(query, keys->fields);
strcat(query, " );");
#endif
#ifdef USE_PGSQL_GATEWAY
strcpy(query, "create index _");
strcat(query, keys->name);
strcat(query, " on ");
strcat(query, table);
strcat(query, " ( ");
strcat(query, keys->fields);
strcat(query, " );");
#endif
//printf("%s\n", query); getchar();
if(!query_sql_db(NULL, query, 0))
return 0;
break;
}
keys = keys->next;
}
//
free(query);
return 1;
}
// search for the table
struct fd_sql * search_table(struct file_desc *fd) {
struct fd_sql *pfd;
pfd = mount_sql;
while(pfd != NULL && pfd->file != fd)
pfd = pfd->next;
return pfd;
}
// put value in query
int put_value_query(struct fields_sql *fld, char *record, int p, char *query) {
struct fld_desc *porg, *pdst;
char *org, *dst, *pnt;
int s, piclen;
char cDecimal = (bDecimalComma) ? ',' : '.';
s = fld->size + fld->decimals; // total bytes
// alphanumeric and unsigned integer
if(fld->decimals == 0 && fld->type != 's') {
if(*(record + p) == 0 && fld->type == '9')
strcat(query, "0");
else
strncat(query, (record + p), s);
p += s;
return p;
}
// signed numeric or with decimals
porg = malloc(sizeof(struct fld_desc));
pdst = malloc(sizeof(struct fld_desc));
org = malloc(sizeof(char) * (s + 1));// *org = 0;
dst = malloc(sizeof(char) * (s + 3));// *dst = 0;
memset(org, 0, (s+1));
memset(dst, 0, (s+3));
porg->len = s;
porg->type = DTYPE_DISPLAY;
porg->pscale = 0;
porg->decimals = fld->decimals;
porg->pic = NULL;
*pdst = *porg;
pdst->type = DTYPE_EDITED;
piclen = tcob_picReqLen(4);
porg->pic = malloc(sizeof(char) * piclen);
pdst->pic = malloc(sizeof(char) * piclen);
tcob_picCreate(porg->pic, piclen, NULL);
tcob_picCreate(pdst->pic, piclen, NULL);
if(fld->type == 's') {
tcob_picAppend(porg->pic, piclen, 'S', 1, NULL);
tcob_picAppend(pdst->pic, piclen, '-', 1, NULL);
pdst->len++;
}
if(fld->size) {
tcob_picAppend(porg->pic, piclen, '9', fld->size, NULL);
tcob_picAppend(pdst->pic, piclen, '9', fld->size, NULL);
}
if(fld->decimals) {
tcob_picAppend(porg->pic, piclen, 'V', 1, '9', fld->decimals, NULL);
tcob_picAppend(pdst->pic, piclen, cDecimal, 1, '9', fld->decimals, NULL);
pdst->len++;
}
strncpy(org, (record + p), s);
tcob_move(porg, org, pdst, dst);
if(fld->decimals) { // change this after, remenber to see how to configure mysql or pgsql to accept "," in float fields
pnt = dst;
while(*pnt) {
if(*pnt == ',')
*pnt = '.';
pnt++;
}
}
strcat(query, dst);
p += s;
free(org);
free(dst);
free(porg->pic);
free(pdst->pic);
return p;
}
// insert data into table
int insert_sql_db(struct file_desc *fd, char *record) {
struct fd_sql *pfd;
struct fields_sql *fld;
char *query;
int tem, p;
if(!(pfd = search_table(fd))) // no table
return 0;
if(!(fld = pfd->fields)) // no fields
return 0;
query = malloc(sizeof(char) * (strlen(record) + 4096)); *query = 0;
strcpy(query, "insert into ");
strcat(query, pfd->name);
strcat(query, " ( ");
fld = pfd->fields;
tem = 0;
while(fld != NULL) {
if(fld->size > 0 || fld->decimals > 0) {
if(tem)
strcat(query, ", ");
strcat(query, fld->name);
tem = 1;
}
fld = fld->next;
}
strcat(query, " ) values (");
fld = pfd->fields;
tem = 0;
p = 0;
while(fld != NULL) {
if(fld->size > 0 || fld->decimals > 0) {
if(tem)
strcat(query, "', ");
strcat(query, "'");
p = put_value_query(fld, record, p, query);
tem = 1;
}
fld = fld->next;
}
strcat(query, "' );");
//printf("%s\n", query); getchar();
if(!query_sql_db(pfd, query, 0)) {
free(query);
return 0;
}
free(query);
return 1;
}
// start into table
int start_sql_db(struct file_desc *fd, char *record, int cond, char *key_ptr) {
struct fd_sql *pfd;
struct fields_sql *fld;
struct fields_sql *xfld;
char *query, comp[3], new_record[fd->reclen], *name_index;
int level, tem, p;
if(!(pfd = search_table(fd))) // no table
return 0;
if(!(fld = pfd->fields)) // no fields
return 0;
free_sql_db(pfd); // free results
if(fd->start_record) { // free before
free(fd->start_record);
fd->start_record = NULL;
}
switch(cond) {
case 1: strcpy(comp, "="); break;
case 2: strcpy(comp, "<"); break;
case 3: strcpy(comp, "<="); break;
case 4: strcpy(comp, ">"); break;
case 5: strcpy(comp, ">="); break;
}
query = malloc(sizeof(char) * (strlen(record) + 4096)); *query = 0;
name_index = malloc(sizeof(char) * 1024); *name_index = 0;
strcpy(query, "select * from ");
strcat(query, pfd->name);
strcat(query, " where ");
p = 0;
if(pfd->file->key_in_use) // begin of alternate field
while(fld != NULL && fld->alt != pfd->file->key_in_use) {
p += (fld->size + fld->decimals);
fld = fld->next;
}
level = 0;
while(fld != NULL) { // index ?
if(fld->index && !level)
level = fld->level;
if(fld->type != '0') // index ?
break;
else
fld = fld->next;
}
if(key_ptr) // start verb
p = 0;
tem = 0;
do {
if(fld->size > 0 || fld->decimals > 0) {
if(tem) {
strcat(query, "' && ");
strcat(name_index, ", ");
}
strcat(name_index, fld->name);
strcat(query, fld->name);
strcat(query, " ");
strcat(query, comp);
switch(cond) {
case 2:
case 4: xfld = fld->next;
if(xfld != NULL && xfld->level > level) // exist another fild for key
strcat(query,"=");
}
strcat(query, " '");
if(key_ptr) // start verb
p = put_value_query(fld, key_ptr, p, query);
else
p = put_value_query(fld, record, p, query);
tem = 1;
}
fld = fld->next;
} while(fld != NULL && fld->level > level);
strcat(query, "' order by ");
strcat(query, name_index);
strcat(query, ";");
// strcat(query, " limit 1;");
//printf("%s\n",query); getchar();
//mvaddstr(20,0,query); clrtobot(); refresh(); getch();
if(!query_sql_db(pfd, query, 1)) {
free(query);
return 0;
}
free(query);
pfd->row = 1;
memset(new_record, 0, fd->reclen);
if(key_ptr) {
if(read_offset_db(pfd, new_record)) { // store in start_record
// if(fd->start_record) { // free before
// free(fd->start_record);
// fd->start_record = NULL;
// }
fd->start_record = malloc(sizeof(char) * fd->reclen);
memmove(fd->start_record, new_record, fd->reclen);
pfd->row = 2;
}
}
return 1;
}
// read from query result
int read_sql_db(struct file_desc *fd, char *record) {
struct fd_sql *pfd;
struct fields_sql *fld;
if(!(pfd = search_table(fd))) // no table
return 0;
if(!(fld = pfd->fields)) // no fields
return 0;
// if(!pfd->sql_result)
if(!start_sql_db(fd, record, 1, NULL)) // start the table
return 0;
if(!read_offset_db(pfd, record))
return 0;
return 1;
}
// read next from query result
int readnext_sql_db(struct file_desc *fd, char *record) {
struct fd_sql *pfd;
struct fields_sql *fld;
if(!(pfd = search_table(fd))) // no table
return 0;
if(!(fld = pfd->fields)) // no fields
return 0;
if(!pfd->sql_result) // start greater than low-value (first record on table)
memset(record, 0, (int) fd->reclen);
#ifdef USE_MYSQL_GATEWAY
if(pfd->sql_result) {
unsigned long long nrows;
nrows = mysql_num_rows(pfd->sql_result);
if((pfd->row == 1 && nrows == 1) || (pfd->row > nrows)) // no rows to read
free_sql_db(pfd);
}
#endif
#ifdef USE_PGSQL_GATEWAY
if(pfd->sql_result && pfd->row >= PQntuples(pfd->sql_result)) // no rows to read
free_sql_db(pfd);
#endif
if(!pfd->sql_result)
if(!start_sql_db(fd, record, 4, NULL)) // start the table
return 0;
memset(record, 0, fd->reclen);
if(!read_offset_db(pfd, record))
return 0;
pfd->row++; // next row
return 1;
}
// read previous from query result
int readprevious_sql_db(struct file_desc *fd, char *record) {
struct fd_sql *pfd;
struct fields_sql *fld;
if(!(pfd = search_table(fd))) // no table
return 0;
if(!(fld = pfd->fields)) // no fields
return 0;
if(!pfd->sql_result) // no start before
memset(record, 0, (int) fd->reclen);
if(pfd->row == 0) // no rows to read
free_sql_db(pfd);
// free_sql_db(pfd);
if(!pfd->sql_result) // no start before
if(!start_sql_db(fd, record, 2, NULL)) // start the table
return 0;
memset(record, 0, fd->reclen);
if(!read_offset_db(pfd, record))
return 0;
pfd->row--;
return 1;
}
// read offset pointer by fld and put values in record
int read_offset_db(struct fd_sql *pfd, char *record) {
struct fields_sql *fld;
int p, i;
unsigned long long offset;
#ifdef USE_MYSQL_GATEWAY
MYSQL_ROW row;
#endif
#ifdef USE_PGSQL_GATEWAY
char *row;
#endif
if(!(fld = pfd->fields)) // no fields
return 0;
p = 0; i = 0; // move row to record
#ifdef USE_MYSQL_GATEWAY
offset = (long long) pfd->row - 1;
mysql_data_seek(pfd->sql_result, offset); // seek table
row = mysql_fetch_row(pfd->sql_result); // fetch fields
if(!row) // no rows, return with error
return 0;
#endif
#ifdef USE_PGSQL_GATEWAY
int nfield=0;
int maxfield = PQnfields(pfd->sql_result);
while (nfield < maxfield && fld != NULL) {
row = PQgetvalue(pfd->sql_result, 0, nfield++);
#endif
while(fld != NULL) {
if(fld->size > 0 || fld->decimals > 0) {
#ifdef USE_MYSQL_GATEWAY
put_value_record(fld, record, p, row[i++]);
#endif
#ifdef USE_PGSQL_GATEWAY
put_value_record(fld, record, p, row);
#endif
p += (fld->size + fld->decimals);
#ifdef USE_PGSQL_GATEWAY
fld = fld->next;
break;
#endif
}
fld = fld->next;
}
#ifdef USE_PGSQL_GATEWAY
}
#endif
return 1;
}
// delete into table
int delete_sql_db(struct file_desc *fd, char *record) {
struct fd_sql *pfd;
struct fields_sql *fld;
char *query;
int level, tem, p;
if(!(pfd = search_table(fd))) // no table
return 0;
if(!(fld = pfd->fields)) // no fields
return 0;
//free_sql_db(pfd); // free sql_result
query = malloc(sizeof(char) * (strlen(record) + 4096)); *query = 0;
strcpy(query, "delete from ");
strcat(query, pfd->name);
strcat(query, " where ");
p = 0;
level = 0;
while(fld != NULL) { // index ?
if(fld->index && !level)
level = fld->level;
if(fld->type != '0') // index ?
break;
else
fld = fld->next;
}
tem = 0;
do {
if(fld->size > 0 || fld->decimals > 0) {
if(tem)
strcat(query, "' && ");
strcat(query, fld->name);
strcat(query, " = '");
p = put_value_query(fld, record, p, query);
tem = 1;
}
fld = fld->next;
} while(fld != NULL && fld->level > level);
strcat(query, "';");
//printf("%s\n", query); getchar();
if(!query_sql_db(pfd, query, 0)) {
free(query);
return 0;
}
free(query);
return 1;
}
// insert data into table
int update_sql_db(struct file_desc *fd, char *record) {
struct fd_sql *pfd;
struct fields_sql *fld;
char *query;
int level, tem, p;
if(!(pfd = search_table(fd))) // no table
return 0;
if(!(fld = pfd->fields)) // no fields
return 0;
query = malloc(sizeof(char) * (strlen(record) + 4096)); *query = 0;
strcpy(query, "update ");
strcat(query, pfd->name);
strcat(query, " set ");
fld = pfd->fields;
tem = 0;
p = 0;
while(fld != NULL) {
if(fld->size > 0 || fld->decimals > 0) {
if(tem)
strcat(query, "', ");
strcat(query, fld->name);
strcat(query, " = '");
p = put_value_query(fld, record, p, query);
tem = 1;
}
fld = fld->next;
}
strcat(query, "' where ");
fld = pfd->fields;
p = 0;
level = 0;
while(fld != NULL) { // index ?
if(fld->index && !level)
level = fld->level;
if(fld->type != '0') // index ?
break;
else
fld = fld->next;
}
tem = 0;
do {
if(fld->size > 0 || fld->decimals > 0) {
if(tem)
strcat(query, "' && ");
strcat(query, fld->name);
strcat(query, " = '");
p = put_value_query(fld, record, p, query);
tem = 1;
}
fld = fld->next;
} while(fld != NULL && fld->level > level);
strcat(query, "' limit 1;");
if(!query_sql_db(pfd, query, 0)) {
free(query);
return 0;
}
free(query);
return 1;
}
// put value in record
void put_value_record(struct fields_sql *fld, char *record, int p, char *row) {
struct fld_desc *porg, *pdst;
char *dst, *str1;
int s, piclen;
char cDecimal = (bDecimalComma) ? ',' : '.';
s = fld->size + fld->decimals; // total bytes
// alphanumeric and unsigned integer
if(fld->type == 'x') {
memset((record + p), 32, s);
memmove((record + p), row, strlen(row));
return;
}
// signed numeric or with decimals
porg = malloc(sizeof(struct fld_desc));
pdst = malloc(sizeof(struct fld_desc));
dst = malloc(sizeof(char) * (s + 3)); *dst = 0;
porg->len = strlen(row);
porg->type = DTYPE_ALPHANUMERIC;
porg->decimals = 0;
porg->pscale = 0;
porg->all = 0;
porg->just_r = 0;
porg->separate_sign = 0;
porg->leading_sign = 0;
porg->blank = 0;
porg->reserved = 0;
porg->pic = NULL;
*pdst = *porg;
pdst->type = DTYPE_DISPLAY;
pdst->len = s;
pdst->decimals = fld->decimals;
piclen = tcob_picReqLen(4);
porg->pic = malloc(sizeof(char) * piclen);
pdst->pic = malloc(sizeof(char) * piclen);
tcob_picCreate(porg->pic, piclen, 'X', porg->len, NULL);
tcob_picCreate(pdst->pic, piclen, NULL);
if(fld->type == 's')
tcob_picAppend(pdst->pic, piclen, 'S', 1, NULL);
if(fld->size)
tcob_picAppend(pdst->pic, piclen, '9', fld->size, NULL);
if(fld->decimals)
tcob_picAppend(pdst->pic, piclen, 'V', 1, '9', fld->decimals, NULL);
switch(cDecimal) {
case '.': str1 = strstr(row, ",");
break;
case ',': str1 = strstr(row, ".");
break;
}
if(str1)
*str1 = cDecimal;
tcob_move(porg, row, pdst, dst);
memcpy((record + p), dst, s);
free(dst);
free(porg->pic);
free(pdst->pic);
return;
}
// connect to sql data base
int connect_sql_db(void) {
if(sql_conn != NULL) // already connect
return 1;
#ifdef USE_MYSQL_GATEWAY
sql_conn = (MYSQL *) malloc(sizeof(MYSQL));
if(!mysql_init(sql_conn))
return 0;
if(!mysql_real_connect(sql_conn, sql_host, sql_user, sql_passwd, sql_db, 0, NULL, 0)) {
#ifdef DEBUG_RTS
fprintf(stderr, "Conectando %s, %s, %s, %s\n", sql_host, sql_user, sql_passwd, sql_db);
fprintf(stderr, "Failed to connect to database: Error: %s\n", mysql_error(sql_conn));
#endif
return 0;
}
#endif
#ifdef USE_PGSQL_GATEWAY
int status;
sql_conn = PQsetdbLogin(NULL, NULL, NULL, NULL, sql_db, sql_user, sql_passwd);
status = PQstatus(sql_conn);
if(status) {
#ifdef DEBUG_RTS
fprintf(stderr, "Conectando %s, %s, %s, %s\n", sql_host, sql_user, sql_passwd, sql_db);
fprintf(stderr, "Failed to connect to database: Error: %i\n", status);
#endif
return 0;
}
#endif
return 1;
}
// execute the query command
int query_sql_db(struct fd_sql *pfd, char *query, int store_result) {
if(sql_conn == NULL) // not connected, try first
if(!connect_sql_db())
return 0;
//mvaddstr(24, 0, query); clrtobot(); refresh(); getch();
#ifdef USE_MYSQL_GATEWAY
if(mysql_query(sql_conn, query) != 0) {
#ifdef DEBUG_RTS
fprintf(stderr, "Failed to query database: Error: %s\n", mysql_error(sql_conn));
#endif
//mvaddstr(20, 0, mysql_error(sql_conn));
//refresh(); getch();
return 0;
}
if(pfd && store_result) { // use for select only
if(!(pfd->sql_result = mysql_store_result(sql_conn))) { // store result
free_sql_db(pfd);
return 0;
}
if(mysql_num_rows(pfd->sql_result) == 0) { // no rows affected
free_sql_db(pfd);
return 0;
}
}
#endif
#ifdef USE_PGSQL_GATEWAY
char *error_message;
if(store_result)// {
pfd->sql_result = PQexec(sql_conn, query);
// status = PQresultStatus(pfd->sql_result);
// } else {
else
PQexec(sql_conn, query);
// status = PQstatus(sql_conn);
// }
// status = PQresultStatus(pfd->sql_result);
// if(!store_result)
// free_sql_db(pfd);
error_message = PQerrorMessage(sql_conn);
//printf("query -> %s\nPqerrorMessage %s\n%i\n", query, error_message, *error_message);
if(*error_message)
return 0;
/* switch(status) {
case PGRES_EMPTY_QUERY: printf("empty_query\n"); getchar(); break;
case PGRES_COPY_OUT: printf("copy_out\n"); getchar(); break;
case PGRES_COPY_IN: printf("copy_in\n"); getchar(); break;
case PGRES_BAD_RESPONSE: printf("bad_response\n"); getchar(); break;
case PGRES_COMMAND_OK: printf("comand_ok\n"); getchar(); break;
case PGRES_TUPLES_OK: printf("tuples_ok\n"); getchar(); break;
case PGRES_NONFATAL_ERROR: printf("nonfatal_error\n"); getchar(); break;
case PGRES_FATAL_ERROR: printf("fatal_error\n"); getchar(); break;
default: //fprintf(stderr, "Failed to query database: Error: %i\n", status);
printf("sei la %i\n", status); getchar(); break;
return 0;
break;
}*/
if(pfd && store_result) { // use for select only
if(!pfd->sql_result) { // store result
free_sql_db(pfd);
return 0;
}
if(PQntuples(pfd->sql_result) == 0) { // no rows affected
free_sql_db(pfd);
return 0;
}
}
#endif
return 1;
}
// free sql_result
void free_sql_db(struct fd_sql *pfd) {
if(!pfd) // no descriptor
return;
if(pfd->sql_result) // free sql_result before
#ifdef USE_MYSQL_GATEWAY
mysql_free_result(pfd->sql_result);
#endif
#ifdef USE_PGSQL_GATEWAY
PQclear(pfd->sql_result);
#endif
pfd->sql_result = NULL;
pfd->row = 0;
return;
}
// close sql table
int close_sql_table(struct file_desc *f) {
struct fd_sql *pfd=mount_sql;
struct fd_sql *before=mount_sql;
struct fd_sql *next=NULL;
if(mount_sql)
next = mount_sql->next;
while(mount_sql != NULL && mount_sql->file != f) { // search for the file
before = mount_sql;
mount_sql = mount_sql->next;
next = NULL;
if(mount_sql)
next = mount_sql->next;
}
if(!mount_sql || mount_sql->file != f) { // no pointer, return error
mount_sql = pfd;
return 0;
}
free_sql_db(mount_sql); // release sql_result
free(mount_sql); // release the actual pointer
if(mount_sql == pfd) // first was closed
mount_sql = next;
else { // points to begin again
mount_sql = before;
mount_sql->next = next;
mount_sql = pfd;
}
if(!mount_sql) // close connection if we don't have open "table"
close_sql_db();
return 1;
}
// close sql data base
int close_sql_db(void) {
#ifdef USE_MYSQL_GATEWAY
mysql_close(sql_conn);
free(sql_conn); // free memory
#endif
#ifdef USE_PGSQL_GATEWAY
PQfinish(sql_conn);
#endif
sql_conn = NULL; // force to point NULL
return 1;
}
/* EOF filesql.c */