|
|
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.