|
|
1.1 ! root 1: /* Evaluator.m: ! 2: * You may freely copy, distribute, and reuse the code in this example. ! 3: * NeXT disclaims any warranty of any kind, expressed or implied, as to its ! 4: * fitness for any particular use. ! 5: * ! 6: * ! 7: * ! 8: */ ! 9: ! 10: #import <foundation/NSString.h> ! 11: #import <foundation/NSUtilities.h> ! 12: ! 13: #import "ScrollViewExtras.h" ! 14: #import "Evaluator.h" ! 15: #import "EOFDelegateAdaptorCategory.h" ! 16: ! 17: ! 18: #define FAILURE NXLocalizedString("Failure:", NULL, \ ! 19: "Message given to user when an operation has failed.") ! 20: ! 21: #define CANNOT_CONNECT NXLocalizedString("Cannot connect to database", NULL, \ ! 22: "Message given to user to explain what fails. ") ! 23: ! 24: #define OK NXLocalizedString("OK", NULL, "Okay to continue ") ! 25: ! 26: @implementation Evaluator ! 27: ! 28: - initWithModelFile:(NSString *)filePath ! 29: { ! 30: char path[MAXPATHLEN]; ! 31: BOOL result=NO; ! 32: ! 33: [super init]; ! 34: ! 35: // open the model file and connect to the database ! 36: model = [[[EOModel alloc] ! 37: initWithContentsOfFile: filePath] autorelease]; ! 38: ! 39: if (!model) ! 40: return nil; ! 41: ! 42: ! 43: adaptor = [EOAdaptor adaptorWithModel:model]; ! 44: if (!adaptor) ! 45: return nil; ! 46: ! 47: context = [adaptor createAdaptorContext]; ! 48: if (!context) ! 49: return nil; ! 50: ! 51: ! 52: channel = [context createAdaptorChannel]; ! 53: ! 54: if (!channel) ! 55: return nil; ! 56: ! 57: if (![channel isOpen]) ! 58: result = [channel openChannel]; ! 59: if (result) ! 60: [resultsView sprintf:"Connection successful\n"]; ! 61: else ! 62: [resultsView sprintf:"Connection failed\n"]; ! 63: ! 64: [[NXBundle mainBundle] getPath:path forResource:"SQLWindow" ofType:"nib"]; ! 65: [NXApp loadNibFile:path owner:self withNames:NO]; ! 66: [(Window *)[resultsView window] setDelegate:self]; ! 67: [[resultsView window] setTitleAsFilename:[filePath cString]]; ! 68: [[queryView docView] selectAll:self]; ! 69: [[resultsView window] makeKeyAndOrderFront:self]; ! 70: ! 71: /*---------------------------------------------------------------------- ! 72: * set up the channel delegate to SybaseDelegate for Sybase model files ! 73: * use EOFDelegateCategory for Oracle model files ! 74: *--------------------------------------------------------------------*/ ! 75: ! 76: if ([[adaptor name] isEqualToString:@"Sybase"]) { ! 77: sybaseDelegate = [[SybaseDelegate alloc] init]; ! 78: [channel setDelegate:sybaseDelegate]; ! 79: } ! 80: else { ! 81: sybaseDelegate = nil; ! 82: [channel setDelegate:[[EOFDelegateAdaptorCategory alloc] init]]; ! 83: } ! 84: ! 85: return self; ! 86: } ! 87: ! 88: - free ! 89: { ! 90: [model release]; ! 91: [adaptor release]; ! 92: [context release]; ! 93: [channel release]; ! 94: if (sybaseDelegate) ! 95: [sybaseDelegate release]; ! 96: ! 97: return [super free]; ! 98: } ! 99: ! 100: - evaluate:sender ! 101: { ! 102: BOOL result = NO; ! 103: int charCount; ! 104: char *buffer = NULL; ! 105: NSDictionary *row; ! 106: ! 107: /*---------------------------------------------------------------------- ! 108: * get the SQL statement ! 109: *--------------------------------------------------------------------*/ ! 110: ! 111: if ((charCount = [[queryView docView] textLength]) > 0) { ! 112: buffer = malloc((charCount+1) * sizeof(char)); ! 113: [[queryView docView] getSubstring:buffer start:0 length:charCount]; ! 114: buffer[charCount] = 0; ! 115: while (charCount > 0 && buffer[--charCount] == '\n') ! 116: buffer[charCount] = 0; ! 117: [resultsView sprintf:"%s\n", buffer]; ! 118: ! 119: } ! 120: else { ! 121: [resultsView sprintf:"Can't execute an empty string!\n"]; ! 122: return self; ! 123: } ! 124: ! 125: /*---------------------------------------------------------------------- ! 126: * evaluate the SQL statement ! 127: *--------------------------------------------------------------------*/ ! 128: ! 129: [context beginTransaction]; ! 130: result = [channel evaluateExpression: ! 131: [[NSString alloc] initWithCString:(const char *)buffer]]; ! 132: ! 133: if (result){ ! 134: [resultsView sprintf:"SQL successfully evaluated\n"]; ! 135: ! 136: while ([channel isFetchInProgress] == YES) { ! 137: // get the array of attributes from the result set ! 138: attributes = [channel describeResults]; ! 139: ! 140: // since the EO Framework attributes are stored as Attribute1, ! 141: // Attribute2, etc., build a dictionary to do conversion. ! 142: ! 143: [self buildColumnNamesDictionary:attributes]; ! 144: ! 145: // The NSDictionary contains all the data for one row ! 146: while ((row = [channel fetchAttributes: attributes withZone: ! 147: [adaptor zone]]) != nil) ! 148: // read data back ! 149: [self readDataFromDict:row ]; ! 150: ! 151: } ! 152: [context commitTransaction]; ! 153: ! 154: } ! 155: else { ! 156: // do clean-up if SQL statement cannot be evaluated. ! 157: [resultsView sprintf:"SQL evaluation failed\n"]; ! 158: if ([channel isFetchInProgress] == YES) ! 159: [channel cancelFetch]; ! 160: [context rollbackTransaction]; ! 161: } ! 162: free(buffer); ! 163: return self; ! 164: } ! 165: ! 166: ! 167: ! 168: /* Build a dictionary where the Keys are Attribute1, Attribute2, etc., ! 169: * while the values are the actual column names as specified in the ! 170: * database. ! 171: */ ! 172: - buildColumnNamesDictionary:(NSArray *) attributesArray ! 173: { ! 174: NSEnumerator *enumerator; ! 175: EOAttribute *attribute; ! 176: NSMutableArray *keys = [NSMutableArray array]; ! 177: NSMutableArray *values = [NSMutableArray array]; ! 178: ! 179: enumerator = [attributesArray objectEnumerator]; ! 180: ! 181: while ((attribute = [enumerator nextObject]) != nil) { ! 182: [keys addObject:[attribute name]]; ! 183: [values addObject:[attribute columnName]]; ! 184: } ! 185: columnNamesDict = [NSDictionary dictionaryWithObjects:values ! 186: forKeys: keys]; ! 187: return self; ! 188: } ! 189: ! 190: /* Cycle through the key and value pairs of the dictionary ! 191: * and print them to result view ! 192: * ! 193: */ ! 194: - readDataFromDict:(NSDictionary *) dictionary ! 195: { ! 196: NSEnumerator *keyEnumerator; ! 197: NSString * key; ! 198: NSString * newKey; ! 199: id value; ! 200: char buffer[1024]; ! 201: SybaseRowType rowType=0; ! 202: ! 203: keyEnumerator = [dictionary keyEnumerator]; ! 204: if (sybaseDelegate) ! 205: rowType = [sybaseDelegate currentRowType]; ! 206: ! 207: //print the full dictionary for Sybase regular rows or if the Oracle adaptor is used ! 208: if ( ((sybaseDelegate) && (rowType == SybaseRegularRow )) ! 209: || (sybaseDelegate == nil) ) ! 210: { ! 211: while ((key = [keyEnumerator nextObject]) != nil) { ! 212: newKey = [columnNamesDict objectForKey:[key description]]; ! 213: ! 214: value = [dictionary objectForKey:key]; ! 215: sprintf(buffer, "%s: \t %s\n", [[newKey description] cString], ! 216: [[(NSObject *)value description] cString]); ! 217: [resultsView sprintf:buffer]; ! 218: } ! 219: } ! 220: else { ! 221: // This must be one special sybase row ! 222: switch (rowType) { ! 223: case SybaseComputeRow: ! 224: case SybaseReturnStatusRow: ! 225: // print one row of data only ! 226: key = [keyEnumerator nextObject]; ! 227: value = [dictionary objectForKey:key]; ! 228: sprintf(buffer, "Row type: %s \t %s\n", (rowType == SybaseComputeRow) ? ! 229: "SybaseComputeRow": "SybaseReturnStatusRow", ! 230: [[(NSObject *)value description] cString]); ! 231: [resultsView sprintf:buffer]; ! 232: sprintf(buffer, "************************************\n"); ! 233: [resultsView sprintf:buffer]; ! 234: break; ! 235: case SybaseReturnParameterRow: ! 236: // Exercise for the reader: How to format this row ! 237: [resultsView sprintf:"SybaseReturnParameterRow: No data printed\n"]; ! 238: break; ! 239: case SybaseRegularRow: ! 240: default: ! 241: break; ! 242: } ! 243: } ! 244: ! 245: ! 246: return self; ! 247: } ! 248: ! 249: - clear:sender ! 250: { ! 251: [resultsView clear:sender]; ! 252: [[queryView docView] selectText:self]; ! 253: return self; ! 254: } ! 255: ! 256: - close:sender ! 257: { ! 258: // close the adaptor channel and disconnect from the database ! 259: [channel closeChannel]; ! 260: // close the main window ! 261: [[NXApp mainWindow] performClose:sender]; ! 262: return self; ! 263: } ! 264: ! 265: ! 266: ! 267: /*-------------------------------------------------------------------------- ! 268: * Announcing Trace Info ! 269: *------------------------------------------------------------------------*/ ! 270: - (void) logString:(NSString *) aString ! 271: { ! 272: [resultsView sprintf: "%s", [aString cString]]; ! 273: } ! 274: ! 275: - (void) announce:sender selector:(SEL)selector ! 276: { ! 277: return [self announce:sender selector:selector with:nil]; ! 278: } ! 279: ! 280: ! 281: - (void) announce:sender selector:(SEL)selector with:array ! 282: { ! 283: NSMutableString *string; ! 284: ! 285: string = [NSMutableString stringWithFormat:@"BEGIN> {Sender = %s%s", ! 286: [[(NSObject *)[sender class] description] cString], "}" ]; ! 287: ! 288: ! 289: [string appendFormat:@" \n\t{Delegate Method = %s} ", sel_getName(selector)]; ! 290: ! 291: if (array) ! 292: { ! 293: id object; ! 294: id verboseString = [NSMutableString stringWithCapacity:0]; ! 295: id enumerator = [array objectEnumerator]; ! 296: ! 297: while ((object = [enumerator nextObject]) != nil) ! 298: [verboseString ! 299: appendFormat:@"\n\t{Argument = %s} \n\t{Argument Description = %s} ", ! 300: [[(NSObject *)[object class] description] cString], ! 301: [[(NSObject *) object description] cString]]; ! 302: ! 303: [string appendString:verboseString]; ! 304: } ! 305: ! 306: ! 307: [string appendFormat:@"\n"]; ! 308: [resultsView sprintf: "%s", [string cString]]; ! 309: } ! 310: ! 311: ! 312: /* Window Delegate method -- constrain window resizing */ ! 313: ! 314: - windowWillResize:sender toSize:(NXSize *)frameSize ! 315: { ! 316: if ( frameSize->height < 230 ) frameSize->height= 230; ! 317: return self; ! 318: } ! 319: ! 320: ! 321: @end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.