Mailing List Archive



Back to the month index Back to the list index

cjs@iamerica.net
Sun, 19 Jan 1997 03:46:09 -0600 (CST)


From: "cjs@iamerica.net" <cjs2895@ns1.zencom.com>
Message-Id: <199701190946.DAA11448@zencom.com>
Subject: [mSQL] 2.0B3 -- New math operations in updates patch
Date: Sun, 19 Jan 1997 03:46:09 -0600 (CST)

I've written this simple patch to MSQL 2.0b3 to do -simple- atomic
math operations when updating a record. I've included the ability to
add, subtract, multiply, and divide both ints and reals. This is my
second revision of this path, and it includes a good bit of validation
and will catch dividing by zeros and such. The syntax is pretty
simple, I've barrowed the symbols from C:

        += Addition
        -= Subtraction
        *= Multiplication
        /= Division

Example:
   UPDATE table SET val1 += 1, val2 *= 10, val3 /= 5 WHERE val4 = 1

Pretty straightforward, eh?

Here is the patch..

Christopher

diff -rwu msql-2.0-B3/src/msql/errmsg.h msql-2.0-B3.new/src/msql/errmsg.h
--- msql-2.0-B3/src/msql/errmsg.h Mon Jan 13 09:15:52 1997
+++ msql-2.0-B3.new/src/msql/errmsg.h Sun Jan 19 00:45:58 1997
@@ -100,6 +100,8 @@
 # define NULL_INDEX_ERROR "Index field \"%s\" cannot be NULL"
 # define NULL_COND_ERR "Index condition for \"%s\" cannot be NULL"
 
+# define DIVIDE_BY_ZERO "Cannot divide field '%s' by zero"
+# define NO_MATH_OPS "Cannot do math ops on field '%s'"
 #endif
 
 
@@ -178,5 +180,7 @@
 # define NULL_INDEX_ERROR "Index field \"%s\" cannot be NULL"
 # define NULL_COND_ERR "Index condition for \"%s\" cannot be NULL"
 
+# define DIVIDE_BY_ZERO "Cannot divide field '%s' by zero"
+# define NO_MATH_OPS "Cannot do math ops on field '%s'"
 #endif
 
Only in msql-2.0-B3.new/src/msql: errmsg.h~
diff -rwu msql-2.0-B3/src/msql/msql_lex.c msql-2.0-B3.new/src/msql/msql_lex.c
--- msql-2.0-B3/src/msql/msql_lex.c Mon Jan 13 09:15:59 1997
+++ msql-2.0-B3.new/src/msql/msql_lex.c Sat Jan 18 18:51:03 1997
@@ -413,6 +413,11 @@
                                         state = 9;
                                         break;
                                 }
+ if (c == '*' || c == '/')
+ {
+ state = 20;
+ break;
+ }
                                 if (iscompop(c))
                                 {
                                         state = 10;
@@ -540,7 +545,7 @@
                                 yyReturn(token(REAL_NUM));
 
 
- /* State 9: Incomplete signed number */
+ /* State 9: Incomplete signed number or math op */
                         CASE(9)
                                 c = yyGet();
                                 if (isdigit(c))
@@ -553,6 +558,13 @@
                                         state = 7;
                                         break;
                                 }
+ if (c == '=')
+ {
+ if (*tokStart == '+')
+ yyReturn(token(PLUSOP));
+ if (*tokStart == '-')
+ yyReturn(token(MINUSOP));
+ }
                                 state = 999;
                                 break;
 
@@ -673,6 +685,18 @@
                                 yyReturn(token(SYS_VAR));
                                 
 
+ /* State 20: Other math ops */
+ CASE(20)
+ c = yyGet();
+ if (c == '=')
+ {
+ if (*tokStart == '*')
+ yyReturn(token(MULOP));
+ if (*tokStart == '/')
+ yyReturn(token(DIVOP));
+ }
+ state = 999;
+ break;
                         /* State 999 : Unknown token. Revert to single char */
                         CASE(999)
                                 yyRevert();
Only in msql-2.0-B3.new/src/msql: msql_lex.c~
diff -rwu msql-2.0-B3/src/msql/msql_priv.h msql-2.0-B3.new/src/msql/msql_priv.h
--- msql-2.0-B3/src/msql/msql_priv.h Mon Jan 13 09:16:00 1997
+++ msql-2.0-B3.new/src/msql/msql_priv.h Sun Jan 19 01:12:41 1997
@@ -68,6 +68,7 @@
                 ident_t *identVal;
         } val;
         int type,
+ op,
                 nullVal,
                 dataLen;
 } val_t;
@@ -91,6 +92,7 @@
                 funct[NAME_LEN + 1];
         val_t *value;
         int type,
+ op,
                 sysvar,
                 length,
                 dataLength,
@@ -337,6 +339,13 @@
 #define NOT_RLIKE_OP 11
 #define NOT_CLIKE_OP 12
 
+#define PLUS_OP 13
+#define MINUS_OP 14
+#define MUL_OP 15
+#define DIV_OP 16
+#define MATH_NOP 17
+
+
 #define NO_BOOL 0
 #define AND_BOOL 1
 #define OR_BOOL 2
@@ -525,7 +534,7 @@
 int checkSysVarCond __ANSI_PROTO((cond_t *));
 
 /* msql_proc.c prototypes */
-int msqlAddField __ANSI_PROTO((ident_t*,int,char *,int,int));
+int msqlAddField __ANSI_PROTO((ident_t*,int,char *,int,int,int));
 void msqlProcessQuery ();
 void msqlPushCond ();
 void msqlAddSubCond __ANSI_PROTO((int));
@@ -534,7 +543,7 @@
 void msqlSetDB __ANSI_PROTO((char *));
 void msqlSetSelectLimit __ANSI_PROTO((val_t *));
 void msqlAddFieldValue __ANSI_PROTO((val_t *));
-void msqlAddCond __ANSI_PROTO((ident_t*,int,val_t*,int));
+int msqlAddCond __ANSI_PROTO((ident_t*,int,val_t*,int));
 void msqlAddOrder __ANSI_PROTO((ident_t*,int));
 void msqlAddTable __ANSI_PROTO((char*,char*));
 void msqlAddIndex __ANSI_PROTO((char*, char*, int, int));
Only in msql-2.0-B3.new/src/msql: msql_priv.h~
diff -rwu msql-2.0-B3/src/msql/msql_proc.c msql-2.0-B3.new/src/msql/msql_proc.c
--- msql-2.0-B3/src/msql/msql_proc.c Mon Jan 13 09:16:00 1997
+++ msql-2.0-B3.new/src/msql/msql_proc.c Sun Jan 19 01:18:17 1997
@@ -475,12 +475,13 @@
 ** if the field is of type CHAR
 */
 
-int msqlAddField(ident,type,length,notNull,priKey)
+int msqlAddField(ident,type,length,notNull,priKey,op)
         ident_t *ident;
         int type;
         char *length;
         int notNull,
- priKey;
+ priKey,
+ op;
 {
         register field_t *new;
         char *name,
@@ -532,6 +533,7 @@
                 new->offset = new->null = new->flags =
                 new->fieldID = new->overflow = 0;
 
+ new->op = op;
 
         if (table)
         {
@@ -687,7 +689,7 @@
 ** element of a where_clause.
 */
 
-void msqlAddCond(ident,op,value,bool)
+int msqlAddCond(ident,op,value,bool)
         ident_t *ident;
         int op;
         val_t *value;
@@ -699,6 +701,11 @@
 
         msqlTrace(TRACE_IN,"msqlAddCond()");
 
+ if ((op < EQ_OP) || (op > NOT_CLIKE_OP)) {
+ free(ident);
+ msqlTrace(TRACE_OUT,"msqlAddCond()");
+ return(-1);
+ }
         if (*(ident->seg2))
         {
                 name = ident->seg2;
@@ -733,6 +740,7 @@
         }
         free(ident);
         msqlTrace(TRACE_OUT,"msqlAddCond()");
+ return(0);
 }
 
 
Only in msql-2.0-B3.new/src/msql: msql_proc.c~
diff -rwu msql-2.0-B3/src/msql/msql_yacc.y msql-2.0-B3.new/src/msql/msql_yacc.y
--- msql-2.0-B3/src/msql/msql_yacc.y Mon Jan 13 09:16:01 1997
+++ msql-2.0-B3.new/src/msql/msql_yacc.y Sun Jan 19 01:17:05 1997
@@ -120,6 +120,11 @@
 
 %token AVL_INDEX
 
+%token PLUSOP
+%token MINUSOP
+%token MULOP
+%token DIVOP
+
 %%
 
 /*
@@ -187,7 +192,7 @@
 index_list
         : IDENT
                 {
- if(msqlAddField(msqlCreateIdent(NULL,$1),(int)NULL,0,0,0)<0)
+ if(msqlAddField(msqlCreateIdent(NULL,$1),(int)NULL,0,0,0,MATH_NOP)<0)
                         {
                                 msqlClean();
                                 return(-1);
@@ -196,7 +201,7 @@
                 }
         | index_list ',' IDENT
                 {
- if(msqlAddField(msqlCreateIdent(NULL,$3),(int)NULL,0,0,0)<0)
+ if(msqlAddField(msqlCreateIdent(NULL,$3),(int)NULL,0,0,0,MATH_NOP)<0)
                         {
                                 msqlClean();
                                 return(-1);
@@ -258,7 +263,7 @@
         : qual_ident type opt_nullspec opt_keyspec
                 {
                         if(msqlAddField((ident_t *)$1,(int)$2,arrayLen,
- notnullflag,keyflag)<0)
+ notnullflag,keyflag,MATH_NOP)<0)
                         {
                                 msqlClean();
                                 return(-1);
@@ -352,18 +357,18 @@
                         ident_t *tmp;
 
                         tmp = msqlCreateIdent(NULL,"*");
- msqlAddField((ident_t *)tmp,0,0,0,0);
+ msqlAddField((ident_t *)tmp,0,0,0,0,MATH_NOP);
                         selectWildcard = 1;
                 }
 
 select_item
         : qual_ident
                 {
- msqlAddField((ident_t *)$1,0,0,0,0);
+ msqlAddField((ident_t *)$1,0,0,0,0,MATH_NOP);
                 }
         | qual_sysvar
                 {
- msqlAddField((ident_t *)$1,0,0,0,0);
+ msqlAddField((ident_t *)$1,0,0,0,0,MATH_NOP);
                 }
 
 /*
@@ -426,11 +431,21 @@
 
 cond_list
         : cond_list cond_cont cond_field cond_op cond_literal
- { msqlAddCond((ident_t *)$3,(int)$4,(val_t *)$5,(int)$2); }
+ { if (msqlAddCond((ident_t *)$3,(int)$4,(val_t *)$5,(int)$2)<0)
+ {
+ msqlClean();
+ return(-1);
+ }
+ }
         | cond_list cond_cont sub_cond
                 { msqlAddSubCond((int)$2); }
         | cond_field cond_op cond_literal
- { msqlAddCond((ident_t *)$1,(int)$2,(val_t *)$3,NO_BOOL); }
+ { if (msqlAddCond((ident_t *)$1,(int)$2,(val_t *)$3,NO_BOOL)<0)
+ {
+ msqlClean();
+ return(-1);
+ }
+ }
         | sub_cond
                 { msqlAddSubCond(NO_BOOL); }
 
@@ -558,7 +573,7 @@
                         ident_t *tmp;
 
                         tmp = msqlCreateIdent(NULL,"*");
- msqlAddField((ident_t *)tmp,0,0,0,0);
+ msqlAddField((ident_t *)tmp,0,0,0,0,MATH_NOP);
                         $$ = (char *) 1;
                 }
         | '(' fields ')'
@@ -570,11 +585,11 @@
 fields
         : fields ',' qual_ident
                 {
- msqlAddField((ident_t *)$3,0,0,0,0);
+ msqlAddField((ident_t *)$3,0,0,0,0,MATH_NOP);
                 }
         | qual_ident
                 {
- msqlAddField((ident_t *)$1,0,0,0,0);
+ msqlAddField((ident_t *)$1,0,0,0,0,MATH_NOP);
                 }
 
 
@@ -605,10 +620,16 @@
 
 update_list
         : update_list ',' qual_ident EQ literal
- { msqlAddField((ident_t *)$3,0,0,0,0);
+ { msqlAddField((ident_t *)$3,0,0,0,0,MATH_NOP);
                   msqlAddFieldValue((val_t *)$5); }
         | qual_ident EQ update_value
- { msqlAddField((ident_t *)$1,0,0,0,0);
+ { msqlAddField((ident_t *)$1,0,0,0,0,MATH_NOP);
+ msqlAddFieldValue((val_t *) $3); }
+ | update_list ',' qual_ident mathop literal
+ { msqlAddField((ident_t *)$3,0,0,0,0,(int)$4);
+ msqlAddFieldValue((val_t *)$5); }
+ | qual_ident mathop update_value
+ { msqlAddField((ident_t *)$1,0,0,0,0,(int)$2);
                   msqlAddFieldValue((val_t *) $3); }
 
 
@@ -617,6 +638,17 @@
                 { $$ = $1; }
         | qual_sysvar
                 { $$ = $1; }
+
+mathop
+ : PLUSOP
+ { $$ = (char *)PLUS_OP; }
+ | MINUSOP
+ { $$ = (char *)MINUS_OP; }
+ | MULOP
+ { $$ = (char *)MUL_OP; }
+ | DIVOP
+ { $$ = (char *)DIV_OP; }
+
 
 /*
 ** Delete : conditionally delete table entries (or all entries)
Only in msql-2.0-B3.new/src/msql: msql_yacc.y~
diff -rwu msql-2.0-B3/src/msql/table.c msql-2.0-B3.new/src/msql/table.c
--- msql-2.0-B3/src/msql/table.c Mon Jan 13 09:16:15 1997
+++ msql-2.0-B3.new/src/msql/table.c Sun Jan 19 00:53:06 1997
@@ -1321,6 +1321,8 @@
         u_char *data,
                 *cp;
         u_int pos;
+ int tmpInt;
+ double tmpReal;
 
         msqlTrace(TRACE_IN,"updateValues()");
         data = row->data;
@@ -1336,16 +1338,47 @@
                         switch(curField->type)
                         {
                                 case INT_TYPE:
+ switch(curField->op) {
+ case MATH_NOP:
+ tmpInt = curField->value->val.intVal;
+ break;
+ case PLUS_OP:
+ tmpInt = unpackInt32(cp);
+ tmpInt += curField->value->val.intVal;
+ break;
+ case MINUS_OP:
+ tmpInt = unpackInt32(cp);
+ tmpInt -= curField->value->val.intVal;
+ break;
+ case MUL_OP:
+ tmpInt = unpackInt32(cp);
+ tmpInt *= curField->value->val.intVal;
+ break;
+ case DIV_OP:
+ if (curField->value->val.intVal == 0)
+ {
+ sprintf(errMsg,DIVIDE_BY_ZERO,
+ curField->name);
+ return(-1);
+ }
+ tmpInt = unpackInt32(cp);
+ tmpInt /= curField->value->val.intVal;
+ break;
+ }
 #ifndef _CRAY
- bcopy4(&(curField->value->val.intVal),
- cp);
+ bcopy4(&tmpInt, cp);
 #else
- packInt32(curField->value->val.intVal,
- cp);
+ packInt32(tmpInt, cp);
 #endif
                                         break;
                 
                                 case CHAR_TYPE:
+ if (curField->op != MATH_NOP)
+ {
+ sprintf(errMsg,NO_MATH_OPS,
+ curField->name);
+ return(-1);
+ }
                                         length = strlen((char *)
                                                 curField->value->val.charVal);
                                         if (length > curField->length)
@@ -1361,6 +1394,12 @@
                                         break;
 
                                 case TEXT_TYPE:
+ if (curField->op != MATH_NOP)
+ {
+ sprintf(errMsg,NO_MATH_OPS,
+ curField->name);
+ return(-1);
+ }
                                         bcopy(cp + sizeof(int), &pos,
                                                 sizeof(u_int));
                                         deleteVarChar(entry, pos);
@@ -1382,8 +1421,34 @@
                                         break;
 
                                 case REAL_TYPE:
- bcopy8(&(curField->value->val.realVal),
- cp);
+ switch(curField->op) {
+ case MATH_NOP:
+ tmpReal = curField->value->val.realVal;
+ break;
+ case PLUS_OP:
+ bcopy8(cp, (char *)&tmpReal);
+ tmpReal += curField->value->val.realVal;
+ break;
+ case MINUS_OP:
+ bcopy8(cp, (char *)&tmpReal);
+ tmpReal -= curField->value->val.realVal;
+ break;
+ case MUL_OP:
+ bcopy8(cp, (char *)&tmpReal);
+ tmpReal *= curField->value->val.realVal;
+ break;
+ case DIV_OP:
+ if (curField->value->val.realVal == 0)
+ {
+ sprintf(errMsg,DIVIDE_BY_ZERO,
+ curField->name);
+ return(-1);
+ }
+ bcopy8(cp, (char *)&tmpReal);
+ tmpReal /= curField->value->val.realVal;
+ break;
+ }
+ bcopy8(&tmpReal, cp);
                                         break;
                         }
                 }
--------------------------------------------------------------------------
To remove yourself from the Mini SQL mailing list send a message containing
"unsubscribe" to "unsubscribe" to msql-list-request@bunyip.com. Send a message containing
"info msql-list" to majordomo@bunyip.com for info on monthly archives of
the list. For more help, mail owner-msql-list@bunyip.com NOT the msql-list!