This is msql_proc.c in view mode; [Download] [Up]
/* ** msql_proc.c - ** ** ** Copyright (c) 1993-95 David J. Hughes ** Copyright (c) 1995 Hughes Technologies Pty Ltd ** ** Permission to use, copy, and distribute for non-commercial purposes, ** is hereby granted without fee, providing that the above copyright ** notice appear in all copies and that both the copyright notice and this ** permission notice appear in supporting documentation. ** ** This software is provided "as is" without any expressed or implied warranty. ** ** ID = "$Id:" ** */ #ifndef lint static char RCS_id[] = "msql_proc.c,v 1.3 1994/08/19 08:03:15 bambi Exp"; #endif #include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <signal.h> #include <netdb.h> #include <common/debug.h> #include <common/portability.h> #define MSQL_ADT #include "msql_priv.h" #include "msql.h" #include "y.tab.h" int command, notnullflag, keyflag, outSock, msqlSelectLimit; char *curDB, *arrayLen; cond_t *condHead = NULL; field_t *fieldHead = NULL, *lastField = NULL; order_t *orderHead = NULL; tname_t *tableHead = NULL; static cond_t *condTail = NULL; static field_t *fieldTail = NULL; static order_t *orderTail = NULL; static tname_t *tableTail = NULL; static int havePriKey = 0; #define malloc(L) Malloc(L,__FILE__,__LINE__) #define free(A) Free(A,__FILE__,__LINE__) #define safeFree(x) {if (x) { (void) free(x); x = NULL; }} #define REG register extern char *packet; /**************************************************************************** ** _msqlClean - clean out the internal structures ** ** Purpose : Free all space and reset structures after a query ** Args : None ** Returns : Nothing ** Notes : Updates all public data structures */ msqlClean() { register field_t *curField, *tmpField; register cond_t *curCond, *tmpCond; register order_t *curOrder, *tmpOrder; register tname_t *curTable, *tmpTable; msqlTrace(TRACE_IN,"msqlClean()"); command = 0; havePriKey = 0; /* ** blow away the table list from the query */ curTable = tableHead; while(curTable) { tmpTable = curTable; curTable = curTable->next; (void)free(tmpTable); } /* ** blow away the field list from the query */ curField = fieldHead; while(curField) { freeValue(curField->value); tmpField = curField; curField = curField->next; (void)free(tmpField); } /* ** Blow away the condition list from the query */ curCond = condHead; while(curCond) { freeValue(curCond->value); curCond->op = curCond->bool = 0; tmpCond = curCond; curCond = curCond->next; (void)free(tmpCond); } curOrder = orderHead; while(curOrder) { curOrder->dir = 0; tmpOrder = curOrder; curOrder = curOrder->next; (void)free(tmpOrder); } /* ** Reset the list pointers */ condHead = condTail = (cond_t *) NULL; fieldHead = fieldTail = lastField = (field_t *) NULL; orderHead = orderTail = (order_t *) NULL; tableHead = tableTail = (tname_t *) NULL; msqlBackendClean(); msqlTrace(TRACE_OUT,"msqlClean()"); } ident_t *msqlCreateIdent(seg1,seg2) char *seg1, *seg2; { ident_t *new; msqlTrace(TRACE_IN,"msqlCreateIdent()"); if (seg1) { if (strlen(seg1) > NAME_LEN) { sprintf(packet, "-1:Identifier name '%s' too long\n",seg1); writePkt(outSock); msqlTrace(TRACE_OUT,"msqlCreateIdent()"); return(NULL); } } if (seg2) { if (strlen(seg2) > NAME_LEN) { sprintf(packet, "-1:Identifier name '%s' too long\n",seg2); writePkt(outSock); msqlTrace(TRACE_OUT,"msqlCreateIdent()"); return(NULL); } } new = (ident_t *)malloc(sizeof(ident_t)); if (seg1) { (void)strcpy(new->seg1,seg1); } if (seg2) { (void)strcpy(new->seg2,seg2); } msqlTrace(TRACE_OUT,"msqlCreateIdent()"); return(new); } static u_char expandEscape(c,remain) u_char *c; int remain; { u_char ret; switch(*c) { case 'n': ret = '\n'; break; case 't': ret = '\t'; break; case 'r': ret = '\r'; break; case 'b': ret = '\b'; break; default: ret = *c; break; } return(ret); } val_t *msqlCreateValue(textRep,type,tokLen) u_char *textRep; int type, tokLen; { val_t *new; int length, remain, match; REG u_char *cp, *cp2; static u_char nullVal[] = "null"; msqlTrace(TRACE_IN,"msqlCreateValue()"); new = (val_t *)malloc(sizeof(val_t)); new->type = type; new->dataLen = tokLen; switch(type) { case NULL_TYPE: new->nullVal = 1; break; case IDENT_TYPE: new->val.identVal = (ident_t *)textRep; break; case CHAR_TYPE: remain = length = tokLen - 2; new->val.charVal = (u_char *)malloc(length+1); cp = textRep+1; cp2 = new->val.charVal; while(remain) { if (*cp == '\\') { remain--; *cp2 = expandEscape(++cp,remain); if (*cp2) { cp2++; cp++; remain--; } } else { *cp2++ = *cp++; remain--; } } break; case INT_TYPE: new->val.intVal = atoi(textRep); break; case REAL_TYPE: sscanf((char *)textRep ,"%lg",&new->val.realVal); break; } msqlTrace(TRACE_OUT,"msqlCreateValue()"); return(new); } val_t *fillValue(val,type,length) char *val; int type, length; { val_t *new; msqlTrace(TRACE_IN,"fillValue()"); new = (val_t *)malloc(sizeof(val_t)); new->type = type; new->nullVal = 0; switch(type) { case CHAR_TYPE: new->val.charVal = (u_char *)malloc(length+1); (void)bcopy(val,new->val.charVal,length); break; case INT_TYPE: #ifndef _CRAY new->val.intVal = (int) * (int *)val; #else new->val.intVal = unpackInt32(val); #endif break; case REAL_TYPE: new->val.realVal = (double) * (double *)val; break; } msqlTrace(TRACE_OUT,"fillValue()"); return(new); } val_t *nullValue() { val_t *new; new = (val_t *)malloc(sizeof(val_t)); new->nullVal = 1; return(new); } freeValue(val) val_t *val; { msqlTrace(TRACE_IN,"freeValue()"); if (!val) { msqlTrace(TRACE_OUT,"freeValue()"); return; } switch(val->type) { case IDENT_TYPE: (void)free(val->val.identVal); break; case CHAR_TYPE: if (!val->nullVal) (void)free(val->val.charVal); break; } (void)free(val); msqlTrace(TRACE_OUT,"freeValue()"); } /**************************************************************************** ** _msqlAddField - add a field definition to the list ** ** Purpose : store field details from the query for later use ** Args : field name, field type, field length, value ** Returns : Nothing ** Notes : Depending on the query in process, only some of the ** args will be supplied. eg. a SELECT doesn't use the ** type arg. The length arg is only used during a create ** if the field is of type CHAR */ int msqlAddField(ident,type,length,notNull,priKey) ident_t *ident; int type; char *length; int notNull, priKey; { register field_t *new; char *name, *table; msqlTrace(TRACE_IN,"msqlAddField()"); if (*(ident->seg2)) { name = ident->seg2; table = ident->seg1; } else { name = ident->seg1; table = NULL; } /* ** Look for duplicate field names on a table create */ if (type != 0) { new = fieldHead; while(new) { if (strcmp(new->name,name) == 0) { sprintf(packet, "-1:Duplicate field name '%s'\n", name); writePkt(outSock); msqlTrace(TRACE_OUT,"msqlAddField()"); return(-1); } new = new->next; } } if (priKey) { if (havePriKey) { sprintf(packet,"-1:Can't have multiple primary keys\n"); writePkt(outSock); msqlTrace(TRACE_OUT,"msqlAddField()"); return(-1); } else { havePriKey = 1; } } new = (field_t *)malloc(sizeof(field_t)); if (table) { (void)strncpy(new->table,table,NAME_LEN - 1); } (void)strncpy(new->name,name,NAME_LEN - 1); if (notNull) { new->flags |= NOT_NULL_FLAG; } if (priKey) { new->flags |= PRI_KEY_FLAG; new->flags |= NOT_NULL_FLAG; } switch(type) { case INT: new->type = INT_TYPE; new->length = 4; break; case CHAR: new->type = CHAR_TYPE; new->length = atoi(length); break; case REAL: new->type = REAL_TYPE; new->length = sizeof(double); break; default: new->type = 0; new->length = 0; break; } if (!fieldHead) { fieldHead = fieldTail = new; } else { fieldTail->next = new; fieldTail = new; } free(ident); msqlTrace(TRACE_OUT,"msqlAddField()"); return(0); } msqlSetSelectLimit(value) val_t *value; { msqlSelectLimit = value->val.intVal; } msqlAddFieldValue(value) val_t *value; { register field_t *fieldVal; u_char *buf; msqlTrace(TRACE_IN,"msqlAddFieldValue()"); if (!lastField) { lastField = fieldVal = fieldHead; } else { fieldVal = lastField->next; lastField = lastField->next; } if (fieldVal) { if (fieldVal->type == CHAR_TYPE) { buf = (u_char *)malloc(fieldVal->length+1); bcopy(value->val.charVal,buf,value->dataLen); free(value->val.charVal); value->val.charVal = buf; } fieldVal->value = value; } msqlTrace(TRACE_OUT,"msqlAddFieldValue()"); } /**************************************************************************** ** _msqlAddCond - add a conditional spec to the list ** ** Purpose : Store part of a "where_clause" for later use ** Args : field name, test op, value, bool (ie. AND | OR) ** Returns : Nothing ** Notes : the BOOL field is only provided if this is not the first ** element of a where_clause. */ msqlAddCond(ident,op,value,bool) ident_t *ident; int op; val_t *value; int bool; { register cond_t *new; char *name, *table; msqlTrace(TRACE_IN,"msqlAddCond()"); if (*(ident->seg2)) { name = ident->seg2; table = ident->seg1; } else { name = ident->seg1; table = NULL; } new = (cond_t *)malloc(sizeof(cond_t)); (void)strcpy(new->name,name); if (table) { (void)strcpy(new->table,table); } new->op = op; new->bool = bool; new->value = value; if (!condHead) { condHead = condTail = new; } else { condTail->next = new; condTail = new; } free(ident); msqlTrace(TRACE_OUT,"msqlAddCond()"); } /**************************************************************************** ** _msqlAddOrder - add an order definition to the list ** ** Purpose : Store part of an "order_clause" ** Args : field name, order direction (ie. ASC or DESC) ** Returns : Nothing ** Notes : */ msqlAddOrder(ident,dir) ident_t *ident; int dir; { register order_t *new; msqlTrace(TRACE_IN,"msqlAddOrder()"); new = (order_t *)malloc(sizeof(order_t)); if (*ident->seg1) { (void)strcpy(new->table,ident->seg1); } (void)strcpy(new->name,ident->seg2); new->dir = dir; if (!orderHead) { orderHead = orderTail = new; } else { orderTail->next = new; orderTail = new; } free(ident); msqlTrace(TRACE_OUT,"msqlAddOrder()"); } msqlAddTable(name,alias) char *name, *alias; { register tname_t *new; msqlTrace(TRACE_IN,"msqlAddTable()"); new = (tname_t *)malloc(sizeof(tname_t)); if (alias) { (void)strcpy(new->name,alias); (void)strcpy(new->cname,name); } else { (void)strcpy(new->name,name); *(new->cname) = 0; } if (!tableHead) { tableHead = tableTail = new; } else { tableTail->next = new; tableTail = new; } msqlTrace(TRACE_OUT,"msqlAddTable()"); } msqlSetDB(db) char *db; { curDB = db; } /**************************************************************************** ** _msqlProcessQuery - send to query to the approp routine ** ** Purpose : Call the required routine to build the native query ** Args : None ** Returns : Nothing ** Notes : Global command variable used. This is called when the ** end of an individual query is found in the miniSQL code ** and provides the hooks into the per-database routines. */ msqlProcessQuery() { int res; msqlTrace(TRACE_IN,"msqlProcessQuery()"); if (!curDB) { sprintf(packet,"-1:No current database\n"); writePkt(outSock); msqlDebug(MOD_ERR,"No current database\n"); msqlTrace(TRACE_OUT,"msqlProcessQuery()"); return; } switch(command) { case SELECT: if (!msqlCheckPerms(READ_ACCESS)) { sprintf(packet,"-1:Access Denied\n"); writePkt(outSock); msqlTrace(TRACE_OUT,"msqlProcessQuery()"); return; } res = msqlSelect(tableHead,fieldHead,condHead, orderHead,curDB); break; case CREATE: if (!msqlCheckPerms(WRITE_ACCESS)) { sprintf(packet,"-1:Access Denied\n"); writePkt(outSock); msqlTrace(TRACE_OUT,"msqlProcessQuery()"); return; } res = msqlCreate(tableHead->name,fieldHead,curDB); break; case UPDATE: if (!msqlCheckPerms(RW_ACCESS)) { sprintf(packet,"-1:Access Denied\n"); writePkt(outSock); msqlTrace(TRACE_OUT,"msqlProcessQuery()"); return; } res = msqlUpdate(tableHead->name,fieldHead,condHead, curDB); break; case INSERT: if (!msqlCheckPerms(WRITE_ACCESS)) { sprintf(packet,"-1:Access Denied\n"); writePkt(outSock); msqlTrace(TRACE_OUT,"msqlProcessQuery()"); return; } res = msqlInsert(tableHead->name,fieldHead,curDB); break; case DELETE: if (!msqlCheckPerms(WRITE_ACCESS)) { sprintf(packet,"-1:Access Denied\n"); writePkt(outSock); msqlTrace(TRACE_OUT,"msqlProcessQuery()"); return; } res = msqlDelete(tableHead->name,condHead,curDB); break; case DROP: if (!msqlCheckPerms(WRITE_ACCESS)) { sprintf(packet,"-1:Access Denied\n"); writePkt(outSock); msqlTrace(TRACE_OUT,"msqlProcessQuery()"); return; } res = msqlDrop(tableHead->name,curDB); break; } if (res < 0) { extern char errMsg[]; char errBuf[180]; sprintf(packet,"-1:%s\n",errMsg); msqlTrace(TRACE_OUT,"msqlProcessQuery()"); writePkt(outSock); } msqlTrace(TRACE_OUT,"msqlProcessQuery()"); } msqlQueryOverrunError(txt) char *txt; { msqlTrace(TRACE_IN,"msqlQueryOverrunError()"); sprintf(packet,"-1:Syntax error. Bad text after query. '%s'\n",txt); writePkt(outSock); msqlTrace(TRACE_OUT,"msqlQueryOverrunError()"); } char *msqlParseQuery(inBuf,sock) char *inBuf; int sock; { msqlTrace(TRACE_IN,"msqlParseQuery()"); outSock = sock; msqlInitScanner(inBuf); yyparse(); msqlTrace(TRACE_OUT,"msqlParseQuery()"); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.