]> err.no Git - sope/commitdiff
more work on MySQL fetching
authorhelge <helge@e4a50df8-12e2-0310-a44c-efbce7f8a7e3>
Tue, 12 Apr 2005 21:54:49 +0000 (21:54 +0000)
committerhelge <helge@e4a50df8-12e2-0310-a44c-efbce7f8a7e3>
Tue, 12 Apr 2005 21:54:49 +0000 (21:54 +0000)
git-svn-id: http://svn.opengroupware.org/SOPE/trunk@736 e4a50df8-12e2-0310-a44c-efbce7f8a7e3

sope-gdl1/MySQL4/ChangeLog
sope-gdl1/MySQL4/MySQL4Channel.m
sope-gdl1/MySQL4/MySQL4Values.h
sope-gdl1/MySQL4/MySQL4Values.m
sope-gdl1/MySQL4/NSCalendarDate+MySQL4Val.m
sope-gdl1/MySQL4/NSNumber+MySQL4Val.m
sope-gdl1/MySQL4/NSString+MySQL4Val.m
sope-gdl1/MySQL4/Version
sope-gdl1/SQLite3/SQLiteChannel.m

index 399b05c285141beca9e08bce6ebacc455dec2b9f..81ae9e471e603868cf17f07b75e59489ce7bf236 100644 (file)
@@ -1,3 +1,7 @@
+2005-04-13  Helge Hess  <helge.hess@opengroupware.org>
+
+       * MySQL4Channel.m: finished fetching code (v4.5.4)
+
 2005-04-12  Helge Hess  <helge.hess@opengroupware.org>
 
        * MySQL4Channel.m: added some fetch result processing (v4.5.3)
index 7ae346265904c0c4af259ef2973d2448fdd89586..5531aa384086c5303067d8e0c49be398a7f9c90b 100644 (file)
@@ -417,38 +417,6 @@ static int openConnectionCount = 0;
        break;
     }
     
-#if 1
-#  warning IMPLEMENT ME
-#else
-    switch (sqlite3_column_type(self->statement, cnt)) {
-      case SQLITE_INTEGER:
-       [attribute setExternalType:@"INTEGER"];
-       [attribute setValueClassName:@"NSNumber"];
-       [attribute setValueType:@"d"];
-       break;
-      case SQLITE_FLOAT:
-       [attribute setExternalType:@"REAL"];
-       [attribute setValueClassName:@"NSNumber"];
-       [attribute setValueType:@"f"];
-       break;
-      case SQLITE_TEXT:
-       [attribute setExternalType:@"TEXT"];
-       [attribute setValueClassName:@"NSString"];
-       break;
-      case SQLITE_BLOB:
-       [attribute setExternalType:@"BLOB"];
-       [attribute setValueClassName:@"NSData"];
-       break;
-      case SQLITE_NULL:
-       NSLog(@"WARNING(%s): got MySQL4 NULL type at column %i, can't derive "
-             @"type information.",
-             __PRETTY_FUNCTION__, cnt);
-       [attribute setExternalType:@"NULL"];
-       [attribute setValueClassName:@"NSNull"];
-       break;
-      default:
-    }
-#endif    
     [result addObject:attribute];
     [attribute release];
   }
@@ -459,20 +427,6 @@ static int openConnectionCount = 0;
   return [result autorelease];
 }
 
-- (BOOL)isColumnNullInCurrentRow:(int)_column {
-  /* 
-     Note: NULL is MySQL4 is represented as empty strings ..., don't know
-           what to do about that?
-          At least Sybase 10 doesn't support empty strings strings as well
-          and converts them to a single space. So maybe it is reasonable to
-          map empty strings to NSNull?
-          
-          Or is this column-type SQLITE_NULL? If so, thats rather weird,
-          since the type query does not take a row.
-  */
-  return NO;
-}
-
 - (NSMutableDictionary *)primaryFetchAttributes:(NSArray *)_attributes
   withZone:(NSZone *)_zone
 {
@@ -485,9 +439,9 @@ static int openConnectionCount = 0;
   // TODO: add a primaryFetchAttributesX method?
   MYSQL_ROW rawRow;
   NSMutableDictionary *row = nil;
-  NSException *error;
   unsigned attrCount = [_attributes count];
   unsigned cnt;
+  unsigned long *lengths;
   
   if (self->results == NULL) {
     NSLog(@"ERROR(%s): no fetch in progress?", __PRETTY_FUNCTION__);
@@ -511,20 +465,38 @@ static int openConnectionCount = 0;
     [self cancelFetch];
     return nil;
   }
+
+  /* ensure field info */
+  
+  if ([self _fetchFields] == NULL) {
+    [self cancelFetch];
+    [MySQL4Exception raise:@"FetchFailed" 
+                    format:@"could not fetch field info!"];
+    return nil;
+  }
+  
+  if ((lengths = mysql_fetch_lengths(self->results)) == NULL) {
+    [self cancelFetch];
+    [MySQL4Exception raise:@"FetchFailed" 
+                    format:@"could not fetch field lengths!"];
+    return nil;
+  }
   
   /* build row */
   
   row = [NSMutableDictionary dictionaryWithCapacity:attrCount];
-
+  
   for (cnt = 0; cnt < attrCount; cnt++) {
     EOAttribute *attribute;
     NSString    *attrName;
     id          value      = nil;
+    MYSQL_FIELD mfield;
     
     attribute = [_attributes objectAtIndex:cnt];
     attrName  = [attribute name];
-
-    if ([self isColumnNullInCurrentRow:cnt]) {
+    mfield    = ((MYSQL_FIELD *)self->fields)[cnt];
+    
+    if (rawRow[cnt] == NULL) {
       value = [null retain];
     }
     else {
@@ -539,40 +511,9 @@ static int openConnectionCount = 0;
         value = null;
        continue;
       }
-      
-#if 1
-#  warning IMPLEMENT ME
-#else
-      switch (sqlite3_column_type(self->statement, cnt)) {
-      case SQLITE_INTEGER:
-       value = [[valueClass alloc] 
-                 initWithMySQL4Int:sqlite3_column_int(self->statement, cnt)];
-       break;
-      case SQLITE_FLOAT:
-       value = [[valueClass alloc] 
-                 initWithMySQL4Double:
-                   sqlite3_column_double(self->statement, cnt)];
-       break;
-      case SQLITE_TEXT:
-       value = [[valueClass alloc] 
-                 initWithMySQL4Text:
-                   sqlite3_column_text(self->statement, cnt)];
-       break;
-      case SQLITE_BLOB:
-       value = [[valueClass alloc] 
-                 initWithMySQL4Data:
-                   sqlite3_column_blob(self->statement, cnt)
-                 length:sqlite3_column_bytes(self->statement, cnt)];
-       break;
-      case SQLITE_NULL:
-       value = [null retain];
-       break;
-      default:
-       NSLog(@"ERROR(%s): unexpected MySQL4 type at column %i", 
-             __PRETTY_FUNCTION__, cnt);
-       continue;
-      }
-#endif    
+
+      value = [[valueClass alloc] initWithMySQL4Type:mfield.type
+                                 value:rawRow[cnt] length:lengths[cnt]];
       
       if (value == nil) {
         NSLog(@"ERROR(%s): %@: got no value for column:\n"
@@ -596,10 +537,8 @@ static int openConnectionCount = 0;
 
 - (NSException *)evaluateExpressionX:(NSString *)_expression {
   NSMutableString *sql;
-  NSException *error;
   BOOL       result;
   const char *s;
-  const char *tails = NULL;
   int  rc;
 
   *(&result) = YES;
@@ -735,6 +674,8 @@ static int openConnectionCount = 0;
   seqName = [adaptor primaryKeySequenceName];
   pkey    = nil;
   seq     = nil;
+
+  NSLog(@"TODO(%s): implement primary keys for MySQL", __PRETTY_FUNCTION__);
   
   seq = ([seqName length] > 0)
     ? [NSString stringWithFormat:@"SELECT NEXTVAL ('%@')", seqName]
index ba884e7bde2cf6e6f9e623514ed540d683f5270d..44a0b467290a06c7015e76cab5c79d6aa5aedd87 100644 (file)
 
 @interface NSObject(MySQL4Values)
 
-- (id)initWithMySQL4Int:(int)_value;
-- (id)initWithMySQL4Text:(const unsigned char *)_value;
-- (id)initWithMySQL4Double:(double)_value;
-- (id)initWithMySQL4Data:(const void *)_data length:(int)_length;
+- (id)initWithMySQL4Type:(int)_type value:(const void *)_v length:(int)_len;
 
 @end
 
index 15a60008c52a63a00dbde9c17e92222149d31299..5bf7dbb623972ae26140fe5d747936805835a3d8 100644 (file)
@@ -23,8 +23,8 @@
    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
 
-#import "MySQL4Values.h"
-#import "common.h"
+#include "MySQL4Values.h"
+#include "common.h"
 
 @implementation MySQL4DataTypeMappingException
 
 
 @implementation NSObject(MySQL4Values)
 
+- (id)initWithMySQL4Type:(int)_type value:(const void *)_v length:(int)_len {
+  [self release];
+
+  NSLog(@"WARNING(%s): falling back to NSString for MySQL4 value!",
+       __PRETTY_FUNCTION__);
+  
+  return [[NSString alloc] initWithMySQL4Type:_type value:_v length:_len];
+}
+
+#if 0
 - (id)initWithMySQL4Int:(int)_value {
   if ([self respondsToSelector:@selector(initWithInt:)])
     return [(NSNumber *)self initWithInt:_value];
   [self release];
   return nil;
 }
+#endif
 
 @end /* NSObject(MySQL4Values) */
 
index 3f078aed86f2dc5f17dc07e49efbd2d266d55059..674c62f07ce70947230f1131b105093f0081926c 100644 (file)
@@ -24,7 +24,7 @@
 */
 
 
-#import <Foundation/NSString.h>
+#import <Foundation/NSCalendarDate.h>
 #include "MySQL4Channel.h"
 #include "common.h"
 
@@ -34,7 +34,7 @@
 @end
 #endif
 
-static NSString *SQLITE3_DATETIME_FORMAT = @"%b %d %Y %I:%M:%S:000%p";
+static NSString *MYSQL4_DATETIME_FORMAT = @"%b %d %Y %I:%M:%S:000%p";
 
 @implementation NSCalendarDate(MySQL4Values)
 
@@ -46,12 +46,41 @@ static NSString *SQLITE3_DATETIME_FORMAT = @"%b %d %Y %I:%M:%S:000%p";
   Matthew: "07/25/2003 06:00:00 CDT".
 */
 
-static Class      NSCalDateClass     = Nil;
 static NSTimeZone *DefServerTimezone = nil;
+#if 0
 static NSTimeZone *gmt   = nil;
 static NSTimeZone *gmt01 = nil;
 static NSTimeZone *gmt02 = nil;
+#endif
 
+- (id)initWithMySQL4Type:(int)_type value:(const void *)_v length:(int)_len {
+  NSString *s;
+  NSString *calfmt;
+  
+  s      = [[NSString alloc] initWithCString:_v length:_len]; // Unicode
+  calfmt = nil;
+
+  // TODO: avoid using format strings
+  
+  switch (_len) { // as suggested by SQLClient
+  case 14: calfmt = @"%Y%m%d%H%M%S"; break;
+  case 12: calfmt = @"%y%m%d%H%M%S"; break;
+  case 10: calfmt = @"%y%m%d%H%M";   break;
+  case  8: calfmt = @"%y%m%d%H";     break;
+  case  6: calfmt = @"%y%m%d";       break;
+  case  4: calfmt = @"%y%m";         break;
+  default:
+    calfmt = _len > 14 ? @"%Y-%m-%d %H:%M:%S" : @"%y";
+    break;
+  }
+
+  self = [self initWithString:s calendarFormat:calfmt];
+  [s release];
+  [self setCalendarFormat:MYSQL4_DATETIME_FORMAT];
+  return self;
+}
+
+#if 0
 - (id)initWithMySQL4Data:(const void *)_value length:(int)_length {
   static unsigned char buf[28]; // reused buffer, THREAD
   const char *_cstr = _value;
@@ -147,17 +176,7 @@ static NSTimeZone *gmt02 = nil;
   }
   return date;
 }
-
-- (id)initWithMySQL4Double:(double)_value {
-  return [self initWithTimeIntervalSince1970:_value];
-}
-- (id)initWithMySQL4Int:(int)_value {
-  return [self initWithMySQL4Double:_value];
-}
-
-- (id)initWithMySQL4Text:(const unsigned char *)_value {
-  return [self initWithMySQL4Data:_value length:strlen(_value)];
-}
+#endif
 
 /* generating value */
 
@@ -205,7 +224,7 @@ static NSTimeZone *gmt02 = nil;
   format = @"%Y-%m-%d %H:%M:%S%z";
 #endif
   if (format == nil)
-    format = SQLITE3_DATETIME_FORMAT;
+    format = MYSQL4_DATETIME_FORMAT;
   
   [self setTimeZone:serverTimeZone];
   
index 9fdcdc8788a4c35aab068914b796f1a6c9689245..718370177e8bc4af18d82a00a0ce403877b7f990 100644 (file)
    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
 
-#import <Foundation/NSString.h>
+#import <Foundation/NSValue.h>
 #include "MySQL4Channel.h"
 #include "common.h"
+#include <mysql/mysql.h>
 
 @implementation NSNumber(MySQL4Values)
-  
+
+- (id)initWithMySQL4Type:(int)_type value:(const void *)_v length:(int)_len {
+  if (_v == NULL) {
+    [self release];
+    return nil;
+  }
+
+  switch (_type) {
+  case FIELD_TYPE_TINY:
+    // ??: SQLClient => v = [NSString stringWithFormat: @"%u", *p];
+    ; /* fall through */
+  default:
+    NSLog(@"ERROR: unsupported MySQL type: %i", _type);
+    [self release];
+    return nil;
+  }
+}
+
+#if 0  
 - (id)initWithMySQL4Int:(int)_value {
   return [self initWithInt:_value];
 }
@@ -52,6 +71,9 @@
   [self release];
   return nil;
 }
+#endif
+
+/* generation */
 
 - (NSString *)stringValueForMySQL4Type:(NSString *)_type
   attribute:(EOAttribute *)_attribute
index 479713f7a418ea9f8f2a42cd98f07f0282b20547..47a56e074eb3624abf8211f432781aa7cfce3a04 100644 (file)
 #include <NGExtensions/NSString+Ext.h>
 #import <Foundation/NSString.h>
 #include "common.h"
+#include <mysql/mysql.h>
 
 @implementation NSString(MySQL4Values)
 
 static Class EOExprClass = Nil;
 
+- (id)initWithMySQL4Type:(int)_type value:(const void *)_v length:(int)_len {
+  if (_v == NULL) {
+    [self release];
+    return nil;
+  }
+
+  switch (_type) {
+  case FIELD_TYPE_BLOB:
+  case FIELD_TYPE_TINY_BLOB:
+  case FIELD_TYPE_MEDIUM_BLOB:
+  case FIELD_TYPE_LONG_BLOB:
+    ; /* fall through */
+    
+  default:
+    /* we always fallback to the UTF-8 string ... */
+    return [self initWithUTF8String:_v];
+  }
+}
+
+#if 0
 - (id)initWithMySQL4Int:(int)_value {
   char buf[256];
   sprintf(buf, "%i", _value);
@@ -55,6 +76,7 @@ static Class EOExprClass = Nil;
   [d release];
   return self;
 }
+#endif
 
 /* generate SQL value */
 
@@ -93,7 +115,7 @@ static Class EOExprClass = Nil;
     if (EOExprClass == Nil) EOExprClass = [EOQuotedExpression class];
     expr = [[EOExprClass alloc] initWithExpression:expr 
                                quote:@"'" escape:@"\\'"];
-    s = [[expr expressionValueForContext:nil] retain];
+    s = [[(EOQuotedExpression *)expr expressionValueForContext:nil] retain];
     [expr release];
     return [s autorelease];
   }
index f7ead5f24d21968b0b1702cfd9aaaefc23443c32..23e43c1d7a12e51e3fe62b78a59e8d7238168e72 100644 (file)
@@ -1,3 +1,3 @@
 # Version file
 
-SUBMINOR_VERSION:=3
+SUBMINOR_VERSION:=4
index 179dc373ddbabe2627c58114e3fab4e87ce24dda..b77a05cdfe61bd24a099bb6b582346667f4c2646 100644 (file)
@@ -361,7 +361,7 @@ static int openConnectionCount = 0;
 
 - (BOOL)isColumnNullInCurrentRow:(int)_column {
   /* 
-     Note: NULL is SQLite is represented as empty strings ..., don't know
+     Note: NULL in SQLite is represented as empty strings ..., don't know
            what to do about that?
           At least Sybase 10 doesn't support empty strings strings as well
           and converts them to a single space. So maybe it is reasonable to